[zaptel-commits] kpfleming: branch mogorman/zaptel-1.2-transcoder r1990 - in /team/mogorman/za...

zaptel-commits at lists.digium.com zaptel-commits at lists.digium.com
Sat Jan 27 09:20:42 MST 2007


Author: kpfleming
Date: Sat Jan 27 10:20:41 2007
New Revision: 1990

URL: http://svn.digium.com/view/zaptel?view=rev&rev=1990
Log:
Merged revisions 1953,1962-1963,1966,1978,1981,1987 via svnmerge from 
https://origsvn.digium.com/svn/zaptel/branches/1.2

........
r1953 | kpfleming | 2007-01-24 07:01:36 -0600 (Wed, 24 Jan 2007) | 2 lines

might as well fix this driver too :-)

........
r1962 | tzafrir | 2007-01-25 00:45:00 -0600 (Thu, 25 Jan 2007) | 5 lines

xproto old code cleanup:
- Remove old SOFT_SIMULATOR (not used in the last year ;-)
- As a result can merge packet_receive() and packet_process()
- Remove unused macro (MAX_XPACKET_DATALEN) from xproto.h

........
r1963 | tzafrir | 2007-01-25 00:47:12 -0600 (Thu, 25 Jan 2007) | 2 lines

Remove confusing print of ZT_FLAG_RUNNING .

........
r1966 | tzafrir | 2007-01-25 04:48:33 -0600 (Thu, 25 Jan 2007) | 16 lines

* Xbus protocol version: 2.4 (Zaptel 1.2.12/1.4.0 had 2.3).
  XPS Init scripts renamed accordingly.
* Performance improvements for multi-XPD (span) devices.
* Astribank BRI driver (in next commit).
* Changes under /proc:
  - XBUS and XPD numbers have two digits.
  - Every script wildcard should be replaced from XBUS-? to XBUS-[0-9]*
  - Added /proc/xpp/XBUS-*/XPD-*/blink: echo 1 to start and 0 to stop.
* Several countries (South Africa, UAE, anybody else) require a shorter
  ring delay. Adjust FXO reg 0x17 (23)'s bits 0:2 to 011.
* Use tasklets to move most of the interrupt PCM copying out of the interrupt.
* Debugfs-based code to dump data to userspace (used to debug BRI D channel).
* Pretend every 2.6.9 actually has later RHEL's typedefs.
* fpga_load supports /dev/bus/usb .
* Fixed physical order sorting in genzaptelconf.

........
r1978 | mattf | 2007-01-25 17:12:27 -0600 (Thu, 25 Jan 2007) | 2 lines

Add support for additional product.

........
r1981 | mattf | 2007-01-26 09:26:52 -0600 (Fri, 26 Jan 2007) | 2 lines

Fix driver table entry name to original.

........
r1987 | kpfleming | 2007-01-27 10:14:54 -0600 (Sat, 27 Jan 2007) | 2 lines

properly reference the size symbol produced by objcopy

........

Added:
    team/mogorman/zaptel-1.2-transcoder/xpp/firmwares/FPGA_1141.hex
      - copied unchanged from r1987, branches/1.2/xpp/firmwares/FPGA_1141.hex
    team/mogorman/zaptel-1.2-transcoder/xpp/firmwares/USB_1140.hex
      - copied unchanged from r1987, branches/1.2/xpp/firmwares/USB_1140.hex
    team/mogorman/zaptel-1.2-transcoder/xpp/init_card_3_24
      - copied unchanged from r1987, branches/1.2/xpp/init_card_3_24
    team/mogorman/zaptel-1.2-transcoder/xpp/init_card_4_24
      - copied unchanged from r1987, branches/1.2/xpp/init_card_4_24
    team/mogorman/zaptel-1.2-transcoder/xpp/init_card_6_24
      - copied unchanged from r1987, branches/1.2/xpp/init_card_6_24
    team/mogorman/zaptel-1.2-transcoder/xpp/init_card_7_24
      - copied unchanged from r1987, branches/1.2/xpp/init_card_7_24
    team/mogorman/zaptel-1.2-transcoder/xpp/xpp_log.h
      - copied unchanged from r1987, branches/1.2/xpp/xpp_log.h
Removed:
    team/mogorman/zaptel-1.2-transcoder/xpp/init_card_3_23
    team/mogorman/zaptel-1.2-transcoder/xpp/init_card_4_23
Modified:
    team/mogorman/zaptel-1.2-transcoder/   (props changed)
    team/mogorman/zaptel-1.2-transcoder/wcfxo.c
    team/mogorman/zaptel-1.2-transcoder/wct4xxp/base.c
    team/mogorman/zaptel-1.2-transcoder/wctdm24xxp.c
    team/mogorman/zaptel-1.2-transcoder/xpp/Makefile
    team/mogorman/zaptel-1.2-transcoder/xpp/README.Astribank
    team/mogorman/zaptel-1.2-transcoder/xpp/card_fxo.c
    team/mogorman/zaptel-1.2-transcoder/xpp/card_fxs.c
    team/mogorman/zaptel-1.2-transcoder/xpp/card_global.c
    team/mogorman/zaptel-1.2-transcoder/xpp/firmwares/FPGA_1151.hex
    team/mogorman/zaptel-1.2-transcoder/xpp/firmwares/FPGA_FXS.hex   (contents, props changed)
    team/mogorman/zaptel-1.2-transcoder/xpp/utils/Makefile
    team/mogorman/zaptel-1.2-transcoder/xpp/utils/fpga_load.8
    team/mogorman/zaptel-1.2-transcoder/xpp/utils/fpga_load.c
    team/mogorman/zaptel-1.2-transcoder/xpp/utils/genzaptelconf
    team/mogorman/zaptel-1.2-transcoder/xpp/utils/xpp_fxloader
    team/mogorman/zaptel-1.2-transcoder/xpp/xbus-core.c
    team/mogorman/zaptel-1.2-transcoder/xpp/xbus-core.h
    team/mogorman/zaptel-1.2-transcoder/xpp/xdefs.h
    team/mogorman/zaptel-1.2-transcoder/xpp/xpd.h
    team/mogorman/zaptel-1.2-transcoder/xpp/xpp_usb.c
    team/mogorman/zaptel-1.2-transcoder/xpp/xpp_zap.c
    team/mogorman/zaptel-1.2-transcoder/xpp/xpp_zap.h
    team/mogorman/zaptel-1.2-transcoder/xpp/xproto.c
    team/mogorman/zaptel-1.2-transcoder/xpp/xproto.h
    team/mogorman/zaptel-1.2-transcoder/xpp/zap_debug.c
    team/mogorman/zaptel-1.2-transcoder/xpp/zap_debug.h

Propchange: team/mogorman/zaptel-1.2-transcoder/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Sat Jan 27 10:20:41 2007
@@ -1,1 +1,1 @@
-/branches/1.2:1-1951
+/branches/1.2:1-1989

Modified: team/mogorman/zaptel-1.2-transcoder/wcfxo.c
URL: http://svn.digium.com/view/zaptel/team/mogorman/zaptel-1.2-transcoder/wcfxo.c?view=diff&rev=1990&r1=1989&r2=1990
==============================================================================
--- team/mogorman/zaptel-1.2-transcoder/wcfxo.c (original)
+++ team/mogorman/zaptel-1.2-transcoder/wcfxo.c Sat Jan 27 10:20:41 2007
@@ -407,7 +407,6 @@
 #endif
 
 	ints = inb(wc->ioaddr + WC_INTSTAT);
-	outb(ints, wc->ioaddr + WC_INTSTAT);
 
 
 	if (!ints)
@@ -416,6 +415,8 @@
 #else
 		return;
 #endif		
+
+	outb(ints, wc->ioaddr + WC_INTSTAT);
 
 	if (ints & 0x0c) {  /* if there is a rx interrupt pending */
 #ifdef ENABLE_TASKLETS

Modified: team/mogorman/zaptel-1.2-transcoder/wct4xxp/base.c
URL: http://svn.digium.com/view/zaptel/team/mogorman/zaptel-1.2-transcoder/wct4xxp/base.c?view=diff&rev=1990&r1=1989&r2=1990
==============================================================================
--- team/mogorman/zaptel-1.2-transcoder/wct4xxp/base.c (original)
+++ team/mogorman/zaptel-1.2-transcoder/wct4xxp/base.c Sat Jan 27 10:20:41 2007
@@ -2679,8 +2679,8 @@
 	struct firmware embedded_firmware;
 	const struct firmware *firmware = &embedded_firmware;
 #if !defined(HOTPLUG_FIRMWARE)
-	extern const u32 _binary_OCT6114_64D_ima_size;
-	extern const u32 _binary_OCT6114_128D_ima_size;
+	extern const u32 *_binary_OCT6114_64D_ima_size;
+	extern const u32 *_binary_OCT6114_128D_ima_size;
 	extern u8 _binary_OCT6114_64D_ima_start[];
 	extern u8 _binary_OCT6114_128D_ima_start[];
 #endif
@@ -2719,7 +2719,7 @@
 		}
 #else
 		embedded_firmware.data = _binary_OCT6114_64D_ima_start;
-		embedded_firmware.size = _binary_OCT6114_64D_ima_size;
+		embedded_firmware.size = *_binary_OCT6114_64D_ima_size;
 #endif
 		break;
 	case 128:
@@ -2731,7 +2731,7 @@
 		}
 #else
 		embedded_firmware.data = _binary_OCT6114_128D_ima_start;
-		embedded_firmware.size = _binary_OCT6114_128D_ima_size;
+		embedded_firmware.size = *_binary_OCT6114_128D_ima_size;
 #endif
 		break;
 	default:

Modified: team/mogorman/zaptel-1.2-transcoder/wctdm24xxp.c
URL: http://svn.digium.com/view/zaptel/team/mogorman/zaptel-1.2-transcoder/wctdm24xxp.c?view=diff&rev=1990&r1=1989&r2=1990
==============================================================================
--- team/mogorman/zaptel-1.2-transcoder/wctdm24xxp.c (original)
+++ team/mogorman/zaptel-1.2-transcoder/wctdm24xxp.c Sat Jan 27 10:20:41 2007
@@ -2,6 +2,7 @@
  * Wilcard TDM2400P TDM FXS/FXO Interface Driver for Zapata Telephony interface
  *
  * Written by Mark Spencer <markster at digium.com>
+ * Further modified to add support for the  TDM800P by Matthew Fredrickson <creslin at digium.com>
  *
  * Copyright (C) 2005, 2006, Digium, Inc.
  *
@@ -289,9 +290,9 @@
 
 #define CMD_WR(a,b) (((a) << 8) | (b) | __CMD_WR)
 #define CMD_RD(a) (((a) << 8) | __CMD_RD)
-#define CMD_BYTE(card,bit) (((((card) & 0x3) * 3 + (bit)) * 7) \
-			+ ((card) >> 2))
-
+
+#define CMD_BYTE(card,bit,altcs) (((((card) & 0x3) * 3 + (bit)) * 7) \
+			+ ((card) >> 2) + (altcs) + ((altcs) ? -21 : 0))
 
 struct calregs {
 	unsigned char vals[NUM_CAL_REGS];
@@ -326,6 +327,7 @@
 	unsigned char ctlreg;
 	int cards;
 	int cardflag;		/* Bit-map of present cards */
+ 	int altcs[NUM_CARDS + NUM_EC];
 	spinlock_t reglock;
 	wait_queue_head_t regq;
 	/* FXO Stuff */
@@ -358,6 +360,7 @@
 	int modtype[NUM_CARDS + NUM_EC];
 	/* Set hook */
 	int sethook[NUM_CARDS + NUM_EC];
+ 	int type;
 
 #ifdef VPM_SUPPORT
 	int vpm;
@@ -385,9 +388,11 @@
 struct wctdm_desc {
 	char *name;
 	int flags;
+	int ports;
 };
 
-static struct wctdm_desc wctdm = { "Wildcard TDM2400P", 0 };
+static struct wctdm_desc wctdm2400 = { "Wildcard TDM2400P", 0, 24 };
+static struct wctdm_desc wctdm800 = { "Wildcard TDM800P", 0, 8 };
 static int acim2tiss[16] = { 0x0, 0x1, 0x4, 0x5, 0x7, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x2, 0x0, 0x3 };
 
 static struct wctdm *ifaces[WC_MAX_IFACES];
@@ -443,6 +448,7 @@
 	unsigned long flags;
 	unsigned int curcmd=0;
 	int x;
+	int subaddr = card & 0x3;
 #ifdef FANCY_ECHOCAN
 	int ecval;
 	ecval = wc->echocanpos;
@@ -450,6 +456,9 @@
 	ecval = ecval % EC_SIZE;
 #endif
 
+ 	if (wc->altcs[card])
+ 		subaddr = 0;
+ 
 	/* Skip audio */
 	writechunk += 24;
 	spin_lock_irqsave(&wc->reglock, flags);
@@ -485,43 +494,43 @@
 		}
 	}
 	if (wc->modtype[card] == MOD_TYPE_FXS) {
-		writechunk[CMD_BYTE(card, 0)] = (1 << (card & 0x3));
+ 		writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = (1 << (subaddr));
 		if (curcmd & __CMD_WR)
-			writechunk[CMD_BYTE(card, 1)] = (curcmd >> 8) & 0x7f;
+ 			writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = (curcmd >> 8) & 0x7f;
 		else
-			writechunk[CMD_BYTE(card, 1)] = 0x80 | ((curcmd >> 8) & 0x7f);
-		writechunk[CMD_BYTE(card, 2)] = curcmd & 0xff;
+ 			writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x80 | ((curcmd >> 8) & 0x7f);
+ 		writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff;
 	} else if (wc->modtype[card] == MOD_TYPE_FXO) {
 		if (curcmd & __CMD_WR)
-			writechunk[CMD_BYTE(card, 0)] = 0x20 | fxo_addrs[card & 0x3];
+ 			writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x20 | fxo_addrs[subaddr];
 		else
-			writechunk[CMD_BYTE(card, 0)] = 0x60 | fxo_addrs[card & 0x3];
-		writechunk[CMD_BYTE(card, 1)] = (curcmd >> 8) & 0xff;
-		writechunk[CMD_BYTE(card, 2)] = curcmd & 0xff;
+ 			writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x60 | fxo_addrs[subaddr];
+ 		writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = (curcmd >> 8) & 0xff;
+ 		writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff;
 	} else if (wc->modtype[card] == MOD_TYPE_FXSINIT) {
 		/* Special case, we initialize the FXS's into the three-byte command mode then
 		   switch to the regular mode.  To send it into thee byte mode, treat the path as
 		   6 two-byte commands and in the last one we initialize register 0 to 0x80. All modules
 		   read this as the command to switch to daisy chain mode and we're done.  */
-		writechunk[CMD_BYTE(card, 0)] = 0x00;
-		writechunk[CMD_BYTE(card, 1)] = 0x00;
+ 		writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x00;
+ 		writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x00;
 		if ((card & 0x1) == 0x1) 
-			writechunk[CMD_BYTE(card, 2)] = 0x80;
+ 			writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x80;
 		else
-			writechunk[CMD_BYTE(card, 2)] = 0x00;
+ 			writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x00;
 #ifdef VPM_SUPPORT
 	} else if (wc->modtype[card] == MOD_TYPE_VPM) {
 		if (curcmd & __CMD_WR)
-			writechunk[CMD_BYTE(card, 0)] = ((card & 0x3) << 4) | 0xc | ((curcmd >> 16) & 0x1);
+ 			writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = ((card & 0x3) << 4) | 0xc | ((curcmd >> 16) & 0x1);
 		else
-			writechunk[CMD_BYTE(card, 0)] = ((card & 0x3) << 4) | 0xa | ((curcmd >> 16) & 0x1);
-		writechunk[CMD_BYTE(card, 1)] = (curcmd >> 8) & 0xff;
-		writechunk[CMD_BYTE(card, 2)] = curcmd & 0xff;
+ 			writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = ((card & 0x3) << 4) | 0xa | ((curcmd >> 16) & 0x1);
+ 		writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = (curcmd >> 8) & 0xff;
+ 		writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff;
 #endif
 	} else if (wc->modtype[card] == MOD_TYPE_NONE) {
-		writechunk[CMD_BYTE(card, 0)] = 0x00;
-		writechunk[CMD_BYTE(card, 1)] = 0x00;
-		writechunk[CMD_BYTE(card, 2)] = 0x00;
+ 		writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x00;
+ 		writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x00;
+ 		writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x00;
 	}
 #if 0
 	/* XXX */
@@ -552,7 +561,7 @@
 		   	ident = (wc->cmdq[card].cmds[x] >> 24) & 0xff;
 		   	if (ident == wc->rxident) {
 				/* Store result */
-				wc->cmdq[card].cmds[x] |= readchunk[CMD_BYTE(card, 2)];
+				wc->cmdq[card].cmds[x] |= readchunk[CMD_BYTE(card, 2, wc->altcs[card])];
 				wc->cmdq[card].cmds[x] |= __CMD_FIN;
 				if (wc->cmdq[card].cmds[x] & __CMD_WR) {
 					/* Go ahead and clear out writes since they need no acknowledgement */
@@ -624,9 +633,10 @@
 
 	for (x=0;x<ZT_CHUNKSIZE;x++) {
 		/* Send a sample, as a 32-bit word */
-		for (y=0;y < wc->cards;y++) {
+		for (y=0;y < wc->type;y++) {
 			if (!x)
 				cmd_checkisr(wc, y);
+
 			writechunk[y] = wc->chans[y].writechunk[x];
 			cmd_dequeue(wc, writechunk, y, x);
 		}
@@ -877,7 +887,7 @@
 				cmd_retransmit(wc);
 			}
 		}
-		for (y=0;y < wc->cards;y++) {
+		for (y=0;y < wc->type;y++) {
 			wc->chans[y].readchunk[x] = readchunk[y];
 			cmd_decifer(wc, readchunk, y);
 		}
@@ -895,7 +905,7 @@
 		readchunk += (EFRAME_SIZE + EFRAME_GAP);
 	}
 	/* XXX We're wasting 8 taps.  We should get closer :( */
-	for (x=0;x<wc->cards;x++) {
+	for (x=0;x<wc->type;x++) {
 		if (wc->cardflag & (1 << x))
 			zt_ec_chunk(&wc->chans[x], wc->chans[x].readchunk, wc->chans[x].writechunk);
 	}
@@ -1583,7 +1593,7 @@
 	}
 
 	if (vbat < 0xc0) {
-		printk("ProSLIC on module %d failed to powerup within %d ms (%d mV only)\n\n -- DID YOU REMEMBER TO PLUG IN THE HD POWER CABLE TO THE TDM2400P??\n",
+		printk("ProSLIC on module %d failed to powerup within %d ms (%d mV only)\n\n -- DID YOU REMEMBER TO PLUG IN THE HD POWER CABLE TO THE TDM CARD??\n",
 		       card, (int)(((jiffies - origjiffies) * 1000 / HZ)),
 			vbat * 375);
 		return -1;
@@ -2300,7 +2310,7 @@
 		wc->chans[x].pvt = wc;
 	}
 	wc->span.chans = wc->chans;
-	wc->span.channels = wc->cards;
+	wc->span.channels = wc->type;
 	wc->span.hooksig = wctdm_hooksig;
 	wc->span.open = wctdm_open;
 	wc->span.close = wctdm_close;
@@ -2353,7 +2363,7 @@
 
 	newjiffies = jiffies + HZ/10;
 	while(((reg = wctdm_getctl(wc,0x0000)) & 0x00000001) && (newjiffies > jiffies));
-	printk("WCTDM2400P: New Reg: %08x!\n", reg);
+	printk("%s: New Reg: %08x!\n", wc->variety, reg);
 
 	
 	/* Configure watchdogs, access, etc */
@@ -2384,7 +2394,7 @@
 	printk("(post) Reg fc is %08x\n", reg);
 	printk("Detected REG2: %08x\n", wctdm_getsdi(wc, 0x02));
 #endif
-	printk("wctdm2400p: reg is %08x\n", wctdm_getctl(wc, 0x0088));
+	printk("wctdm24xxp: reg is %08x\n", wctdm_getctl(wc, 0x0088));
 
 	return 0;
 }
@@ -2616,13 +2626,20 @@
 	for (x=0;x<wc->cards;x++) 
 		wc->modtype[x] = MOD_TYPE_FXS;
 	spin_unlock_irqrestore(&wc->reglock, flags);
+
 #if 0
 	/* XXX */
 	cmddesc = 0;
 #endif	
+	/* Now that all the cards have been reset, we can stop checking them all if there aren't as many */
+	spin_lock_irqsave(&wc->reglock, flags);
+	wc->cards = wc->type;
+	spin_unlock_irqrestore(&wc->reglock, flags);
+
 	/* Reset modules */
 	for (x=0;x<wc->cards;x++) {
 		int sane=0,ret=0,readi=0;
+retry:
 		/* Init with Auto Calibration */
 		if (!(ret = wctdm_init_proslic(wc, x, 0, 0, sane))) {
 			wc->cardflag |= (1 << x);
@@ -2650,8 +2667,25 @@
 			} 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
-				printk("Port %d: Not installed\n", x + 1);
+			} else {
+ 				if ((wc->type == 8) && ((x & 0x3) == 1) && !wc->altcs[x]) {
+ 					spin_lock_irqsave(&wc->reglock, flags);
+ 					wc->modtype[x] = MOD_TYPE_FXSINIT;
+ 					wc->altcs[x] = 2;
+ 					spin_unlock_irqrestore(&wc->reglock, flags);
+ 					schluffen(&wc->regq);
+ 					spin_lock_irqsave(&wc->reglock, flags);
+ 					wc->modtype[x] = MOD_TYPE_FXS;
+ 					spin_unlock_irqrestore(&wc->reglock, flags);
+ 					if (debug)
+ 						printk("Trying port %d with alternate chip select\n", x + 1);
+ 					goto retry;
+ 				} else {
+ 					printk("Port %d: Not installed\n", x + 1);
+ 					wc->modtype[x] = MOD_TYPE_NONE;
+ 					wc->cardflag |= (1 << x);
+ 				}
+			}
 		}
 	}
 #ifdef VPM_SUPPORT
@@ -2671,7 +2705,7 @@
 	int x;
 	int y;
 	static int initd_ifaces=0;
-	
+
 	if(initd_ifaces){
 		memset((void *)ifaces,0,(sizeof(struct wctdm *))*WC_MAX_IFACES);
 		initd_ifaces=1;
@@ -2694,13 +2728,14 @@
 			wc->curcard = -1;
 			wc->cards = NUM_CARDS;
 			wc->iobase = pci_resource_start(pdev, 0);
+			wc->type = d->ports;
 			wc->dev = pdev;
 			wc->pos = x;
 			wc->variety = d->name;
 			for (y=0;y<NUM_CARDS;y++)
 				wc->flags[y] = d->flags;
 			/* Keep track of whether we need to free the region */
-			if (request_region(wc->iobase, 0xff, "wctdm")) 
+			if (request_region(wc->iobase, 0xff, "wctdm24xxp")) 
 				wc->freeregion = 1;
 
 			/* Allocate enough memory for two zt chunks, receive and transmit.  Each sample uses
@@ -2726,7 +2761,7 @@
 			init_waitqueue_head(&wc->regq);
 
 			if (wctdm_initialize(wc)) {
-				printk("wctdm: Unable to intialize FXS\n");
+				printk("%s: Unable to register span with zaptel\n", wc->variety);
 				/* Set Reset Low */
 				wctdm_stop_dma(wc);
 				/* Free Resources */
@@ -2744,8 +2779,8 @@
 			/* Keep track of which device we are */
 			pci_set_drvdata(pdev, wc);
 
-			if (request_irq(pdev->irq, wctdm_interrupt, SA_SHIRQ, "wctdm24xxp", wc)) {
-				printk("wctdm: Unable to request IRQ %d\n", pdev->irq);
+			if (request_irq(pdev->irq, wctdm_interrupt, SA_SHIRQ, wc->variety, wc)) {
+				printk("wctdm24xxp: Unable to request IRQ %d\n", pdev->irq);
 				if (wc->freeregion)
 					release_region(wc->iobase, 0xff);
 				pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma);
@@ -2783,7 +2818,7 @@
 			/* Final initialization */
 			wctdm_post_initialize(wc);
 
-			printk("Found a Wildcard TDM: %s (%d modules)\n", wc->variety, wc->cards);
+			printk("Found a Wildcard TDM: %s (%d modules)\n", wc->variety, wc->type);
 			res = 0;
 		} else
 			res = -ENOMEM;
@@ -2824,7 +2859,8 @@
 }
 
 static struct pci_device_id wctdm_pci_tbl[] = {
-	{ 0xd161, 0x2400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm },
+	{ 0xd161, 0x2400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm2400 },
+	{ 0xd161, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm800 },
 	{ 0 }
 };
 
@@ -2909,7 +2945,7 @@
 MODULE_PARM(dtmfthreshold, "i");
 #endif
 #endif
-MODULE_DESCRIPTION("Wildcard TDM2400P Zaptel Driver");
+MODULE_DESCRIPTION("Wildcard TDM2400P/TDM800P Zaptel Driver");
 MODULE_AUTHOR("Mark Spencer <markster at digium.com>");
 #ifdef MODULE_LICENSE
 MODULE_LICENSE("GPL");

Modified: team/mogorman/zaptel-1.2-transcoder/xpp/Makefile
URL: http://svn.digium.com/view/zaptel/team/mogorman/zaptel-1.2-transcoder/xpp/Makefile?view=diff&rev=1990&r1=1989&r2=1990
==============================================================================
--- team/mogorman/zaptel-1.2-transcoder/xpp/Makefile (original)
+++ team/mogorman/zaptel-1.2-transcoder/xpp/Makefile Sat Jan 27 10:20:41 2007
@@ -1,15 +1,33 @@
-EXTRA_CFLAGS	= -g3 -I$(SUBDIRS) -DDEBUG -DPOLL_DIGITAL_INPUTS -DWITH_ECHO_SUPPRESSION
+EXTRA_CFLAGS	=	$(XPP_LOCAL_CFLAGS)	\
+			-g3 -I$(SUBDIRS)	\
+			-DDEBUG			\
+			-DPOLL_DIGITAL_INPUTS	\
+			-DWITH_ECHO_SUPPRESSION	\
+			-DPROTOCOL_DEBUG	\
+			-DZAPTEL_EC_TYPEDEF	\
+
+# Useful for Astribank-BRI debugging, and maybe more later on.
+# Requires debugfs support in the kernel.
+#			-DXPP_DEBUGFS
+
+DRIVER_DIR	= $(SUBDIRS)
 
 obj-m		+= xpp.o xpd_fxs.o xpd_fxo.o
+
+HAS_BRISTUFF			:= $(shell cpp $(CPPFLAGS) -dM $(DRIVER_DIR)/zconfig.h | sed -n 's/^.*CONFIG_ZAPATA_BRI_DCHANS/y/p')
 
 # Build only supported modules
 ifneq	(,$(filter y m,$(CONFIG_USB)))
 obj-m		+= xpp_usb.o
 endif
+ifneq	(,$(HAS_BRISTUFF))
+obj-m		+= xpd_bri.o
+endif
 
 xpp-y		+= xbus-core.o xpp_zap.o xproto.o card_global.o
 xpd_fxs-y	+= card_fxs.o
 xpd_fxo-y	+= card_fxo.o
+xpd_bri-y	+= card_bri.o
 
 ctags:
 	ctags *.[ch]

Modified: team/mogorman/zaptel-1.2-transcoder/xpp/README.Astribank
URL: http://svn.digium.com/view/zaptel/team/mogorman/zaptel-1.2-transcoder/xpp/README.Astribank?view=diff&rev=1990&r1=1989&r2=1990
==============================================================================
--- team/mogorman/zaptel-1.2-transcoder/xpp/README.Astribank (original)
+++ team/mogorman/zaptel-1.2-transcoder/xpp/README.Astribank Sat Jan 27 10:20:41 2007
@@ -22,9 +22,10 @@
 
   make -C xpp/utils
   
-In order to build the user space utilities, you will need the libusb-dev 
-package on Debian (and derivatives like ubuntu) or libusb-devel on RedHat 
+In order to build the user space utilities, you will need the libusb-dev
+package on Debian (and derivatives like ubuntu) or libusb-devel on RedHat
 (and derivatives like Centox/Trixbox).
+  
 
 INSTALLATION:
 """"""""""""
@@ -130,11 +131,54 @@
 this will be the old value + 1.
 
 
+Firmware Loading with Hotplug:
+"""""""""""""""""""""""""""""
+The Hotplug framework was popular for hotplugging and usually also 
+autoloading drivers. If it is used on your system, you'll see 
+/etc/hotplug with many files under it. Hotplug will automatically load
+most relevant USB and PCI kernel modules by the relevant USB and PCI
+IDs. Again: if the framework is in place and the proper configuration
+files are in place, the firmware should be loaded automatically.
+
+In order to get hotplug to autoload the firmware into the Astribank, 
+the configuration file xpp_fxloader.usermap and the script xpp_fxloader 
+should be copied into /etc/hotplug/usb/ . This is done by 'make -C
+xpp/utils install' .
+
+xpp_fxloader.usermap includes a map of USB IDs and the command to run 
+when they are encountered. It instructs hotplug to run the script 
+xpp_fxloader from that directory. This is done by 'make -C
+xpp/utils install' .
+
+When xpp_fxloader is run without any parameters it assumes that it was
+run by the hotplug scripts. It will then check if the even is an "add"
+event (and not a "remove" event), and if so, install the required
+firmware file. It will be called twice, as after the load of the USB
+firmware the device will reenumerate itself and thus "unplug" and
+"replug" to load the FPGA firmware.
+
+
 Firmware Loading with UDEV:
 """"""""""""""""""""""""""
-Firmware loading with udev should work but is not installed 
-automatically, yet. See the comments in the beginning of the script
-/etc/hotplug/usb/xpp_fxloader .
+The UDEV framework has replaced Hotplug in most recent systems. If you
+have a recent 2.6 system with no Hotplug and files under /etc/udev,
+chances are you ude udev. udev does quite a few nice things.
+Again: if the framework is in place and the proper configuration
+files are in place, the firmware should be loaded automatically.
+
+In order to get hotplug to autoload the firmware into the Astribank, 
+the configuration file xpp.rules should be copied into /etc/udev/rules.d 
+and the script xpp_fxloader should be copied into /etc/hotplug/usb/ . 
+This is done by 'make -C xpp/utils install' .
+
+xpp.rules instructs udevd to run xpp_fxloader with the option udev and
+the USB ID when an Astribank is plugged and needs loading firmware.
+When xpp_fxloader is run with the option udev it assumes that it was
+run by udevd scripts. It will then install the required firmware file. 
+It will be called twice, as after the load of the USB firmware the
+device will reenumerate itself and thus "unplug" and "replug" to load 
+the FPGA firmware.
+
 
 Loading The Modules:
 """""""""""""""""""
@@ -301,6 +345,47 @@
           13 XPP_IN/0-12 FXOKS (In use) 
           14 XPP_IN/0-13 FXOKS (In use) 
 
+Sample dialplan (extentions.conf) for all the above:
+
+[phones-zap] 
+; 401 will dial to channel 1, 420, to zaptel channel 20, etc. 
+exten => _4XX,1,Dial(ZAP/${EXTEN:1}) 
+ 
+[trunk-9] 
+; Dial through the first FXO port availble.  
+; This assumes that all FXO ports are in group 0 and all others are not,  
+; as in the sample zapata.conf for 8FXS/8FXO below, and as is generated 
+; by genzaptelconf by default. 
+exten => 9.,Dial(Zap/g0/${EXTEN:1}) 
+ 
+[from-internal] 
+;  The context of FXS ports: analog phones.  
+; They are allowed to dial to all other phones 
+include => phones-zap 
+; They are also allowed to call through the trunk: 
+include => trunk-9 
+ 
+[from-pstn] 
+; Calls from the PSTN enter here. Redirect calls to an IVR 
+; or a default extension in the s context here. In this case we  
+; redirect calls to Zaptel channel 1: 
+exten => s,1,Dial(Zap/1) 
+ 
+[astribank-inputs] 
+exten => s,1,Set(ZAP_CHAN=Cut(${CHANNEL},-,1)) 
+exten => s,n,Set(ZAP_CHAN=Cut(${ZAP_CHAN},/,2)) 
+; 11 is the number of the first input port. At least in the sample 
+; configuration below. 
+exten => s,n,Set(INPUT_NUM=Math(${ZAP_CHAN}-11)) 
+; The sample below just logs the signal.  
+exten => s,n,NoOp(Got signal from input port number ${INPUT_NUM}) 
+; Alternatively: 
+;exten => s,n,System(run something) 
+ 
+; No. We did not forget the context astribank-outputs. Output 
+; ports only get calls from the PBX. Thus they don't need a context 
+; of their own. 
+
 
 /proc Interface
 """""""""""""""

Modified: team/mogorman/zaptel-1.2-transcoder/xpp/card_fxo.c
URL: http://svn.digium.com/view/zaptel/team/mogorman/zaptel-1.2-transcoder/xpp/card_fxo.c?view=diff&rev=1990&r1=1989&r2=1990
==============================================================================
--- team/mogorman/zaptel-1.2-transcoder/xpp/card_fxo.c (original)
+++ team/mogorman/zaptel-1.2-transcoder/xpp/card_fxo.c Sat Jan 27 10:20:41 2007
@@ -29,6 +29,7 @@
 #include "xpp_zap.h"
 #include "card_fxo.h"
 #include "zap_debug.h"
+#include "xbus-core.h"
 
 static const char rcsid[] = "$Id$";
 
@@ -65,7 +66,6 @@
 /*---------------- FXO Protocol Commands ----------------------------------*/
 
 static /* 0x0F */ DECLARE_CMD(FXO, XPD_STATE, bool on);
-static /* 0x0F */ DECLARE_CMD(FXO, CHAN_CID, lineno_t chan);
 static /* 0x0F */ DECLARE_CMD(FXO, RING, lineno_t chan, bool on);
 static /* 0x0F */ DECLARE_CMD(FXO, RELAY_OUT, byte which, bool on);
 
@@ -152,7 +152,7 @@
 	for_each_line(xpd, i) {
 		if(IS_SET(xpd->digital_outputs, i) || IS_SET(xpd->digital_inputs, i))
 			continue;
-		if(IS_BLINKING(priv,i,color)) {
+		if(xpd->blink_mode || IS_BLINKING(priv,i,color)) {
 			// led state is toggled
 			if((timer_count % LED_BLINK_PERIOD) == 0) {
 				DBG("%s/%s/%d: ledstate=%s\n", xpd->xbus->busname, xpd->xpdname, i,
@@ -421,46 +421,41 @@
 
 /* FIXME: based on data from from wctdm.h */
 #include <wctdm.h>
-static const int echotune_reg[] = {30,45,46,47,58,49,50,51,52};
-union echotune {
-	/* "coeff 0" is acim */
-	unsigned char		coeff[sizeof(echotune_reg)];
-	struct wctdm_echo_coefs	wctdm_struct;
-};
+/*
+ * The first register is the ACIM, the other are coefficient registers.
+ * We define the array size explicitly to track possible inconsistencies
+ * if the struct is modified.
+ */
+static const char echotune_regs[sizeof(struct wctdm_echo_coefs)] = {30, 45, 46, 47, 48, 49, 50, 51, 52};
 
 static int FXO_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long arg)
 {
-	union echotune	echoregs;
-	int 		i,ret;
-
-	BUG_ON(!xpd);
-	DBG("cmd: 0x%X, expecting: 0x%X, pos=%d.\n", cmd, WCTDM_SET_ECHOTUNE, pos);
+	int 			i,ret;
+	unsigned char		echotune_data[ARRAY_SIZE(echotune_regs)];
+
+	BUG_ON(!xpd);
 	switch (cmd) {
 		case WCTDM_SET_ECHOTUNE:
 			DBG("-- Setting echo registers: \n");
 			/* first off: check if this span is fxs. If not: -EINVALID */
-			if (copy_from_user(&echoregs.wctdm_struct, 
-				(struct wctdm_echo_coefs __user *)arg, sizeof(echoregs.wctdm_struct)))
+			if (copy_from_user(&echotune_data, (void __user *)arg, sizeof(echotune_data)))
 				return -EFAULT;
 
-			/* Set the ACIM register */
-			/* quick and dirty registers writing: */
-			for (i=0; i<sizeof(echotune_reg); i++) {
-				char buf[22];
-				sprintf(buf, "%d WD %2X %2X",
-					pos,echotune_reg[i],echoregs.coeff[i]
-				);
-				/* FIXME: code duplicated from proc_xpd_register_write */
-				ret = handle_register_command(xpd, buf);
-				if(ret < 0)
+			for (i = 0; i < ARRAY_SIZE(echotune_regs); i++) {
+				DBG("Reg=0x%02X, data=0x%02X\n", echotune_regs[i], echotune_data[i]);
+				ret = DAA_DIRECT_REQUEST(xpd->xbus, xpd, pos, DAA_WRITE, echotune_regs[i], echotune_data[i]);
+				if (ret < 0) {
+					NOTICE("%s/%s/%d: Couldn't write %0x02X to register %0x02X\n",
+							xpd->xbus->busname, xpd->xpdname, pos, echotune_data[i], echotune_regs[i]);
 					return ret;
+				}
 				msleep(1);
 			}
 
 			DBG("-- Set echo registers successfully\n");
-
 			break;
 		default:
+			DBG("%s/%s/%d: Unknown command 0x%X.\n", xpd->xbus->busname, xpd->xpdname, pos, cmd);
 			return -ENOTTY;
 	}
 	return 0;
@@ -471,6 +466,7 @@
 /* 0x0F */ HOSTCMD(FXO, REGISTER_REQUEST, byte chipsel, bool writing, bool do_subreg, byte regnum, byte subreg, byte data_low, byte data_high)
 {
 	int		ret = 0;
+	xframe_t	*xframe;
 	xpacket_t	*pack;
 	reg_cmd_t	*reg_cmd;
 
@@ -478,7 +474,7 @@
 		DBG("NO XBUS\n");
 		return -EINVAL;
 	}
-	XPACKET_NEW(pack, xbus, GLOBAL, REGISTER_REQUEST, xpd->id);
+	XFRAME_NEW(xframe, pack, xbus, GLOBAL, REGISTER_REQUEST, xpd->id);
 #if 0
 	DBG("%s/%s/%d: %c%c R%02X S%02X %02X %02X\n",
 			xbus->busname, xpd->xpdname, chipsel,
@@ -487,7 +483,6 @@
 			regnum, subreg, data_low, data_high);
 #endif
 	reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
-	pack->datalen = sizeof(*reg_cmd);
 	reg_cmd->bytes = sizeof(*reg_cmd) - 1;	// do not count the 'bytes' field
 	REG_FIELD(reg_cmd, chipsel) = chipsel;
 	REG_FIELD(reg_cmd, read_request) = (writing) ? 0 : 1;
@@ -496,7 +491,7 @@
 	REG_FIELD(reg_cmd, subreg) = subreg;
 	REG_FIELD(reg_cmd, data_low) = data_low;
 	REG_FIELD(reg_cmd, data_high) = data_high;
-	ret = packet_send(xbus, pack);
+	ret = xframe_send(xbus, xframe);
 	return ret;
 }
 
@@ -521,17 +516,6 @@
 	return ret;
 }
 
-static /* 0x0F */ HOSTCMD(FXO, CHAN_CID, lineno_t chan)
-{
-	int		ret = 0;
-
-	BUG_ON(!xbus);
-	BUG_ON(!xpd);
-	DBG("%s/%s/%d:\n", xbus->busname, xpd->xpdname, chan);
-	return ret;
-}
-
-
 static /* 0x0F */ HOSTCMD(FXO, RING, lineno_t chan, bool on)
 {
 	BUG_ON(!xbus);
@@ -557,7 +541,7 @@
 
 	if(!xpd) {
 		NOTICE("%s: received %s for non-existing xpd: %d\n",
-				__FUNCTION__, cmd->name, XPD_NUM(pack->content.addr));
+				__FUNCTION__, cmd->name, XPD_NUM(pack->addr));
 		return -EPROTO;
 	}
 	priv = xpd->priv;
@@ -567,9 +551,10 @@
 	for_each_line(xpd, i) {
 		if(IS_SET(sig_toggles, i)) {
 			if(!IS_SET(priv->battery, i)) {
-				DBG("%s/%s/%d: battery is off. ignore false alarm.\n",
+				DBG("%s/%s/%d: SIG_CHANGED while battery is off.\n",
 					xbus->busname, xpd->xpdname, i);
-				continue;
+				// FIXME: allow dialing without battery polling...
+				// continue;
 			}
 			mark_ring(xpd, i, IS_SET(sig_status, i), 1);
 		}
@@ -587,7 +572,7 @@
 
 	if(!xpd) {
 		NOTICE("%s: received %s for non-existing xpd: %d\n",
-				__FUNCTION__, cmd->name, XPD_NUM(pack->content.addr));
+				__FUNCTION__, cmd->name, XPD_NUM(pack->addr));
 		return -EPROTO;
 	}
 	spin_lock_irqsave(&xpd->lock, flags);
@@ -658,10 +643,8 @@
 		.RING		= XPROTO_CALLER(FXO, RING),
 		.RELAY_OUT	= XPROTO_CALLER(FXO, RELAY_OUT),
 		.XPD_STATE	= XPROTO_CALLER(FXO, XPD_STATE),
-		.CHAN_CID	= XPROTO_CALLER(FXO, CHAN_CID),
 
 		.SYNC_SOURCE	= XPROTO_CALLER(GLOBAL, SYNC_SOURCE),
-		.PCM_WRITE	= XPROTO_CALLER(GLOBAL, PCM_WRITE),
 	},
 	.packet_is_valid = fxo_packet_is_valid,
 	.packet_dump = fxo_packet_dump,
@@ -672,7 +655,7 @@
 	const xproto_entry_t	*xe;
 
 	//DBG("\n");
-	xe = xproto_card_entry(&PROTO_TABLE(FXO), pack->content.opcode);
+	xe = xproto_card_entry(&PROTO_TABLE(FXO), pack->opcode);
 	return xe != NULL;
 }
 
@@ -896,7 +879,7 @@
 
 int __init card_fxo_startup(void)
 {
-	INFO("%s\n", THIS_MODULE->name);
+	INFO("%s revision %s\n", THIS_MODULE->name, XPP_VERSION);
 	xproto_register(&PROTO_TABLE(FXO));
 	return 0;
 }
@@ -909,6 +892,7 @@
 MODULE_DESCRIPTION("XPP FXO Card Driver");
 MODULE_AUTHOR("Oron Peled <oron at actcom.co.il>");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(XPP_VERSION);
 MODULE_ALIAS_XPD(XPD_TYPE_FXO);
 
 module_init(card_fxo_startup);

Modified: team/mogorman/zaptel-1.2-transcoder/xpp/card_fxs.c
URL: http://svn.digium.com/view/zaptel/team/mogorman/zaptel-1.2-transcoder/xpp/card_fxs.c?view=diff&rev=1990&r1=1989&r2=1990
==============================================================================
--- team/mogorman/zaptel-1.2-transcoder/xpp/card_fxs.c (original)
+++ team/mogorman/zaptel-1.2-transcoder/xpp/card_fxs.c Sat Jan 27 10:20:41 2007
@@ -29,6 +29,7 @@
 #include "xpp_zap.h"
 #include "card_fxo.h"
 #include "zap_debug.h"
+#include "xbus-core.h"
 
 static const char rcsid[] = "$Id$";
 
@@ -64,14 +65,13 @@
 #define	SLIC_DIRECT_REQUEST(xbus,xpd,chipsel,writing,reg,dL)	\
 	CALL_PROTO(FXS, REGISTER_REQUEST, (xbus), (xpd), (chipsel), (writing), 0, (reg), 0, (dL), 0)
 #define	SLIC_INDIRECT_REQUEST(xbus,xpd,chipsel,writing,reg,dL,dH)	\
-	PROTO(FXS, REGISTER_REQUEST, (xbus), (xpd), (chipsel), (writing), 1, (reg), 0, (dL), (dH))
+	CALL_PROTO(FXS, REGISTER_REQUEST, (xbus), (xpd), (chipsel), (writing), 1, 0x1E, (reg), (dL), (dH))
 
 #define	VALID_CHIPSEL(x)	(((chipsel) >= 0 && (chipsel) <= 7) || (chipsel) == ALL_CHANS)
 
 /*---------------- FXS Protocol Commands ----------------------------------*/
 
 static /* 0x0F */ DECLARE_CMD(FXS, XPD_STATE, bool on);
-static /* 0x0F */ DECLARE_CMD(FXS, CHAN_CID, lineno_t chan);
 static /* 0x0F */ DECLARE_CMD(FXS, RING, lineno_t chan, bool on);
 static /* 0x0F */ DECLARE_CMD(FXS, RELAY_OUT, byte which, bool on);
 
@@ -80,6 +80,7 @@
 static int proc_fxs_info_read(char *page, char **start, off_t off, int count, int *eof, void *data);
 static int proc_xpd_register_read(char *page, char **start, off_t off, int count, int *eof, void *data);
 static int proc_xpd_register_write(struct file *file, const char __user *buffer, unsigned long count, void *data);
+static void start_stop_vm_led(xbus_t *xbus, xpd_t *xpd, lineno_t pos);
 
 #define	PROC_REGISTER_FNAME	"slics"
 #define	PROC_FXS_INFO_FNAME	"fxs_info"
@@ -89,6 +90,8 @@
 	struct proc_dir_entry		*fxs_info;
 	xpp_line_t			ledstate[NUM_LEDS];	/* 0 - OFF, 1 - ON */
 	xpp_line_t			ledcontrol[NUM_LEDS];	/* 0 - OFF, 1 - ON */
+	xpp_line_t			found_fsk_pattern;
+	xpp_line_t			msg_waiting;
 	int				blinking[NUM_LEDS][CHANNELS_PERXPD];
 };
 
@@ -137,7 +140,7 @@
 /*
  * pos can be:
  * 	- A line number
- * 	- ALL_LINES
+ * 	- ALL_LINES. This is not valid anymore since 8-Jan-2007.
  */
 static int do_led(xpd_t *xpd, lineno_t chan, byte which, bool on)
 {
@@ -147,6 +150,7 @@
 	xbus_t			*xbus;
 
 	BUG_ON(!xpd);
+	BUG_ON(chan == ALL_LINES);
 	xbus = xpd->xbus;
 	priv = xpd->priv;
 	which = which % NUM_LEDS;
@@ -186,7 +190,7 @@
 		for_each_line(xpd, i) {
 			if(IS_SET(xpd->digital_outputs, i) || IS_SET(xpd->digital_inputs, i))
 				continue;
-			if(IS_BLINKING(priv, i, color)) {		// Blinking
+			if(xpd->blink_mode || IS_BLINKING(priv, i, color)) {		// Blinking
 				// led state is toggled
 				if((timer_count % LED_BLINK_PERIOD) == 0) {
 					DBG("%s/%s/%d ledstate=%s\n", xpd->xbus->busname, xpd->xpdname, i,
@@ -206,6 +210,21 @@
 		}
 	}
 }
+
+static int do_callerid(xbus_t *xbus, xpd_t *xpd, lineno_t chan)
+{
+	int		ret = 0;
+	int		i;
+
+	BUG_ON(!xbus);
+	BUG_ON(!xpd);
+	DBG("%s/%s/%d:\n", xbus->busname, xpd->xpdname, chan);
+	ret = SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, 0x40, FXS_LINE_CID);
+	for_each_line(xpd, i)
+		xpd->lasttxhook[i] = FXS_LINE_CID;
+	return ret;
+}
+
 
 /*---------------- FXS: Methods -------------------------------------------*/
 
@@ -337,9 +356,11 @@
 		cur_chan->pvt = xpd;
 		cur_chan->sigcap = FXS_DEFAULT_SIGCAP;
 	}
-	spin_lock_irqsave(&xpd->lock, flags);
-	do_led(xpd, ALL_LINES, color, LED_OFF);
-	spin_unlock_irqrestore(&xpd->lock, flags);
+	for_each_line(xpd, i) {
+		spin_lock_irqsave(&xpd->lock, flags);
+		do_led(xpd, i, color, LED_OFF);
+		spin_unlock_irqrestore(&xpd->lock, flags);
+	}
 	for_each_line(xpd, i) {
 		MARK_LED(priv, i, color, LED_ON);
 		msleep(50);
@@ -387,6 +408,8 @@
 				return ret;
 			}
 			ret = CALL_XMETHOD(RING, xbus, xpd, pos, 0);			// RING off
+			if (!IS_SET(xpd->offhook, pos))
+				start_stop_vm_led(xbus, xpd, pos);
 #if 0
 			switch(chan->sig) {
 				case ZT_SIG_EM:
@@ -403,7 +426,7 @@
 		case ZT_TXSIG_OFFHOOK:
 			if(xpd->ringing[pos]) {
 				BIT_SET(xpd->cid_on, pos);
-				ret = CALL_XMETHOD(CHAN_CID, xpd->xbus, xpd, pos);		// CALLER ID
+				ret = do_callerid(xpd->xbus, xpd, pos);		// CALLER ID
 			}
 			xpd->ringing[pos] = 0;
 #if 0
@@ -438,6 +461,107 @@
 	return ret;
 }
 
+#ifdef	VMWI_IOCTL
+/*
+ * Private ioctl()
+ * We don't need it now, since we detect vmwi via FSK patterns
+ */
+static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long arg)
+{
+	struct FXS_priv_data *priv;
+	xbus_t *xbus;
+	
+	BUG_ON(!xpd);
+	priv = xpd->priv;
+	BUG_ON(!priv);
+	xbus = xpd->xbus;
+	BUG_ON(!xbus);
+	
+	if (pos < 0 || pos >= xpd->channels) {
+		NOTICE("%s/%s: Bad channel number %d in %s(), cmd=%u\n", xbus->busname, xpd->xpdname, pos, __FUNCTION__, cmd);
+		return -EINVAL;
+	}
+	
+	switch (cmd) {
+		case _IOW(ZT_CODE, 60, int):		/* message-waiting led control */
+			/* Digital inputs/outputs don't have VM leds */
+			if (IS_SET(xpd->digital_inputs | xpd->digital_outputs, pos))
+				return 0;
+			if (arg)
+				BIT_SET(priv->msg_waiting, pos);
+			else
+				BIT_CLR(priv->msg_waiting, pos);
+			return 0;
+	}
+	return -ENOTTY;
+}
+#endif
+
+static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos, int on)
+{
+	int	ret = 0;
+	BUG_ON(!xbus);
+	BUG_ON(!xpd);
+
+	if (on) {
+		/* A write to register 0x40 will now turn on/off the VM led */
+		ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x16, 0xE8, 0x03);
+		ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x15, 0xEF, 0x7B);
+		ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x14, 0x9F, 0x00);
+		ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x22, 0x19);
+		ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x4A, 0x34);
+		ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x30, 0xE0);
+		ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x31, 0x01);
+		ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x32, 0xF0);
+		ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x33, 0x05);
+		ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x1D, 0x00, 0x46);
+	} else {
+		/* A write to register 0x40 will now turn on/off the ringer */
+		ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x16, 0x00, 0x00);
+		ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x15, 0x60, 0x01);
+		ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x14, 0xF0, 0x7E);
+		ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x22, 0x00);
+		ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x4A, 0x34);
+		ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x30, 0x00);
+		ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x31, 0x00);
+		ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x32, 0x00);
+		ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x33, 0x00);
+		ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x1D, 0x00, 0x36);
+	}
+
+	return (ret ? -EPROTO : 0);
+}
+
+static void start_stop_vm_led(xbus_t *xbus, xpd_t *xpd, lineno_t pos)
+{
+	bool		on;
+
+	if (IS_SET(xpd->digital_outputs | xpd->digital_inputs, pos))
+		return;
+	on = IS_SET(((struct FXS_priv_data *)xpd->priv)->msg_waiting, pos);
+	DBG("%s/%s/%d %s\n", xbus->busname, xpd->xpdname, pos, (on)?"ON":"OFF");
+	set_vm_led_mode(xbus, xpd, pos, on);

[... 6498 lines stripped ...]


More information about the zaptel-commits mailing list