From b730255a7b8f572a2d6d905c128c7a86b75eca2e Mon Sep 17 00:00:00 2001 From: kpfleming Date: Tue, 6 Feb 2007 21:57:38 +0000 Subject: revert transcoder driver to last version that passed PQ testing... improved version will come back once testing has been completed and bugs are found/fixed git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.2@2092 5390a7c7-147a-4af0-8ec9-7488f05a26cb --- wctc4xxp/base.c | 1896 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 997 insertions(+), 899 deletions(-) (limited to 'wctc4xxp/base.c') diff --git a/wctc4xxp/base.c b/wctc4xxp/base.c index f42c577..46fac4d 100644 --- a/wctc4xxp/base.c +++ b/wctc4xxp/base.c @@ -1,10 +1,9 @@ /* - * Wildcard TC400B Interface Driver for Zapata Telephony interface + * Wildcard TC400B Driver * * Written by John Sloan - * and Kevin P. Fleming * - * Copyright (C) 2006-2007, Digium, Inc. + * Copyright (C) 2006, Digium, Inc. * * All rights reserved. * @@ -24,6 +23,7 @@ * */ + #include #include #include @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -42,30 +43,30 @@ #include #include #include -#include - +#ifdef CONFIG_DEVFS_FS +#include +#endif #ifdef STANDALONE_ZAPATA #include "zaptel.h" #else #include #endif -#if defined(HOTPLUG_FIRMWARE) -static const char *tc400m_firmware = "tc400m-firmware.bin"; +#ifdef HOTPLUG_FIRMWARE +static const char *dte_firmware = "tc400m-firmware.bin"; #else extern u8 _binary_tc400m_firmware_bin_start[]; extern void _binary_tc400m_firmware_bin_size; #endif -static struct pci_driver driver; - -#define module_printk(fmt, args...) printk("%s: " fmt, driver.name, ## args) -#define debug_printk(test, fmt, args...) if (debug && (test)) printk("%s (%s): " fmt, driver.name, __FUNCTION__, ## args) /* #define USE_TEST_HW */ #define USE_TDM_CONFIG -#define WC_MAX_IFACES 8 +#define WC_MAX_IFACES 128 + +#define NUM_CARDS 24 +#define NUM_EC 4 /* NUM_CHANNELS must be checked if new firmware (dte_firm.h) is used */ #define NUM_CHANNELS 97 @@ -79,22 +80,30 @@ static struct pci_driver driver; #define G729_LENGTH 20 #define G723_LENGTH 30 -#define G729_SAMPLES 160 -#define G723_SAMPLES 240 +#define G729_SAMPLES 160 /* g.729 */ +#define G723_SAMPLES 240 /* g.723 */ + +#define G729_BYTES 20 /* g.729 */ +#define G723_BYTES 20 /* g.723 */ -#define G729_BYTES 20 -#define G723_BYTES 20 -/* 274 for 30ms ulaw, 194 for 20ms ulaw */ + +#define ACK_SPACE 20 + +#define MAX_COMMANDS (NUM_CHANNELS + ACK_SPACE) +#define MAX_RCV_COMMANDS 16 + +/* 1432 for boot, 274 for 30msec ulaw, 194 for 20mec ulaw */ +#define BOOT_CMD_LEN 1500 #define OTHER_CMD_LEN 300 -#define MAX_COMMAND_LEN OTHER_CMD_LEN +#define MAX_COMMAND_LEN BOOT_CMD_LEN /* Must be the larger of BOOT_CMD_LEN or OTHER_CMD_LEN */ #define ERING_SIZE (NUM_CHANNELS / 2) /* Maximum ring size */ #define SFRAME_SIZE MAX_COMMAND_LEN -#define PCI_WINDOW_SIZE ((2 * 2 * ERING_SIZE * SFRAME_SIZE) + (2 * ERING_SIZE * 4)) +#define PCI_WINDOW_SIZE ((2* 2 * ERING_SIZE * SFRAME_SIZE) + (2 * ERING_SIZE * 4)) #define MDIO_SHIFT_CLK 0x10000 #define MDIO_DATA_WRITE0 0x00000 @@ -108,130 +117,182 @@ static struct pci_driver driver; #define RCV_CSMENCAPS_ACK 3 #define RCV_OTHER 99 + /* TDM Commands */ +#define CMD_MSG_TDM_SELECT_BUS_MODE_LEN 30 #define CMD_MSG_TDM_SELECT_BUS_MODE(s) { \ 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x01, 0x00,0x06,0x17,0x04, 0xFF,0xFF, \ 0x04,0x00 } +#define CMD_MSG_TDM_ENABLE_BUS_LEN 30 #define CMD_MSG_TDM_ENABLE_BUS(s) { \ 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x02, 0x00,0x06,0x05,0x04, 0xFF,0xFF, \ 0x04,0x00 } +#define CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN 34 #define CMD_MSG_SUPVSR_SETUP_TDM_PARMS(s,p1,p2,p3) { \ 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x10, p1, 0x00,0x06,0x07,0x04, 0xFF,0xFF, \ p2,0x83, 0x00,0x0C, 0x00,0x00, p3,0x00 } +#define CMD_MSG_TDM_OPT_LEN 30 #define CMD_MSG_TDM_OPT(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,0x35,0x04, 0xFF,0xFF, \ 0x00,0x00 } +#define CMD_MSG_DEVICE_SET_COUNTRY_CODE_LEN 30 #define CMD_MSG_DEVICE_SET_COUNTRY_CODE(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,0x1B,0x04, 0xFF,0xFF, \ 0x00,0x00 } /* CPU Commands */ +#define CMD_MSG_SET_ARM_CLK_LEN 32 #define CMD_MSG_SET_ARM_CLK(s) { \ 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,0x11,0x04, 0x00,0x00, \ 0x2C,0x01, 0x00,0x00 } +#define CMD_MSG_SET_SPU_CLK_LEN 32 #define CMD_MSG_SET_SPU_CLK(s) { \ 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,0x12,0x04, 0x00,0x00, \ 0x2C,0x01, 0x00,0x00 } +#define CMD_MSG_SPU_FEATURES_CONTROL_LEN 30 #define CMD_MSG_SPU_FEATURES_CONTROL(s,p1) { \ 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,0x13,0x00, 0xFF,0xFF, \ p1,0x00 } +#define CMD_MSG_DEVICE_STATUS_CONFIG_LEN 30 #define CMD_MSG_DEVICE_STATUS_CONFIG(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,0x0F,0x04, 0xFF,0xFF, \ 0x05,0x00 } /* General IP/RTP Commands */ +#define CMD_MSG_SET_ETH_HEADER_LEN 44 #define CMD_MSG_SET_ETH_HEADER(s) { \ 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x18, 0x00, 0x00,0x06,0x00,0x01, 0xFF,0xFF, \ 0x01,0x00, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x00,0x11,0x22,0x33,0x44,0x55, 0x08,0x00 } +#define CMD_MSG_IP_SERVICE_CONFIG_LEN 30 #define CMD_MSG_IP_SERVICE_CONFIG(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,0x02,0x03, 0xFF,0xFF, \ 0x00,0x02 } +#define CMD_MSG_ARP_SERVICE_CONFIG_LEN 30 #define CMD_MSG_ARP_SERVICE_CONFIG(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,0x05,0x01, 0xFF,0xFF, \ 0x01,0x00 } +#define CMD_MSG_ICMP_SERVICE_CONFIG_LEN 30 #define CMD_MSG_ICMP_SERVICE_CONFIG(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,0x04,0x03, 0xFF,0xFF, \ 0x01,0xFF } +#define CMD_MSG_IP_OPTIONS_LEN 30 #define CMD_MSG_IP_OPTIONS(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,0x06,0x03, 0xFF,0xFF, \ 0x02,0x00 } /* Supervisor channel commands */ +#define CMD_MSG_CREATE_CHANNEL_LEN 32 #define CMD_MSG_CREATE_CHANNEL(s,t) { \ 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_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, \ 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x12, 0x00, 0x00,0x06,0x22,0x93, 0x00,0x00, \ e,0x00, (c1&0x00FF),((c1&0xFF00)>>8), f1,0x00, (c2&0x00FF),((c2&0xFF00)>>8), f2,0x00 } +#define CMD_MSG_DESTROY_CHANNEL_LEN 32 #define CMD_MSG_DESTROY_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, 0x00,0x06,0x11,0x00, 0x00,0x00, \ (t&0x00FF),((t&0xFF00)>>8), 0x00, 0x00 } /* Individual channel config commands */ +#define CMD_MSG_SET_IP_HDR_CHANNEL_LEN 58 #define CMD_MSG_SET_IP_HDR_CHANNEL(s,c,t2,t1) { \ 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ 0x00,0x01, s&0x0F, 0x01, ((c&0xFF00) >> 8),(c&0x00FF), 0x26, 0x00, 0x00,0x02,0x00,0x90, 0x00,0x00, \ 0x00,0x00, 0x45,0x00, 0x00,0x00, 0x00,0x00, 0x40,0x00, 0x80,0x11, 0x00,0x00, \ 0xC0,0xA8,0x09,0x03, 0xC0,0xA8,0x09,0x03, \ ((t2&0xFF00)>>8)+0x50,(t2&0x00FF), ((t1&0xFF00)>>8)+0x50,(t1&0x00FF), 0x00,0x00, 0x00,0x00 } +#define CMD_MSG_VOIP_VCEOPT_LEN 40 #define CMD_MSG_VOIP_VCEOPT(s,c,l,w) { \ 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ 0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x12, 0x00, 0x00,0x02,0x01,0x80, 0x00,0x00, \ 0x21,l, 0x00,0x1C, 0x04,0x00, 0x00,0x00, w,0x00, 0x80,0x11 } +#define CMD_MSG_VOIP_VOPENA_LEN 44 #define CMD_MSG_VOIP_VOPENA(s,c,f) { \ 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ 0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x16, 0x00, 0x00,0x02,0x00,0x80, 0x00,0x00, \ 0x01,0x00, 0x80,f, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x12,0x34, 0x56,0x78, 0x00,0x00 } +#define CMD_MSG_VOIP_VOPENA_CLOSE_LEN 32 #define CMD_MSG_VOIP_VOPENA_CLOSE(s,c) { \ 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ 0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x0A, 0x00, 0x00,0x02,0x00,0x80, 0x00,0x00, \ 0x00,0x00, 0x00,0x00 } +#define CMD_MSG_VOIP_INDCTRL_LEN 32 #define CMD_MSG_VOIP_INDCTRL(s,c) {0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ 0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x0A, 0x00, 0x00,0x02,0x84,0x80, 0x00,0x00, \ 0x07,0x00, 0x00,0x00 } /* CPU ACK command */ +#define CMD_MSG_ACK_LEN 20 #define CMD_MSG_ACK(s,c) { \ 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ 0x00,0x01, s, 0xE0, (c&0x00FF), ((c>>8)&0x00FF) } /* 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) { \ 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} + +#define zt_send_cmd(wc, command, length, hex) \ + ({ \ + int ret = 0; \ + do { \ + if (ret == 2) \ + { \ + wc->ztsnd_rtx++; \ + if (hex == 0x0010) \ + wc->ztsnd_0010_rtx++; \ + } \ + down(&wc->cmdqsem); \ + wc->last_command_sent = hex; \ + if ( (((wc->cmdq_wndx + 1) % MAX_COMMANDS) == wc->cmdq_rndx) && debug ) \ + printk("wcdte error: cmdq is full.\n"); \ + else { \ + unsigned char fifo[OTHER_CMD_LEN] = command; \ + int i; \ + wc->cmdq[wc->cmdq_wndx].cmdlen = length; \ + for (i = 0; i < length; i++) \ + wc->cmdq[wc->cmdq_wndx].cmd[i] = fifo[i]; \ + wc->cmdq_wndx = (wc->cmdq_wndx + 1) % MAX_COMMANDS; \ + } \ + __transmit_demand(wc); \ + up(&wc->cmdqsem); \ + ret = wcdte_waitfor_csmencaps(wc, RCV_CSMENCAPS, 0); \ + if (ret == 1) \ + return(1); \ + } while (ret == 2); \ + }) + + struct cmdq { - struct list_head list; - size_t cmdspace; - size_t cmdlen; - u8 cmd[0]; + unsigned int cmdlen; + unsigned int cmd[MAX_COMMAND_LEN]; }; -#define MAX_PACKET_SIZE 1500 -#define MAX_TOTAL_CMDQ 40 - struct wcdte { struct pci_dev *dev; - const char *variety; + char *variety; unsigned int intcount; unsigned int rxints; unsigned int txints; @@ -240,15 +301,16 @@ struct wcdte { int freeregion; int rdbl; int tdbl; + int cards; spinlock_t reglock; wait_queue_head_t regq; int rcvflags; struct semaphore chansem; struct semaphore cmdqsem; - struct list_head pending_cmdq; - struct list_head free_cmdq; - u32 total_cmdq; /* total of all cmdq entries, both pending and free */ + struct cmdq cmdq[MAX_COMMANDS]; + unsigned int cmdq_wndx; + unsigned int cmdq_rndx; unsigned int last_command_sent; unsigned int last_rcommand; @@ -259,16 +321,16 @@ struct wcdte { unsigned int ztsnd_rtx; unsigned int ztsnd_0010_rtx; - unsigned int numchannels; + unsigned char numchannels; unsigned char complexname[40]; unsigned long iobase; - dma_addr_t readdma; - dma_addr_t writedma; - dma_addr_t descripdma; - volatile u8 *writechunk; /* write buffers */ - volatile u8 *readchunk; /* read buffers */ - volatile u32 *descripchunk; /* descriptors */ + dma_addr_t readdma; + dma_addr_t writedma; + dma_addr_t descripdma; + volatile unsigned int *writechunk; /* Double-word aligned write memory */ + volatile unsigned int *readchunk; /* Double-word aligned read memory */ + volatile unsigned int *descripchunk; /* Descriptors */ int wqueints; struct workqueue_struct *dte_wq; @@ -278,27 +340,40 @@ struct wcdte { struct zt_transcoder *udecode; }; +static void dte_wque_run(struct wcdte *wc); + struct wcdte_desc { - const char *name; + char *name; int flags; }; -static const struct wcdte_desc wcdte = { "Wildcard TC400P+TC400M", 0 }; +static struct wcdte_desc wcdte = { "Wildcard TC400P+TC400M", 0 }; static struct wcdte *ifaces[WC_MAX_IFACES]; + + +/* + * The following is the definition of the state structure + * used by the G.721/G.723 encoder and decoder to preserve their internal + * state between successive calls. The meanings of the majority + * of the state structure fields are explained in detail in the + * CCITT Recommendation G.721. The field names are essentially indentical + * to variable names in the bit level description of the coding algorithm + * included in this Recommendation. + */ struct dte_state { - int encoder; + int encoder; /* If we're an encoder */ struct wcdte *wc; unsigned int timestamp; unsigned int seqno; - unsigned int timeslot_in_num; - unsigned int timeslot_out_num; + unsigned int timeslot_in_num; /* DTE chennel on which results we be received from */ + unsigned int timeslot_out_num; /* DTE channel to send data to */ - unsigned int chan_in_num; - unsigned int chan_out_num; + unsigned int chan_in_num; /* DTE chennel on which results we be received from */ + unsigned int chan_out_num; /* DTE channel to send data to */ unsigned int packets_sent; unsigned int packets_received; @@ -307,17 +382,21 @@ struct dte_state { unsigned int dte_seqno_rcv; }; + +static struct zt_transcoder *uencode; +static struct zt_transcoder *udecode; +static struct dte_state *encoders; +static struct dte_state *decoders; static int debug = 0; -static char *mode[2] = { "g729", "g723" }; -static int mode_count = 2; -u32 debug_packets = 0; -u32 debug_cmd_packets = 0; +static char *mode; +int debug_packets = 0; + -static int 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 destroy_channel(struct wcdte *wc, unsigned int chan1, unsigned int chan2); +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_destroy_channel(struct wcdte *wc, unsigned int chan1, unsigned int chan2); /* Sanity check values */ -static inline int sanitycheck(struct zt_transcode_header *zth, unsigned int outbytes) +static inline int zt_tc_sanitycheck(struct zt_transcode_header *zth, unsigned int outbytes) { if (zth->dstoffset >= sizeof(zth->dstdata)) return 0; @@ -336,136 +415,23 @@ static inline int sanitycheck(struct zt_transcode_header *zth, unsigned int outb return 1; } -static void dump_cmdq(struct wcdte *wc) -{ - struct cmdq *cmdq; - - debug_printk(1, "pending_cmdq: "); - list_for_each_entry(cmdq, &wc->pending_cmdq, list) - printk("%p(%zd) ", cmdq, cmdq->cmdspace); - printk("\n"); - - debug_printk(1, "free_cmdq: "); - list_for_each_entry(cmdq, &wc->free_cmdq, list) - printk("%p(%zd) ", cmdq, cmdq->cmdspace); - printk("\n"); -} - -static struct cmdq *get_free_cmdq(struct wcdte *wc, size_t size_needed) -{ - struct cmdq *winner = NULL; - struct cmdq *candidate = NULL; - size_t candidate_size = MAX_PACKET_SIZE; - struct cmdq *smallest_seen = NULL; - size_t smallest_seen_size = MAX_PACKET_SIZE; - struct cmdq *entry; - - size_needed = ((size_needed / 16) + 1) * 16; - - if (size_needed > MAX_PACKET_SIZE) - return NULL; - - list_for_each_entry(entry, &wc->free_cmdq, list) { - if (entry->cmdspace == size_needed) { - winner = entry; - break; - } else if ((entry->cmdspace > size_needed) && - (entry->cmdspace < candidate_size)) { - candidate = entry; - candidate_size = entry->cmdspace; - } else if (entry->cmdspace < smallest_seen_size) { - smallest_seen = entry; - smallest_seen_size = entry->cmdspace; - } - } - - /* at this point, we either have a winner, a candidate, - a potentially freeable too-small entry, or nothing... - deal with the results - */ - - if (winner) { - list_del_init(&winner->list); - return winner; - } else if (candidate) { - list_del_init(&candidate->list); - return candidate; - } else if (wc->total_cmdq < MAX_TOTAL_CMDQ) { - /* we can make a new entry */ - if (debug) - dump_cmdq(wc); - if ((winner = kmalloc(sizeof(*winner) + size_needed, GFP_KERNEL))) { - debug_printk(1, "created a '%zd' byte cmdq entry at '%p'\n", size_needed, winner); - winner->cmdspace = size_needed; - INIT_LIST_HEAD(&winner->list); - } - return winner; - } else if (smallest_seen) { - /* we can't allocate new entries, but we have a - too-small entry we can free and replace */ - if (debug) - dump_cmdq(wc); - list_del(&smallest_seen->list); - kfree(smallest_seen); - if ((winner = kmalloc(sizeof(*winner) + size_needed, GFP_KERNEL))) { - debug_printk(1, "replaced a '%zd' byte cmdq entry at '%p' with a '%zd' byte one at '%p'\n", smallest_seen_size, smallest_seen, size_needed, winner); - winner->cmdspace = size_needed; - INIT_LIST_HEAD(&winner->list); - } - return winner; - } else { - /* we failed */ - module_printk("no cmdq entries available; limit of %d reached\n", MAX_TOTAL_CMDQ); - return NULL; - } -} - -static int queue_cmd(struct wcdte *wc, u8 *data, size_t length) -{ - struct cmdq *cmdq = get_free_cmdq(wc, length); - - if (!cmdq) - return -1; - - cmdq->cmdlen = length; - memcpy(cmdq->cmd, data, length); - list_add_tail(&cmdq->list, &wc->pending_cmdq); - - return 0; -} - -#define send_cmd(wc, command, length, hex) \ - ({ \ - int ret = 0; \ - u8 fifo[] = command; \ - do { \ - if (ret == 2) { \ - wc->ztsnd_rtx++; \ - if (hex == 0x0010) \ - wc->ztsnd_0010_rtx++; \ - } \ - down(&wc->cmdqsem); \ - queue_cmd(wc, fifo, sizeof(fifo)); \ - wc->last_command_sent = hex; \ - __transmit_demand(wc); \ - up(&wc->cmdqsem); \ - ret = waitfor_csmencaps(wc, RCV_CSMENCAPS, 0); \ - if (ret == 1) \ - return 1; \ - } while (ret == 2); \ - }) - static void dte_init_state(struct dte_state *state_ptr, int encoder, unsigned int channel, struct wcdte *wc) { - memset(state_ptr, 0, sizeof(*state_ptr)); - state_ptr->encoder = encoder; state_ptr->wc = wc; + state_ptr->timestamp = 0; + state_ptr->seqno = 0; + + state_ptr->packets_sent = 0; + state_ptr->packets_received = 0; + state_ptr->last_dte_seqno = 0; + state_ptr->dte_seqno_rcv = 0; state_ptr->chan_in_num = 999; state_ptr->chan_out_num = 999; - if (encoder) { + if (encoder == 1) + { state_ptr->timeslot_in_num = channel * 2; state_ptr->timeslot_out_num = channel * 2 + 1; } else { @@ -474,141 +440,138 @@ static void dte_init_state(struct dte_state *state_ptr, int encoder, unsigned in } } -static inline unsigned int zapfmt_to_dtefmt(unsigned int fmt) +static unsigned int wcdte_zapfmt_to_dtefmt(unsigned int fmt) { - switch (fmt) { - case ZT_FORMAT_G723_1: - return DTE_FORMAT_G723_1; - case ZT_FORMAT_ULAW: - return DTE_FORMAT_ULAW; - case ZT_FORMAT_ALAW: - return DTE_FORMAT_ALAW; - case ZT_FORMAT_G729A: - return DTE_FORMAT_G729A; - default: - return DTE_FORMAT_UNDEF; + unsigned int pt; + + switch(fmt) + { + case ZT_FORMAT_G723_1: + pt = DTE_FORMAT_G723_1; + break; + case ZT_FORMAT_ULAW: + pt = DTE_FORMAT_ULAW; + break; + case ZT_FORMAT_ALAW: + pt = DTE_FORMAT_ALAW; + break; + case ZT_FORMAT_G729A: + pt = DTE_FORMAT_G729A; + break; + default: + pt = DTE_FORMAT_UNDEF; } + + return(pt); } -static inline void __setctl(struct wcdte *wc, unsigned int addr, unsigned int val) +static inline void __wcdte_setctl(struct wcdte *wc, unsigned int addr, unsigned int val) { outl(val, wc->iobase + addr); } -static inline unsigned int __getctl(struct wcdte *wc, unsigned int addr) +static inline unsigned int __wcdte_getctl(struct wcdte *wc, unsigned int addr) { return inl(wc->iobase + addr); } -static inline void setctl(struct wcdte *wc, unsigned int addr, unsigned int val) -{ - unsigned long flags; - - spin_lock_irqsave(&wc->reglock, flags); - __setctl(wc, addr, val); - spin_unlock_irqrestore(&wc->reglock, flags); -} - -static inline unsigned int getctl(struct wcdte *wc, unsigned int addr) +static inline void wcdte_setctl(struct wcdte *wc, unsigned int addr, unsigned int val) { unsigned long flags; - unsigned int val; - spin_lock_irqsave(&wc->reglock, flags); - val = __getctl(wc, addr); + __wcdte_setctl(wc, addr, val); spin_unlock_irqrestore(&wc->reglock, flags); - - return val; } -static inline void reinit_descriptor(struct wcdte *wc, int tx, int dbl, char *s) +static inline void wcdte_reinit_descriptor(struct wcdte *wc, int tx, int dbl, char *s) { - unsigned int o2; - - o2 = dbl * 4; + int o2 = 0; + o2 += dbl * 4; if (!tx) o2 += ERING_SIZE * 4; wc->descripchunk[o2] = cpu_to_le32(0x80000000); - setctl(wc, 0x0008, 0x00000000); + wcdte_setctl(wc, 0x0008, 0x00000000); } -static inline void __transmit_one(struct wcdte *wc, u8 *data, size_t length) +static inline unsigned int wcdte_getctl(struct wcdte *wc, unsigned int addr) { - u32 o2 = wc->tdbl * 4; - volatile u8 *writechunk = (volatile u8 *) wc->writechunk + (wc->tdbl * SFRAME_SIZE); - size_t xmt_length; - - /* Yes... this is a busy loop, that is not interruptible. However, it is - highly unlikely (and testing proves) that the wait for a descriptor - to become available will ever be long enough for this to be an issue. - */ - do {} while ((le32_to_cpu(wc->descripchunk[o2]) & 0x80000000)); - - xmt_length = max(length, (size_t) 64); - - wc->descripchunk[o2 + 1] = cpu_to_le32((le32_to_cpu(wc->descripchunk[o2 + 1]) & 0xFBFFF800) | xmt_length); - - memcpy((void *) writechunk, data, length); - if (length < xmt_length) - memset((void *) writechunk + length, 0, xmt_length - length); - - wc->descripchunk[o2] = cpu_to_le32(0x80000000); - setctl(wc, 0x0008, 0x00000000); /* Transmit Poll Demand */ - - wc->tdbl = (wc->tdbl + 1) % ERING_SIZE; + unsigned long flags; + unsigned int val; + spin_lock_irqsave(&wc->reglock, flags); + val = __wcdte_getctl(wc, addr); + spin_unlock_irqrestore(&wc->reglock, flags); + return val; } static inline int __transmit_demand(struct wcdte *wc) { - int i; - unsigned int reg; - struct cmdq *cmdq; + volatile unsigned char *writechunk; + int o2,i,j; + unsigned int reg, xmt_length; - reg = getctl(wc, 0x0028) & 0x00700000; + reg = wcdte_getctl(wc, 0x0028) & 0x00700000; + /* Already transmiting, no need to demand another */ + if (!((reg == 0) || (reg = 6))) + return(1); + /* Nothing to transmit */ - if (list_empty(&wc->pending_cmdq)) - return 1; + if (wc->cmdq_rndx == wc->cmdq_wndx) + return(1); - /* pop the first entry off the list */ - cmdq = list_entry(wc->pending_cmdq.next, struct cmdq, list); - list_del_init(&cmdq->list); + /* Nothing to transmit */ + if (wc->cmdq[wc->cmdq_rndx].cmdlen == 0 ) + return(1); - debug_printk(1, "transmitting command at '%p' of '%zd' bytes\n", cmdq, cmdq->cmdlen); + writechunk = (volatile unsigned char *)(wc->writechunk); - __transmit_one(wc, cmdq->cmd, cmdq->cmdlen); + writechunk += wc->tdbl * SFRAME_SIZE; - if (debug_packets) { - debug_printk(1, "TX: "); - for (i = 0; i < min((size_t) debug_packets, cmdq->cmdlen); i++) - printk("%02X ", cmdq->cmd[i]); - printk("\n"); - } + o2 = wc->tdbl * 4; + + do + { + } while ((le32_to_cpu(wc->descripchunk[o2]) & 0x80000000)); - if (debug_cmd_packets && - (cmdq->cmd[12] == 0x88) && - (cmdq->cmd[13] == 0x9B)) { - debug_printk(1, "TX: "); - for (i = 0; i < min((size_t) debug_cmd_packets, cmdq->cmdlen); i++) - printk("%02X ", cmdq->cmd[i]); + xmt_length = wc->cmdq[wc->cmdq_rndx].cmdlen; + if (xmt_length < 64) + xmt_length = 64; + + wc->descripchunk[o2+1] = cpu_to_le32((le32_to_cpu(wc->descripchunk[o2+1]) & 0xFBFFF800) | xmt_length); + + for(i = 0; i < wc->cmdq[wc->cmdq_rndx].cmdlen; i++) + writechunk[i] = wc->cmdq[wc->cmdq_rndx].cmd[i]; + for (j = i; j < xmt_length; j++) + writechunk[j] = 0; + + if (debug_packets && (writechunk[12] == 0x88) && (writechunk[13] == 0x9B)) + { + printk("wcdte debug: TX: "); + for (i=0; ilist, &wc->free_cmdq); + wc->cmdq[wc->cmdq_rndx].cmdlen = 0; - return 0; + wc->descripchunk[o2] = cpu_to_le32(0x80000000); + wcdte_setctl(wc, 0x0008, 0x00000000); /* Transmit Poll Demand */ + + wc->tdbl = (wc->tdbl + 1) % ERING_SIZE; + + wc->cmdq_rndx = (wc->cmdq_rndx + 1) % MAX_COMMANDS; + + return(0); } static inline int transmit_demand(struct wcdte *wc) { int val; - down(&wc->cmdqsem); val = __transmit_demand(wc); up(&wc->cmdqsem); - return val; } @@ -621,61 +584,63 @@ static int dte_operation(struct zt_transcoder_channel *ztc, int op) unsigned char *chars; unsigned int inbytes = 0; unsigned int timestamp_inc = 0; + int i = 0; int res = 0; - u32 ipchksum; - - switch (op) { + unsigned int ipchksum, ndx; + switch(op) { case ZT_TCOP_ALLOCATE: - if (ztc->flags.chan_built) - break; down(&wc->chansem); - if (st->encoder) - create_channel(wc, zapfmt_to_dtefmt(zth->srcfmt), zapfmt_to_dtefmt(zth->dstfmt), - st->timeslot_in_num, st->timeslot_out_num, &(st->chan_in_num), - &(st->chan_out_num)); - else - create_channel(wc, zapfmt_to_dtefmt(zth->dstfmt), zapfmt_to_dtefmt(zth->srcfmt), - st->timeslot_out_num, st->timeslot_in_num, &(st->chan_out_num), - &(st->chan_in_num)); - /* Mark this channel as built */ - ztc->flags.chan_built = 1; - ztc->built_fmts = zth->dstfmt | zth->srcfmt; - - /* Mark the channel complement (other half of encoder/decoder pair) as built */ - if (st->encoder) - compl_ztc = &(wc->udecode->channels[st->timeslot_in_num >> 1]); - else - compl_ztc = &(wc->uencode->channels[st->timeslot_in_num >> 1]); - compl_ztc->flags.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; + 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)); + /* Mark this channel as built */ + ztc->chan_built = 1; + ztc->built_fmts = zth->dstfmt | zth->srcfmt; + + /* Mark the channel complement (other half of encoder/decoder pair) as built */ + ndx = st->timeslot_in_num/2; + if (st->encoder == 1) + compl_ztc = &(wc->udecode->channels[ndx]); + else + compl_ztc = &(wc->uencode->channels[ndx]); + 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; + } up(&wc->chansem); break; case ZT_TCOP_RELEASE: down(&wc->chansem); + ndx = st->timeslot_in_num/2; - if (st->encoder) - compl_ztc = &(wc->udecode->channels[st->timeslot_in_num >> 1]); + if (st->encoder == 1) + compl_ztc = &(wc->udecode->channels[ndx]); else - compl_ztc = &(wc->uencode->channels[st->timeslot_in_num >> 1]); + 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.busy) { - if (st->encoder) - destroy_channel(wc, st->chan_in_num, st->chan_out_num); + 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 - destroy_channel(wc, st->chan_out_num, st->chan_in_num); + wcdte_destroy_channel(wc, st->chan_out_num, st->chan_in_num); /* Mark this channel as not built */ - ztc->flags.chan_built = 0; + 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->flags.chan_built = 0; + compl_ztc->chan_built = 0; compl_ztc->built_fmts = 0; compl_st = compl_ztc->pvt; compl_st->chan_in_num = 999; @@ -685,66 +650,61 @@ static int dte_operation(struct zt_transcoder_channel *ztc, int op) up(&wc->chansem); break; case ZT_TCOP_TRANSCODE: - 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))) { - struct cmdq *cmdq; - - do { - chars = (u8 *)(zth->srcdata + zth->srcoffset); - - switch (zth->srcfmt) { - case ZT_FORMAT_ULAW: - case ZT_FORMAT_ALAW: - switch (zth->dstfmt) { - case ZT_FORMAT_G729A: - inbytes = G729_SAMPLES; - timestamp_inc = G729_SAMPLES; - break; - case ZT_FORMAT_G723_1: - inbytes = G723_SAMPLES; - timestamp_inc = G723_SAMPLES; - break; + 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)) ) + { + do + { + chars = (unsigned char *)(zth->srcdata + zth->srcoffset); + + if ((zth->srcfmt == ZT_FORMAT_ULAW) || (zth->srcfmt == ZT_FORMAT_ALAW)) + { + if (zth->dstfmt == ZT_FORMAT_G729A) { + inbytes = G729_SAMPLES; + timestamp_inc = G729_SAMPLES; + } else if (zth->dstfmt == ZT_FORMAT_G723_1) { + inbytes = G723_SAMPLES; + timestamp_inc = G723_SAMPLES; } - break; - case ZT_FORMAT_G729A: + + } else if (zth->srcfmt == ZT_FORMAT_G729A) + { inbytes = G729_BYTES; timestamp_inc = G729_SAMPLES; - break; - case ZT_FORMAT_G723_1: + } else if (zth->srcfmt == ZT_FORMAT_G723_1) + { inbytes = G723_BYTES; timestamp_inc = G723_SAMPLES; - break; } zth->srclen -= inbytes; - + { - u8 fifo[] = CMD_MSG_IP_UDP_RTP( - ((inbytes+40) >> 8) & 0xFF, - (inbytes+40) & 0xFF, - st->seqno & 0xFF, - 0x00, - 0x00, + unsigned char fifo[OTHER_CMD_LEN] = CMD_MSG_IP_UDP_RTP( + ((inbytes+40) >> 8) & 0xFF, + (inbytes+40) & 0xFF, + st->seqno & 0xFF, + 0x00, + 0x00, (((st->timeslot_out_num) >> 8)+0x50) & 0xFF, - (st->timeslot_out_num) & 0xFF, + (st->timeslot_out_num) & 0xFF, (((st->timeslot_in_num) >> 8)+0x50) & 0xFF, - (st->timeslot_in_num) & 0xFF, - ((inbytes+20) >> 8) & 0xFF, - (inbytes+20) & 0xFF, - 0x00, - 0x00, - zapfmt_to_dtefmt(zth->srcfmt), - ((st->seqno) >> 8) & 0xFF, - (st->seqno) & 0xFF, - ((st->timestamp) >> 24) & 0xFF, - ((st->timestamp) >> 16) & 0xFF, - ((st->timestamp) >> 8) & 0xFF, - (st->timestamp) & 0xFF); - - ipchksum = 0x9869 + (fifo[16] << 8) + fifo[17] + (fifo[18] << 8) + fifo[19]; + (st->timeslot_in_num) & 0xFF, + ((inbytes+20) >> 8) & 0xFF, + (inbytes+20) & 0xFF, + 0x00, + 0x00, + wcdte_zapfmt_to_dtefmt(zth->srcfmt), + ((st->seqno) >> 8) & 0xFF, + (st->seqno) & 0xFF, + ((st->timestamp) >> 24) & 0xFF, + ((st->timestamp) >> 16) & 0xFF, + ((st->timestamp) >> 8) & 0xFF, + (st->timestamp) & 0xFF); + + ipchksum = 0x9869 + (fifo[16] << 8) + fifo[17] + + (fifo[18] << 8) + fifo[19]; while (ipchksum >> 16) ipchksum = (ipchksum & 0xFFFF) + (ipchksum >> 16); ipchksum = (~ipchksum) & 0xFFFF; @@ -755,198 +715,273 @@ static int dte_operation(struct zt_transcoder_channel *ztc, int op) st->seqno += 1; st->timestamp += timestamp_inc; - down(&wc->cmdqsem); + for (i = 0; i < inbytes; i++) + fifo[i+CMD_MSG_IP_UDP_RTP_LEN]= chars[i]; - if (!(cmdq = get_free_cmdq(wc, sizeof(fifo) + inbytes))) { - up(&wc->cmdqsem); - res = -EIO; - break; - } + down(&wc->cmdqsem); - memcpy(cmdq->cmd, fifo, sizeof(fifo)); - memcpy(cmdq->cmd + sizeof(fifo), chars, inbytes); - cmdq->cmdlen = sizeof(fifo) + inbytes; - list_add_tail(&cmdq->list, &wc->pending_cmdq); + if ( (((wc->cmdq_wndx + 1) % MAX_COMMANDS) == wc->cmdq_rndx) && debug ) + printk("wcdte error: cmdq is full.\n"); + else + { + wc->cmdq[wc->cmdq_wndx].cmdlen = CMD_MSG_IP_UDP_RTP_LEN+inbytes; + for (i = 0; i < CMD_MSG_IP_UDP_RTP_LEN+inbytes; i++) + wc->cmdq[wc->cmdq_wndx].cmd[i] = fifo[i]; + wc->cmdq_wndx = (wc->cmdq_wndx + 1) % MAX_COMMANDS; + } + __transmit_demand(wc); up(&wc->cmdqsem); - st->packets_sent++; - zth->srcoffset += inbytes; } - } while ((((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))); + st->packets_sent++; + + + + zth->srcoffset += inbytes; + + + } while ((((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)) ); + } else { zt_transcoder_alert(ztc); - res = -EINVAL; } + res = 0; break; } - return res; } -static void stop_dma(struct wcdte *wc); +static void wcdte_stop_dma(struct wcdte *wc); -static inline void receiveprep(struct wcdte *wc, int dbl) +static inline void wcdte_receiveprep(struct wcdte *wc, int dbl) { - volatile u8 *readchunk = wc->readchunk + (dbl * SFRAME_SIZE); + volatile unsigned char *readchunk; struct zt_transcoder_channel *ztc = NULL; struct zt_transcode_header *zth = NULL; struct dte_state *st = NULL; - int o2, i; + int o2,i; unsigned char rseq, rcodec; unsigned int rcommand, rchannel, rlen, rtp_rseq, rtp_eseq; - u8 *chars = NULL; + unsigned char *chars = NULL; unsigned int ztc_ndx; + readchunk = (volatile unsigned char *)wc->readchunk; + readchunk += dbl * SFRAME_SIZE; + o2 = dbl * 4; o2 += ERING_SIZE * 4; - if (debug_packets) { - debug_printk(1, "RX: "); - for (i = 0; i < debug_packets; i++) - printk("%02X ", readchunk[i]); - printk("\n"); - } - - if ((readchunk[12] == 0x88) && (readchunk[13] == 0x9B)) { - /* Control in packet */ - if (debug_cmd_packets) { - debug_printk(1, "RX: "); - for (i = 0; i < debug_cmd_packets; i++) + /* Control in packet */ + if ((readchunk[12] == 0x88) && (readchunk[13] == 0x9B)) + { + if (debug_packets) + { + printk("wcdte debug: RX: "); + for (i=0; icmdqsem); - queue_cmd(wc, fifo, sizeof(fifo)); - __transmit_demand(wc); - wc->rcvflags = RCV_CSMENCAPS; - wc->last_rcommand = rcommand; - wc->last_rparm2 = readchunk[30] | (readchunk[31] << 8); - wake_up_interruptible(&wc->regq); - up(&wc->cmdqsem); + 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; } - } else { + + __transmit_demand(wc); + + + wc->rcvflags = RCV_CSMENCAPS; + wc->last_rcommand = rcommand; + wc->last_rparm2 = readchunk[30] | (readchunk[31] << 8); + wake_up_interruptible(&wc->regq); + up(&wc->cmdqsem); + } + else + { wc->rcvflags = RCV_CSMENCAPS_ACK; wake_up_interruptible(&wc->regq); } - } else if ((readchunk[12] == 0x08) && (readchunk[13] == 0x00) && - (readchunk[50] == 0x12) && (readchunk[51] == 0x34) && - (readchunk[52] = 0x56) && (readchunk[53] == 0x78)) { - /* IP/UDP in packet */ + } + + /* IP/UDP in packet */ + else if ((readchunk[12] == 0x08) && (readchunk[13] == 0x00) + && (readchunk[50] == 0x12) && (readchunk[51] == 0x34) && (readchunk[52] = 0x56) && (readchunk[53] == 0x78)) + { rchannel = (readchunk[37] | (readchunk[36] << 8)) - 0x5000; rlen = (readchunk[39] | (readchunk[38] << 8)) - 20; rtp_rseq = (readchunk[45] | (readchunk[44] << 8)); rcodec = readchunk[43]; - ztc_ndx = rchannel >> 1; + ztc_ndx = rchannel/2; - if (ztc_ndx >= wc->numchannels) { - debug_printk(1, "Invalid channel number received (ztc_ndx = %d) (numchannels = %d)\n", ztc_ndx, wc->numchannels); + if (ztc_ndx >= wc->numchannels) + { + if (debug) + printk("wcdte error: Invalid channel number received (ztc_ndx = %d) (numchannels = %d)\n", ztc_ndx, wc->numchannels); rcodec = DTE_FORMAT_UNDEF; } - switch (rcodec) { - case 0x00: /* ulaw */ - case 0x08: /* alaw */ + if ((rcodec == 0x00) || (rcodec == 0x08)) /* ulaw or alaw (decoders) */ + { ztc = &(wc->udecode->channels[ztc_ndx]); - break; - case 0x04: /* g.723.1 */ - case 0x12: /* g.729 */ - ztc = &(wc->uencode->channels[ztc_ndx]); - break; - } + zth = ztc->tch; + st = ztc->pvt; - zth = ztc->tch; - st = ztc->pvt; + if (zth == NULL) + { + if (debug) + printk("wcdte error: Tried to put DTE data into a freed zth header!\n"); + rcodec = DTE_FORMAT_UNDEF; + } else { + chars = (unsigned char *)(zth->dstdata + zth->dstoffset + zth->dstlen); + st->packets_received++; + } + + } - if (!zth) { - debug_printk(1, "Tried to put data into a freed zth header\n"); - rcodec = DTE_FORMAT_UNDEF; - } else { - chars = (u8 *)(zth->dstdata + zth->dstoffset + zth->dstlen); - st->packets_received++; + if ((rcodec == 0x04) || (rcodec == 0x12)) /* g.723 or g.729 (encoders) */ + { + ztc = &(wc->uencode->channels[ztc_ndx]); + zth = ztc->tch; + st = ztc->pvt; + + if (zth == NULL) + { + if (debug) + printk("wcdte error: Tried to put DTE data into a freed zth header!\n"); + rcodec = DTE_FORMAT_UNDEF; + } else { + chars = (unsigned char *)(zth->dstdata + zth->dstoffset + zth->dstlen); + st->packets_received++; + } + } - if (st->dte_seqno_rcv == 0) { + if (st->dte_seqno_rcv == 0) + { st->dte_seqno_rcv = 1; st->last_dte_seqno = rtp_rseq; } else { rtp_eseq = (st->last_dte_seqno + 1) & 0xFFFF; - debug_printk(rtp_rseq != rtp_eseq, "Bad seqno from module [%d][%d][%d]\n", rchannel, rtp_rseq, st->last_dte_seqno); + if ( (rtp_rseq != rtp_eseq) && debug ) + printk("wcdte error: Bad seqno from DTE! [%d][%d][%d]\n", rchannel, rtp_rseq, st->last_dte_seqno); + st->last_dte_seqno = rtp_rseq; } - switch (rcodec) { - case 0x00: /* ulaw */ - case 0x08: /* alaw */ - if (sanitycheck(zth, rlen) && - ((zth->srcfmt == ZT_FORMAT_G729A && rlen == G729_SAMPLES) || - (zth->srcfmt == ZT_FORMAT_G723_1 && rlen == G723_SAMPLES))) { - memcpy(chars, (void *) readchunk + 54, rlen); + if (rcodec == 0x00) /* ulaw */ + { + if (zt_tc_sanitycheck(zth, rlen) && ((zth->srcfmt == ZT_FORMAT_G729A && rlen == G729_SAMPLES) || (zth->srcfmt == ZT_FORMAT_G723_1 && rlen == G723_SAMPLES))) { + for (i = 0; i < rlen; i++) + chars[i] = readchunk[i+54]; + zth->dstlen += rlen; zth->dstsamples = zth->dstlen; + } else { ztc->errorstatus = -EOVERFLOW; } zt_transcoder_alert(ztc); - break; - case 0x04: /* g.723.1 */ - if (sanitycheck(zth, rlen) && (rlen == G723_BYTES)) { - memcpy(chars, (void *) readchunk + 54, rlen); + } + else if (rcodec == 0x08) /* alaw */ + { + if (zt_tc_sanitycheck(zth, rlen) && ((zth->srcfmt == ZT_FORMAT_G729A && rlen == G729_SAMPLES) || (zth->srcfmt == ZT_FORMAT_G723_1 && rlen == G723_SAMPLES))) { + + for (i = 0; i < rlen; i++) + chars[i] = readchunk[i+54]; + + zth->dstlen += rlen; + zth->dstsamples = zth->dstlen; + + } else { + ztc->errorstatus = -EOVERFLOW; + } + zt_transcoder_alert(ztc); + } + else if (rcodec == 0x04) /* g.723.1 */ + { + if (zt_tc_sanitycheck(zth, rlen) && (rlen == G723_BYTES)) + { + for (i = 0; i < rlen; i++) + chars[i] = readchunk[i+54]; + zth->dstlen += rlen; zth->dstsamples = zth->dstlen * 12; + } else { ztc->errorstatus = -EOVERFLOW; } - if ((zth->dstsamples % G723_SAMPLES) == 0) + + if (!(zth->dstsamples % G723_SAMPLES)) + { zt_transcoder_alert(ztc); - break; - case 0x12: /* g.729 */ - if (sanitycheck(zth, rlen) && (rlen == G729_BYTES)) { - memcpy(chars, (void *) readchunk + 54, rlen); + } + } + else if (rcodec == 0x12) /* g.729a */ + { + if (zt_tc_sanitycheck(zth, rlen) && (rlen == G729_BYTES)) + { + for (i = 0; i < rlen; i++) + chars[i] = readchunk[i+54]; + zth->dstlen += rlen; zth->dstsamples = zth->dstlen * 8; + } else { ztc->errorstatus = -EOVERFLOW; } - if ((zth->dstsamples % G729_SAMPLES) == 0) + if (!(zth->dstsamples % G729_SAMPLES)) + { zt_transcoder_alert(ztc); + } } } } -static int check_descriptor(struct wcdte *wc) + + + + +/* static inline int wcdte_check_descriptor(struct wcdte *wc) */ +static int wcdte_check_descriptor(struct wcdte *wc) { - int o2 = (ERING_SIZE * 4) + (wc->rdbl * 4); + int o2 = 0; + + o2 += ERING_SIZE * 4; + o2 += wc->rdbl * 4; if (!(le32_to_cpu(wc->descripchunk[o2]) & 0x80000000)) { wc->rxints++; - receiveprep(wc, wc->rdbl); - reinit_descriptor(wc, 0, wc->rdbl, "rxchk"); + wcdte_receiveprep(wc, wc->rdbl); + wcdte_reinit_descriptor(wc, 0, wc->rdbl, "rxchk"); wc->rdbl = (wc->rdbl + 1) % ERING_SIZE; return 1; } - return 0; } -static void init_descriptors(struct wcdte *wc) +static void wcdte_init_descriptors(struct wcdte *wc) { - volatile u32 *descrip; + volatile unsigned int *descrip; dma_addr_t descripdma; dma_addr_t writedma; dma_addr_t readdma; @@ -957,23 +992,23 @@ static void init_descriptors(struct wcdte *wc) writedma = wc->writedma; readdma = wc->readdma; - for (x = 0; x < ERING_SIZE; x++) { + for (x=0;xdescripdma; /* Transmit descriptor */ - descrip[0] = cpu_to_le32(0x00000000); - descrip[1] = cpu_to_le32(0xe5800000 | (SFRAME_SIZE)); - descrip[2] = cpu_to_le32(writedma + x * SFRAME_SIZE); - descrip[3] = cpu_to_le32(descripdma); + descrip[0 ] = cpu_to_le32(0x00000000); + descrip[1 ] = cpu_to_le32(0xe5800000 | (SFRAME_SIZE)); + descrip[2 ] = cpu_to_le32(writedma + x*SFRAME_SIZE); + descrip[3 ] = cpu_to_le32(descripdma); /* Receive descriptor */ descrip[0 + ERING_SIZE * 4] = cpu_to_le32(0x80000000); descrip[1 + ERING_SIZE * 4] = cpu_to_le32(0x01000000 | (SFRAME_SIZE)); - descrip[2 + ERING_SIZE * 4] = cpu_to_le32(readdma + (x * SFRAME_SIZE)); - descrip[3 + ERING_SIZE * 4] = cpu_to_le32(descripdma + (ERING_SIZE * 16)); + descrip[2 + ERING_SIZE * 4] = cpu_to_le32(readdma + x*SFRAME_SIZE); + descrip[3 + ERING_SIZE * 4] = cpu_to_le32(descripdma + ERING_SIZE * 16); /* Advance descriptor */ descrip += 4; @@ -986,27 +1021,31 @@ static void dte_wque_run(struct wcdte *wc) if (wc->wqueints & 0x00000040) { /* Loop descriptors is available */ - do {} while ((res = check_descriptor(wc))); + do { + res = wcdte_check_descriptor(wc); + } while(res); } /* Handle TX interrupts */ - if (wc->wqueints & 0x00000001) { + if (wc->wqueints & 0x00000001) + { wc->txints++; transmit_demand(wc); wc->intcount++; } } -ZAP_IRQ_HANDLER(interrupt_handler) +ZAP_IRQ_HANDLER(wcdte_interrupt) { struct wcdte *wc = dev_id; unsigned int ints; - if (!(ints = getctl(wc, 0x0028))) - return IRQ_NONE; - - setctl(wc, 0x0028, ints); + /* Read and clear interrupts */ + ints = wcdte_getctl(wc, 0x0028); + wcdte_setctl(wc, 0x0028, ints); + if (!ints) + return IRQ_NONE; ints &= wc->intmask; if (ints & 0x00000041) { @@ -1014,122 +1053,147 @@ ZAP_IRQ_HANDLER(interrupt_handler) queue_work(wc->dte_wq, &wc->dte_work); } - if (!debug) - return IRQ_RETVAL(1); + if ((ints & 0x00008000) && debug) + printk("wcdte: Abnormal Interrupt: "); + + if ((ints & 0x00002000) && debug) + printk("wcdte: Fatal Bus Error INT\n"); + + if ((ints & 0x00000100) && debug) + printk("wcdte: Receive Stopped INT\n"); + + if ((ints & 0x00000080) && debug) + printk("wcdte: Receive Desciptor Unavailable INT\n"); + + if ((ints & 0x00000020) && debug) + printk("wcdte: Transmit Under-flow INT\n"); + + if ((ints & 0x00000008) && debug) + printk("wcdte: Jabber Timer Time-out INT\n"); - debug_printk(ints & 0x00008000, "Abnormal Interrupt\n"); - debug_printk(ints & 0x00002000, "Fatal Bus Error\n"); - debug_printk(ints & 0x00000100, "Receive Stopped\n"); - debug_printk(ints & 0x00000080, "Receive Desciptor Unavailable\n"); - debug_printk(ints & 0x00000020, "Transmit Under-flow\n"); - debug_printk(ints & 0x00000008, "Jabber Timer Time-out\n"); - debug_printk(ints & 0x00000004, "Transmit Descriptor Unavailable\n"); - debug_printk(ints & 0x00000002, "Transmit Processor Stopped\n"); + if ((ints & 0x00000004) && debug) + printk("wcdte: Transmit Descriptor Unavailable INT\n"); + + if ((ints & 0x00000002) && debug) + printk("wcdte: Transmit Processor Stopped INT\n"); return IRQ_RETVAL(1); + } - -static int hardware_init(struct wcdte *wc) +static int wcdte_hardware_init(struct wcdte *wc) { /* Hardware stuff */ unsigned int reg; unsigned long newjiffies; /* Initialize descriptors */ - init_descriptors(wc); + wcdte_init_descriptors(wc); /* Enable I/O Access */ pci_read_config_dword(wc->dev, 0x0004, ®); reg |= 0x00000007; pci_write_config_dword(wc->dev, 0x0004, reg); - setctl(wc, 0x0000, 0xFFF88001); + wcdte_setctl(wc, 0x0000, 0xFFF88001); newjiffies = jiffies + HZ/10; - while (((reg = getctl(wc, 0x0000)) & 0x00000001) && (newjiffies > jiffies)); + while(((reg = wcdte_getctl(wc,0x0000)) & 0x00000001) && (newjiffies > jiffies)); + /* Configure watchdogs, access, etc */ - setctl(wc, 0x0030, 0x00280048); - setctl(wc, 0x0078, 0x00000013 /* | (1 << 28) */); + wcdte_setctl(wc, 0x0030, 0x00280048); + wcdte_setctl(wc, 0x0078, 0x00000013 /* | (1 << 28) */); - reg = getctl(wc, 0x00fc); - setctl(wc, 0x00fc, (reg & ~0x7) | 0x7); + reg = wcdte_getctl(wc, 0x00fc); + wcdte_setctl(wc, 0x00fc, (reg & ~0x7) | 0x7); - reg = getctl(wc, 0x00fc); + reg = wcdte_getctl(wc, 0x00fc); return 0; } -static inline void setintmask(struct wcdte *wc, unsigned int intmask) +static void wcdte_setintmask(struct wcdte *wc, unsigned int intmask) { wc->intmask = intmask; - setctl(wc, 0x0038, intmask); + wcdte_setctl(wc, 0x0038, intmask); } -static inline void enable_interrupts(struct wcdte *wc) +static void wcdte_enable_interrupts(struct wcdte *wc) { - setintmask(wc, !debug ? 0x00010041 : 0x0001A1EB); + /* Enable interrupts */ + if (!debug) + wcdte_setintmask(wc, 0x00010041); + else + wcdte_setintmask(wc, 0x0001A1EB); } -static void start_dma(struct wcdte *wc) +static void wcdte_start_dma(struct wcdte *wc) { unsigned int reg; - wmb(); - setctl(wc, 0x0020, wc->descripdma); - setctl(wc, 0x0018, wc->descripdma + (16 * ERING_SIZE)); + wcdte_setctl(wc, 0x0020, wc->descripdma); + wcdte_setctl(wc, 0x0018, wc->descripdma + (16 * ERING_SIZE)); /* Start receiver/transmitter */ - reg = getctl(wc, 0x0030); - setctl(wc, 0x0030, reg | 0x00002002); /* Start XMT and RCD */ - setctl(wc, 0x0010, 0x00000000); /* Receive Poll Demand */ - reg = getctl(wc, 0x0028); - setctl(wc, 0x0028, reg); -} + reg = wcdte_getctl(wc, 0x0030); + wcdte_setctl(wc, 0x0030, reg | 0x00002002); /* Start XMT and RCD */ + wcdte_setctl(wc, 0x0010, 0x00000000); /* Receive Poll Demand */ + reg = wcdte_getctl(wc, 0x0028); + wcdte_setctl(wc, 0x0028, reg); -static void disable_interrupts(struct wcdte *wc) -{ - setintmask(wc, 0x00000000); - setctl(wc, 0x0084, 0x00000000); } -static void stop_dma(struct wcdte *wc) +static void wcdte_stop_dma(struct wcdte *wc) { + /* Disable interrupts and reset */ unsigned int reg; - - disable_interrupts(wc); - setctl(wc, 0x0048, 0x00000000); + /* Disable interrupts */ + wcdte_setintmask(wc, 0x00000000); + wcdte_setctl(wc, 0x0084, 0x00000000); + wcdte_setctl(wc, 0x0048, 0x00000000); /* Reset the part to be on the safe side */ - reg = getctl(wc, 0x0000); + reg = wcdte_getctl(wc, 0x0000); reg |= 0x00000001; - setctl(wc, 0x0000, reg); + wcdte_setctl(wc, 0x0000, reg); +} + +static void wcdte_disable_interrupts(struct wcdte *wc) +{ + /* Disable interrupts */ + wcdte_setintmask(wc, 0x00000000); + wcdte_setctl(wc, 0x0084, 0x00000000); } -static int waitfor_csmencaps(struct wcdte *wc, unsigned int mask, int use_mask) +static int wcdte_waitfor_csmencaps(struct wcdte *wc, unsigned int mask, int use_mask) { int ret; - ret = wait_event_interruptible_timeout(wc->regq, - use_mask ? (wc->rcvflags == mask) : (wc->last_rcommand == wc->last_command_sent), - wc->timeout); + + if (use_mask) + ret = wait_event_interruptible_timeout(wc->regq, (wc->rcvflags == mask), wc->timeout); + else + ret = wait_event_interruptible_timeout(wc->regq, (wc->last_rcommand == wc->last_command_sent), wc->timeout); wc->rcvflags = 0; wc->last_rcommand = 0; wc->last_command_sent = 0; - if (ret < 0) { - debug_printk(1, "Wait interrupted, need to stop boot (ret = %d)\n", ret); - return 1; + if (ret < 0) + { + if (debug) + printk("wcdte error: Wait interrupted, need to stop boot (ret = %d)\n", ret); + return(1); } - - if (!ret) { - debug_printk(1, "Waitfor CSMENCAPS response timed out (ret = %d)\n", ret); - return 2; + if (ret == 0) + { + if (debug) + printk("wcdte error: Waitfor CSMENCAPS response timed out (ret = %d)\n", ret); + return(2); } - - return 0; + return(0); } -static int read_phy(struct wcdte *wc, int location) + +static int wcdte_read_phy(struct wcdte *wc, int location) { int i; long mdio_addr = 0x0048; @@ -1138,35 +1202,34 @@ static int read_phy(struct wcdte *wc, int location) /* Establish sync by sending at least 32 logic ones. */ for (i = 32; i >= 0; i--) { - setctl(wc, mdio_addr, MDIO_ENB | MDIO_DATA_WRITE1); - getctl(wc, mdio_addr); - setctl(wc, mdio_addr, MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK); - getctl(wc, mdio_addr); + wcdte_setctl(wc, mdio_addr, MDIO_ENB | MDIO_DATA_WRITE1); + wcdte_getctl(wc, mdio_addr); + wcdte_setctl(wc, mdio_addr, MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK); + wcdte_getctl(wc, mdio_addr); } /* Shift the read command bits out. */ for (i = 17; i >= 0; i--) { int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0; - setctl(wc, mdio_addr, MDIO_ENB | dataval); - getctl(wc, mdio_addr); - setctl(wc, mdio_addr, MDIO_ENB | dataval | MDIO_SHIFT_CLK); - getctl(wc, mdio_addr); + wcdte_setctl(wc, mdio_addr, MDIO_ENB | dataval); + wcdte_getctl(wc, mdio_addr); + wcdte_setctl(wc, mdio_addr, MDIO_ENB | dataval | MDIO_SHIFT_CLK); + wcdte_getctl(wc, mdio_addr); } /* Read the two transition, 16 data, and wire-idle bits. */ for (i = 19; i > 0; i--) { - setctl(wc, mdio_addr, MDIO_ENB_IN); - getctl(wc, mdio_addr); - retval = (retval << 1) | ((getctl(wc, mdio_addr) & MDIO_DATA_READ) ? 1 : 0); - setctl(wc, mdio_addr, MDIO_ENB_IN | MDIO_SHIFT_CLK); - getctl(wc, mdio_addr); + wcdte_setctl(wc, mdio_addr, MDIO_ENB_IN); + wcdte_getctl(wc, mdio_addr); + retval = (retval << 1) | ((wcdte_getctl(wc, mdio_addr) & MDIO_DATA_READ) ? 1 : 0); + wcdte_setctl(wc, mdio_addr, MDIO_ENB_IN | MDIO_SHIFT_CLK); + wcdte_getctl(wc, mdio_addr); } - retval = (retval >> 1) & 0xffff; - + retval = (retval>>1) & 0xffff; return retval; } -void write_phy(struct wcdte *wc, int location, int value) +void wcdte_write_phy(struct wcdte *wc, int location, int value) { int i; int cmd = (0x5002 << 16) | (1 << 23) | (location<<18) | value; @@ -1174,124 +1237,150 @@ void write_phy(struct wcdte *wc, int location, int value) /* Establish sync by sending 32 logic ones. */ for (i = 32; i >= 0; i--) { - setctl(wc, mdio_addr, MDIO_ENB | MDIO_DATA_WRITE1); - getctl(wc, mdio_addr); - setctl(wc, mdio_addr, MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK); - getctl(wc, mdio_addr); + wcdte_setctl(wc, mdio_addr, MDIO_ENB | MDIO_DATA_WRITE1); + wcdte_getctl(wc, mdio_addr); + wcdte_setctl(wc, mdio_addr, MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK); + wcdte_getctl(wc, mdio_addr); } /* Shift the command bits out. */ for (i = 31; i >= 0; i--) { int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0; - setctl(wc, mdio_addr, MDIO_ENB | dataval); - getctl(wc, mdio_addr); - setctl(wc, mdio_addr, MDIO_ENB | dataval | MDIO_SHIFT_CLK); - getctl(wc, mdio_addr); + wcdte_setctl(wc, mdio_addr, MDIO_ENB | dataval); + wcdte_getctl(wc, mdio_addr); + wcdte_setctl(wc, mdio_addr, MDIO_ENB | dataval | MDIO_SHIFT_CLK); + wcdte_getctl(wc, mdio_addr); } /* Clear out extra bits. */ for (i = 2; i > 0; i--) { - setctl(wc, mdio_addr, MDIO_ENB_IN); - getctl(wc, mdio_addr); - setctl(wc, mdio_addr, MDIO_ENB_IN | MDIO_SHIFT_CLK); - getctl(wc, mdio_addr); + wcdte_setctl(wc, mdio_addr, MDIO_ENB_IN); + wcdte_getctl(wc, mdio_addr); + wcdte_setctl(wc, mdio_addr, MDIO_ENB_IN | MDIO_SHIFT_CLK); + wcdte_getctl(wc, mdio_addr); } return; } -static int boot_processor(struct wcdte *wc, const struct firmware *firmware) +static int wcdte_boot_processor(struct wcdte *wc, const struct firmware *firmware) { - int byteloc, last_byteloc, length, delay_count; + int i, j, byteloc, last_byteloc, length, delay_count; unsigned int reg, ret; -#if !defined(USE_TEST_HW) +#ifndef USE_TEST_HW /* Turn off auto negotiation */ - write_phy(wc, 0, 0x2100); - - debug_printk(1, "PHY register 0 = %X", read_phy(wc, 0)); + wcdte_write_phy(wc, 0, 0x2100); + if (debug) + printk("wcdte: PHY register 0 = %X", wcdte_read_phy(wc, 0)); /* Set reset */ - setctl(wc, 0x00A0, 0x04000000); + wcdte_setctl(wc, 0x00A0, 0x04000000); - /* Wait 1000ms to ensure processor reset */ + /* Wait 1000msec to ensure processor reset */ mdelay(1000); /* Clear reset */ - setctl(wc, 0x00A0, 0x04080000); - - /* Wait for Ethernet link */ - for (delay_count = 0; - ((getctl(wc, 0x00fc) & 0xE0000000) != 0xE0000000) && delay_count < 100; - mdelay(100), delay_count++); + wcdte_setctl(wc, 0x00A0, 0x04080000); + + /* Waitfor ethernet link */ + delay_count = 0; + do + { + reg = wcdte_getctl(wc, 0x00fc); + mdelay(100); + delay_count++; + + if (delay_count >= 100) + { + printk("wcdte error: Failed to link to DTE processor!\n"); + return(1); + } + } while ((reg & 0xE0000000) != 0xE0000000); - if (delay_count == 100) { - module_printk("Failed to link to DTE processor!\n"); - return 1; - } /* Turn off booted LED */ - setctl(wc, 0x00A0, 0x04084000); -#endif /* !defined(USE_TEST_HW) */ + wcdte_setctl(wc, 0x00A0, 0x04084000); - if (debug) { - reg = getctl(wc, 0x00fc); - debug_printk(1, "LINK STATUS: reg(0xfc) = %X\n", reg); - } + +#endif - for (ret = 0, last_byteloc = byteloc = 17; byteloc < (firmware->size - 20); last_byteloc = byteloc) { - length = (firmware->data[byteloc] << 8) | firmware->data[byteloc + 1]; + reg = wcdte_getctl(wc, 0x00fc); + if (debug) + printk("wcdte: LINK STATUS: reg(0xfc) = %X\n", reg); + + reg = wcdte_getctl(wc, 0x00A0); + + byteloc = 17; + j = 0; + do + { + last_byteloc = byteloc; + + length = (firmware->data[byteloc] << 8) |firmware->data[byteloc+1]; byteloc += 2; - __transmit_one(wc, firmware->data + byteloc, length); - byteloc += length; - ret = waitfor_csmencaps(wc, RCV_CSMENCAPS_ACK, 1); + + down(&wc->cmdqsem); + if ( (((wc->cmdq_wndx + 1) % MAX_COMMANDS) == wc->cmdq_rndx) && debug ) + printk("wcdte error: cmdq is full.\n"); + else + { + wc->cmdq[wc->cmdq_wndx].cmdlen = length; + for (i = 0; i < length; i++) + wc->cmdq[wc->cmdq_wndx].cmd[i] = firmware->data[byteloc++]; + wc->cmdq_wndx = (wc->cmdq_wndx + 1) % MAX_COMMANDS; + } + + __transmit_demand(wc); + up(&wc->cmdqsem); + + ret = wcdte_waitfor_csmencaps(wc, RCV_CSMENCAPS_ACK, 1); if (ret == 1) - return 1; - else if (ret == 2) /* Retransmit if processor times out */ + return(1); + else if (ret == 2) /* Retransmit if dte processor times out */ byteloc = last_byteloc; - } + j++; + } while (byteloc < firmware->size-20); wc->timeout = 10 * HZ; - if (waitfor_csmencaps(wc, RCV_CSMENCAPS, 1)) - return 1; + if (wcdte_waitfor_csmencaps(wc, RCV_CSMENCAPS, 1)) + return(1); /* Turn on booted LED */ - setctl(wc, 0x00A0, 0x04080000); - - debug_printk(1, "Successfully booted DTE processor.\n"); + wcdte_setctl(wc, 0x00A0, 0x04080000); + if(debug) + printk("wcdte: Successfully booted DTE processor.\n"); - return 0; + return(0); } -static int 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 simple, int complicated, int part1_id, int part2_id, unsigned int *dte_chan1, unsigned int *dte_chan2) { int length = 0; unsigned char chan1, chan2; - - if (complicated == DTE_FORMAT_G729A) + if(complicated == DTE_FORMAT_G729A) length = G729_LENGTH; else if (complicated == DTE_FORMAT_G723_1) length = G723_LENGTH; /* Create complex channel */ - send_cmd(wc, CMD_MSG_CREATE_CHANNEL(wc->seq_num++, part1_id), CMD_MSG_CREATE_CHANNEL_LEN, 0x0010); + 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 */ - send_cmd(wc, CMD_MSG_CREATE_CHANNEL(wc->seq_num++, part2_id), CMD_MSG_CREATE_CHANNEL_LEN, 0x0010); + zt_send_cmd(wc, CMD_MSG_CREATE_CHANNEL(wc->seq_num++, part2_id), CMD_MSG_CREATE_CHANNEL_LEN, 0x0010); chan2 = wc->last_rparm2; /* Configure complex channel */ - send_cmd(wc, CMD_MSG_SET_IP_HDR_CHANNEL(wc->seq_num++, chan1, part2_id, part1_id), CMD_MSG_SET_IP_HDR_CHANNEL_LEN, 0x9000); - send_cmd(wc, CMD_MSG_VOIP_VCEOPT(wc->seq_num++, chan1, length, 0), CMD_MSG_VOIP_VCEOPT_LEN, 0x8001); + zt_send_cmd(wc, CMD_MSG_SET_IP_HDR_CHANNEL(wc->seq_num++, chan1, part2_id, part1_id), CMD_MSG_SET_IP_HDR_CHANNEL_LEN, 0x9000); + zt_send_cmd(wc, CMD_MSG_VOIP_VCEOPT(wc->seq_num++, chan1, length, 0), CMD_MSG_VOIP_VCEOPT_LEN, 0x8001); /* Configure simple channel */ - send_cmd(wc, CMD_MSG_SET_IP_HDR_CHANNEL(wc->seq_num++, chan2, part1_id, part2_id), CMD_MSG_SET_IP_HDR_CHANNEL_LEN, 0x9000); - send_cmd(wc, CMD_MSG_VOIP_VCEOPT(wc->seq_num++, chan2, length, 0), CMD_MSG_VOIP_VCEOPT_LEN, 0x8001); + zt_send_cmd(wc, CMD_MSG_SET_IP_HDR_CHANNEL(wc->seq_num++, chan2, part1_id, part2_id), CMD_MSG_SET_IP_HDR_CHANNEL_LEN, 0x9000); + zt_send_cmd(wc, CMD_MSG_VOIP_VCEOPT(wc->seq_num++, chan2, length, 0), CMD_MSG_VOIP_VCEOPT_LEN, 0x8001); - send_cmd(wc, CMD_MSG_TRANS_CONNECT(wc->seq_num++, 1, chan1, chan2, complicated, simple), CMD_MSG_TRANS_CONNECT_LEN, 0x9322); - send_cmd(wc, CMD_MSG_VOIP_INDCTRL(wc->seq_num++, chan1), CMD_MSG_VOIP_INDCTRL_LEN, 0x8084); - send_cmd(wc, CMD_MSG_VOIP_INDCTRL(wc->seq_num++, chan2), CMD_MSG_VOIP_INDCTRL_LEN, 0x8084); - send_cmd(wc, CMD_MSG_VOIP_VOPENA(wc->seq_num++, chan1, complicated), CMD_MSG_VOIP_VOPENA_LEN, 0x8000); - send_cmd(wc, CMD_MSG_VOIP_VOPENA(wc->seq_num++, chan2, simple), CMD_MSG_VOIP_VOPENA_LEN, 0x8000); + zt_send_cmd(wc, CMD_MSG_TRANS_CONNECT(wc->seq_num++, 1, chan1, chan2, complicated, simple), CMD_MSG_TRANS_CONNECT_LEN, 0x9322); + zt_send_cmd(wc, CMD_MSG_VOIP_INDCTRL(wc->seq_num++, chan1), CMD_MSG_VOIP_INDCTRL_LEN, 0x8084); + zt_send_cmd(wc, CMD_MSG_VOIP_INDCTRL(wc->seq_num++, chan2), CMD_MSG_VOIP_INDCTRL_LEN, 0x8084); + zt_send_cmd(wc, CMD_MSG_VOIP_VOPENA(wc->seq_num++, chan1, complicated), CMD_MSG_VOIP_VOPENA_LEN, 0x8000); + zt_send_cmd(wc, CMD_MSG_VOIP_VOPENA(wc->seq_num++, chan2, simple), CMD_MSG_VOIP_VOPENA_LEN, 0x8000); *dte_chan1 = chan1; *dte_chan2 = chan2; @@ -1299,407 +1388,416 @@ static int create_channel(struct wcdte *wc, int simple, int complicated, int par return 1; } -static int destroy_channel(struct wcdte *wc, unsigned int chan1, unsigned int chan2) +static int wcdte_destroy_channel(struct wcdte *wc, unsigned int chan1, unsigned int chan2) { + /* Turn off both channels */ - send_cmd(wc, CMD_MSG_VOIP_VOPENA_CLOSE(wc->seq_num++, chan1), CMD_MSG_VOIP_VOPENA_CLOSE_LEN, 0x8000); - send_cmd(wc, CMD_MSG_VOIP_VOPENA_CLOSE(wc->seq_num++, chan2), CMD_MSG_VOIP_VOPENA_CLOSE_LEN, 0x8000); + zt_send_cmd(wc, CMD_MSG_VOIP_VOPENA_CLOSE(wc->seq_num++, chan1), CMD_MSG_VOIP_VOPENA_CLOSE_LEN, 0x8000); + zt_send_cmd(wc, CMD_MSG_VOIP_VOPENA_CLOSE(wc->seq_num++, chan2), CMD_MSG_VOIP_VOPENA_CLOSE_LEN, 0x8000); /* Disconnect the channels */ - send_cmd(wc, CMD_MSG_TRANS_CONNECT(wc->seq_num++, 0, chan1, chan2, 0, 0), CMD_MSG_TRANS_CONNECT_LEN, 0x9322); + 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 */ - send_cmd(wc, CMD_MSG_DESTROY_CHANNEL(wc->seq_num++, chan1), CMD_MSG_DESTROY_CHANNEL_LEN, 0x0011); - send_cmd(wc, CMD_MSG_DESTROY_CHANNEL(wc->seq_num++, chan2), CMD_MSG_DESTROY_CHANNEL_LEN, 0x0011); + 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 setup_channels(struct wcdte *wc) +static int wcdte_setup_channels(struct wcdte *wc) { #ifndef USE_TEST_HW - send_cmd(wc, CMD_MSG_SET_ARM_CLK(wc->seq_num++), CMD_MSG_SET_ARM_CLK_LEN, 0x0411); - send_cmd(wc, CMD_MSG_SET_SPU_CLK(wc->seq_num++), CMD_MSG_SET_SPU_CLK_LEN, 0x0412); + zt_send_cmd(wc, CMD_MSG_SET_ARM_CLK(wc->seq_num++), CMD_MSG_SET_ARM_CLK_LEN, 0x0411); + zt_send_cmd(wc, CMD_MSG_SET_SPU_CLK(wc->seq_num++), CMD_MSG_SET_SPU_CLK_LEN, 0x0412); #endif #ifdef USE_TDM_CONFIG - send_cmd(wc, CMD_MSG_TDM_SELECT_BUS_MODE(wc->seq_num++), CMD_MSG_TDM_SELECT_BUS_MODE_LEN, 0x0417); - send_cmd(wc, CMD_MSG_TDM_ENABLE_BUS(wc->seq_num++), CMD_MSG_TDM_ENABLE_BUS_LEN, 0x0405); - send_cmd(wc, CMD_MSG_SUPVSR_SETUP_TDM_PARMS(wc->seq_num++, 0x03, 0x20, 0x00), CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN, 0x0407); - send_cmd(wc, CMD_MSG_SUPVSR_SETUP_TDM_PARMS(wc->seq_num++, 0x04, 0x80, 0x04), CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN, 0x0407); - send_cmd(wc, CMD_MSG_SUPVSR_SETUP_TDM_PARMS(wc->seq_num++, 0x05, 0x20, 0x08), CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN, 0x0407); - send_cmd(wc, CMD_MSG_SUPVSR_SETUP_TDM_PARMS(wc->seq_num++, 0x06, 0x80, 0x0C), CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN, 0x0407); + zt_send_cmd(wc, CMD_MSG_TDM_SELECT_BUS_MODE(wc->seq_num++), CMD_MSG_TDM_SELECT_BUS_MODE_LEN, 0x0417); + zt_send_cmd(wc, CMD_MSG_TDM_ENABLE_BUS(wc->seq_num++), CMD_MSG_TDM_ENABLE_BUS_LEN, 0x0405); + zt_send_cmd(wc, CMD_MSG_SUPVSR_SETUP_TDM_PARMS(wc->seq_num++, 0x03, 0x20, 0x00), CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN, 0x0407); + zt_send_cmd(wc, CMD_MSG_SUPVSR_SETUP_TDM_PARMS(wc->seq_num++, 0x04, 0x80, 0x04), CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN, 0x0407); + zt_send_cmd(wc, CMD_MSG_SUPVSR_SETUP_TDM_PARMS(wc->seq_num++, 0x05, 0x20, 0x08), CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN, 0x0407); + zt_send_cmd(wc, CMD_MSG_SUPVSR_SETUP_TDM_PARMS(wc->seq_num++, 0x06, 0x80, 0x0C), CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN, 0x0407); #endif - send_cmd(wc, CMD_MSG_SET_ETH_HEADER(wc->seq_num++), CMD_MSG_SET_ETH_HEADER_LEN, 0x0100); - send_cmd(wc, CMD_MSG_IP_SERVICE_CONFIG(wc->seq_num++), CMD_MSG_IP_SERVICE_CONFIG_LEN, 0x0302); - send_cmd(wc, CMD_MSG_ARP_SERVICE_CONFIG(wc->seq_num++), CMD_MSG_ARP_SERVICE_CONFIG_LEN, 0x0105); - send_cmd(wc, CMD_MSG_ICMP_SERVICE_CONFIG(wc->seq_num++), CMD_MSG_ICMP_SERVICE_CONFIG_LEN, 0x0304); + zt_send_cmd(wc, CMD_MSG_SET_ETH_HEADER(wc->seq_num++), CMD_MSG_SET_ETH_HEADER_LEN, 0x0100); + zt_send_cmd(wc, CMD_MSG_IP_SERVICE_CONFIG(wc->seq_num++), CMD_MSG_IP_SERVICE_CONFIG_LEN, 0x0302); + zt_send_cmd(wc, CMD_MSG_ARP_SERVICE_CONFIG(wc->seq_num++), CMD_MSG_ARP_SERVICE_CONFIG_LEN, 0x0105); + zt_send_cmd(wc, CMD_MSG_ICMP_SERVICE_CONFIG(wc->seq_num++), CMD_MSG_ICMP_SERVICE_CONFIG_LEN, 0x0304); #ifdef USE_TDM_CONFIG - send_cmd(wc, CMD_MSG_DEVICE_SET_COUNTRY_CODE(wc->seq_num++), CMD_MSG_DEVICE_SET_COUNTRY_CODE_LEN, 0x041B); + zt_send_cmd(wc, CMD_MSG_DEVICE_SET_COUNTRY_CODE(wc->seq_num++), CMD_MSG_DEVICE_SET_COUNTRY_CODE_LEN, 0x041B); #endif - send_cmd(wc, CMD_MSG_SPU_FEATURES_CONTROL(wc->seq_num++, 0x02), CMD_MSG_SPU_FEATURES_CONTROL_LEN, 0x0013); - send_cmd(wc, CMD_MSG_IP_OPTIONS(wc->seq_num++), CMD_MSG_IP_OPTIONS_LEN, 0x0306); - send_cmd(wc, CMD_MSG_SPU_FEATURES_CONTROL(wc->seq_num++, 0x04), CMD_MSG_SPU_FEATURES_CONTROL_LEN, 0x0013); + zt_send_cmd(wc, CMD_MSG_SPU_FEATURES_CONTROL(wc->seq_num++, 0x02), CMD_MSG_SPU_FEATURES_CONTROL_LEN, 0x0013); + zt_send_cmd(wc, CMD_MSG_IP_OPTIONS(wc->seq_num++), CMD_MSG_IP_OPTIONS_LEN, 0x0306); + zt_send_cmd(wc, CMD_MSG_SPU_FEATURES_CONTROL(wc->seq_num++, 0x04), CMD_MSG_SPU_FEATURES_CONTROL_LEN, 0x0013); #ifdef USE_TDM_CONFIG - send_cmd(wc, CMD_MSG_TDM_OPT(wc->seq_num++), CMD_MSG_TDM_OPT_LEN, 0x0435); + zt_send_cmd(wc, CMD_MSG_TDM_OPT(wc->seq_num++), CMD_MSG_TDM_OPT_LEN, 0x0435); #endif - wc->timeout = HZ/100 + 1; + wc->timeout = HZ/100 + 1; /* 10msec */ - return 0; + return(0); } -static int __devinit init_one(struct pci_dev *pdev, const struct pci_device_id *ent) +static int __devinit wcdte_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - int res = 0, reg; + int res, reg; struct wcdte *wc; - struct wcdte_desc *d = (struct wcdte_desc *) ent->driver_data; + struct wcdte_desc *d = (struct wcdte_desc *)ent->driver_data; int x; - unsigned int g729_numchannels, g723_numchannels; - u8 firmware_ver; - unsigned int complexfmts = 0; - struct firmware embedded_firmware; + static int initd_ifaces=0; + unsigned char g729_numchannels, g723_numchannels, min_numchannels, dte_firmware_ver; + unsigned int complexfmts; + struct firmware embedded_firmware = { +#if !defined(HOTPLUG_FIRMWARE) + /* Yes... this is weird. objcopy gives us a symbol containing + the size of the firmware, not a pointer to a variable containing + the size. The only way we can get the value of the symbol + 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_tc400m_firmware_bin_size, + .data = _binary_tc400m_firmware_bin_start, +#endif + }; const struct firmware *firmware = &embedded_firmware; - struct dte_state *encoders; - struct dte_state *decoders; - for (x = 0; x < (sizeof(ifaces) / sizeof(ifaces[0])); x++) + if (!initd_ifaces) { + memset((void *)ifaces,0,(sizeof(struct wcdte *))*WC_MAX_IFACES); + initd_ifaces=1; + } + for (x=0;x= WC_MAX_IFACES) { + printk("wcdte: Too many interfaces\n"); return -EIO; } - if (pci_enable_device(pdev)) - return -EIO; + if (pci_enable_device(pdev)) { + res = -EIO; + } else { - if (!(wc = kmalloc(sizeof(*wc), GFP_KERNEL))) - return -ENOMEM; - - memset(wc, 0, sizeof(*wc)); - ifaces[x] = wc; - spin_lock_init(&wc->reglock); - sema_init(&wc->chansem, 1); - sema_init(&wc->cmdqsem, 1); - wc->iobase = pci_resource_start(pdev, 0); - wc->dev = pdev; - wc->pos = x; - wc->variety = d->name; - - wc->seq_num = 6; - wc->timeout = HZ; + wc = vmalloc(sizeof(struct wcdte)); + if (wc) { + ifaces[x] = wc; + memset(wc, 0, sizeof(struct wcdte)); + spin_lock_init(&wc->reglock); + sema_init(&wc->chansem, 1); + sema_init(&wc->cmdqsem, 1); + wc->cards = NUM_CARDS; + wc->iobase = pci_resource_start(pdev, 0); + wc->dev = pdev; + wc->pos = x; + wc->variety = d->name; + + wc->tdbl = 0; + wc->rdbl = 0; + wc->rcvflags = 0; + wc->last_command_sent = 0; + wc->last_rcommand = 0; + wc->last_rparm2 = 0; + wc->cmdq_wndx = 0; + wc->cmdq_rndx = 0; + wc->seq_num = 6; + wc->timeout = 1 * HZ; /* 1 sec */ + wc->ztsnd_rtx = 0; + wc->ztsnd_0010_rtx = 0; + + /* Keep track of whether we need to free the region */ + if (request_region(wc->iobase, 0xff, "wcdte")) + wc->freeregion = 1; + + /* Allocate enought memory for all TX buffers, RX buffers, and descriptors */ + wc->writechunk = (int *)pci_alloc_consistent(pdev, PCI_WINDOW_SIZE, &wc->writedma); + if (!wc->writechunk) { + printk("wcdte error: Unable to allocate DMA-able memory\n"); + if (wc->freeregion) + release_region(wc->iobase, 0xff); + return -ENOMEM; + } - INIT_LIST_HEAD(&wc->pending_cmdq); - INIT_LIST_HEAD(&wc->free_cmdq); - - /* Keep track of whether we need to free the region */ - if (request_region(wc->iobase, 0xff, "wctc4xxp")) - wc->freeregion = 1; - - /* Allocate enough memory for all TX buffers, RX buffers, and descriptors */ - wc->writechunk = pci_alloc_consistent(pdev, PCI_WINDOW_SIZE, &wc->writedma); - if (!wc->writechunk) { - module_printk("Unable to allocate DMA-able memory\n"); - if (wc->freeregion) - release_region(wc->iobase, 0xff); - - return -ENOMEM; - } - - wc->readchunk = wc->writechunk + (SFRAME_SIZE * ERING_SIZE); - wc->readdma = wc->writedma + (SFRAME_SIZE * ERING_SIZE); - - wc->descripchunk = (u32 *) (wc->readchunk + (SFRAME_SIZE * ERING_SIZE)); - wc->descripdma = wc->readdma + (SFRAME_SIZE * ERING_SIZE); - - init_waitqueue_head(&wc->regq); - - /* Initialize the work queue */ - wc->dte_wq = create_workqueue("wctc4xxp"); + wc->readchunk = wc->writechunk + (SFRAME_SIZE * ERING_SIZE) / 4; /* in doublewords */ + wc->readdma = wc->writedma + (SFRAME_SIZE * ERING_SIZE); /* in bytes */ + + wc->descripchunk = wc->readchunk + (SFRAME_SIZE * ERING_SIZE) / 4; /* in doublewords */ + wc->descripdma = wc->readdma + (SFRAME_SIZE * ERING_SIZE); /* in bytes */ - INIT_WORK(&wc->dte_work, (void (*)(void *)) dte_wque_run, wc); + /* Initialize Write/Buffers to all blank data */ + memset((void *)wc->writechunk,0x00, SFRAME_SIZE * 2); + memset((void *)wc->readchunk, 0x00, SFRAME_SIZE * 2); + init_waitqueue_head(&wc->regq); + + /* Initialize the work queue */ + wc->dte_wq = create_workqueue("tc400b"); + INIT_WORK(&wc->dte_work, (void (*)(void *))dte_wque_run, wc); #ifdef HOTPLUG_FIRMWARE - if ((request_firmware(&firmware, tc400m_firmware, &wc->dev->dev) != 0) || !firmware) { - module_printk("Firmware %s not available from userspace\n", tc400m_firmware); - return -1; - } -#else - embedded_firmware.data = _binary_tc400m_firmware_bin_start; - /* Yes... this is weird. objcopy gives us a symbol containing - the size of the firmware, not a pointer a variable containing - the size. The only way we can get the value of the symbol - is to take its address, so we do that and then cast that - value to the proper type. - */ - embedded_firmware.size = (size_t) &_binary_tc400m_firmware_bin_size; + if ((request_firmware(&firmware, dte_firmware, &wc->dev->dev) != 0) || !firmware) { + printk("TC400B: firmware %s not available from userspace\n", dte_firmware); + return -1; + } #endif + dte_firmware_ver = firmware->data[0]; + g729_numchannels = firmware->data[1]; + g723_numchannels = firmware->data[2]; - firmware_ver = firmware->data[0]; - g729_numchannels = firmware->data[1]; - g723_numchannels = firmware->data[2]; - - wc->numchannels = 2048; /* someday... */ + if (g723_numchannels < g729_numchannels) + min_numchannels = g723_numchannels; + else + min_numchannels = g729_numchannels; + + /* Setup Encoders nad Decoders */ + + if (!mode || strlen(mode) < 4) + { + sprintf(wc->complexname, "g.729a / g.723.1 5.3kbps"); + complexfmts = ZT_FORMAT_G729A | ZT_FORMAT_G723_1; + wc->numchannels = min_numchannels; + } + else if (mode[3] == '9') /* "g729" */ + { + sprintf(wc->complexname, "g.729a"); + complexfmts = ZT_FORMAT_G729A; + wc->numchannels = g729_numchannels; + } + else if (mode[3] == '3') /* "g723" */ + { + sprintf(wc->complexname, "g.723.1 5.3kbps"); + complexfmts = ZT_FORMAT_G723_1; + wc->numchannels = g723_numchannels; + } + else + { + sprintf(wc->complexname, "g.729a / g.723.1 5.3kbps"); + complexfmts = ZT_FORMAT_G729A | ZT_FORMAT_G723_1; + wc->numchannels = min_numchannels; + } + + uencode = zt_transcoder_alloc(wc->numchannels); + udecode = zt_transcoder_alloc(wc->numchannels); + encoders = vmalloc(sizeof(struct dte_state) * wc->numchannels); + decoders = vmalloc(sizeof(struct dte_state) * wc->numchannels); + memset(encoders, 0, sizeof(struct dte_state) * wc->numchannels); + memset(decoders, 0, sizeof(struct dte_state) * wc->numchannels); + if (!uencode || !udecode || !encoders || !decoders) { + if (uencode) + zt_transcoder_free(uencode); + if (udecode) + zt_transcoder_free(udecode); + if (encoders) + vfree(encoders); + if (decoders) + vfree(decoders); + return -ENOMEM; + } + sprintf(udecode->name, "DTE Decoder"); + sprintf(uencode->name, "DTE Encoder"); - for (x = 0; x < mode_count; x++) { - if (!strcmp(mode[x], "g729") || - !strcmp(mode[x], "G729")) { - if (!g729_numchannels) { - module_printk("Format '%s' not supported by the firmware for this module; ignored.\n", mode[x]); - continue; + udecode->srcfmts = uencode->dstfmts = complexfmts; + udecode->dstfmts = uencode->srcfmts = ZT_FORMAT_ULAW | ZT_FORMAT_ALAW; + + udecode->operation = uencode->operation = dte_operation; + + for (x=0;xnumchannels;x++) { + dte_init_state(encoders + x, 1, x, wc); + encoders[x].encoder = 1; + decoders[x].encoder = 0; + dte_init_state(decoders + x, 0, x, wc); + uencode->channels[x].pvt = encoders + x; + udecode->channels[x].pvt = decoders + x; } - strcat(wc->complexname, "G.729A / "); - complexfmts |= ZT_FORMAT_G729A; - wc->numchannels = min(wc->numchannels, g729_numchannels); - } else if (!strcmp(mode[x], "g723") || - !strcmp(mode[x], "G723")) { - if (!g723_numchannels) { - module_printk("Format '%s' not supported by the firmware for this module; ignored.\n", mode[x]); - continue; + + wc->uencode = uencode; + wc->udecode = udecode; + + zt_transcoder_register(uencode); + zt_transcoder_register(udecode); + + printk("Zaptel DTE (%s) Transcoder support LOADED (firm ver = %d)\n", wc->complexname, dte_firmware_ver); + + + /* Enable bus mastering */ + pci_set_master(pdev); + + /* Keep track of which device we are */ + pci_set_drvdata(pdev, wc); + + if (request_irq(pdev->irq, wcdte_interrupt, SA_SHIRQ, "tc400b", wc)) { + printk("wcdte error: Unable to request IRQ %d\n", pdev->irq); + if (wc->freeregion) + release_region(wc->iobase, 0xff); + pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); + pci_set_drvdata(pdev, NULL); + vfree(wc); + return -EIO; } - strcat(wc->complexname, "G.723.1 5.3Kbps / "); - complexfmts |= ZT_FORMAT_G723_1; - wc->numchannels = min(wc->numchannels, g723_numchannels); - } else { - module_printk("Invalid transcoder format specified: %s\n", mode[x]); - } - } - if (!complexfmts) { - module_printk("No valid transcoder formats specified; module will not be enabled.\n"); - return -1; - } - wc->complexname[strlen(wc->complexname) - 3] = '\0'; - - wc->uencode = zt_transcoder_alloc(wc->numchannels); - wc->udecode = zt_transcoder_alloc(wc->numchannels); - encoders = kmalloc(sizeof(*encoders) * wc->numchannels, GFP_KERNEL); - decoders = kmalloc(sizeof(*decoders) * wc->numchannels, GFP_KERNEL); - if (!wc->uencode || !wc->udecode || !encoders || !decoders) { - if (wc->uencode) - zt_transcoder_free(wc->uencode); - if (wc->udecode) - zt_transcoder_free(wc->udecode); - if (encoders) - kfree(encoders); - if (decoders) - kfree(decoders); - - return -ENOMEM; - } + if (wcdte_hardware_init(wc)) { + /* Set Reset Low */ + wcdte_stop_dma(wc); + /* Free Resources */ + free_irq(pdev->irq, wc); + if (wc->freeregion) + release_region(wc->iobase, 0xff); + pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); + pci_set_drvdata(pdev, NULL); + vfree(wc); + return -EIO; - strcpy(wc->udecode->name, wc->variety); - strcpy(wc->uencode->name, wc->variety); - - wc->udecode->srcfmts = wc->uencode->dstfmts = complexfmts; - wc->udecode->dstfmts = wc->uencode->srcfmts = ZT_FORMAT_ULAW | ZT_FORMAT_ALAW; - - wc->udecode->operation = wc->uencode->operation = dte_operation; - - for (x = 0;x < wc->numchannels; x++) { - dte_init_state(&encoders[x], 1, x, wc); - dte_init_state(&decoders[x], 0, x, wc); - wc->uencode->channels[x].pvt = &encoders[x]; - wc->udecode->channels[x].pvt = &decoders[x]; - } - - wc->uencode->owner = wc->udecode->owner = THIS_MODULE; + } - zt_transcoder_register(wc->uencode); - zt_transcoder_register(wc->udecode); - - /* Enable bus mastering */ - pci_set_master(pdev); - - /* Keep track of which device we are */ - pci_set_drvdata(pdev, wc); - - if (request_irq(pdev->irq, interrupt_handler, SA_SHIRQ, driver.name, wc)) { - module_printk("Unable to request IRQ %d\n", pdev->irq); - if (wc->freeregion) - release_region(wc->iobase, 0xFF); - pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *) wc->writechunk, wc->writedma); - pci_set_drvdata(pdev, NULL); - kfree(wc); - /* TODO: what about all the encoders and decoders (do this earlier)? */ - return -EIO; - } - - if (hardware_init(wc)) { - /* Set Reset Low */ - stop_dma(wc); - /* Free Resources */ - free_irq(pdev->irq, wc); - if (wc->freeregion) - release_region(wc->iobase, 0xff); - pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *) wc->writechunk, wc->writedma); - pci_set_drvdata(pdev, NULL); - kfree(wc); - return -EIO; - } - - /* Enable interrupts */ - enable_interrupts(wc); - - /* Start DMA */ - start_dma(wc); + /* Enable interrupts */ + wcdte_enable_interrupts(wc); + + /* Start DMA */ + wcdte_start_dma(wc); + if (wcdte_boot_processor(wc,firmware)) { + if (firmware != &embedded_firmware) + release_firmware(firmware); + + /* Set Reset Low */ + wcdte_stop_dma(wc); + /* Free Resources */ + free_irq(pdev->irq, wc); + if (wc->freeregion) + release_region(wc->iobase, 0xff); + pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); + pci_set_drvdata(pdev, NULL); + vfree(wc); + return -EIO; + } - if (boot_processor(wc, firmware)) { - /* Set Reset Low */ - stop_dma(wc); - /* Free Resources */ - free_irq(pdev->irq, wc); - if (wc->freeregion) - release_region(wc->iobase, 0xff); - pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *) wc->writechunk, wc->writedma); - pci_set_drvdata(pdev, NULL); - kfree(wc); - return -EIO; - } - - if (setup_channels(wc)) { - /* Set Reset Low */ - stop_dma(wc); - /* Free Resources */ - free_irq(pdev->irq, wc); - if (wc->freeregion) - release_region(wc->iobase, 0xff); - pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *) wc->writechunk, wc->writedma); - pci_set_drvdata(pdev, NULL); - kfree(wc); - return -EIO; - } - - if (debug) { - reg = getctl(wc, 0x00fc); - debug_printk(1, "(post-boot) Reg fc is %08x\n", reg); + if (wcdte_setup_channels(wc)) + { + /* Set Reset Low */ + wcdte_stop_dma(wc); + /* Free Resources */ + free_irq(pdev->irq, wc); + if (wc->freeregion) + release_region(wc->iobase, 0xff); + pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); + pci_set_drvdata(pdev, NULL); + 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); + res = 0; + } else + res = -ENOMEM; } - - module_printk("%s supporting '%s' with firmware version '%d'\n", wc->variety, wc->complexname, firmware_ver); - - res = 0; - return res; } -static void release(struct wcdte *wc) +static void wcdte_release(struct wcdte *wc) { - struct cmdq *cmdq, *next; - if (wc->freeregion) release_region(wc->iobase, 0xff); - list_for_each_entry_safe(cmdq, next, &wc->pending_cmdq, list) { - debug_printk(1, "freeing cmdq entry at '%p'\n", cmdq); - list_del(&cmdq->list); - kfree(cmdq); - } - list_for_each_entry_safe(cmdq, next, &wc->free_cmdq, list) { - debug_printk(1, "freeing cmdq entry at '%p'\n", cmdq); - list_del(&cmdq->list); - kfree(cmdq); - } - kfree(wc); + vfree(wc); } -static void __devexit remove_one(struct pci_dev *pdev) +static void __devexit wcdte_remove_one(struct pci_dev *pdev) { int i; struct wcdte *wc = pci_get_drvdata(pdev); struct zt_transcoder_channel *ztc_en, *ztc_de; struct dte_state *st_en, *st_de; - if (!wc) - return; - - zt_transcoder_unregister(wc->udecode); - zt_transcoder_unregister(wc->uencode); - - if (debug) { - debug_printk(1, "wc->ztsnd_rtx = %d\n", wc->ztsnd_rtx); - debug_printk(1, "wc->ztsnd_0010_rtx = %d\n", wc->ztsnd_0010_rtx); - - for (i = 0; i < wc->numchannels; i++) { - ztc_en = &(wc->uencode->channels[i]); - st_en = ztc_en->pvt; - - ztc_de = &(wc->udecode->channels[i]); - st_de = ztc_de->pvt; + if (wc) { + if (debug) + { + printk("wcdte debug: wc->ztsnd_rtx = %d\n", wc->ztsnd_rtx); + printk("wcdte debug: wc->ztsnd_0010_rtx = %d\n", wc->ztsnd_0010_rtx); + + for(i = 0; i < wc->numchannels; i++) + { + ztc_en = &(wc->uencode->channels[i]); + st_en = ztc_en->pvt; - debug_printk(1, "en[%d] snt = %d, rcv = %d [%d]\n", i, st_en->packets_sent, st_en->packets_received, st_en->packets_sent - st_en->packets_received); - debug_printk(1, "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); + ztc_de = &(wc->udecode->channels[i]); + st_de = ztc_de->pvt; + + printk("wcdte debug: en[%d] snt = %d, rcv = %d [%d]\n", i, st_en->packets_sent, st_en->packets_received, st_en->packets_sent - st_en->packets_received); + 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); + } } - } - - /* Stop any DMA */ - stop_dma(wc); - /* In case hardware is still there */ - disable_interrupts(wc); + zt_transcoder_unregister(wc->udecode); + zt_transcoder_unregister(wc->uencode); + zt_transcoder_free(wc->uencode); + zt_transcoder_free(wc->udecode); + vfree(wc->uencode->channels[0].pvt); + vfree(wc->udecode->channels[0].pvt); - /* Kill workqueue */ - destroy_workqueue(wc->dte_wq); - - /* Immediately free resources */ - pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *) wc->writechunk, wc->writedma); - free_irq(pdev->irq, wc); - - kfree(wc->uencode->channels[0].pvt); - kfree(wc->udecode->channels[0].pvt); + /* Stop any DMA */ + wcdte_stop_dma(wc); + + /* In case hardware is still there */ + wcdte_disable_interrupts(wc); - zt_transcoder_free(wc->uencode); - zt_transcoder_free(wc->udecode); + /* Kill workqueue */ + destroy_workqueue(wc->dte_wq); + + /* Immediately free resources */ + pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); + free_irq(pdev->irq, wc); - /* Release span, possibly delayed */ - release(wc); + /* Release span, possibly delayed */ + wcdte_release(wc); + } } -static struct pci_device_id pci_tbl[] = { +static struct pci_device_id wcdte_pci_tbl[] = { #ifndef USE_TEST_HW - { 0xd161, 0x3400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcdte }, /* digium board */ + { 0xd161, 0x3400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcdte }, /* Digium board */ #else { 0x1317, 0x0985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcdte }, /* reference board */ #endif { 0 } }; -MODULE_DEVICE_TABLE(pci, pci_tbl); +MODULE_DEVICE_TABLE(pci, wcdte_pci_tbl); -static struct pci_driver driver = { +static struct pci_driver wcdte_driver = { name: "wctc4xxp", - probe: init_one, - remove: __devexit_p(remove_one), + probe: wcdte_init_one, + remove: __devexit_p(wcdte_remove_one), suspend: NULL, resume: NULL, - id_table: pci_tbl, + id_table: wcdte_pci_tbl, }; -static int init(void) +int ztdte_init(void) { - return pci_module_init(&driver) ? -ENODEV : 0; + int res; + + res = pci_module_init(&wcdte_driver); + if (res) + return -ENODEV; + return 0; } -static void cleanup(void) +void ztdte_cleanup(void) { - pci_unregister_driver(&driver); + pci_unregister_driver(&wcdte_driver); } module_param(debug, int, S_IRUGO | S_IWUSR); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) -module_param_array(mode, charp, &mode_count, S_IRUGO | S_IWUSR); -#else -module_param_array(mode, charp, mode_count, S_IRUGO | S_IWUSR); -#endif -module_param(debug_packets, uint, S_IRUGO | S_IWUSR); -module_param(debug_cmd_packets, uint, S_IRUGO | S_IWUSR); -MODULE_DESCRIPTION("Wildcard TC400P+TC400M Transcoder"); +module_param(mode, charp, S_IRUGO | S_IWUSR); +MODULE_DESCRIPTION("Wildcard TC400P+TC400M Driver"); MODULE_AUTHOR("John Sloan "); +#ifdef MODULE_LICENSE MODULE_LICENSE("GPL"); +#endif -module_init(init); -module_exit(cleanup); +module_init(ztdte_init); +module_exit(ztdte_cleanup); -- cgit v1.2.3