[Asterisk-cvs] zaptel fxstest.c,1.3,1.4 wcfxs.c,1.40,1.41

markster at lists.digium.com markster at lists.digium.com
Wed Feb 25 10:46:23 CST 2004


Update of /usr/cvsroot/zaptel
In directory mongoose.digium.com:/tmp/cvs-serv1124

Modified Files:
	fxstest.c wcfxs.c 
Log Message:
Add support for FXO module


Index: fxstest.c
===================================================================
RCS file: /usr/cvsroot/zaptel/fxstest.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- fxstest.c	5 Jul 2003 18:00:34 -0000	1.3
+++ fxstest.c	25 Feb 2004 15:35:13 -0000	1.4
@@ -66,21 +66,31 @@
 		}
 	} else if (!strcasecmp(argv[2], "regdump")) {
 		struct wcfxs_regs regs;
+		int numregs = NUM_REGS;
+		memset(&regs, 0, sizeof(regs));
 		res = ioctl(fd, WCFXS_GET_REGS, &regs);
 		if (res) {
 			fprintf(stderr, "Unable to get registers on channel %s\n", argv[1]);
 		} else {
+			for (x=60;x<NUM_REGS;x++) {
+				if (regs.direct[x])
+					break;
+			}
+			if (x == NUM_REGS) 
+				numregs = 60;
 			printf("Direct registers: \n");
-			for (x=0;x<NUM_REGS;x++) {
+			for (x=0;x<numregs;x++) {
 				printf("%3d. %02x  ", x, regs.direct[x]);
 				if ((x % 8) == 7)
 					printf("\n");
 			}
-			printf("\n\nIndirect registers: \n");
-			for (x=0;x<NUM_INDIRECT_REGS;x++) {
-				printf("%3d. %04x  ", x, regs.indirect[x]);
-				if ((x % 6) == 5)
-					printf("\n");
+			if (numregs == NUM_REGS) {
+				printf("\n\nIndirect registers: \n");
+				for (x=0;x<NUM_INDIRECT_REGS;x++) {
+					printf("%3d. %04x  ", x, regs.indirect[x]);
+					if ((x % 6) == 5)
+						printf("\n");
+				}
 			}
 			printf("\n\n");
 		}

Index: wcfxs.c
===================================================================
RCS file: /usr/cvsroot/zaptel/wcfxs.c,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -d -r1.40 -r1.41
--- wcfxs.c	6 Jan 2004 13:26:44 -0000	1.40
+++ wcfxs.c	25 Feb 2004 15:35:13 -0000	1.41
@@ -1,5 +1,5 @@
 /*
- * Wilcard TDM400P FXS Interface Driver for Zapata Telephony interface
+ * Wilcard TDM400P TDM FXS/FXO Interface Driver for Zapata Telephony interface
  *
  * Written by Mark Spencer <markster at linux-support.net>
  *            Matthew Fredrickson <creslin at linux-support.net>
@@ -91,6 +91,8 @@
 #include <linux/zaptel.h>
 #endif
 
+#define NUM_FXO_REGS 60
+
 #define WC_MAX_IFACES 128
 
 #define WC_CNTL    	0x00
@@ -140,6 +142,9 @@
 
 #define MAX_ALARMS 10
 
+#define MOD_TYPE_FXS	0
+#define MOD_TYPE_FXO	1
+
 struct wcfxs {
 	struct pci_dev *dev;
 	char *variety;
@@ -158,6 +163,7 @@
 	spinlock_t lock;
 
 	/* Receive hook state and debouncing */
+	int modtype[NUM_CARDS];
 	int oldrxhook[NUM_CARDS];
 	int debouncehook[NUM_CARDS];
 	int lastrxhook[NUM_CARDS];
@@ -248,8 +254,8 @@
 	zt_receive(&wc->span);
 }
 
-static inline void wcfxs_check_hook(struct wcfxs *wc, int card);
-static inline void wcfxs_recheck_sanity(struct wcfxs *wc, int card);
+static inline void wcfxs_proslic_check_hook(struct wcfxs *wc, int card);
+static inline void wcfxs_proslic_recheck_sanity(struct wcfxs *wc, int card);
 
 static void wcfxs_stop_dma(struct wcfxs *wc);
 static void wcfxs_reset_tdm(struct wcfxs *wc);
@@ -281,6 +287,32 @@
 	outb(wc->ios, wc->ioaddr + WC_AUXD);
 	
 }
+
+static inline void __reset_spi(struct wcfxs *wc)
+{
+	/* Drop chip select and clock once and raise and clock once */
+	wc->ios |= BIT_SCLK;
+	outb(wc->ios, wc->ioaddr + WC_AUXD);
+	wc->ios &= ~BIT_CS;
+	outb(wc->ios, wc->ioaddr + WC_AUXD);
+	wc->ios |= BIT_SDI;
+	wc->ios &= ~BIT_SCLK;
+	outb(wc->ios, wc->ioaddr + WC_AUXD);
+	/* Now raise SCLK high again and repeat */
+	wc->ios |= BIT_SCLK;
+	outb(wc->ios, wc->ioaddr + WC_AUXD);
+	/* Finally raise CS back high again */
+	wc->ios |= BIT_CS;
+	outb(wc->ios, wc->ioaddr + WC_AUXD);
+	/* Clock again */
+	wc->ios &= ~BIT_SCLK;
+	outb(wc->ios, wc->ioaddr + WC_AUXD);
+	/* Now raise SCLK high again and repeat */
+	wc->ios |= BIT_SCLK;
+	outb(wc->ios, wc->ioaddr + WC_AUXD);
+	
+}
+
 static inline unsigned char __read_8bits(struct wcfxs *wc)
 {
 	unsigned char res=0, c;
@@ -334,7 +366,12 @@
 static void __wcfxs_setreg(struct wcfxs *wc, int card, unsigned char reg, unsigned char value)
 {
 	__wcfxs_setcard(wc, card);
-	__write_8bits(wc, reg & 0x7f);
+	if (wc->modtype[card] == MOD_TYPE_FXO) {
+		__write_8bits(wc, 0x20);
+		__write_8bits(wc, reg & 0x7f);
+	} else {
+		__write_8bits(wc, reg & 0x7f);
+	}
 	__write_8bits(wc, value);
 }
 
@@ -349,10 +386,25 @@
 static unsigned char __wcfxs_getreg(struct wcfxs *wc, int card, unsigned char reg)
 {
 	__wcfxs_setcard(wc, card);
-	__write_8bits(wc, reg | 0x80);
+	if (wc->modtype[card] == MOD_TYPE_FXO) {
+		__write_8bits(wc, 0x60);
+		__write_8bits(wc, reg & 0x7f);
+	} else {
+		__write_8bits(wc, reg | 0x80);
+	}
 	return __read_8bits(wc);
 }
 
+static inline void reset_spi(struct wcfxs *wc, int card)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&wc->lock, flags);
+	__wcfxs_setcard(wc, card);
+	__reset_spi(wc);
+	__reset_spi(wc);
+	spin_unlock_irqrestore(&wc->lock, flags);
+}
+
 static unsigned char wcfxs_getreg(struct wcfxs *wc, int card, unsigned char reg)
 {
 	unsigned long flags;
@@ -388,7 +440,7 @@
 	return 0;
 }
 
-static int wcfxs_setreg_indirect(struct wcfxs *wc, int card, unsigned char address, unsigned short data)
+static int wcfxs_proslic_setreg_indirect(struct wcfxs *wc, int card, unsigned char address, unsigned short data)
 {
 	unsigned long flags;
 	int res = -1;
@@ -403,7 +455,7 @@
 	return res;
 }
 
-static int wcfxs_getreg_indirect(struct wcfxs *wc, int card, unsigned char address)
+static int wcfxs_proslic_getreg_indirect(struct wcfxs *wc, int card, unsigned char address)
 { 
 	unsigned long flags;
 	int res = -1;
@@ -426,20 +478,20 @@
 	return res;
 }
 
-static int wcfxs_init_indirect_regs(struct wcfxs *wc, int card)
+static int wcfxs_proslic_init_indirect_regs(struct wcfxs *wc, int card)
 {
 	unsigned char i;
 
 	for (i=0; i<sizeof(indirect_regs) / sizeof(indirect_regs[0]); i++)
 	{
-		if(wcfxs_setreg_indirect(wc, card, indirect_regs[i].address,indirect_regs[i].initial))
+		if(wcfxs_proslic_setreg_indirect(wc, card, indirect_regs[i].address,indirect_regs[i].initial))
 			return -1;
 	}
 
 	return 0;
 }
 
-static int wcfxs_verify_indirect_regs(struct wcfxs *wc, int card)
+static int wcfxs_proslic_verify_indirect_regs(struct wcfxs *wc, int card)
 { 
 	int passed = 1;
 	unsigned short i, initial;
@@ -447,7 +499,7 @@
 
 	for (i=0; i<sizeof(indirect_regs) / sizeof(indirect_regs[0]); i++) 
 	{
-		if((j = wcfxs_getreg_indirect(wc, card, (unsigned char) indirect_regs[i].address)) < 0) {
+		if((j = wcfxs_proslic_getreg_indirect(wc, card, (unsigned char) indirect_regs[i].address)) < 0) {
 			printk("Failed to read indirect register %d\n", i);
 			return -1;
 		}
@@ -470,6 +522,7 @@
     }
     return 0;
 }
+
 #ifdef LINUX26
 static irqreturn_t wcfxs_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 #else
@@ -492,7 +545,7 @@
 
 	if (ints & 0x10) {
 		/* Stop DMA, wait for watchdog */
-		printk("FXS PCI Master abort\n");
+		printk("TDM PCI Master abort\n");
 		wcfxs_stop_dma(wc);
 #ifdef LINUX26
 		return IRQ_RETVAL(1);
@@ -511,7 +564,8 @@
 	}
 
 	for (x=0;x<4;x++) {
-		if ((x < wc->cards) && (wc->cardflag & (1 << x))) {
+		if ((x < wc->cards) && (wc->cardflag & (1 << x)) &&
+			(wc->modtype[x] == MOD_TYPE_FXS)) {
 			if (wc->lasttxhook[x] == 0x4) {
 				/* RINGing, prepare for OHT */
 				wc->ohttimer[x] = OHT_TIMER << 3;
@@ -536,15 +590,19 @@
 		wc->intcount++;
 		x = wc->intcount % 4;
 		if ((x < wc->cards) && (wc->cardflag & (1 << x))) {
-			wcfxs_check_hook(wc, x);
-			if (!(wc->intcount & 0xfc))
-				wcfxs_recheck_sanity(wc, x);
+			if (wc->modtype[x] == MOD_TYPE_FXS) {
+				wcfxs_proslic_check_hook(wc, x);
+				if (!(wc->intcount & 0xfc))
+					wcfxs_proslic_recheck_sanity(wc, x);
+			}
 		}
 		if (!(wc->intcount % 10000)) {
 			/* Accept an alarm once per 10 seconds */
 			for (x=0;x<4;x++) 
-				if (wc->palarms[x])
-					wc->palarms[x]--;
+				if (wc->modtype[x] == MOD_TYPE_FXS) {
+					if (wc->palarms[x])
+						wc->palarms[x]--;
+				}
 		}
 		wcfxs_receiveprep(wc, ints);
 		wcfxs_transmitprep(wc, ints);
@@ -555,6 +613,18 @@
 	
 }
 
+static int wcfxs_voicedaa_insane(struct wcfxs *wc, int card)
+{
+	int blah;
+	blah = wcfxs_getreg(wc, card, 2);
+	if (blah != 0x3)
+		return -2;
+	blah = wcfxs_getreg(wc, card, 11);
+	if (debug)
+		printk("VoiceDAA System: %02x\n", blah & 0xf);
+	return 0;
+}
+
 static int wcfxs_proslic_insane(struct wcfxs *wc, int card)
 {
 	int blah,insane_report;
@@ -570,7 +640,7 @@
 		return -1;
 	}
 #endif
-	if ((blah & 0xf) == 0) {
+	if (((blah & 0xf) == 0) || ((blah & 0xf) == 0xf)) {
 		/* SLIC not loaded */
 		return -1;
 	}
@@ -608,7 +678,7 @@
 	return 0;
 }
 
-static int wcfxs_powerleak_test(struct wcfxs *wc, int card)
+static int wcfxs_proslic_powerleak_test(struct wcfxs *wc, int card)
 {
 	unsigned long origjiffies;
 	unsigned char vbat;
@@ -701,7 +771,7 @@
 
 }
 
-static int wcfxs_manual_calibrate(struct wcfxs *wc, int card){
+static int wcfxs_proslic_manual_calibrate(struct wcfxs *wc, int card){
 	unsigned long origjiffies;
 	unsigned char i;
 
@@ -726,12 +796,12 @@
 	// Delay 10ms
 	origjiffies=jiffies; 
 	while((jiffies-origjiffies)<1);
-	wcfxs_setreg_indirect(wc, card, 88,0);
-	wcfxs_setreg_indirect(wc,card,89,0);
-	wcfxs_setreg_indirect(wc,card,90,0);
-	wcfxs_setreg_indirect(wc,card,91,0);
-	wcfxs_setreg_indirect(wc,card,92,0);
-	wcfxs_setreg_indirect(wc,card,93,0);
+	wcfxs_proslic_setreg_indirect(wc, card, 88,0);
+	wcfxs_proslic_setreg_indirect(wc,card,89,0);
+	wcfxs_proslic_setreg_indirect(wc,card,90,0);
+	wcfxs_proslic_setreg_indirect(wc,card,91,0);
+	wcfxs_proslic_setreg_indirect(wc,card,92,0);
+	wcfxs_proslic_setreg_indirect(wc,card,93,0);
 
 	wcfxs_setreg(wc, card, 98,0x10); // This is necessary if the calibration occurs other than at reset time
 	wcfxs_setreg(wc, card, 99,0x10);
@@ -775,7 +845,7 @@
 
 }
 #if 1
-static int wcfxs_calibrate(struct wcfxs *wc, int card)
+static int wcfxs_proslic_calibrate(struct wcfxs *wc, int card)
 {
 	unsigned long origjiffies;
 	int x;
@@ -804,6 +874,63 @@
 	return 0;
 }
 #endif
+
+static int wcfxs_init_voicedaa(struct wcfxs *wc, int card, int fast, int manual, int sane)
+{
+	long newjiffies;
+	wc->modtype[card] = MOD_TYPE_FXO;
+	/* Sanity check the ProSLIC */
+	reset_spi(wc, card);
+	if (!sane && wcfxs_voicedaa_insane(wc, card))
+		return -2;
+
+	/* Software reset */
+	wcfxs_setreg(wc, card, 1, 0x80);
+
+	/* Wait just a bit */
+	newjiffies = jiffies + (HZ/10);
+	while(jiffies < newjiffies);
+
+	/* Enable PCM, ulaw */
+	wcfxs_setreg(wc, card, 33, 0x28);
+
+	/* Misc. DAA parameters */
+	wcfxs_setreg(wc, card, 31, 0xa3);
+
+	/* Set AC Impedence */
+	wcfxs_setreg(wc, card, 30, 0x00);
+
+	/* Set DC Termination */
+	wcfxs_setreg(wc, card, 26, 0xc0);
+
+	/* Set Transmit/Receive timeslot */
+	wcfxs_setreg(wc, card, 34, (3-card) * 8);
+	wcfxs_setreg(wc, card, 35, 0x00);
+	wcfxs_setreg(wc, card, 36, (3-card) * 8);
+	wcfxs_setreg(wc, card, 37, 0x00);
+
+	/* Enable ISO-Cap */
+	wcfxs_setreg(wc, card, 6, 0x00);
+
+	/* Wait 1000ms for ISO-cap to come up */
+	newjiffies = jiffies;
+	newjiffies += 2 * HZ;
+	while((jiffies < newjiffies) && !(wcfxs_getreg(wc, card, 11) & 0xf0));
+
+	if (!(wcfxs_getreg(wc, card, 11) & 0xf0)) {
+		printk("VoiceDAA did not bring up ISO link properly!\n");
+		return -1;
+	}
+	if (debug)
+		printk("ISO-Cap is now up, line side: %02x rev %02x\n", 
+		       wcfxs_getreg(wc, card, 11) >> 4,
+		       (wcfxs_getreg(wc, card, 13) >> 2) & 0xf);
+	/* Enable on-hook line monitor */
+	wcfxs_setreg(wc, card, 5, 0x40);
+	return 0;
+		
+}
+
 static int wcfxs_init_proslic(struct wcfxs *wc, int card, int fast, int manual, int sane)
 {
 
@@ -822,13 +949,13 @@
 		wcfxs_setreg(wc, card, 14, 0x10);
 	}
 
-	if (wcfxs_init_indirect_regs(wc, card)) {
+	if (wcfxs_proslic_init_indirect_regs(wc, card)) {
 		printk(KERN_INFO "Indirect Registers failed to initialize on module %d.\n", card);
 		return -1;
 	}
 
 	/* Clear scratch pad area */
-	wcfxs_setreg_indirect(wc, card, 97,0);
+	wcfxs_proslic_setreg_indirect(wc, card, 97,0);
 
 	/* Clear digital loopback */
 	wcfxs_setreg(wc, card, 8, 0);
@@ -846,8 +973,8 @@
 	/* Flush ProSLIC digital filters by setting to clear, while
 	   saving old values */
 	for (x=0;x<5;x++) {
-		tmp[x] = wcfxs_getreg_indirect(wc, card, x + 35);
-		wcfxs_setreg_indirect(wc, card, x + 35, 0x8000);
+		tmp[x] = wcfxs_proslic_getreg_indirect(wc, card, x + 35);
+		wcfxs_proslic_setreg_indirect(wc, card, x + 35, 0x8000);
 	}
 
 	/* Power up the DC-DC converter */
@@ -859,7 +986,7 @@
 	if (!fast) {
 
 		/* Check for power leaks */
-		if (wcfxs_powerleak_test(wc, card)) {
+		if (wcfxs_proslic_powerleak_test(wc, card)) {
 			printk("ProSLIC module %d failed leakage test.  Check for short circuit\n", card);
 		}
 		/* Power up again */
@@ -870,9 +997,9 @@
 #ifndef NO_CALIBRATION
 		/* Perform calibration */
 		if(manual) {
-			if (wcfxs_manual_calibrate(wc, card)) {
+			if (wcfxs_proslic_manual_calibrate(wc, card)) {
 				//printk("Proslic failed on Manual Calibration\n");
-				if (wcfxs_manual_calibrate(wc, card)) {
+				if (wcfxs_proslic_manual_calibrate(wc, card)) {
 					printk("Proslic Failed on Second Attempt to Calibrate Manually. (Try -DNO_CALIBRATION in Makefile)\n");
 					return -1;
 				}
@@ -880,9 +1007,9 @@
 			}
 		}
 		else {
-			if(wcfxs_calibrate(wc, card))  {
+			if(wcfxs_proslic_calibrate(wc, card))  {
 				//printk("ProSlic died on Auto Calibration.\n");
-				if (wcfxs_calibrate(wc, card)) {
+				if (wcfxs_proslic_calibrate(wc, card)) {
 					printk("Proslic Failed on Second Attempt to Auto Calibrate\n");
 					return -1;
 				}
@@ -894,10 +1021,10 @@
 	}
 	/* Calibration complete, restore original values */
 	for (x=0;x<5;x++) {
-		wcfxs_setreg_indirect(wc, card, x + 35, tmp[x]);
+		wcfxs_proslic_setreg_indirect(wc, card, x + 35, tmp[x]);
 	}
 
-	if (wcfxs_verify_indirect_regs(wc, card)) {
+	if (wcfxs_proslic_verify_indirect_regs(wc, card)) {
 		printk(KERN_INFO "Indirect Registers failed verification.\n");
 		return -1;
 	}
@@ -910,7 +1037,7 @@
 #endif
 
 #if 0
-    if (wcfxs_setreg_indirect(wc, card, 97, 0x0)) { // Stanley: for the bad recording fix
+    if (wcfxs_proslic_setreg_indirect(wc, card, 97, 0x0)) { // Stanley: for the bad recording fix
 		 printk(KERN_INFO "ProSlic IndirectReg Died.\n");
 		 return -1;
 	}
@@ -943,16 +1070,14 @@
 #endif
 
 #ifdef BOOST_RINGER
-    	wcfxs_setreg(wc, card, 74, 0x3f);
-	
 	/* Beef up Ringing voltage to 89V */
-	if (wcfxs_setreg_indirect(wc, card, 21, 0x1e1))
+	if (wcfxs_proslic_setreg_indirect(wc, card, 23, 0x1d1))
 			return -1;
 #endif
 	return 0;
 }
 
-static inline void wcfxs_recheck_sanity(struct wcfxs *wc, int card)
+static inline void wcfxs_proslic_recheck_sanity(struct wcfxs *wc, int card)
 {
 	int res;
 	/* Check loopback */
@@ -976,7 +1101,7 @@
 	}
 }
 
-static inline void wcfxs_check_hook(struct wcfxs *wc, int card)
+static inline void wcfxs_proslic_check_hook(struct wcfxs *wc, int card)
 {
 	char res;
 	int hook;
@@ -1038,17 +1163,26 @@
 	int x;
 	switch (cmd) {
 	case WCFXS_GET_STATS:
+		if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS)
+			return -EINVAL;
 		stats.tipvolt = wcfxs_getreg(wc, chan->chanpos - 1, 80) * -376;
+
 		stats.ringvolt = wcfxs_getreg(wc, chan->chanpos - 1, 81) * -376;
 		stats.batvolt = wcfxs_getreg(wc, chan->chanpos - 1, 82) * -376;
 		if (copy_to_user((struct wcfxs_stats *)data, &stats, sizeof(stats)))
 			return -EFAULT;
 		break;
 	case WCFXS_GET_REGS:
-		for (x=0;x<NUM_INDIRECT_REGS;x++)
-			regs.indirect[x] = wcfxs_getreg_indirect(wc, chan->chanpos -1, x);
-		for (x=0;x<NUM_REGS;x++)
-			regs.direct[x] = wcfxs_getreg(wc, chan->chanpos - 1, x);
+		if (wc->modtype == MOD_TYPE_FXS) {
+			for (x=0;x<NUM_INDIRECT_REGS;x++)
+				regs.indirect[x] = wcfxs_proslic_getreg_indirect(wc, chan->chanpos -1, x);
+			for (x=0;x<NUM_REGS;x++)
+				regs.direct[x] = wcfxs_getreg(wc, chan->chanpos - 1, x);
+		} else {
+			memset(&regs, 0, sizeof(regs));
+			for (x=0;x<NUM_FXO_REGS;x++)
+				regs.direct[x] = wcfxs_getreg(wc, chan->chanpos - 1, x);
+		}
 		if (copy_to_user((struct wcfxs_regs *)data, &regs, sizeof(regs)))
 			return -EFAULT;
 		break;
@@ -1056,25 +1190,16 @@
 		if (copy_from_user(&regop, (struct wcfxs_regop *)data, sizeof(regop)))
 			return -EFAULT;
 		if (regop.indirect) {
+			if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS)
+				return -EINVAL;
 			printk("Setting indirect %d to 0x%04x on %d\n", regop.reg, regop.val, chan->chanpos);
-			wcfxs_setreg_indirect(wc, chan->chanpos - 1, regop.reg, regop.val);
+			wcfxs_proslic_setreg_indirect(wc, chan->chanpos - 1, regop.reg, regop.val);
 		} else {
 			regop.val &= 0xff;
 			printk("Setting direct %d to %04x on %d\n", regop.reg, regop.val, chan->chanpos);
 			wcfxs_setreg(wc, chan->chanpos - 1, regop.reg, regop.val);
 		}
 		break;
-	case ZT_ONHOOKTRANSFER:
-		if (copy_from_user(&x, (int *)data, sizeof(x)))
-			return -EFAULT;
-		/* RINGing, prepare for OHT */
-		wc->ohttimer[x] = x << 3;
-		wc->idletxhookstate[chan->chanpos - 1] = 0x2;	/* OHT mode when idle */
-		if (!wc->lasttxhook[chan->chanpos - 1]) {
-			wc->lasttxhook[chan->chanpos-1] = wc->idletxhookstate[chan->chanpos-1];
-			wcfxs_setreg(wc, chan->chanpos - 1, 64, wc->lasttxhook[chan->chanpos-1]);
-		}
-		break;
 	default:
 		return -ENOTTY;
 	}
@@ -1090,15 +1215,13 @@
 	if (wc->dead)
 		return -ENODEV;
 	wc->usecount++;
-#ifndef LINUX26
 	MOD_INC_USE_COUNT;
-#endif	
 	return 0;
 }
 
 static int wcfxs_watchdog(struct zt_span *span, int event)
 {
-	printk("FXS: Restarting DMA\n");
+	printk("TDM: Restarting DMA\n");
 	wcfxs_restart_dma(span->pvt);
 	return 0;
 }
@@ -1108,9 +1231,7 @@
 	struct wcfxs *wc = chan->pvt;
 	int x;
 	wc->usecount--;
-#ifndef LINUX26
 	MOD_DEC_USE_COUNT;
-#endif
 	for (x=0;x<wc->cards;x++)
 		wc->idletxhookstate[x] = 1;
 	/* If we're dead, release us now */
@@ -1123,36 +1244,51 @@
 {
 	struct wcfxs *wc = chan->pvt;
 	int reg=0;
-	switch(txsig) {
-	case ZT_TXSIG_ONHOOK:
-		switch(chan->sig) {
-		case ZT_SIG_FXOKS:
-		case ZT_SIG_FXOLS:
+	if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) {
+		/* XXX Enable hooksig for FXO XXX */
+		switch(txsig) {
+		case ZT_TXSIG_START:
+		case ZT_TXSIG_OFFHOOK:
+			wcfxs_setreg(wc, chan->chanpos - 1, 5, 0x41);
+			break;
+		case ZT_TXSIG_ONHOOK:
+			wcfxs_setreg(wc, chan->chanpos - 1, 5, 0x40);
+			break;
+		default:
+			printk("wcfxo: Can't set tx state to %d\n", txsig);
+		}
+	} else {
+		switch(txsig) {
+		case ZT_TXSIG_ONHOOK:
+			switch(chan->sig) {
+			case ZT_SIG_FXOKS:
+			case ZT_SIG_FXOLS:
+				wc->lasttxhook[chan->chanpos-1] = wc->idletxhookstate[chan->chanpos-1];
+				break;
+			case ZT_SIG_FXOGS:
+				wc->lasttxhook[chan->chanpos-1] = 3;
+				break;
+			}
+			break;
+		case ZT_TXSIG_OFFHOOK:
 			wc->lasttxhook[chan->chanpos-1] = wc->idletxhookstate[chan->chanpos-1];
 			break;
-		case ZT_SIG_FXOGS:
-			wc->lasttxhook[chan->chanpos-1] = 3;
+		case ZT_TXSIG_START:
+			wc->lasttxhook[chan->chanpos-1] = 4;
+			break;
+		case ZT_TXSIG_KEWL:
+			wc->lasttxhook[chan->chanpos-1] = 0;
 			break;
+		default:
+			printk("wcfxs: Can't set tx state to %d\n", txsig);
 		}
-		break;
-	case ZT_TXSIG_OFFHOOK:
-		wc->lasttxhook[chan->chanpos-1] = wc->idletxhookstate[chan->chanpos-1];
-		break;
-	case ZT_TXSIG_START:
-		wc->lasttxhook[chan->chanpos-1] = 4;
-		break;
-	case ZT_TXSIG_KEWL:
-		wc->lasttxhook[chan->chanpos-1] = 0;
-		break;
-	default:
-		printk("wcfxs: Can't set tx state to %d\n", txsig);
-	}
-	if (debug)
-		printk("Setting hook state to %d (%02x)\n", txsig, reg);
+		if (debug)
+			printk("Setting FXS hook state to %d (%02x)\n", txsig, reg);
 
 #if 1
-	wcfxs_setreg(wc, chan->chanpos - 1, 64, wc->lasttxhook[chan->chanpos-1]);
+		wcfxs_setreg(wc, chan->chanpos - 1, 64, wc->lasttxhook[chan->chanpos-1]);
 #endif
+	}
 	return 0;
 }
 
@@ -1160,12 +1296,13 @@
 {
 	int x;
 	/* Zapata stuff */
-	sprintf(wc->span.name, "WCFXS/%d", wc->pos);
+	sprintf(wc->span.name, "WCTDM/%d", wc->pos);
 	sprintf(wc->span.desc, "%s Board %d", wc->variety, wc->pos + 1);
 	wc->span.deflaw = ZT_LAW_MULAW;
 	for (x=0;x<wc->cards;x++) {
-		sprintf(wc->chans[x].name, "WCFXS/%d/%d", wc->pos, x);
-		wc->chans[x].sigcap = ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_SF;
+		sprintf(wc->chans[x].name, "WCTDM/%d/%d", wc->pos, x);
+		wc->chans[x].sigcap = ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_SF;
+		wc->chans[x].sigcap |= ZT_SIG_FXSKS | ZT_SIG_FXSLS | ZT_SIG_SF;
 		wc->chans[x].chanpos = x+1;
 		wc->chans[x].pvt = wc;
 	}
@@ -1187,6 +1324,20 @@
 	return 0;
 }
 
+static void wcfxs_post_initialize(struct wcfxs *wc)
+{
+	int x;
+	/* Finalize signalling  */
+	for (x=0;x<wc->cards;x++) {
+		if (wc->cardflag & (1 << x)) {
+			if (wc->modtype[x] == MOD_TYPE_FXO)
+				wc->chans[x].sigcap = ZT_SIG_FXSKS | ZT_SIG_FXSLS | ZT_SIG_SF;
+			else
+				wc->chans[x].sigcap = ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_SF;
+		}
+	}
+}
+
 static int wcfxs_hardware_init(struct wcfxs *wc)
 {
 	/* Hardware stuff */
@@ -1220,7 +1371,7 @@
 			return -1;
 		}
 		/* Go to half-duty FSYNC */
-		__wcfxs_setcreg(wc, WC_SYNC, 0x00);
+		__wcfxs_setcreg(wc, WC_SYNC, 0x01);
 		y = __wcfxs_getcreg(wc, WC_SYNC);
 	} else {
 		printk("No freshmaker chip\n");
@@ -1270,25 +1421,34 @@
 
 	for (x=0;x<wc->cards;x++) {
 		int sane=0,ret=0;
+#if 1
 		/* Init with Auto Calibration */
 		if (!(ret=wcfxs_init_proslic(wc, x, 0, 0, sane))) {
 			wc->cardflag |= (1 << x);
-			printk("Module %d: Installed -- AUTO\n",x);
+			printk("Module %d: Installed -- AUTO FXS\n",x);
 		} else {
-			if(ret!=-2) sane=1;
-			/* Init with Manual Calibration */
-			if (!wcfxs_init_proslic(wc, x, 0, 1, sane)) {
+			if(ret!=-2) {
+				sane=1;
+				/* Init with Manual Calibration */
+				if (!wcfxs_init_proslic(wc, x, 0, 1, sane)) {
+					wc->cardflag |= (1 << x);
+					printk("Module %d: Installed -- MANUAL FXS\n",x);
+				} else {
+					printk("Module %d: FAILED FXS\n", x);
+				} 
+			} else if (!(ret = wcfxs_init_voicedaa(wc, x, 0, 0, sane))) {
 				wc->cardflag |= (1 << x);
-				printk("Module %d: Installed -- MANUAL\n",x);
-			} else 
+				printk("Module %d: Installed -- AUTO FXO\n",x);
+			} else
 				printk("Module %d: Not installed\n", x);
 		}
+#endif
 	}
 
 	/* Return error if nothing initialized okay. */
 	if (!wc->cardflag)
 		return -1;
-	__wcfxs_setcreg(wc, WC_SYNC, wc->cardflag << 1);
+	__wcfxs_setcreg(wc, WC_SYNC, (wc->cardflag << 1) | 0x1);
 	return 0;
 }
 
@@ -1387,6 +1547,11 @@
 
 			if (wcfxs_initialize(wc)) {
 				printk("wcfxs: Unable to intialize FXS\n");
+				/* Set Reset Low */
+				x=inb(wc->ioaddr + WC_CNTL);
+				outb((~0x1)&x, wc->ioaddr + WC_CNTL);
+				/* Free Resources */
+				free_irq(pdev->irq, wc);
 				if (wc->freeregion)
 					release_region(wc->ioaddr, 0xff);
 				pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)wc->writechunk, wc->writedma);
@@ -1400,7 +1565,7 @@
 			/* Keep track of which device we are */
 			pci_set_drvdata(pdev, wc);
 
-			if (request_irq(pdev->irq, wcfxs_interrupt, SA_SHIRQ, "wcfxs", wc)) {
+			if (request_irq(pdev->irq, wcfxs_interrupt, SA_SHIRQ, "wctdm", wc)) {
 				printk("wcfxs: Unable to request IRQ %d\n", pdev->irq);
 				if (wc->freeregion)
 					release_region(wc->ioaddr, 0xff);
@@ -1418,14 +1583,17 @@
 				outb((~0x1)&x, wc->ioaddr + WC_CNTL);
 				/* Free Resources */
 				free_irq(pdev->irq, wc);
-				zt_unregister(&wc->span);
 				if (wc->freeregion)
 					release_region(wc->ioaddr, 0xff);
 				pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)wc->writechunk, wc->writedma);
 				pci_set_drvdata(pdev, NULL);
 				kfree(wc);
 				return -EIO;
+
 			}
+
+			wcfxs_post_initialize(wc);
+
 			/* Enable interrupts */
 			wcfxs_enable_interrupts(wc);
 			/* Initialize Write/Buffers to all blank data */
@@ -1434,7 +1602,7 @@
 			/* Start DMA */
 			wcfxs_start_dma(wc);
 
-			printk("Found a Wildcard FXS: %s (%d modules)\n", wc->variety, wc->cards);
+			printk("Found a Wildcard TDM: %s (%d modules)\n", wc->variety, wc->cards);
 			res = 0;
 		} else
 			res = -ENOMEM;




More information about the svn-commits mailing list