summaryrefslogtreecommitdiff
path: root/wctc4xxp
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 /wctc4xxp
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
Diffstat (limited to 'wctc4xxp')
-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