[svn-commits] mattf: branch 1.4 r3211 - in /branches/1.4: firmware/Makefile wctc4xxp/base.c

SVN commits to the Digium repositories svn-commits at lists.digium.com
Sat Nov 3 11:23:20 CDT 2007


Author: mattf
Date: Sat Nov  3 11:23:20 2007
New Revision: 3211

URL: http://svn.digium.com/view/zaptel?view=rev&rev=3211
Log:
Major update for tc4xxp driver.  Fixes many outstanding issues related to channel lockups, etc.  It also raises the maximum channel count for g.729 to 120 channels.

Modified:
    branches/1.4/firmware/Makefile
    branches/1.4/wctc4xxp/base.c

Modified: branches/1.4/firmware/Makefile
URL: http://svn.digium.com/view/zaptel/branches/1.4/firmware/Makefile?view=diff&rev=3211&r1=3210&r2=3211
==============================================================================
--- branches/1.4/firmware/Makefile (original)
+++ branches/1.4/firmware/Makefile Sat Nov  3 11:23:20 2007
@@ -19,7 +19,7 @@
 
 OCT6114_064_VERSION:=1.05.01
 OCT6114_128_VERSION:=1.05.01
-TC400M_VERSION:=MR5.6
+TC400M_VERSION:=MR6.12
 VPMADT032_VERSION:=1.07
 
 FIRMWARE_URL:=http://downloads.digium.com/pub/telephony/firmware/releases

Modified: branches/1.4/wctc4xxp/base.c
URL: http://svn.digium.com/view/zaptel/branches/1.4/wctc4xxp/base.c?view=diff&rev=3211&r1=3210&r2=3211
==============================================================================
--- branches/1.4/wctc4xxp/base.c (original)
+++ branches/1.4/wctc4xxp/base.c Sat Nov  3 11:23:20 2007
@@ -54,6 +54,9 @@
 
 #ifdef HOTPLUG_FIRMWARE
 static const char *dte_firmware = "zaptel-fw-tc400m.bin";
+#else
+extern u8 _binary_tc400m_firmware_bin_start[];
+extern void _binary_tc400m_firmware_bin_size;
 #endif
 
 
@@ -67,7 +70,7 @@
 #define NUM_EC	  4
 
 /* NUM_CHANNELS must be checked if new firmware (dte_firm.h) is used */
-#define NUM_CHANNELS 97
+#define NUM_CHANNELS 120
 
 #define DTE_FORMAT_ULAW   0x00
 #define DTE_FORMAT_G723_1 0x04
@@ -198,6 +201,11 @@
 	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
 	0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0C, 0x00, 0x00,0x06,0x10,0x00, 0x00,0x00, \
 	0x02,0x00, (t&0x00FF), ((t&0xFF00) >> 8) }
+#define CMD_MSG_QUERY_CHANNEL_LEN 30
+#define CMD_MSG_QUERY_CHANNEL(s,t) { \
+	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
+	0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x01,0x06,0x10,0x00, 0x00,0x00, \
+	(t&0x00FF), ((t&0xFF00) >> 8) }
 #define CMD_MSG_TRANS_CONNECT_LEN 38
 #define CMD_MSG_TRANS_CONNECT(s,e,c1,c2,f1,f2) { \
 	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
@@ -256,12 +264,24 @@
 
 /* Wrapper for RTP packets */
 #define CMD_MSG_IP_UDP_RTP_LEN 54
-#define CMD_MSG_IP_UDP_RTP(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16,p17,p18,p19,p20) { \
+#define CMD_MSG_IP_UDP_RTP(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16,p17,p18,p19,p20,s) { \
 	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x08,0x00, \
 	0x45,0x00, p1,p2, 0x00,p3, 0x40,0x00, 0x80,0x11, p4,p5, \
 	0xC0,0xA8,0x09,0x03, 0xC0,0xA8,0x09,0x03, p6,p7, p8,p9, p10,p11, p12,p13, \
-	0x80,p14, p15,p16, p17,p18,p19,p20, 0x12,0x34,0x56,0x78}
-
+	0x80,p14, p15,p16, p17,p18,p19,p20, 0x12,0x34,0x56,(s&0xFF)}
+
+#define CMD_MSG_DW_WRITE_LEN 38
+#define CMD_MSG_DW_WRITE(s,a,d) { \
+	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
+	0x00,0x01,s&0x0F,0x00,0x00,0x00,0x00,0x00,0x04,0x17,0x00,0x00, \
+	((a>>24)&0x00FF),((a>>16)&0x00FF), ((a>>8)&0x00FF),(a&0x00FF), \
+	((d>>24)&0x00FF),((d>>16)&0x00FF), ((d>>8)&0x00FF),(d&0x00FF) }
+
+#define CMD_MSG_FORCE_ALERT_LEN 32
+#define CMD_MSG_FORCE_ALERT(s) { \
+	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
+	0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x09,0x04, 0x00,0x00, \
+	0x24,0x00, 0x00,0x00 }
 
 #define zt_send_cmd(wc, command, length, hex) \
 	({ \
@@ -288,7 +308,18 @@
 			} \
 			__transmit_demand(wc); \
 			up(&wc->cmdqsem); \
-			ret = wcdte_waitfor_csmencaps(wc, RCV_CSMENCAPS, 0); \
+			if (hex == 0x0000) \
+				ret = wcdte_waitfor_csmencaps(wc, RCV_CSMENCAPS_ACK, 2); \
+			else { \
+				ret = wcdte_waitfor_csmencaps(wc, RCV_CSMENCAPS, 0); \
+				if (wc->dsp_crashed) \
+				{ \
+					printk("Aborting zt_send_cmd()\n"); \
+					return 1; \
+				} \
+				if ((ret == 2) && (wc->last_command_sent == 0x0010)) \
+					printk("Detected timeout on 0x0010\n"); \
+			} \
 			if (ret == 1) \
 				return(1); \
 		} while (ret == 2); \
@@ -326,9 +357,12 @@
 	unsigned int last_rseqno;
 	unsigned int last_command_sent;
 	unsigned int last_rcommand;
-	unsigned int last_rparm2;
+	unsigned int last_rparm1;
 	unsigned int seq_num;
 	long timeout;
+
+	unsigned int dsp_crashed;
+	unsigned int dumping;
 
 	unsigned int ztsnd_rtx;
 	unsigned int ztsnd_0010_rtx;
@@ -393,6 +427,8 @@
 
 	unsigned int last_dte_seqno;
 	unsigned int dte_seqno_rcv;
+
+	unsigned char ssrc;
 };
 
 
@@ -401,12 +437,74 @@
 static struct dte_state *encoders;
 static struct dte_state *decoders;
 static int debug = 0;
+static int debug_des = 0;			/* Set the number of descriptor packet bytes to output on errors, 0 disables output */
+static int debug_des_cnt = 0;			/* Set the number of times descriptor packets are displayed before the output is disabled */
+static int force_alert = 0;
+static int debug_notimeout = 0;
 static char *mode;
-int debug_packets = 0;
-
-
-static int wcdte_create_channel(struct wcdte *wc, int simple, int complicated, int part1_id, int part2_id, unsigned int *dte_chan1, unsigned int *dte_chan2);
+static int debug_packets = 0;
+
+static int wcdte_create_channel(struct wcdte *wc, int part1_id, int part2_id, unsigned int *dte_chan1, unsigned int *dte_chan2);
+static int wcdte_open_channel(struct wcdte *wc, int simple, int complicated, int part1_id, int part2_id, int chan1, int chan2);
 static int wcdte_destroy_channel(struct wcdte *wc, unsigned int chan1, unsigned int chan2);
+static int wcdte_close_channel(struct wcdte *wc, unsigned int chan1, unsigned int chan2);
+static int __wcdte_setup_channels(struct wcdte *wc);
+static void wcdte_release(struct wcdte *wc);
+
+static int __dump_descriptors(struct wcdte *wc)
+{
+	volatile unsigned char *writechunk, *readchunk;
+	int o2, i, j;
+
+	if (debug_des_cnt == 0)
+		return 1;
+
+	printk("Transmit Descriptors (wc->tdbl = %d)\n", wc->tdbl);
+	for (i = 0; i < ERING_SIZE; i++)
+	{
+		writechunk = (volatile unsigned char *)(wc->writechunk);
+		writechunk += i * SFRAME_SIZE;
+		o2 = i * 4;
+
+		if (i == wc->tdbl)
+			printk("->");
+		else
+			printk("  ");
+		if ((le32_to_cpu(wc->descripchunk[o2]) & 0x80000000))
+			printk("AN983 owns : ");
+		else
+			printk("Driver owns: ");
+
+		for (j = 0; j < debug_des; j++)
+			printk("%02X ", writechunk[j]);
+		printk("\n");
+	}
+
+	printk("Receive Descriptors (wc->rdbl = %d)\n", wc->rdbl);
+	for (i = 0; i < ERING_SIZE; i++)
+	{
+		readchunk = (volatile unsigned char *)wc->readchunk;
+		readchunk += i * SFRAME_SIZE;
+		o2 = i * 4;
+		o2 += ERING_SIZE * 4;
+
+		if (i == wc->rdbl)
+			printk("->");
+		else
+			printk("  ");
+		if ((le32_to_cpu(wc->descripchunk[o2]) & 0x80000000))
+			printk("AN983 owns : ");
+		else
+			printk("Driver owns: ");
+
+		for (j = 0; j < debug_des; j++)
+			printk("%02X ", readchunk[j]);
+		printk("\n");
+	}
+	if (debug_des_cnt > 0)
+		debug_des_cnt--;
+	return 0;
+}
 
 /* Sanity check values */
 static inline int zt_tc_sanitycheck(struct zt_transcode_header *zth, unsigned int outbytes)
@@ -444,6 +542,8 @@
 
 	state_ptr->chan_in_num = 999;
 	state_ptr->chan_out_num = 999;
+
+	state_ptr->ssrc = 0x78;
 	
 	if (encoder == 1)
 	{
@@ -545,7 +645,7 @@
 	writechunk += wc->tdbl * SFRAME_SIZE;
 
 	o2 = wc->tdbl * 4;
-		
+
 	do
 	{
 	} while ((le32_to_cpu(wc->descripchunk[o2]) & 0x80000000));
@@ -602,17 +702,34 @@
 	int i = 0;
 	int res = 0;
 	unsigned int ipchksum, ndx;
+
 	switch(op) {
-	case ZT_TCOP_ALLOCATE:
+ 	case ZT_TCOP_ALLOCATE:
 		down(&wc->chansem);
-		if (ztc->chan_built == 0)
-		{
-			if (st->encoder == 1)
-				wcdte_create_channel(wc, wcdte_zapfmt_to_dtefmt(zth->srcfmt), wcdte_zapfmt_to_dtefmt(zth->dstfmt),
-						st->timeslot_in_num, st->timeslot_out_num, &(st->chan_in_num), &(st->chan_out_num));
-			else
-				wcdte_create_channel(wc, wcdte_zapfmt_to_dtefmt(zth->dstfmt), wcdte_zapfmt_to_dtefmt(zth->srcfmt),
-						st->timeslot_out_num, st->timeslot_in_num, &(st->chan_out_num), &(st->chan_in_num));
+		if (ztc->chan_built == 0) {
+			if (ztc->built_fmts == (zth->dstfmt | zth->srcfmt)) {
+				ztc->chan_built = 1;
+				st->ssrc += 1;
+			} else {
+				/* If channel is built for the wrong codecs, teardown and rebuild */
+				if (st->encoder == 1) {
+					if (st->chan_in_num != 999) {
+						wcdte_close_channel(wc, st->chan_in_num, st->chan_out_num);
+						wcdte_destroy_channel(wc, st->chan_in_num, st->chan_out_num);
+					}
+					wcdte_create_channel(wc, st->timeslot_in_num, st->timeslot_out_num, &(st->chan_in_num), &(st->chan_out_num));
+					wcdte_open_channel(wc, wcdte_zapfmt_to_dtefmt(zth->srcfmt), wcdte_zapfmt_to_dtefmt(zth->dstfmt),
+						st->timeslot_in_num, st->timeslot_out_num, st->chan_in_num, st->chan_out_num);
+				} else {
+					if (st->chan_in_num != 999) {
+						wcdte_close_channel(wc, st->chan_out_num, st->chan_in_num);
+						wcdte_destroy_channel(wc, st->chan_out_num, st->chan_in_num);
+					}
+					wcdte_create_channel(wc, st->timeslot_out_num, st->timeslot_in_num, &(st->chan_out_num), &(st->chan_in_num));
+					wcdte_open_channel(wc, wcdte_zapfmt_to_dtefmt(zth->srcfmt), wcdte_zapfmt_to_dtefmt(zth->dstfmt),
+						st->timeslot_out_num, st->timeslot_in_num, st->chan_out_num, st->chan_in_num);
+				}
+			}
 			/* Mark this channel as built */
 			ztc->chan_built = 1;
 			ztc->built_fmts = zth->dstfmt | zth->srcfmt;
@@ -623,9 +740,9 @@
 				compl_ztc = &(wc->udecode->channels[ndx]);
 			else
 				compl_ztc = &(wc->uencode->channels[ndx]);
+			compl_st = compl_ztc->pvt;
 			compl_ztc->chan_built = 1;
 			compl_ztc->built_fmts = zth->dstfmt | zth->srcfmt;
-			compl_st = compl_ztc->pvt;
 			compl_st->chan_in_num = st->chan_out_num;
 			compl_st->chan_out_num = st->chan_in_num;
 		}
@@ -634,39 +751,24 @@
 	case ZT_TCOP_RELEASE:
 		down(&wc->chansem);
 		ndx = st->timeslot_in_num/2;
-			
+
 		if (st->encoder == 1)
 			compl_ztc = &(wc->udecode->channels[ndx]);
 		else
 			compl_ztc = &(wc->uencode->channels[ndx]);
 
-		/* If the channel complement (other half of the encoder/decoder pair) is not being used... */
 		if ((compl_ztc->flags & ZT_TC_FLAG_BUSY) == 0)
-		{
-			if (st->encoder == 1)
-				wcdte_destroy_channel(wc, st->chan_in_num, st->chan_out_num);
-			else
-				wcdte_destroy_channel(wc, st->chan_out_num, st->chan_in_num);
-
+		{			
 			/* Mark this channel as not built */
 			ztc->chan_built = 0;
-			ztc->built_fmts = 0;
-			st->chan_in_num = 999;
-			st->chan_out_num = 999;
-			
+
 			/* Mark the channel complement as not built */
 			compl_ztc->chan_built = 0;
-			compl_ztc->built_fmts = 0;
-			compl_st = compl_ztc->pvt;
-			compl_st->chan_in_num = 999;
-			compl_st->chan_out_num = 999;
-		}
-		st->dte_seqno_rcv = 0;
+		}
+			
 		up(&wc->chansem);
 		break;
 	case ZT_TCOP_TRANSCODE:
-		if (ztc->chan_built == 0)
-			printk("wcdte error: Sending data to a channel that isn't built yet\n");
 		if ( (((zth->srcfmt == ZT_FORMAT_ULAW) || (zth->srcfmt == ZT_FORMAT_ALAW)) && ((zth->dstfmt == ZT_FORMAT_G729A  && zth->srclen >= G729_SAMPLES) ||(zth->dstfmt == ZT_FORMAT_G723_1  && zth->srclen >= G723_SAMPLES)) )
 			|| ((zth->srcfmt == ZT_FORMAT_G729A) && (zth->srclen >= G729_BYTES))
 			|| ((zth->srcfmt == ZT_FORMAT_G723_1) && (zth->srclen >= G723_BYTES)) )
@@ -718,7 +820,8 @@
 						 ((st->timestamp) >> 24)             & 0xFF,
 						 ((st->timestamp) >> 16)             & 0xFF,
 	 					 ((st->timestamp) >> 8)              & 0xFF,
-						  (st->timestamp)                    & 0xFF);
+						  (st->timestamp)                    & 0xFF,
+						  (st->ssrc)                         & 0xFF);
 
 					ipchksum = 0x9869 + (fifo[16] << 8) + fifo[17]
 						+ (fifo[18] << 8) + fifo[19];
@@ -802,33 +905,34 @@
 			printk("\n");
 		}
 		/* See if message must be ACK'd */
-		if ((readchunk[17] & 0xC0) == 0)
+		if ((readchunk[17] & 0x80) == 0)
 		{
 			rcommand = readchunk[24] | (readchunk[25] << 8);
 			rchannel = readchunk[18] | (readchunk[19] << 8);
 			rseq = readchunk[16];
-			
+
 			down(&wc->cmdqsem);
-			if ( (((wc->cmdq_wndx + 1) % MAX_COMMANDS) == wc->cmdq_rndx) && debug )
-				printk("wcdte error: cmdq is full (rndx = %d, wndx = %d).\n", wc->cmdq_rndx, wc->cmdq_wndx);
-			else
-			{
-				unsigned char fifo[OTHER_CMD_LEN] = CMD_MSG_ACK(rseq++, rchannel);
-
-				wc->cmdq[wc->cmdq_wndx].cmdlen = CMD_MSG_ACK_LEN;
-				for (i = 0; i < wc->cmdq[wc->cmdq_wndx].cmdlen; i++)
-					wc->cmdq[wc->cmdq_wndx].cmd[i] = fifo[i];
-				wc->cmdq_wndx = (wc->cmdq_wndx + 1) % MAX_COMMANDS;
-			}
-				
-			__transmit_demand(wc);
-
+			if ((readchunk[17] & 0x40) == 0) {
+				if ( (((wc->cmdq_wndx + 1) % MAX_COMMANDS) == wc->cmdq_rndx) && debug )
+					printk("wcdte error: cmdq is full (rndx = %d, wndx = %d).\n", wc->cmdq_rndx, wc->cmdq_wndx);
+				else
+				{
+					unsigned char fifo[OTHER_CMD_LEN] = CMD_MSG_ACK(rseq++, rchannel);
+
+					wc->cmdq[wc->cmdq_wndx].cmdlen = CMD_MSG_ACK_LEN;
+					for (i = 0; i < wc->cmdq[wc->cmdq_wndx].cmdlen; i++)
+						wc->cmdq[wc->cmdq_wndx].cmd[i] = fifo[i];
+					wc->cmdq_wndx = (wc->cmdq_wndx + 1) % MAX_COMMANDS;
+				}
+
+				__transmit_demand(wc);
+			}
 		
 			wc->rcvflags = RCV_CSMENCAPS;
 			if (rcommand == wc->last_command_sent) {
 				wc->last_rcommand = rcommand;
-				wc->last_rparm2 = readchunk[30] | (readchunk[31] << 8);
-				wake_up_interruptible(&wc->regq);
+				wc->last_rparm1 = readchunk[28] | (readchunk[29] << 8);
+				wake_up(&wc->regq);
 			} else {
 				if (debug)
 				printk("wcdte error: unexpected command response received (sent: %04X, received: %04X)\n", wc->last_command_sent, rcommand);
@@ -839,7 +943,27 @@
 		{
 			wc->last_rseqno = readchunk[16];
 			wc->rcvflags = RCV_CSMENCAPS_ACK;
-			wake_up_interruptible(&wc->regq);
+			if (!wc->dumping)
+				wake_up_interruptible(&wc->regq);
+			else
+				wake_up(&wc->regq);
+		}
+
+		if ((readchunk[22] == 0x75) && (readchunk[23] = 0xC1))
+		{
+			if (debug)
+				printk("wcdte error: received alert (0x%02X%02X) from dsp\n", readchunk[29], readchunk[28]);
+			if (debug_des) {
+				down(&wc->cmdqsem);
+				__dump_descriptors(wc);
+				up(&wc->cmdqsem);
+			}
+		}
+
+		if (wc->dumping && (readchunk[22] == 0x04) && (readchunk[23] = 0x14)) {
+			for (i = 27; i < 227; i++)
+				printk("%02X ", readchunk[i]);
+			printk("\n");
 		}
 	}
 
@@ -870,7 +994,12 @@
 			if (zth == NULL)
 			{
 				if (debug)
-					printk("wcdte error: Tried to put DTE data into a freed zth header!\n");
+					printk("wcdte error: Tried to put DTE data into a freed zth header! (ztc_ndx = %d, ztc->chan_built = %d)\n", ztc_ndx, ztc->chan_built);
+				if (debug_des) {
+					down(&wc->cmdqsem);
+					__dump_descriptors(wc);
+					up(&wc->cmdqsem);
+				}
 				rcodec = DTE_FORMAT_UNDEF;
 			} else {
 				chars = (unsigned char *)(zth->dstdata + zth->dstoffset + zth->dstlen);
@@ -888,7 +1017,12 @@
 			if (zth == NULL)
 			{
 				if (debug)
-					printk("wcdte error: Tried to put DTE data into a freed zth header!\n");
+					printk("wcdte error: Tried to put DTE data into a freed zth header! (ztc_ndx = %d, ztc->chan_built = %d)\n", ztc_ndx, ztc->chan_built);
+				if (debug_des) {
+					down(&wc->cmdqsem);
+					__dump_descriptors(wc);
+					up(&wc->cmdqsem);
+				}
 				rcodec = DTE_FORMAT_UNDEF;
 			} else {
 				chars = (unsigned char *)(zth->dstdata + zth->dstoffset + zth->dstlen);
@@ -904,7 +1038,7 @@
 		} else {
 			rtp_eseq = (st->last_dte_seqno + 1) & 0xFFFF;
 			if ( (rtp_rseq != rtp_eseq) && debug )
-				printk("wcdte error: Bad seqno from DTE! [%d][%d][%d]\n", rchannel, rtp_rseq, st->last_dte_seqno);
+				printk("wcdte error: Bad seqno from DTE! [%04X][%d][%d][%d]\n", (readchunk[37] | (readchunk[36] << 8)), rchannel, rtp_rseq, st->last_dte_seqno);
 
 			st->last_dte_seqno = rtp_rseq;
 		}
@@ -978,9 +1112,6 @@
 		}
 	}
 }
-
-
-
 
 
 /* static inline int wcdte_check_descriptor(struct wcdte *wc) */
@@ -1194,9 +1325,17 @@
 	if (wait_mode == 1)
 		ret = wait_event_interruptible_timeout(wc->regq, (wc->rcvflags == mask), wc->timeout);
 	else if (wait_mode == 2)
-		ret = wait_event_interruptible_timeout(wc->regq, ((wc->last_seqno == wc->last_rseqno) && (wc->rcvflags == mask)), wc->timeout);
-	else
-		ret = wait_event_interruptible_timeout(wc->regq, ((wc->last_rcommand == wc->last_command_sent) && (wc->last_seqno == wc->last_rseqno) && (wc->rcvflags == mask)), wc->timeout);
+		ret = wait_event_timeout(wc->regq, (wc->rcvflags == mask), wc->timeout);
+	else {
+		if (!debug_notimeout) {
+			ret = wait_event_timeout(wc->regq, ((wc->last_rcommand == wc->last_command_sent) && (wc->last_seqno == wc->last_rseqno) && (wc->rcvflags == mask)), wc->timeout);
+		}
+		else {
+			ret = wait_event_interruptible(wc->regq, ((wc->last_rcommand == wc->last_command_sent) && (wc->last_seqno == wc->last_rseqno) && (wc->rcvflags == mask)));
+			if (ret == 0)
+				ret = 1;
+		}
+	}
 	wc->rcvflags = 0;
 	wc->last_rcommand = 0;
 	wc->last_seqno = 0;
@@ -1211,6 +1350,11 @@
 	{
 		if (debug)
 			printk("wcdte error: Waitfor CSMENCAPS response timed out (ret = %d) (cmd_snt = %04X)\n", ret, wc->last_command_sent);
+		if (debug_des) {
+			down(&wc->cmdqsem);
+			__dump_descriptors(wc);
+			up(&wc->cmdqsem);
+		}
 		return(2);
 	}
 	if (wait_mode == 0)
@@ -1287,7 +1431,7 @@
 	return;
 }
 
-static int wcdte_boot_processor(struct wcdte *wc, const struct firmware *firmware)
+static int wcdte_boot_processor(struct wcdte *wc, const struct firmware *firmware, int full)
 {
 	int i, j, byteloc, last_byteloc, length, delay_count;
 	unsigned int reg, ret;
@@ -1297,12 +1441,12 @@
 	wcdte_write_phy(wc, 0, 0x2100);
 	if (debug)
 		printk("wcdte: PHY register 0 = %X", wcdte_read_phy(wc, 0));
-	
+
 	/* Set reset */
 	wcdte_setctl(wc, 0x00A0, 0x04000000);
 
 	/* Wait 1000msec to ensure processor reset */
-	mdelay(1000);
+	mdelay(4);
 
 	/* Clear reset */
 	wcdte_setctl(wc, 0x00A0, 0x04080000);
@@ -1312,10 +1456,10 @@
 	do
 	{
 		reg = wcdte_getctl(wc, 0x00fc);
-		mdelay(100);
+		mdelay(2);
 		delay_count++;
 
-		if (delay_count >= 100)
+		if (delay_count >= 5000)
 		{
 			printk("wcdte error: Failed to link to DTE processor!\n");
 			return(1);
@@ -1355,7 +1499,7 @@
 			wc->cmdq_wndx = (wc->cmdq_wndx + 1) % MAX_COMMANDS;
 		}
 	
-		__transmit_demand(wc);
+		ret = __transmit_demand(wc);
   		up(&wc->cmdqsem);
 
 		ret = wcdte_waitfor_csmencaps(wc, RCV_CSMENCAPS_ACK, 1);
@@ -1364,6 +1508,12 @@
 		else if (ret == 2)		/* Retransmit if dte processor times out */
 			byteloc = last_byteloc;
 		j++;
+
+		if (!full && (byteloc > 189)) { /* Quit if not fully booting */
+			wcdte_setctl(wc, 0x00A0, 0x04080000);
+			return 0;
+		}
+
 
 	} while (byteloc < firmware->size-20);
 	wc->timeout = 10 * HZ;
@@ -1379,10 +1529,30 @@
 	return(0);
 }
 
-static int wcdte_create_channel(struct wcdte *wc, int simple, int complicated, int part1_id, int part2_id, unsigned int *dte_chan1, unsigned int *dte_chan2)
+
+static int wcdte_create_channel(struct wcdte *wc, int part1_id, int part2_id, unsigned int *dte_chan1, unsigned int *dte_chan2)
+{
+	unsigned char chan1, chan2;
+
+	/* Create complex channel */
+	zt_send_cmd(wc, CMD_MSG_CREATE_CHANNEL(wc->seq_num++, part1_id), CMD_MSG_CREATE_CHANNEL_LEN, 0x0010);
+	zt_send_cmd(wc, CMD_MSG_QUERY_CHANNEL(wc->seq_num++, part1_id), CMD_MSG_QUERY_CHANNEL_LEN, 0x0010);
+	chan1 = wc->last_rparm1;
+
+	/* Create simple channel */
+	zt_send_cmd(wc, CMD_MSG_CREATE_CHANNEL(wc->seq_num++, part2_id), CMD_MSG_CREATE_CHANNEL_LEN, 0x0010);
+	zt_send_cmd(wc, CMD_MSG_QUERY_CHANNEL(wc->seq_num++, part2_id), CMD_MSG_QUERY_CHANNEL_LEN, 0x0010);
+	chan2 = wc->last_rparm1;
+
+	*dte_chan1 = chan1;
+	*dte_chan2 = chan2;
+
+	return 0;
+}
+
+static int wcdte_open_channel(struct wcdte *wc, int simple, int complicated, int part1_id, int part2_id, int chan1, int chan2)
 {
 	int length = 0;
-	unsigned char chan1, chan2;
 	struct zt_transcoder_channel *ztc1, *ztc2;
 	struct dte_state *st1, *st2;
 	if(complicated == DTE_FORMAT_G729A)
@@ -1390,18 +1560,15 @@
 	else if (complicated == DTE_FORMAT_G723_1)
 		length = G723_LENGTH;
 
-	/* Create complex channel */
-	zt_send_cmd(wc, CMD_MSG_CREATE_CHANNEL(wc->seq_num++, part1_id), CMD_MSG_CREATE_CHANNEL_LEN, 0x0010);
-	chan1 = wc->last_rparm2;
-
-	/* Create simple channel */
-	zt_send_cmd(wc, CMD_MSG_CREATE_CHANNEL(wc->seq_num++, part2_id), CMD_MSG_CREATE_CHANNEL_LEN, 0x0010);
-	chan2 = wc->last_rparm2;
-
 	ztc1 = &(wc->uencode->channels[part1_id/2]);
 	ztc2 = &(wc->udecode->channels[part2_id/2]);
 	st1 = ztc1->pvt;
 	st2 = ztc2->pvt;
+
+	if (force_alert) {
+		printk("Sending FORCE ALERT\n");
+		zt_send_cmd(wc, CMD_MSG_FORCE_ALERT(wc->seq_num++), CMD_MSG_FORCE_ALERT_LEN, 0xFFFF);
+	}
 
 	/* Configure complex channel */
 	zt_send_cmd(wc, CMD_MSG_SET_IP_HDR_CHANNEL(st1->cmd_seqno++, chan1, part2_id, part1_id), CMD_MSG_SET_IP_HDR_CHANNEL_LEN, 0x9000);
@@ -1424,13 +1591,19 @@
 	zt_send_cmd(wc, CMD_MSG_VOIP_VOPENA(st1->cmd_seqno++, chan1, complicated), CMD_MSG_VOIP_VOPENA_LEN, 0x8000);
 	zt_send_cmd(wc, CMD_MSG_VOIP_VOPENA(st2->cmd_seqno++, chan2, simple), CMD_MSG_VOIP_VOPENA_LEN, 0x8000);
 
-	*dte_chan1 = chan1;
-	*dte_chan2 = chan2;
-
-	return 1;
+	return 0;
 }
 
 static int wcdte_destroy_channel(struct wcdte *wc, unsigned int chan1, unsigned int chan2)
+{
+	/* Remove the channels */
+	zt_send_cmd(wc, CMD_MSG_DESTROY_CHANNEL(wc->seq_num++, chan1), CMD_MSG_DESTROY_CHANNEL_LEN, 0x0011);
+	zt_send_cmd(wc, CMD_MSG_DESTROY_CHANNEL(wc->seq_num++, chan2), CMD_MSG_DESTROY_CHANNEL_LEN, 0x0011);
+
+	return 0;
+}
+
+static int wcdte_close_channel(struct wcdte *wc, unsigned int chan1, unsigned int chan2)
 {
 	struct zt_transcoder_channel *ztc1, *ztc2;
 	struct dte_state *st1, *st2;
@@ -1447,16 +1620,13 @@
 	/* Disconnect the channels */
 	zt_send_cmd(wc, CMD_MSG_TRANS_CONNECT(wc->seq_num++, 0, chan1, chan2, 0, 0), CMD_MSG_TRANS_CONNECT_LEN, 0x9322);
 
-	/* Remove the channels */
-	zt_send_cmd(wc, CMD_MSG_DESTROY_CHANNEL(wc->seq_num++, chan1), CMD_MSG_DESTROY_CHANNEL_LEN, 0x0011);
-	zt_send_cmd(wc, CMD_MSG_DESTROY_CHANNEL(wc->seq_num++, chan2), CMD_MSG_DESTROY_CHANNEL_LEN, 0x0011);
-
-	return 1;
-}
-
-static int wcdte_setup_channels(struct wcdte *wc)	
-{
-	down(&wc->chansem);
+	return 0;
+}
+
+
+static int __wcdte_setup_channels(struct wcdte *wc)
+{
+	wc->seq_num = 6;
 
 #ifndef USE_TEST_HW
 	zt_send_cmd(wc, CMD_MSG_SET_ARM_CLK(wc->seq_num++), CMD_MSG_SET_ARM_CLK_LEN, 0x0411);
@@ -1491,9 +1661,16 @@
 
 	wc->timeout = HZ/10 + 1; 	/* 100msec */
 
+	return(0);
+}
+
+static int wcdte_setup_channels(struct wcdte *wc)
+{
+	down(&wc->chansem);
+	__wcdte_setup_channels(wc);
 	up(&wc->chansem);
 
-	return(0);
+	return 0;
 }
 
 static int __devinit wcdte_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
@@ -1503,12 +1680,8 @@
 	struct wcdte_desc *d = (struct wcdte_desc *)ent->driver_data;
 	int x;
 	static int initd_ifaces=0;
-	unsigned char g729_numchannels, g723_numchannels, min_numchannels, dte_firmware_ver;
+	unsigned char g729_numchannels, g723_numchannels, min_numchannels, dte_firmware_ver, dte_firmware_ver_minor;
 	unsigned int complexfmts;
-#if !defined(HOTPLUG_FIRMWARE)
-	extern void _binary_zaptel_fw_tc400m_bin_size;
-	extern u8 _binary_zaptel_fw_tc400m_bin_start[];
-#endif
 	struct firmware embedded_firmware = {
 #if !defined(HOTPLUG_FIRMWARE)
 		/* Yes... this is weird. objcopy gives us a symbol containing
@@ -1517,8 +1690,8 @@
 		   is to take its address, so we define it as a pointer and
 		   then cast that value to the proper type.
 		*/
-		.size = (size_t) &_binary_zaptel_fw_tc400m_bin_size,
-		.data = _binary_zaptel_fw_tc400m_bin_start,
+		.size = (size_t) &_binary_tc400m_firmware_bin_size,
+		.data = _binary_tc400m_firmware_bin_start,
 #endif
 	};
 	const struct firmware *firmware = &embedded_firmware;
@@ -1557,11 +1730,13 @@
 			wc->last_seqno = 999;
 			wc->last_command_sent = 0;
 			wc->last_rcommand = 0;
-			wc->last_rparm2 = 0;
+			wc->last_rparm1 = 0;
 			wc->cmdq_wndx = 0;
 			wc->cmdq_rndx = 0;
 			wc->seq_num = 6;
 			wc->timeout = 1 * HZ;		/* 1 sec */
+			wc->dsp_crashed = 0;
+			wc->dumping = 0;
 			wc->ztsnd_rtx = 0;
 			wc->ztsnd_0010_rtx = 0;
 			
@@ -1605,6 +1780,7 @@
 			}
 #endif
 			dte_firmware_ver = firmware->data[0];
+			dte_firmware_ver_minor = firmware->data[16];
 			g729_numchannels = firmware->data[1];
 			g723_numchannels = firmware->data[2];
 
@@ -1680,7 +1856,7 @@
 			zt_transcoder_register(uencode);
 			zt_transcoder_register(udecode);
 
-			printk("Zaptel DTE (%s) Transcoder support LOADED (firm ver = %d)\n", wc->complexname, dte_firmware_ver);
+			printk("Zaptel DTE (%s) Transcoder support LOADED (firm ver = %d.%d)\n", wc->complexname, dte_firmware_ver, dte_firmware_ver_minor);
 
 
 			/* Enable bus mastering */
@@ -1719,7 +1895,7 @@
 
 			/* Start DMA */
 			wcdte_start_dma(wc);
-			if (wcdte_boot_processor(wc,firmware)) {
+			if (wcdte_boot_processor(wc,firmware,1)) {
 				if (firmware != &embedded_firmware)
 					release_firmware(firmware);
 
@@ -1734,7 +1910,6 @@
 				vfree(wc);
 				return -EIO;
 			}
-
 			if (wcdte_setup_channels(wc))
 			{
 				/* Set Reset Low */
@@ -1748,12 +1923,17 @@
 				vfree(wc);
 				return -EIO;
 			}
-			
+
 			reg = wcdte_getctl(wc, 0x00fc);
 			if (debug)
 				printk("wcdte debug: (post-boot) Reg fc is %08x\n", reg);
 			
 			printk("Found and successfully installed a Wildcard TC: %s \n", wc->variety);
+			if (debug) {
+				printk("TC400B operating in DEBUG mode\n");
+				printk("debug_des = %d, debug_des_cnt = %d, force_alert = %d,\n debug_notimeout = %d, debug_packets = %d\n", 
+					debug_des, debug_des_cnt, force_alert, debug_notimeout, debug_packets);
+			}
 			res = 0;
 		} else
 			res = -ENOMEM;
@@ -1793,7 +1973,7 @@
 				printk("wcdte debug: de[%d] snt = %d, rcv = %d [%d]\n", i, st_de->packets_sent, st_de->packets_received, st_de->packets_sent - st_de->packets_received);
 			}
 		}
-	
+
 		zt_transcoder_unregister(wc->udecode);
 		zt_transcoder_unregister(wc->uencode);
 		zt_transcoder_free(wc->uencode);
@@ -1856,6 +2036,10 @@
 }
 
 module_param(debug, int, S_IRUGO | S_IWUSR);
+module_param(debug_des, int, S_IRUGO | S_IWUSR);
+module_param(debug_des_cnt, int, S_IRUGO | S_IWUSR);
+module_param(debug_notimeout, int, S_IRUGO | S_IWUSR);
+module_param(force_alert, int, S_IRUGO | S_IWUSR);
 module_param(mode, charp, S_IRUGO | S_IWUSR);
 MODULE_DESCRIPTION("Wildcard TC400P+TC400M Driver");
 MODULE_AUTHOR("John Sloan <jsloan at digium.com>");




More information about the svn-commits mailing list