[zaptel-commits] kpfleming: branch 1.2 r2092 - in /branches/1.2: ./ wctc4xxp/

zaptel-commits at lists.digium.com zaptel-commits at lists.digium.com
Tue Feb 6 14:57:39 MST 2007


Author: kpfleming
Date: Tue Feb  6 15:57:38 2007
New Revision: 2092

URL: http://svn.digium.com/view/zaptel?view=rev&rev=2092
Log:
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

Modified:
    branches/1.2/wctc4xxp/base.c
    branches/1.2/zaptel.h
    branches/1.2/zttranscode.c

Modified: branches/1.2/wctc4xxp/base.c
URL: http://svn.digium.com/view/zaptel/branches/1.2/wctc4xxp/base.c?view=diff&rev=2092&r1=2091&r2=2092
==============================================================================
--- branches/1.2/wctc4xxp/base.c (original)
+++ branches/1.2/wctc4xxp/base.c Tue Feb  6 15:57:38 2007
@@ -1,10 +1,9 @@
 /*
- * Wildcard TC400B Interface Driver for Zapata Telephony interface
+ * Wildcard TC400B Driver
  *
  * Written by John Sloan <jsloan at digium.com>
- *        and Kevin P. Fleming <kpfleming at digium.com>
  *
- * Copyright (C) 2006-2007, Digium, Inc.
+ * Copyright (C) 2006, Digium, Inc.
  *
  * All rights reserved.
  *
@@ -24,6 +23,7 @@
  *
  */
 
+
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/module.h>
@@ -34,6 +34,7 @@
 #include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
+#include <linux/vmalloc.h>
 #include <linux/mman.h>
 #include <linux/delay.h>
 #include <asm/io.h>
@@ -42,30 +43,30 @@
 #include <linux/workqueue.h>
 #include <linux/moduleparam.h>
 #include <linux/firmware.h>
-#include <linux/list.h>
-
+#ifdef CONFIG_DEVFS_FS
+#include <linux/devfs_fs_kernel.h>
+#endif
 #ifdef STANDALONE_ZAPATA
 #include "zaptel.h"
 #else
 #include <linux/zaptel.h>
 #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 @@
 #define G729_LENGTH 20
 #define G723_LENGTH 30
 
-#define G729_SAMPLES 160
-#define G723_SAMPLES 240
-
-#define G729_BYTES 20
-#define G723_BYTES 20
-
-/* 274 for 30ms ulaw, 194 for 20ms ulaw */
+#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 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 @@
 #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 @@
 	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 @@
 	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 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 chan_in_num;
-	unsigned int chan_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;		/* 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 @@
 	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 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 char *mode;
+int debug_packets = 0;
+
+
+static int wcdte_create_channel(struct wcdte *wc, int simple, int complicated, int part1_id, int part2_id, unsigned int *dte_chan1, unsigned int *dte_chan2);
+static int 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 @@
 	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 inline unsigned int 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;
-	}
-}
-
-static inline void __setctl(struct wcdte *wc, unsigned int addr, unsigned int val)
+static unsigned int wcdte_zapfmt_to_dtefmt(unsigned int fmt)
+{
+	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 __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)
+static inline void wcdte_setctl(struct wcdte *wc, unsigned int addr, unsigned int val)
 {
 	unsigned long flags;
-
 	spin_lock_irqsave(&wc->reglock, flags);
-	__setctl(wc, addr, val);
+	__wcdte_setctl(wc, addr, val);
 	spin_unlock_irqrestore(&wc->reglock, flags);
 }
 
-static inline unsigned int getctl(struct wcdte *wc, unsigned int addr)
-{
-	unsigned long flags;
-	unsigned int val;
-
-	spin_lock_irqsave(&wc->reglock, flags);
-	val = __getctl(wc, addr);
-	spin_unlock_irqrestore(&wc->reglock, flags);
-
-	return val;
-}
-
-static inline void reinit_descriptor(struct wcdte *wc, int tx, int dbl, char *s)
-{
-	unsigned int o2;
-
-	o2 = dbl * 4;
+static inline void wcdte_reinit_descriptor(struct wcdte *wc, int tx, int dbl, char *s)
+{
+	int o2 = 0;
+	o2 += dbl * 4;
 
 	if (!tx)
 		o2 += ERING_SIZE * 4;
 	wc->descripchunk[o2] = cpu_to_le32(0x80000000);
 
-	setctl(wc, 0x0008, 0x00000000);
-}
-
-static inline void __transmit_one(struct wcdte *wc, u8 *data, size_t length)
-{
-	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);
+	wcdte_setctl(wc, 0x0008, 0x00000000);
+}
+
+static inline unsigned int wcdte_getctl(struct wcdte *wc, unsigned int addr)
+{
+	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)
+{
+	volatile unsigned char *writechunk;
+	int o2,i,j;
+	unsigned int reg, xmt_length;
+
+	reg = wcdte_getctl(wc, 0x0028) & 0x00700000;
+	
+	/* Already transmiting, no need to demand another */
+	if (!((reg == 0) || (reg = 6)))
+		return(1);
+
+	/* Nothing to transmit */
+	if (wc->cmdq_rndx == wc->cmdq_wndx)
+		return(1);
+
+	/* Nothing to transmit */
+	if (wc->cmdq[wc->cmdq_rndx].cmdlen == 0 )
+		return(1);
+
+	writechunk = (volatile unsigned char *)(wc->writechunk);
+
+	writechunk += wc->tdbl * SFRAME_SIZE;
+
+	o2 = wc->tdbl * 4;
+		
+	do
+	{
+	} while ((le32_to_cpu(wc->descripchunk[o2]) & 0x80000000));
+
+	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);
 				
-	memcpy((void *) writechunk, data, length);
-	if (length < xmt_length)
-		memset((void *) writechunk + length, 0, xmt_length - 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; i<debug_packets; i++)
+			printk("%02X ", writechunk[i]);
+		printk("\n");
+	}
+
+	wc->cmdq[wc->cmdq_rndx].cmdlen = 0;
 
 	wc->descripchunk[o2] = cpu_to_le32(0x80000000);
-	setctl(wc, 0x0008, 0x00000000);			/* Transmit Poll Demand */
+	wcdte_setctl(wc, 0x0008, 0x00000000);			/* Transmit Poll Demand */
 	
 	wc->tdbl = (wc->tdbl + 1) % ERING_SIZE;
-}
-
-static inline int __transmit_demand(struct wcdte *wc)
-{
-	int i;
-	unsigned int reg;
-	struct cmdq *cmdq;
-
-	reg = getctl(wc, 0x0028) & 0x00700000;
-	
-	/* Nothing to transmit */
-	if (list_empty(&wc->pending_cmdq))
-		return 1;
-
-	/* pop the first entry off the list */
-	cmdq = list_entry(wc->pending_cmdq.next, struct cmdq, list);
-	list_del_init(&cmdq->list);
-
-	debug_printk(1, "transmitting command at '%p' of '%zd' bytes\n", cmdq, cmdq->cmdlen);
-
-	__transmit_one(wc, cmdq->cmd, cmdq->cmdlen);
-
-	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");
-	}
-
-	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]);
-		printk("\n");
-	}
-
-	list_add_tail(&cmdq->list, &wc->free_cmdq);
-
-	return 0;
+
+	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 @@
 	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 @@
 		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 @@
 					st->seqno += 1;
 					st->timestamp += timestamp_inc;
 
+					for (i = 0; i < inbytes; i++)
+						fifo[i+CMD_MSG_IP_UDP_RTP_LEN]= chars[i];
+
 					down(&wc->cmdqsem);
-
-					if (!(cmdq = get_free_cmdq(wc, sizeof(fifo) + inbytes))) {
-						up(&wc->cmdqsem);
-						res = -EIO;
-						break;
+		
+					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;
 					}
-		
-					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);
+					
 					__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 inline void receiveprep(struct wcdte *wc, int dbl)
-{
-	volatile u8 *readchunk = wc->readchunk + (dbl * SFRAME_SIZE);
+static void wcdte_stop_dma(struct wcdte *wc);
+
+static inline void wcdte_receiveprep(struct wcdte *wc, int dbl)
+{
+	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; i<debug_packets; i++)
 				printk("%02X ", readchunk[i]);
 			printk("\n");
 		}
 		/* See if message must be ACK'd */
-		if ((readchunk[17] & 0xC0) == 0) {
+		if ((readchunk[17] & 0xC0) == 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
 			{
-				u8 fifo[] = CMD_MSG_ACK(rseq++, rchannel);
-			
-				down(&wc->cmdqsem);
-				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);
-			}
-		} else {
+				unsigned char fifo[OTHER_CMD_LEN] = CMD_MSG_ACK(rseq++, rchannel);
+
+				wc->cmdq[wc->cmdq_wndx].cmdlen = CMD_MSG_ACK_LEN;
+				for (i = 0; i < wc->cmdq[wc->cmdq_wndx].cmdlen; i++)
+					wc->cmdq[wc->cmdq_wndx].cmd[i] = fifo[i];
+				wc->cmdq_wndx = (wc->cmdq_wndx + 1) % MAX_COMMANDS;
+			}
+				
+			__transmit_demand(wc);
+
+		
+			wc->rcvflags = RCV_CSMENCAPS;
+			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;
-
-		if (ztc_ndx >= wc->numchannels) {
-			debug_printk(1, "Invalid channel number received (ztc_ndx = %d) (numchannels = %d)\n", ztc_ndx, wc->numchannels);
+		ztc_ndx = rchannel/2;
+
+		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 */
+			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 {

[... 1815 lines stripped ...]


More information about the zaptel-commits mailing list