[zaptel-commits] mattf: trunk r1970 - /trunk/wctdm24xxp.c

zaptel-commits at lists.digium.com zaptel-commits at lists.digium.com
Thu Jan 25 15:18:07 MST 2007


Author: mattf
Date: Thu Jan 25 16:18:07 2007
New Revision: 1970

URL: http://svn.digium.com/view/zaptel?view=rev&rev=1970
Log:
Add additional product support.

Modified:
    trunk/wctdm24xxp.c

Modified: trunk/wctdm24xxp.c
URL: http://svn.digium.com/view/zaptel/trunk/wctdm24xxp.c?view=diff&rev=1970&r1=1969&r2=1970
==============================================================================
--- trunk/wctdm24xxp.c (original)
+++ trunk/wctdm24xxp.c Thu Jan 25 16:18:07 2007
@@ -2,6 +2,8 @@
  * 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.
  * All rights reserved.
  *
@@ -43,7 +45,7 @@
 #include "wctdm.h"
 
 /* Comment to disable VPM support */
-#define VPM_SUPPORT
+/* #define VPM_SUPPORT */
 
 #ifdef VPM_SUPPORT
 
@@ -300,9 +302,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];
@@ -337,6 +339,7 @@
 	unsigned char ctlreg;
 	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];
@@ -383,6 +386,7 @@
 	/* Set hook */
 	int sethook[NUM_CARDS + NUM_EC];
 	int dacssrc[NUM_CARDS];
+	int type;
 
 #ifdef VPM_SUPPORT
 	int vpm;
@@ -410,9 +414,11 @@
 struct wctdm_desc {
 	char *name;
 	int flags;
+	int ports;
 };
 
-static struct wctdm_desc wctdm = { "Wildcard TDM2400P", 0 };
+static struct wctdm_desc wctdm2400 = { "TDM2400P", 0, 24 };
+static struct wctdm_desc wctdm800 = { "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];
@@ -445,6 +451,19 @@
 
 static int wctdm_init_proslic(struct wctdm *wc, int card, int fast , int manual, int sane);
 
+#if 0
+static inline int CMD_BYTE(int card,int bit,int altcs)
+{
+	int res;
+	res = (((((card) & 0x3) * 3 + (bit)) * 7) \
+			+ ((card) >> 2) + (altcs));
+			//+ ((card) >> 2) + (altcs) + (altcs ? 42 : 0));
+	if (((res == 31) || (res == 24) || (res == 38)) && (card != 5))
+		printk("%d %d %d\n", card, bit, altcs);
+	return res;
+}
+#endif
+
 /* sleep in user space until woken up. Equivilant of tsleep() in BSD */
 static int schluffen(wait_queue_head_t *q)
 {
@@ -473,6 +492,7 @@
 	unsigned long flags;
 	unsigned int curcmd=0;
 	int x;
+	int subaddr = card & 0x3;
 #ifdef FANCY_ECHOCAN
 	int ecval;
 	ecval = wc->echocanpos;
@@ -485,6 +505,9 @@
 	{
 		return;
 	}
+	if (wc->altcs[card])
+		subaddr = 0;
+
 	/* Skip audio */
 	writechunk += 24;
 	spin_lock_irqsave(&wc->reglock, flags);
@@ -522,59 +545,59 @@
 		}
 	}
 	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_QRV) {
 
-		writechunk[CMD_BYTE(card, 0)] = 0x00;
+		writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x00;
 		if (!curcmd)
 		{
-			writechunk[CMD_BYTE(card, 1)] = 0x00;
-			writechunk[CMD_BYTE(card, 2)] = 0x00;
+			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)] = 0x40 | ((curcmd >> 8) & 0x3f);
+				writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x40 | ((curcmd >> 8) & 0x3f);
 			else
-				writechunk[CMD_BYTE(card, 1)] = 0xc0 | ((curcmd >> 8) & 0x3f);
-			writechunk[CMD_BYTE(card, 2)] = curcmd & 0xff;
+				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)] = 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 */
@@ -610,7 +633,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 */
@@ -686,9 +709,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);
 		}
@@ -951,7 +975,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);
 		}
@@ -969,7 +993,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);
 	}
@@ -1714,7 +1738,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;
@@ -2910,7 +2934,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;
@@ -2966,7 +2990,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 */
@@ -2997,7 +3021,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("%s: reg is %08x\n", wc->variety, wctdm_getctl(wc, 0x0088));
 
 	return 0;
 }
@@ -3229,13 +3253,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);
@@ -3267,9 +3298,23 @@
 				wc->cardflag |= 1 << x;
 				printk("Port %d: Installed -- QRV DRI card\n",x + 1);
 			} else {
-				printk("Port %d: Not installed\n", x + 1);
-				wc->modtype[x] = MOD_TYPE_NONE;
-				wc->cardflag |= (1 << x);
+				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);
+				}
 			}
 		}
 	}
@@ -3290,6 +3335,8 @@
 	int x;
 	int y;
 	static int initd_ifaces=0;
+
+	d = &wctdm800;
 	
 	if(initd_ifaces){
 		memset((void *)ifaces,0,(sizeof(struct wctdm *))*WC_MAX_IFACES);
@@ -3313,6 +3360,7 @@
 			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;
@@ -3321,7 +3369,7 @@
 				wc->dacssrc[y] = -1;
 			}
 			/* Keep track of whether we need to free the region */
-			if (request_region(wc->iobase, 0xff, "wctdm")) 
+			if (request_region(wc->iobase, 0xff, wc->variety)) 
 				wc->freeregion = 1;
 
 			/* Allocate enough memory for two zt chunks, receive and transmit.  Each sample uses
@@ -3347,7 +3395,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 */
@@ -3365,8 +3413,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("%s: Unable to request IRQ %d\n", wc->variety, pdev->irq);
 				if (wc->freeregion)
 					release_region(wc->iobase, 0xff);
 				pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma);
@@ -3404,7 +3452,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;
@@ -3445,14 +3493,15 @@
 }
 
 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 }
 };
 
 MODULE_DEVICE_TABLE(pci, wctdm_pci_tbl);
 
 static struct pci_driver wctdm_driver = {
-	name: 	"wctdm24xxp",
+	name: 	"wctdmxxp",
 	probe: 	wctdm_init_one,
 #ifdef LINUX26
 	remove:	__devexit_p(wctdm_remove_one),
@@ -3541,7 +3590,7 @@
 MODULE_PARM(dtmfthreshold, "i");
 #endif
 #endif
-MODULE_DESCRIPTION("Wildcard TDM2400P Zaptel Driver");
+MODULE_DESCRIPTION("Wildcard TDMXX00P Zaptel Driver");
 MODULE_AUTHOR("Mark Spencer <markster at digium.com>");
 #ifdef MODULE_LICENSE
 MODULE_LICENSE("GPL");



More information about the zaptel-commits mailing list