summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormattf <mattf@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-11-03 16:10:49 +0000
committermattf <mattf@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-11-03 16:10:49 +0000
commitebfa391bb98078c551439c6357bde687d0c1b6ee (patch)
tree328273077293881028a28bddb870ae5082fc88bd
parentf764bc73f672913f02becc4fc78b777a700d2b20 (diff)
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.
git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.2@3209 5390a7c7-147a-4af0-8ec9-7488f05a26cb
-rw-r--r--wctc4xxp/base.c385
-rw-r--r--wctc4xxp/tc400m-firmware.binbin1400630 -> 1787818 bytes
2 files changed, 285 insertions, 100 deletions
diff --git a/wctc4xxp/base.c b/wctc4xxp/base.c
index 42727d7..0bb4be2 100644
--- a/wctc4xxp/base.c
+++ b/wctc4xxp/base.c
@@ -70,7 +70,7 @@ extern void _binary_tc400m_firmware_bin_size;
#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
@@ -201,6 +201,11 @@ extern void _binary_tc400m_firmware_bin_size;
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, \
@@ -259,12 +264,24 @@ extern void _binary_tc400m_firmware_bin_size;
/* 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) \
({ \
@@ -291,7 +308,18 @@ extern void _binary_tc400m_firmware_bin_size;
} \
__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); \
@@ -329,10 +357,13 @@ struct wcdte {
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;
@@ -396,6 +427,8 @@ struct dte_state {
unsigned int last_dte_seqno;
unsigned int dte_seqno_rcv;
+
+ unsigned char ssrc;
};
@@ -404,12 +437,74 @@ static struct zt_transcoder *udecode;
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 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 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)
@@ -447,6 +542,8 @@ static void dte_init_state(struct dte_state *state_ptr, int encoder, unsigned in
state_ptr->chan_in_num = 999;
state_ptr->chan_out_num = 999;
+
+ state_ptr->ssrc = 0x78;
if (encoder == 1)
{
@@ -548,7 +645,7 @@ static inline int __transmit_demand(struct wcdte *wc)
writechunk += wc->tdbl * SFRAME_SIZE;
o2 = wc->tdbl * 4;
-
+
do
{
} while ((le32_to_cpu(wc->descripchunk[o2]) & 0x80000000));
@@ -605,17 +702,34 @@ static int dte_operation(struct zt_transcoder_channel *ztc, int op)
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;
@@ -626,9 +740,9 @@ static int dte_operation(struct zt_transcoder_channel *ztc, int op)
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;
}
@@ -637,39 +751,24 @@ static int dte_operation(struct zt_transcoder_channel *ztc, int op)
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)) )
@@ -721,7 +820,8 @@ static int dte_operation(struct zt_transcoder_channel *ztc, int op)
((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];
@@ -805,33 +905,34 @@ static inline void wcdte_receiveprep(struct wcdte *wc, int dbl)
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);
+ 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->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);
@@ -842,7 +943,27 @@ static inline void wcdte_receiveprep(struct wcdte *wc, int dbl)
{
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");
}
}
@@ -873,7 +994,12 @@ static inline void wcdte_receiveprep(struct wcdte *wc, int dbl)
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);
@@ -891,7 +1017,12 @@ static inline void wcdte_receiveprep(struct wcdte *wc, int dbl)
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);
@@ -907,7 +1038,7 @@ static inline void wcdte_receiveprep(struct wcdte *wc, int dbl)
} 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;
}
@@ -983,9 +1114,6 @@ static inline void wcdte_receiveprep(struct wcdte *wc, int dbl)
}
-
-
-
/* static inline int wcdte_check_descriptor(struct wcdte *wc) */
static int wcdte_check_descriptor(struct wcdte *wc)
{
@@ -1197,9 +1325,17 @@ static int wcdte_waitfor_csmencaps(struct wcdte *wc, unsigned int mask, int wait
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;
@@ -1214,6 +1350,11 @@ static int wcdte_waitfor_csmencaps(struct wcdte *wc, unsigned int mask, int wait
{
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)
@@ -1290,7 +1431,7 @@ void wcdte_write_phy(struct wcdte *wc, int location, int value)
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;
@@ -1300,12 +1441,12 @@ static int wcdte_boot_processor(struct wcdte *wc, const struct firmware *firmwar
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);
@@ -1315,10 +1456,10 @@ static int wcdte_boot_processor(struct wcdte *wc, const struct firmware *firmwar
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);
@@ -1358,7 +1499,7 @@ static int wcdte_boot_processor(struct wcdte *wc, const struct firmware *firmwar
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);
@@ -1368,6 +1509,12 @@ static int wcdte_boot_processor(struct wcdte *wc, const struct firmware *firmwar
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;
wc->last_command_sent = 0;
@@ -1382,30 +1529,47 @@ static int wcdte_boot_processor(struct wcdte *wc, const struct firmware *firmwar
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)
{
- int length = 0;
unsigned char chan1, chan2;
- struct zt_transcoder_channel *ztc1, *ztc2;
- struct dte_state *st1, *st2;
- if(complicated == DTE_FORMAT_G729A)
- length = G729_LENGTH;
- 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;
+ 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);
- chan2 = wc->last_rparm2;
+ 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;
+ struct zt_transcoder_channel *ztc1, *ztc2;
+ struct dte_state *st1, *st2;
+ if(complicated == DTE_FORMAT_G729A)
+ length = G729_LENGTH;
+ else if (complicated == DTE_FORMAT_G723_1)
+ length = G723_LENGTH;
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);
zt_send_cmd(wc, CMD_MSG_VOIP_VCEOPT(st1->cmd_seqno++, chan1, length, 0), CMD_MSG_VOIP_VCEOPT_LEN, 0x8001);
@@ -1427,14 +1591,20 @@ static int wcdte_create_channel(struct wcdte *wc, int simple, int complicated, i
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;
@@ -1450,16 +1620,13 @@ static int wcdte_destroy_channel(struct wcdte *wc, unsigned int chan1, unsigned
/* 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;
+ return 0;
}
-static int wcdte_setup_channels(struct wcdte *wc)
+
+static int __wcdte_setup_channels(struct wcdte *wc)
{
- down(&wc->chansem);
+ 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);
@@ -1494,9 +1661,16 @@ static int wcdte_setup_channels(struct wcdte *wc)
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)
@@ -1506,7 +1680,7 @@ static int __devinit wcdte_init_one(struct pci_dev *pdev, const struct pci_devic
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;
struct firmware embedded_firmware = {
#if !defined(HOTPLUG_FIRMWARE)
@@ -1556,11 +1730,13 @@ static int __devinit wcdte_init_one(struct pci_dev *pdev, const struct pci_devic
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;
@@ -1604,6 +1780,7 @@ static int __devinit wcdte_init_one(struct pci_dev *pdev, const struct pci_devic
}
#endif
dte_firmware_ver = firmware->data[0];
+ dte_firmware_ver_minor = firmware->data[16];
g729_numchannels = firmware->data[1];
g723_numchannels = firmware->data[2];
@@ -1679,7 +1856,7 @@ static int __devinit wcdte_init_one(struct pci_dev *pdev, const struct pci_devic
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 */
@@ -1718,7 +1895,7 @@ static int __devinit wcdte_init_one(struct pci_dev *pdev, const struct pci_devic
/* 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);
@@ -1733,7 +1910,6 @@ static int __devinit wcdte_init_one(struct pci_dev *pdev, const struct pci_devic
vfree(wc);
return -EIO;
}
-
if (wcdte_setup_channels(wc))
{
/* Set Reset Low */
@@ -1747,12 +1923,17 @@ static int __devinit wcdte_init_one(struct pci_dev *pdev, const struct pci_devic
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;
@@ -1792,7 +1973,7 @@ static void __devexit wcdte_remove_one(struct pci_dev *pdev)
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);
@@ -1855,6 +2036,10 @@ void ztdte_cleanup(void)
}
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@digium.com>");
diff --git a/wctc4xxp/tc400m-firmware.bin b/wctc4xxp/tc400m-firmware.bin
index 2e6c743..2412e28 100644
--- a/wctc4xxp/tc400m-firmware.bin
+++ b/wctc4xxp/tc400m-firmware.bin
Binary files differ