Author: mattf
Date: Fri Jul 20 13:54:20 2007
New Revision: 2762

URL: http://svn.digium.com/view/zaptel?view=rev&rev=2762
Log:
Merged revisions 2761 via svnmerge from 
https://origsvn.digium.com/svn/zaptel/branches/1.2

........
r2761 | mattf | 2007-07-20 11:19:47 -0500 (Fri, 20 Jul 2007) | 1 line

New product support, new echo canceler and new boards
........

Added:
    branches/1.4/wctdm24xxp/
      - copied from r2761, branches/1.2/wctdm24xxp/
    branches/1.4/wctdm24xxp/GpakApi.c
      - copied unchanged from r2761, branches/1.2/wctdm24xxp/GpakApi.c
    branches/1.4/wctdm24xxp/GpakApi.h
      - copied unchanged from r2761, branches/1.2/wctdm24xxp/GpakApi.h
    branches/1.4/wctdm24xxp/GpakCust.c
      - copied unchanged from r2761, branches/1.2/wctdm24xxp/GpakCust.c
    branches/1.4/wctdm24xxp/GpakCust.h
      - copied unchanged from r2761, branches/1.2/wctdm24xxp/GpakCust.h
    branches/1.4/wctdm24xxp/GpakHpi.h
      - copied unchanged from r2761, branches/1.2/wctdm24xxp/GpakHpi.h
    branches/1.4/wctdm24xxp/Makefile
      - copied unchanged from r2761, branches/1.2/wctdm24xxp/Makefile
    branches/1.4/wctdm24xxp/Makefile.kernel26
      - copied unchanged from r2761, branches/1.2/wctdm24xxp/Makefile.kernel26
    branches/1.4/wctdm24xxp/base.c
      - copied, changed from r2761, branches/1.2/wctdm24xxp/base.c
    branches/1.4/wctdm24xxp/gpakErrs.h
      - copied unchanged from r2761, branches/1.2/wctdm24xxp/gpakErrs.h
    branches/1.4/wctdm24xxp/gpakenum.h
      - copied unchanged from r2761, branches/1.2/wctdm24xxp/gpakenum.h
    branches/1.4/wctdm24xxp/wctdm24xxp.h
      - copied, changed from r2761, branches/1.2/wctdm24xxp/wctdm24xxp.h
Removed:
    branches/1.4/wctdm24xxp.c
Modified:
    branches/1.4/   (props changed)
    branches/1.4/Makefile
    branches/1.4/zaptel-base.c

Propchange: branches/1.4/
------------------------------------------------------------------------------
Binary property 'branch-1.2-merged' - no diff available.

Modified: branches/1.4/Makefile
URL: 
http://svn.digium.com/view/zaptel/branches/1.4/Makefile?view=diff&rev=2762&r1=2761&r2=2762
==============================================================================
--- branches/1.4/Makefile (original)
+++ branches/1.4/Makefile Fri Jul 20 13:54:20 2007
@@ -98,8 +98,8 @@
   BUILD_XPP:=yes
 endif
 
-TOPDIR_MODULES:=pciradio tor2 torisa wcfxo wct1xxp wctdm wctdm24xxp wcte11xp 
wcusb zaptel ztd-eth ztd-loc ztdummy ztdynamic zttranscode wcte12xp
-SUBDIR_MODULES:=wct4xxp wctc4xxp xpp
+TOPDIR_MODULES:=pciradio tor2 torisa wcfxo wct1xxp wctdm wcte11xp wcusb zaptel 
ztd-eth ztd-loc ztdummy ztdynamic zttranscode wcte12xp
+SUBDIR_MODULES:=wct4xxp wctc4xxp xpp wctdm24xxp
 BUILD_TOPDIR_MODULES:=$(filter-out $(MENUSELECT_MODULES),$(TOPDIR_MODULES))
 BUILD_SUBDIR_MODULES:=$(filter-out $(MENUSELECT_MODULES),$(SUBDIR_MODULES))
 BUILD_MODULES:=$(BUILD_TOPDIR_MODULES) $(BUILD_SUBDIR_MODULES)

Copied: branches/1.4/wctdm24xxp/base.c (from r2761, 
branches/1.2/wctdm24xxp/base.c)
URL: 
http://svn.digium.com/view/zaptel/branches/1.4/wctdm24xxp/base.c?view=diff&rev=2762&p1=branches/1.2/wctdm24xxp/base.c&r1=2761&p2=branches/1.4/wctdm24xxp/base.c&r2=2762
==============================================================================
--- branches/1.2/wctdm24xxp/base.c (original)
+++ branches/1.4/wctdm24xxp/base.c Fri Jul 20 13:54:20 2007
@@ -4,8 +4,11 @@
  * Written by Mark Spencer <[EMAIL PROTECTED]>
  * Support for TDM800P and VPM150M by Matthew Fredrickson <[EMAIL PROTECTED]>
  *
- * Copyright (C) 2005, 2006, Digium, Inc.
+ * Copyright (C) 2005,2006, Digium, Inc.
+ * All rights reserved.
  *
+ * Sections for QRV cards written by Jim Dixon <[EMAIL PROTECTED]>
+ * Copyright (C) 2006, Jim Dixon and QRV Communications
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -23,6 +26,13 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  */
+/* For QRV DRI cards, gain is signed short, expressed in hundredths of
+db (in reference to 1v Peak @ 1000Hz) , as follows:
+
+Rx Gain: -11.99 to 15.52 db
+Tx Gain - No Pre-Emphasis: -35.99 to 12.00 db
+Tx Gain - W/Pre-Emphasis: -23.99 to 0.00 db
+*/
 
 #include <linux/version.h>
 #include <linux/kernel.h>
@@ -225,7 +235,7 @@
 #ifdef STANDALONE_ZAPATA
 #include "zaptel.h"
 #else
-#include <linux/zaptel.h>
+#include <zaptel/zaptel.h>
 #endif
 
 #ifdef LINUX26
@@ -266,6 +276,11 @@
 static int fxshonormode = 0;
 static int alawoverride = 0;
 static int fxo_addrs[4] = { 0x00, 0x08, 0x04, 0x0c };
+static int fxotxgain = 0;
+static int fxorxgain = 0;
+static int fxstxgain = 0;
+static int fxsrxgain = 0;
+static int nativebridge = 1;
 #ifdef VPM_SUPPORT
 static int vpmsupport = 1;
 static int vpmdtmfsupport = 0;
@@ -470,8 +485,14 @@
        ecval = ecval % EC_SIZE;
 #endif
 
+       /* if a QRV card, map it to its first channel */  
+       if ((wc->modtype[card] ==  MOD_TYPE_QRV) && (card & 3))
+       {
+               return;
+       }
        if (wc->altcs[card])
                subaddr = 0;
+ 
 
  
        /* Skip audio */
@@ -497,6 +518,8 @@
                        curcmd = CMD_RD(64);
                else if (wc->modtype[card] == MOD_TYPE_FXO)
                        curcmd = CMD_RD(12);
+               else if (wc->modtype[card] == MOD_TYPE_QRV)
+                       curcmd = CMD_RD(3);
                else if (wc->modtype[card] == MOD_TYPE_VPM) {
 #ifdef FANCY_ECHOCAN
                        if (wc->blinktimer >= 0xf) {
@@ -543,6 +566,22 @@
                writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff;
        } else if (wc->modtype[card] == MOD_TYPE_VPM150M) {
 #endif
+       } else if (wc->modtype[card] == MOD_TYPE_QRV) {
+ 
+               writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x00;
+               if (!curcmd)
+               {
+                       writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x00;
+                       writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x00;
+               }
+               else
+               {
+                       if (curcmd & __CMD_WR)
+                               writechunk[CMD_BYTE(card, 1, wc->altcs[card])] 
= 0x40 | ((curcmd >> 8) & 0x3f);
+                       else
+                               writechunk[CMD_BYTE(card, 1, wc->altcs[card])] 
= 0xc0 | ((curcmd >> 8) & 0x3f);
+                       writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd 
& 0xff;
+               }
        } else if (wc->modtype[card] == MOD_TYPE_NONE) {
                writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x00;
                writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x00;
@@ -601,6 +640,11 @@
        unsigned char ident;
        int x;
 
+       /* if a QRV card, map it to its first channel */  
+       if ((wc->modtype[card] ==  MOD_TYPE_QRV) && (card & 3))
+       {
+               return;
+       }
        /* Skip audio */
        readchunk += 24;
        spin_lock_irqsave(&wc->reglock, flags);
@@ -644,6 +688,8 @@
                        wc->cmdq[card].cmds[USER_COMMANDS + 0] = CMD_RD(68);    
/* Hook state */
                } else if (wc->modtype[card] == MOD_TYPE_FXO) {
                        wc->cmdq[card].cmds[USER_COMMANDS + 0] = CMD_RD(5);     
/* Hook/Ring state */
+               } else if (wc->modtype[card] == MOD_TYPE_QRV) {
+                       wc->cmdq[card & 0xfc].cmds[USER_COMMANDS + 0] = 
CMD_RD(3);      /* COR/CTCSS state */
 #ifdef VPM_SUPPORT
                } else if (wc->modtype[card] == MOD_TYPE_VPM) {
                        wc->cmdq[card].cmds[USER_COMMANDS + 0] = CMD_RD(0xb9); 
/* DTMF interrupt */
@@ -659,6 +705,8 @@
 #endif
                } else if (wc->modtype[card] == MOD_TYPE_FXO) {
                        wc->cmdq[card].cmds[USER_COMMANDS + 1] = CMD_RD(29);    
/* Battery */
+               } else if (wc->modtype[card] == MOD_TYPE_QRV) {
+                       wc->cmdq[card & 0xfc].cmds[USER_COMMANDS + 1] = 
CMD_RD(3);      /* Battery */
 #ifdef VPM_SUPPORT
                } else if (wc->modtype[card] == MOD_TYPE_VPM) {
                        wc->cmdq[card].cmds[USER_COMMANDS + 1] = CMD_RD(0xbd); 
/* DTMF interrupt */
@@ -742,6 +790,12 @@
        unsigned long flags;
        int hit=0;
        int ret;
+
+       /* if a QRV card, use only its first channel */  
+       if (wc->modtype[card] ==  MOD_TYPE_QRV)
+       {
+               if (card & 3) return(0);
+       }
        do {
                spin_lock_irqsave(&wc->reglock, flags);
                hit = empty_slot(wc, card);
@@ -773,6 +827,12 @@
        unsigned long flags;
        int hit;
        int ret=0;
+
+       /* if a QRV card, use only its first channel */  
+       if (wc->modtype[card] ==  MOD_TYPE_QRV)
+       {
+               if (card & 3) return(0);
+       }
        do {
                spin_lock_irqsave(&wc->reglock, flags);
                hit = empty_slot(wc, card);
@@ -1162,6 +1222,60 @@
                }
        }
 #endif
+}
+
+static inline void wctdm_qrvdri_check_hook(struct wctdm *wc, int card)
+{
+       signed char b,b1;
+       int qrvcard = card & 0xfc;
+
+       
+       if (wc->qrvdebtime[card] >= 2) wc->qrvdebtime[card]--;
+       b = wc->cmdq[qrvcard].isrshadow[0];     /* Hook/Ring state */
+       b &= 0xcc; /* use bits 3-4 and 6-7 only */
+
+       if (wc->radmode[qrvcard] & RADMODE_IGNORECOR) b &= ~4;
+       else if (!(wc->radmode[qrvcard] & RADMODE_INVERTCOR)) b ^= 4;
+       if (wc->radmode[qrvcard + 1] | RADMODE_IGNORECOR) b &= ~0x40;
+       else if (!(wc->radmode[qrvcard + 1] | RADMODE_INVERTCOR)) b ^= 0x40;
+
+       if ((wc->radmode[qrvcard] & RADMODE_IGNORECT) || 
+               (!(wc->radmode[qrvcard] & RADMODE_EXTTONE))) b &= ~8;
+       else if (!(wc->radmode[qrvcard] & RADMODE_EXTINVERT)) b ^= 8;
+       if ((wc->radmode[qrvcard + 1] & RADMODE_IGNORECT) || 
+               (!(wc->radmode[qrvcard + 1] & RADMODE_EXTTONE))) b &= ~0x80;
+       else if (!(wc->radmode[qrvcard + 1] & RADMODE_EXTINVERT)) b ^= 0x80;
+       /* now b & MASK should be zero, if its active */
+       /* check for change in chan 0 */
+       if ((!(b & 0xc)) != wc->qrvhook[qrvcard + 2])
+       {
+               wc->qrvdebtime[qrvcard] = wc->debouncetime[qrvcard];
+               wc->qrvhook[qrvcard + 2] = !(b & 0xc);
+       } 
+       /* if timed-out and ready */
+       if (wc->qrvdebtime[qrvcard] == 1)
+       {
+               b1 = wc->qrvhook[qrvcard + 2];
+if (debug) printk("QRV channel %d rx state changed to 
%d\n",qrvcard,wc->qrvhook[qrvcard + 2]);
+               zt_hooksig(&wc->chans[qrvcard], 
+                       (b1) ? ZT_RXSIG_OFFHOOK : ZT_RXSIG_ONHOOK);
+               wc->qrvdebtime[card] = 0;
+       }
+       /* check for change in chan 1 */
+       if ((!(b & 0xc0)) != wc->qrvhook[qrvcard + 3])
+       {
+               wc->qrvdebtime[qrvcard + 1] = QRV_DEBOUNCETIME;
+               wc->qrvhook[qrvcard + 3] = !(b & 0xc0);
+       }
+       if (wc->qrvdebtime[qrvcard + 1] == 1)
+       {
+               b1 = wc->qrvhook[qrvcard + 3];
+if (debug) printk("QRV channel %d rx state changed to %d\n",qrvcard + 
1,wc->qrvhook[qrvcard + 3]);
+               zt_hooksig(&wc->chans[qrvcard + 1], 
+                       (b1) ? ZT_RXSIG_OFFHOOK : ZT_RXSIG_ONHOOK);
+               wc->qrvdebtime[card] = 0;
+       }
+       return;
 }
 
 static inline void wctdm_voicedaa_check_hook(struct wctdm *wc, int card)
@@ -1408,6 +1522,7 @@
 static inline void wctdm_isr_misc(struct wctdm *wc)
 {
        int x;
+
        for (x=0;x<wc->cards;x++) {
                if (wc->cardflag & (1 << x)) {
                        if (wc->modtype[x] == MOD_TYPE_FXS) {
@@ -1439,6 +1554,8 @@
                                }
                        } else if (wc->modtype[x] == MOD_TYPE_FXO) {
                                wctdm_voicedaa_check_hook(wc, x);
+                       } else if (wc->modtype[x] == MOD_TYPE_QRV) {
+                               wctdm_qrvdri_check_hook(wc, x);
                        }
                }
        }
@@ -1846,6 +1963,8 @@
        unsigned char reg16=0, reg26=0, reg30=0, reg31=0;
        long newjiffies;
 
+       if (wc->modtype[card & 0xfc] == MOD_TYPE_QRV) return -2;
+
        wc->modtype[card] = MOD_TYPE_NONE;
        /* Wait just a bit */
        wait_just_a_bit(HZ/10);
@@ -1923,6 +2042,40 @@
        /* Apply negative Rx gain of 4.5db to DAA */
        wctdm_setreg(wc, card, 39, 0x14);       /* 4db */
        wctdm_setreg(wc, card, 41, 0x15);       /* 0.5db */
+
+       
+       /* Take values for fxotxgain and fxorxgain and apply them to module */
+       if (fxotxgain) {
+               if (fxotxgain >=  -150 && fxotxgain < 0) {
+                       wctdm_setreg(wc, card, 38, 16 + (fxotxgain/-10));
+                       if(fxotxgain % 10) {
+                               wctdm_setreg(wc, card, 40, 16 + 
(-fxotxgain%10));
+                       }
+               }
+               else if (fxotxgain <= 120 && fxotxgain > 0) {
+                       wctdm_setreg(wc, card, 38, fxotxgain/10);
+                       if(fxotxgain % 10) {
+                               wctdm_setreg(wc, card, 40, (fxotxgain%10));
+                       }
+               }
+       }
+       if (fxorxgain) {
+               if (fxorxgain >=  -150 && fxorxgain < 0) {
+                       wctdm_setreg(wc, card, 39, 16+ (fxorxgain/-10));
+                       if(fxotxgain % 10) {
+                               wctdm_setreg(wc, card, 41, 16 + 
(-fxorxgain%10));
+                       }
+               }
+               else if (fxorxgain <= 120 && fxorxgain > 0) {
+                       wctdm_setreg(wc, card, 39, fxorxgain/10);
+                       if(fxorxgain % 10) {
+                               wctdm_setreg(wc, card, 41, (fxorxgain%10));
+                       }
+               }
+       }
+       
+       if(debug)
+               printk("DEBUG fxotxgain:%i.%i fxorxgain:%i.%i\n", 
(wctdm_getreg(wc, card, 38)/16) ? -(wctdm_getreg(wc, card, 38) - 16) : 
wctdm_getreg(wc, card, 38), (wctdm_getreg(wc, card, 40)/16) ? 
-(wctdm_getreg(wc, card, 40) - 16) : wctdm_getreg(wc, card, 40), 
(wctdm_getreg(wc, card, 39)/16) ? -(wctdm_getreg(wc, card, 39) - 16): 
wctdm_getreg(wc, card, 39), (wctdm_getreg(wc, card, 41)/16)?-(wctdm_getreg(wc, 
card, 41) - 16) : wctdm_getreg(wc, card, 41));
        
        return 0;
                
@@ -1932,9 +2085,11 @@
 {
 
        unsigned short tmp[5];
-       unsigned char r19;
+       unsigned char r19,r9;
        int x;
        int fxsmode=0;
+
+       if (wc->modtype[card & 0xfc] == MOD_TYPE_QRV) return -2;
 
        /* By default, don't send on hook */
        wc->mods[card].fxs.idletxhookstate = 1;
@@ -2125,11 +2280,174 @@
                        printk("Reducing ring power on slot %d (50V peak)\n", 
card + 1);
                }
        }
+
+       if(fxstxgain || fxsrxgain) {
+               r9 = wctdm_getreg(wc, card, 9);
+               switch (fxstxgain) {
+               
+                       case 35:
+                               r9+=8;
+                               break;
+                       case -35:
+                               r9+=4;
+                               break;
+                       case 0: 
+                               break;
+               }
+       
+               switch (fxsrxgain) {
+                       
+                       case 35:
+                               r9+=2;
+                               break;
+                       case -35:
+                               r9+=1;
+                               break;
+                       case 0:
+                               break;
+               }
+               wctdm_setreg(wc,card,9,r9);
+       }
+
+       if(debug)
+                       printk("DEBUG: fxstxgain:%s 
fxsrxgain:%s\n",((wctdm_getreg(wc, card, 9)/8) == 
1)?"3.5":(((wctdm_getreg(wc,card,9)/4) == 1)?"-3.5":"0.0"),((wctdm_getreg(wc, 
card, 9)/2) == 1)?"3.5":((wctdm_getreg(wc,card,9)%2)?"-3.5":"0.0"));
+
        wctdm_setreg(wc, card, 64, 0x01);
        wc->mods[card].fxs.lasttxhook = 1;
        return 0;
 }
 
+static int wctdm_init_qrvdri(struct wctdm *wc, int card)
+{
+       unsigned char x,y;
+       unsigned long endjif;
+
+       /* have to set this, at least for now */
+       wc->modtype[card] = MOD_TYPE_QRV;
+       if (!(card & 3)) /* if at base of card, reset and write it */
+       {
+               wctdm_setreg(wc,card,0,0x80); 
+               wctdm_setreg(wc,card,0,0x55);
+               wctdm_setreg(wc,card,1,0x69);
+               wc->qrvhook[card] = wc->qrvhook[card + 1] = 0;
+               wc->qrvhook[card + 2] = wc->qrvhook[card + 3] = 0xff;
+               wc->debouncetime[card] = wc->debouncetime[card + 1] = 
QRV_DEBOUNCETIME;
+               wc->qrvdebtime[card] = wc->qrvdebtime[card + 1] = 0;
+               wc->radmode[card] = wc->radmode[card + 1] = 0;
+               wc->txgain[card] = wc->txgain[card + 1] = 3599;
+               wc->rxgain[card] = wc->rxgain[card + 1] = 1199;
+       } else { /* channel is on same card as base, no need to test */
+               if (wc->modtype[card & 0x7c] == MOD_TYPE_QRV) 
+               {
+                       /* only lower 2 are valid */
+                       if (!(card & 2)) return 0;
+               }
+               wc->modtype[card] = MOD_TYPE_NONE;
+               return 1;
+       }
+       x = wctdm_getreg(wc,card,0);
+       y = wctdm_getreg(wc,card,1);
+       /* if not a QRV card, return as such */
+       if ((x != 0x55) || (y != 0x69))
+       {
+               wc->modtype[card] = MOD_TYPE_NONE;
+               return 1;
+       }
+       for(x = 0; x < 0x30; x++)
+       {
+               if ((x >= 0x1c) && (x <= 0x1e)) wctdm_setreg(wc,card,x,0xff);
+               else wctdm_setreg(wc,card,x,0);
+       }
+       wctdm_setreg(wc,card,0,0x80); 
+       endjif = jiffies + (HZ/10);
+       while(endjif > jiffies);
+       wctdm_setreg(wc,card,0,0x10); 
+       wctdm_setreg(wc,card,0,0x10); 
+       endjif = jiffies + (HZ/10);
+       while(endjif > jiffies);
+       /* set up modes */
+       wctdm_setreg(wc,card,0,0x1c); 
+       /* set up I/O directions */
+       wctdm_setreg(wc,card,1,0x33); 
+       wctdm_setreg(wc,card,2,0x0f); 
+       wctdm_setreg(wc,card,5,0x0f); 
+       /* set up I/O to quiescent state */
+       wctdm_setreg(wc,card,3,0x11);  /* D0-7 */
+       wctdm_setreg(wc,card,4,0xa);  /* D8-11 */
+       wctdm_setreg(wc,card,7,0);  /* CS outputs */
+       /* set up timeslots */
+       wctdm_setreg(wc,card,0x13,card + 0x80);  /* codec 2 tx, ts0 */
+       wctdm_setreg(wc,card,0x17,card + 0x80);  /* codec 0 rx, ts0 */
+       wctdm_setreg(wc,card,0x14,card + 0x81);  /* codec 1 tx, ts1 */
+       wctdm_setreg(wc,card,0x18,card + 0x81);  /* codec 1 rx, ts1 */
+       /* set up for max gains */
+       wctdm_setreg(wc,card,0x26,0x24); 
+       wctdm_setreg(wc,card,0x27,0x24); 
+       wctdm_setreg(wc,card,0x0b,0x01);  /* "Transmit" gain codec 0 */
+       wctdm_setreg(wc,card,0x0c,0x01);  /* "Transmit" gain codec 1 */
+       wctdm_setreg(wc,card,0x0f,0xff);  /* "Receive" gain codec 0 */
+       wctdm_setreg(wc,card,0x10,0xff);  /* "Receive" gain codec 1 */
+       return 0;
+}
+
+static void qrv_dosetup(struct zt_chan *chan,struct wctdm *wc)
+{
+int qrvcard;
+unsigned char r;
+long l;
+
+       /* actually do something with the values */
+       qrvcard = (chan->chanpos - 1) & 0xfc;
+       if (debug) printk("@@@@@ radmodes: %d,%d  rxgains: %d,%d   txgains: 
%d,%d\n",
+       wc->radmode[qrvcard],wc->radmode[qrvcard + 1],
+               wc->rxgain[qrvcard],wc->rxgain[qrvcard + 1],
+                       wc->txgain[qrvcard],wc->txgain[qrvcard + 1]);
+       r = 0;
+       if (wc->radmode[qrvcard] & RADMODE_DEEMP) r |= 4;               
+       if (wc->radmode[qrvcard + 1] & RADMODE_DEEMP) r |= 8;           
+       if (wc->rxgain[qrvcard] < 1200) r |= 1;
+       if (wc->rxgain[qrvcard + 1] < 1200) r |= 2;
+       wctdm_setreg(wc, qrvcard, 7, r);
+       if (debug) printk("@@@@@ setting reg 7 to %02x hex\n",r);
+       r = 0;
+       if (wc->radmode[qrvcard] & RADMODE_PREEMP) r |= 3;
+       else if (wc->txgain[qrvcard] >= 3600) r |= 1;
+       else if (wc->txgain[qrvcard] >= 1200) r |= 2;
+       if (wc->radmode[qrvcard + 1] & RADMODE_PREEMP) r |= 0xc;
+       else if (wc->txgain[qrvcard + 1] >= 3600) r |= 4;
+       else if (wc->txgain[qrvcard + 1] >= 1200) r |= 8;
+       wctdm_setreg(wc, qrvcard, 4, r);
+       if (debug) printk("@@@@@ setting reg 4 to %02x hex\n",r);
+       r = 0;
+       if (wc->rxgain[qrvcard] >= 2400) r |= 1; 
+       if (wc->rxgain[qrvcard + 1] >= 2400) r |= 2; 
+       wctdm_setreg(wc, qrvcard, 0x25, r);
+       if (debug) printk("@@@@@ setting reg 0x25 to %02x hex\n",r);
+       r = 0;
+       if (wc->txgain[qrvcard] < 2400) r |= 1; else r |= 4;
+       if (wc->txgain[qrvcard + 1] < 2400) r |= 8; else r |= 0x20;
+       wctdm_setreg(wc, qrvcard, 0x26, r);
+       if (debug) printk("@@@@@ setting reg 0x26 to %02x hex\n",r);
+       l = ((long)(wc->rxgain[qrvcard] % 1200) * 10000) / 46875;
+       if (l == 0) l = 1;
+       if (wc->rxgain[qrvcard] >= 2400) l += 181;
+       wctdm_setreg(wc, qrvcard, 0x0b, (unsigned char)l);
+       if (debug) printk("@@@@@ setting reg 0x0b to %02x hex\n",(unsigned 
char)l);
+       l = ((long)(wc->rxgain[qrvcard + 1] % 1200) * 10000) / 46875;
+       if (l == 0) l = 1;
+       if (wc->rxgain[qrvcard + 1] >= 2400) l += 181;
+       wctdm_setreg(wc, qrvcard, 0x0c, (unsigned char)l);
+       if (debug) printk("@@@@@ setting reg 0x0c to %02x hex\n",(unsigned 
char)l);
+       l = ((long)(wc->txgain[qrvcard] % 1200) * 10000) / 46875;
+       if (l == 0) l = 1;
+       wctdm_setreg(wc, qrvcard, 0x0f, (unsigned char)l);
+       if (debug) printk("@@@@@ setting reg 0x0f to %02x hex\n", (unsigned 
char)l);
+       l = ((long)(wc->txgain[qrvcard + 1] % 1200) * 10000) / 46875;
+       if (l == 0) l = 1;
+       wctdm_setreg(wc, qrvcard, 0x10,(unsigned char)l);
+       if (debug) printk("@@@@@ setting reg 0x10 to %02x hex\n",(unsigned 
char)l);
+       return;
+}
 
 static int wctdm_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long 
data)
 {
@@ -2139,6 +2457,10 @@
        struct wctdm_echo_coefs echoregs;
        struct wctdm *wc = chan->pvt;
        int x;
+       union {
+               struct zt_radio_stat s;
+               struct zt_radio_param p;
+       } stack;
 
 #if 0
        /* XXX */
@@ -2202,6 +2524,10 @@
                                regs.indirect[x] = 
wctdm_proslic_getreg_indirect(wc, chan->chanpos -1, x);
                        for (x=0;x<NUM_REGS;x++)
                                regs.direct[x] = wctdm_getreg(wc, chan->chanpos 
- 1, x);
+               } else if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_QRV) {
+                       memset(&regs, 0, sizeof(regs));
+                       for (x=0;x<0x32;x++)
+                               regs.direct[x] = wctdm_getreg(wc, chan->chanpos 
- 1, x);
                } else {
                        memset(&regs, 0, sizeof(regs));
                        for (x=0;x<NUM_FXO_REGS;x++)
@@ -2275,12 +2601,150 @@
                }
                return 0;
 #endif
+       case ZT_RADIO_GETPARAM:
+               if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_QRV) 
+                       return -ENOTTY;
+               if (copy_from_user(&stack.p,(struct zt_radio_param 
*)data,sizeof(struct zt_radio_param))) return -EFAULT;
+               stack.p.data = 0; /* start with 0 value in output */
+               switch(stack.p.radpar) {
+               case ZT_RADPAR_INVERTCOR:
+                       if (wc->radmode[chan->chanpos - 1] & RADMODE_INVERTCOR)
+                               stack.p.data = 1;
+                       break;
+               case ZT_RADPAR_IGNORECOR:
+                       if (wc->radmode[chan->chanpos - 1] & RADMODE_IGNORECOR)
+                               stack.p.data = 1;
+                       break;
+               case ZT_RADPAR_IGNORECT:
+                       if (wc->radmode[chan->chanpos - 1] & RADMODE_IGNORECT)
+                               stack.p.data = 1;
+                       break;
+               case ZT_RADPAR_EXTRXTONE:
+                       stack.p.data = 0;
+                       if (wc->radmode[chan->chanpos - 1] & RADMODE_EXTTONE)
+                       {
+                               stack.p.data = 1;
+                               if (wc->radmode[chan->chanpos - 1] & 
RADMODE_EXTINVERT)
+                               {
+                                       stack.p.data = 2;
+                               }
+                       }
+                       break;
+               case ZT_RADPAR_DEBOUNCETIME:
+                       stack.p.data = wc->debouncetime[chan->chanpos - 1];
+                       break;
+               case ZT_RADPAR_RXGAIN:
+                       stack.p.data = wc->rxgain[chan->chanpos - 1] - 1199;
+                       break;
+               case ZT_RADPAR_TXGAIN:
+                       stack.p.data = wc->txgain[chan->chanpos - 1] - 3599;
+                       break;
+               case ZT_RADPAR_DEEMP:
+                       stack.p.data = 0;
+                       if (wc->radmode[chan->chanpos - 1] & RADMODE_DEEMP)
+                       {
+                               stack.p.data = 1;
+                       }
+                       break;
+               case ZT_RADPAR_PREEMP:
+                       stack.p.data = 0;
+                       if (wc->radmode[chan->chanpos - 1] & RADMODE_PREEMP)
+                       {
+                               stack.p.data = 1;
+                       }
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               if (copy_to_user((struct zt_radio_param 
*)data,&stack.p,sizeof(struct zt_radio_param))) return -EFAULT;
+               break;
+       case ZT_RADIO_SETPARAM:
+               if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_QRV) 
+                       return -ENOTTY;
+               if (copy_from_user(&stack.p,(struct zt_radio_param 
*)data,sizeof(struct zt_radio_param))) return -EFAULT;
+               switch(stack.p.radpar) {
+               case ZT_RADPAR_INVERTCOR:
+                       if (stack.p.data)
+                               wc->radmode[chan->chanpos - 1] |= 
RADMODE_INVERTCOR;
+                       else
+                               wc->radmode[chan->chanpos - 1] &= 
~RADMODE_INVERTCOR;
+                       return 0;
+               case ZT_RADPAR_IGNORECOR:
+                       if (stack.p.data)
+                               wc->radmode[chan->chanpos - 1] |= 
RADMODE_IGNORECOR;
+                       else
+                               wc->radmode[chan->chanpos - 1] &= 
~RADMODE_IGNORECOR;
+                       return 0;
+               case ZT_RADPAR_IGNORECT:
+                       if (stack.p.data)
+                               wc->radmode[chan->chanpos - 1] |= 
RADMODE_IGNORECT;
+                       else
+                               wc->radmode[chan->chanpos - 1] &= 
~RADMODE_IGNORECT;
+                       return 0;
+               case ZT_RADPAR_EXTRXTONE:
+                       if (stack.p.data)
+                               wc->radmode[chan->chanpos - 1] |= 
RADMODE_EXTTONE;
+                       else
+                               wc->radmode[chan->chanpos - 1] &= 
~RADMODE_EXTTONE;
+                       if (stack.p.data > 1)
+                               wc->radmode[chan->chanpos - 1] |= 
RADMODE_EXTINVERT;
+                       else
+                               wc->radmode[chan->chanpos - 1] &= 
~RADMODE_EXTINVERT;
+                       return 0;
+               case ZT_RADPAR_DEBOUNCETIME:
+                       wc->debouncetime[chan->chanpos - 1] = stack.p.data;
+                       return 0;
+               case ZT_RADPAR_RXGAIN:
+                       /* if out of range */
+                       if ((stack.p.data <= -1200) || (stack.p.data > 1552))
+                       {
+                               return -EINVAL;
+                       }
+                       wc->rxgain[chan->chanpos - 1] = stack.p.data + 1199;
+                       break;
+               case ZT_RADPAR_TXGAIN:
+                       /* if out of range */
+                       if (wc->radmode[chan->chanpos -1] & RADMODE_PREEMP)
+                       {
+                               if ((stack.p.data <= -2400) || (stack.p.data > 
0))
+                               {
+                                       return -EINVAL;
+                               }
+                       }
+                       else
+                       {
+                               if ((stack.p.data <= -3600) || (stack.p.data > 
1200))
+                               {
+                                       return -EINVAL;
+                               }
+                       }
+                       wc->txgain[chan->chanpos - 1] = stack.p.data + 3599;
+                       break;
+               case ZT_RADPAR_DEEMP:
+                       if (stack.p.data)
+                               wc->radmode[chan->chanpos - 1] |= RADMODE_DEEMP;
+                       else
+                               wc->radmode[chan->chanpos - 1] &= 
~RADMODE_DEEMP;
+                       wc->rxgain[chan->chanpos - 1] = 1199;
+                       break;
+               case ZT_RADPAR_PREEMP:
+                       if (stack.p.data)
+                               wc->radmode[chan->chanpos - 1] |= 
RADMODE_PREEMP;
+                       else
+                               wc->radmode[chan->chanpos - 1] &= 
~RADMODE_PREEMP;
+                       wc->txgain[chan->chanpos - 1] = 3599;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               qrv_dosetup(chan,wc);
+               return 0;                               
        default:
                return -ENOTTY;
        }
        return 0;
-
-}
+}
+
 static int wctdm_open(struct zt_chan *chan)
 {
        struct wctdm *wc = chan->pvt;
@@ -2308,6 +2772,7 @@
 {
        struct wctdm *wc = chan->pvt;
        int x;
+       signed char reg;
        wc->usecount--;
 #ifndef LINUX26
        MOD_DEC_USE_COUNT;
@@ -2317,6 +2782,23 @@
        for (x=0;x<wc->cards;x++) {
                if (wc->modtype[x] == MOD_TYPE_FXS)
                        wc->mods[x].fxs.idletxhookstate = 1;
+               if (wc->modtype[x] == MOD_TYPE_QRV)
+               {
+                       int qrvcard = x & 0xfc;
+
+                       wc->qrvhook[x] = 0;
+                       wc->qrvhook[x + 2] = 0xff;
+                       wc->debouncetime[x] = QRV_DEBOUNCETIME;
+                       wc->qrvdebtime[x] = 0;
+                       wc->radmode[x] = 0;
+                       wc->txgain[x] = 3599;
+                       wc->rxgain[x] = 1199;
+                       reg = 0;
+                       if (!wc->qrvhook[qrvcard]) reg |= 1;
+                       if (!wc->qrvhook[qrvcard + 1]) reg |= 0x10;
+                       wc->sethook[qrvcard] = CMD_WR(3, reg);
+                       qrv_dosetup(chan,wc);
+               }
        }
        /* If we're dead, release us now */
        if (!wc->usecount && wc->dead) 
@@ -2327,8 +2809,26 @@
 static int wctdm_hooksig(struct zt_chan *chan, zt_txsig_t txsig)
 {
        struct wctdm *wc = chan->pvt;
-       int reg=0;
-       if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) {
+       int reg=0,qrvcard;
+       if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_QRV) {
+               qrvcard = (chan->chanpos - 1) & 0xfc;
+               switch(txsig) {
+               case ZT_TXSIG_START:
+               case ZT_TXSIG_OFFHOOK:
+                       wc->qrvhook[chan->chanpos - 1] = 1;
+                       break;
+               case ZT_TXSIG_ONHOOK:
+                       wc->qrvhook[chan->chanpos - 1] = 0;
+                       break;
+               default:
+                       printk("wctdm24xxp: Can't set tx state to %d\n", txsig);
+               }
+               reg = 0;
+               if (!wc->qrvhook[qrvcard]) reg |= 1;
+               if (!wc->qrvhook[qrvcard + 1]) reg |= 0x10;
+               wc->sethook[qrvcard] = CMD_WR(3, reg);
+               /* wctdm_setreg(wc, qrvcard, 3, reg); */
+       } else if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) {
                switch(txsig) {
                case ZT_TXSIG_START:
                case ZT_TXSIG_OFFHOOK:
@@ -2387,6 +2887,102 @@
        return 0;
 }
 
+static void wctdm_dacs_connect(struct wctdm *wc, int srccard, int dstcard)
+{
+
+       if (wc->dacssrc[dstcard] > - 1) {
+               printk("wctdm_dacs_connect: Can't have double sourcing yet!\n");
+               return;
+       }
+       if (!((wc->modtype[srccard] == MOD_TYPE_FXS)||(wc->modtype[srccard] == 
MOD_TYPE_FXO))){
+               printk("wctdm_dacs_connect: Unsupported modtype for card %d\n", 
srccard);
+               return;
+       }
+       if (!((wc->modtype[dstcard] == MOD_TYPE_FXS)||(wc->modtype[dstcard] == 
MOD_TYPE_FXO))){
+               printk("wctdm_dacs_connect: Unsupported modtype for card %d\n", 
dstcard);
+               return;
+       }
+       if (debug)
+               printk("connect %d => %d\n", srccard, dstcard);
+       wc->dacssrc[dstcard] = srccard;
+
+       /* make srccard transmit to srccard+24 on the TDM bus */
+       if (wc->modtype[srccard] == MOD_TYPE_FXS) {
+               /* proslic */
+               wctdm_setreg(wc, srccard, PCM_XMIT_START_COUNT_LSB, 
((srccard+24) * 8) & 0xff); 
+               wctdm_setreg(wc, srccard, PCM_XMIT_START_COUNT_MSB, 
((srccard+24) * 8) >> 8);
+       } else if(wc->modtype[srccard] == MOD_TYPE_FXO) { 
+               /* daa */
+               wctdm_setreg(wc, srccard, 34, ((srccard+24) * 8) & 0xff); /* TX 
*/
+               wctdm_setreg(wc, srccard, 35, ((srccard+24) * 8) >> 8);   /* TX 
*/
+       }
+
+       /* have dstcard receive from srccard+24 on the TDM bus */
+       if (wc->modtype[dstcard] == MOD_TYPE_FXS) {
+               /* proslic */
+       wctdm_setreg(wc, dstcard, PCM_RCV_START_COUNT_LSB,  ((srccard+24) * 8) 
& 0xff);
+               wctdm_setreg(wc, dstcard, PCM_RCV_START_COUNT_MSB,  
((srccard+24) * 8) >> 8);
+       } else if(wc->modtype[dstcard] == MOD_TYPE_FXO) {
+               /* daa */
+               wctdm_setreg(wc, dstcard, 36, ((srccard+24) * 8) & 0xff); /* RX 
*/
+               wctdm_setreg(wc, dstcard, 37, ((srccard+24) * 8) >> 8);   /* RX 
*/
+       }
+
+}
+
+static void wctdm_dacs_disconnect(struct wctdm *wc, int card)
+{
+       if (wc->dacssrc[card] > -1) {
+               if (debug)
+                       printk("wctdm_dacs_disconnect: restoring TX for %d and 
RX for %d\n",wc->dacssrc[card], card);
+
+               /* restore TX (source card) */
+               if(wc->modtype[wc->dacssrc[card]] == MOD_TYPE_FXS){
+                       wctdm_setreg(wc, wc->dacssrc[card], 
PCM_XMIT_START_COUNT_LSB, (wc->dacssrc[card] * 8) & 0xff);
+                       wctdm_setreg(wc, wc->dacssrc[card], 
PCM_XMIT_START_COUNT_MSB, (wc->dacssrc[card] * 8) >> 8);
+               } else if(wc->modtype[wc->dacssrc[card]] == MOD_TYPE_FXO){
+                       wctdm_setreg(wc, card, 34, (card * 8) & 0xff);
+                       wctdm_setreg(wc, card, 35, (card * 8) >> 8);
+               } else {
+                       printk("WARNING: wctdm_dacs_disconnect() called on 
unsupported modtype\n");
+               }
+
+               /* restore RX (this card) */
+               if(wc->modtype[card] == MOD_TYPE_FXS){
+                       wctdm_setreg(wc, card, PCM_RCV_START_COUNT_LSB, (card * 
8) & 0xff);
+               wctdm_setreg(wc, card, PCM_RCV_START_COUNT_MSB, (card * 8) >> 
8);
+               } else if(wc->modtype[card] == MOD_TYPE_FXO){
+                       wctdm_setreg(wc, card, 36, (card * 8) & 0xff);
+                       wctdm_setreg(wc, card, 37, (card * 8) >> 8);
+               } else {
+                       printk("WARNING: wctdm_dacs_disconnect() called on 
unsupported modtype\n");
+               }
+
+               wc->dacssrc[card] = -1;
+       }
+}
+
+static int wctdm_dacs(struct zt_chan *dst, struct zt_chan *src)
+{
+       struct wctdm *wc;
+
+       if(!nativebridge)
+               return 0; /* should this return -1 since unsuccessful? */
+
+       wc = dst->pvt;
+
+       if(src) {
+               wctdm_dacs_connect(wc, src->chanpos - 1, dst->chanpos - 1);
+               if (debug)
+                       printk("dacs connecct: %d -> %d!\n\n", src->chanpos, 
dst->chanpos);
+       } else {
+               wctdm_dacs_disconnect(wc, dst->chanpos - 1);
+               if (debug)
+                       printk("dacs disconnect: %d!\n", dst->chanpos);
+       }
+       return 0;
+}
+
 static int wctdm_initialize(struct wctdm *wc)
 {
        int x;
@@ -2414,6 +3010,7 @@
        wc->span.flags = ZT_FLAG_RBS;
        wc->span.ioctl = wctdm_ioctl;
        wc->span.watchdog = wctdm_watchdog;
+       wc->span.dacs= wctdm_dacs;
 #ifdef VPM_SUPPORT
        wc->span.echocan = wctdm_echocan;
 #endif 
@@ -2437,6 +3034,8 @@
                                wc->chans[x].sigcap = ZT_SIG_FXSKS | 
ZT_SIG_FXSLS | ZT_SIG_SF | ZT_SIG_CLEAR;
                        else if (wc->modtype[x] == MOD_TYPE_FXS)
                                wc->chans[x].sigcap = ZT_SIG_FXOKS | 
ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_SF | ZT_SIG_EM | ZT_SIG_CLEAR;
+                       else if (wc->modtype[x] == MOD_TYPE_QRV)
+                               wc->chans[x].sigcap = ZT_SIG_SF | ZT_SIG_EM | 
ZT_SIG_CLEAR;
                }
        }
 }
@@ -3237,7 +3836,7 @@
                        if (debug & DEBUG_CARD) {
                                readi = wctdm_getreg(wc,x,LOOP_I_LIMIT);
                                printk("Proslic module %d loop current is 
%dmA\n",x,
-                               ((readi*3)+20));
+                                       ((readi*3)+20));
                        }
                        printk("Port %d: Installed -- AUTO FXS/DPO\n", x + 1);
                } else {
@@ -3249,7 +3848,7 @@
                                 if (debug & DEBUG_CARD) {
                                         readi = 
wctdm_getreg(wc,x,LOOP_I_LIMIT);
                                         printk("Proslic module %d loop current 
is %dmA\n",x,
-                                        ((readi*3)+20));
+                                              ((readi*3)+20));
                                 }
                                        printk("Port %d: Installed -- MANUAL 
FXS\n",x + 1);
                                } else {
@@ -3258,6 +3857,9 @@
                        } else if (!(ret = wctdm_init_voicedaa(wc, x, 0, 0, 
sane))) {
                                wc->cardflag |= (1 << x);
                                printk("Port %d: Installed -- AUTO FXO (%s 
mode)\n",x + 1, fxo_modes[_opermode].name);
+                       } else if (!wctdm_init_qrvdri(wc,x)) {
+                               wc->cardflag |= 1 << x;
+                               printk("Port %d: Installed -- QRV DRI card\n",x 
+ 1);
                        } else {
                                if ((wc->type == 8) && ((x & 0x3) == 1) && 
!wc->altcs[x]) {
                                        spin_lock_irqsave(&wc->reglock, flags);
@@ -3327,8 +3929,10 @@
                        wc->dev = pdev;
                        wc->pos = x;
                        wc->variety = d->name;
-                       for (y=0;y<NUM_CARDS;y++)
+                       for (y=0;y<NUM_CARDS;y++) {
                                wc->flags[y] = d->flags;
+                               wc->dacssrc[y] = -1;
+                       }
                        /* Keep track of whether we need to free the region */
                        if (request_region(wc->iobase, 0xff, "wctdm24xxp")) 
                                wc->freeregion = 1;
@@ -3509,6 +4113,7 @@
 {
        int res;
        int x;
+
        for (x=0;x<(sizeof(fxo_modes) / sizeof(fxo_modes[0])); x++) {
                if (!strcmp(fxo_modes[x].name, opermode))
                        break;
@@ -3549,6 +4154,11 @@
 module_param(battdebounce, int, 0600);
 module_param(battthresh, int, 0600);
 module_param(alawoverride, int, 0600);
+module_param(nativebridge, int, 0600);
+module_param(fxotxgain, int, 0600);
+module_param(fxorxgain, int, 0600);
+module_param(fxstxgain, int, 0600);
+module_param(fxsrxgain, int, 0600);
 #ifdef VPM_SUPPORT
 module_param(vpmsupport, int, 0600);
 module_param(vpmdtmfsupport, int, 0600);
@@ -3567,6 +4177,11 @@
 MODULE_PARM(battdebounce, "i");
 MODULE_PARM(battthresh, "i");
 MODULE_PARM(alawoverride, "i");
+MODULE_PARM(nativebridge, "i");
+MODULE_PARM(fxotxgain, "i");
+MODULE_PARM(fxorxgain, "i");
+MODULE_PARM(fxstxgain, "i");
+MODULE_PARM(fxsrxgain, "i");
 #ifdef VPM_SUPPORT
 MODULE_PARM(vpmsupport, "i");
 MODULE_PARM(vpmdtmfsupport, "i");

Copied: branches/1.4/wctdm24xxp/wctdm24xxp.h (from r2761, 
branches/1.2/wctdm24xxp/wctdm24xxp.h)
URL: 
http://svn.digium.com/view/zaptel/branches/1.4/wctdm24xxp/wctdm24xxp.h?view=diff&rev=2762&p1=branches/1.2/wctdm24xxp/wctdm24xxp.h&r1=2761&p2=branches/1.4/wctdm24xxp/wctdm24xxp.h&r2=2762
==============================================================================
--- branches/1.2/wctdm24xxp/wctdm24xxp.h (original)
+++ branches/1.4/wctdm24xxp/wctdm24xxp.h Fri Jul 20 13:54:20 2007
@@ -29,7 +29,8 @@
 #define MOD_TYPE_FXO           2
 #define MOD_TYPE_FXSINIT       3       
 #define MOD_TYPE_VPM           4
-#define MOD_TYPE_VPM150M       5
+#define MOD_TYPE_QRV           5
+#define MOD_TYPE_VPM150M       6
 
 #define MINPEGTIME     10 * 8          /* 30 ms peak to peak gets us no more 
than 100 Hz */
 #define PEGTIME                50 * 8          /* 50ms peak to peak gets us 
rings of 10 Hz or more */
@@ -61,6 +62,7 @@
 
 #define USER_COMMANDS 8
 #define ISR_COMMANDS  2
+#define        QRV_DEBOUNCETIME 20
 
 #define MAX_COMMANDS (USER_COMMANDS + ISR_COMMANDS)
 
@@ -154,6 +156,19 @@
        int cards;
        int cardflag;           /* Bit-map of present cards */
        int altcs[NUM_CARDS + NUM_EC];
+       char qrvhook[NUM_CARDS];
+       unsigned short qrvdebtime[NUM_CARDS];
+       int radmode[NUM_CARDS];
+#define        RADMODE_INVERTCOR 1
+#define        RADMODE_IGNORECOR 2
+#define        RADMODE_EXTTONE 4
+#define        RADMODE_EXTINVERT 8
+#define        RADMODE_IGNORECT 16
+#define        RADMODE_PREEMP  32
+#define        RADMODE_DEEMP 64
+       unsigned short debouncetime[NUM_CARDS];
+       signed short rxgain[NUM_CARDS];
+       signed short txgain[NUM_CARDS];
        spinlock_t reglock;
        wait_queue_head_t regq;
        /* FXO Stuff */
@@ -186,6 +201,7 @@
        int modtype[NUM_CARDS + NUM_EC];
        /* Set hook */
        int sethook[NUM_CARDS + NUM_EC];
+       int dacssrc[NUM_CARDS];
        int type;
 
 #ifdef VPM_SUPPORT

Modified: branches/1.4/zaptel-base.c
URL: 
http://svn.digium.com/view/zaptel/branches/1.4/zaptel-base.c?view=diff&rev=2762&r1=2761&r2=2762
==============================================================================
--- branches/1.4/zaptel-base.c (original)
+++ branches/1.4/zaptel-base.c Fri Jul 20 13:54:20 2007
@@ -1049,12 +1049,13 @@
        memset(chan->conflast1, 0, sizeof(chan->conflast1));
        memset(chan->conflast2, 0, sizeof(chan->conflast2));
 
+       if (chan->span && chan->span->dacs && oldconf)
+               chan->span->dacs(chan, NULL);
+
+       spin_unlock_irqrestore(&chan->lock, flags);
+
        if (chan->span && chan->span->echocan)
                chan->span->echocan(chan, 0);
-       if (chan->span && chan->span->dacs && oldconf)
-               chan->span->dacs(chan, NULL);
-
-       spin_unlock_irqrestore(&chan->lock, flags);
 
        if (rxgain)
                kfree(rxgain);
@@ -2279,9 +2280,11 @@
                chan->ringcadence[0] = chan->starttime;
                chan->ringcadence[1] = ZT_RINGOFFTIME;
        }
+
+       spin_unlock_irqrestore(&chan->lock, flags);
+
        if (chan->span && chan->span->echocan)
                chan->span->echocan(chan, 0);
-       spin_unlock_irqrestore(&chan->lock, flags);
 
        if (rxgain)
                kfree(rxgain);
@@ -4283,9 +4286,10 @@
                        chan->txgain = defgain;
                        chan->gainalloc = 0;
                        /* Disable any native echo cancellation as well */
+                       spin_unlock_irqrestore(&chan->lock, flags);
+
                        if (chan->span && chan->span->echocan)
                                chan->span->echocan(chan, 0);
-                       spin_unlock_irqrestore(&chan->lock, flags);
 
                        if (rxgain)
                                kfree(rxgain);
@@ -4389,10 +4393,13 @@
                        tec = chan->ec;
                        chan->ec = NULL;
                        /* Attempt hardware native echo can */
+                       spin_unlock_irqrestore(&chan->lock, flags);
+
                        if (chan->span && chan->span->echocan)
                                ret = chan->span->echocan(chan, j);
                        else
                                ret = -ENOTTY;
+
                        if (ret) {
                                /* Use built-in echo can */
                                if ((j == 32) ||
@@ -4405,7 +4412,6 @@
                                } else {
                                        j = deftaps;
                                }
-                               spin_unlock_irqrestore(&chan->lock, flags);
                                ec = echo_can_create(j, 0);
                                if (!ec)
                                        return -ENOMEM;
@@ -4417,8 +4423,8 @@
                                chan->echotimer = 0;
                                echo_can_disable_detector_init(&chan->txecdis);
                                echo_can_disable_detector_init(&chan->rxecdis);
-                       }
-                       spin_unlock_irqrestore(&chan->lock, flags);
+                               spin_unlock_irqrestore(&chan->lock, flags);
+                       }
                        if (tec)
                                echo_can_free(tec);
                } else {
@@ -4429,10 +4435,10 @@
                        chan->echostate = ECHO_STATE_IDLE;
                        chan->echolastupdate = 0;
                        chan->echotimer = 0;
+                       spin_unlock_irqrestore(&chan->lock, flags);
                        /* Attempt hardware native echo can */
                        if (chan->span && chan->span->echocan)
                                chan->span->echocan(chan, 0);
-                       spin_unlock_irqrestore(&chan->lock, flags);
                        if (tec)
                                echo_can_free(tec);
                }


_______________________________________________
--Bandwidth and Colocation Provided by http://www.api-digital.com--

svn-commits mailing list
To UNSUBSCRIBE or update options visit:
   http://lists.digium.com/mailman/listinfo/svn-commits

Reply via email to