[dahdi-commits] sruffell: branch linux/sruffell/dahdi-transcoder r4711 - /linux/team/sruffell...

SVN commits to the DAHDI project dahdi-commits at lists.digium.com
Wed Aug 6 10:04:21 CDT 2008


Author: sruffell
Date: Wed Aug  6 10:04:21 2008
New Revision: 4711

URL: http://svn.digium.com/view/dahdi?view=rev&rev=4711
Log:
Merged everything into a single file and removed unused code paths.

Removed:
    linux/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/wcdte_commands.c
    linux/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/wcdte_commands.h
    linux/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/wcdte_net.c
    linux/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/wcdte_net.h
    linux/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/wctc4xxp.h
Modified:
    linux/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/Kbuild
    linux/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/base.c

Modified: linux/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/Kbuild
URL: http://svn.digium.com/view/dahdi/linux/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/Kbuild?view=diff&rev=4711&r1=4710&r2=4711
==============================================================================
--- linux/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/Kbuild (original)
+++ linux/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/Kbuild Wed Aug  6 10:04:21 2008
@@ -9,8 +9,6 @@
 endif
 
 wctc4xxp-objs := base.o
-wctc4xxp-objs += wcdte_net.o
-wctc4xxp-objs += wcdte_commands.o
 
 ifneq ($(HOTPLUG_FIRMWARE),yes)
 wctc4xxp-objs += $(FIRM_DIR)/dahdi-fw-tc400m.o

Modified: linux/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/base.c
URL: http://svn.digium.com/view/dahdi/linux/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/base.c?view=diff&rev=4711&r1=4710&r2=4711
==============================================================================
--- linux/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/base.c (original)
+++ linux/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/base.c Wed Aug  6 10:04:21 2008
@@ -36,38 +36,57 @@
 #include <linux/moduleparam.h>
 #include <linux/firmware.h>
 #include <linux/if_ether.h>
+#include <linux/ip.h>
+#include <linux/udp.h>
+#include <linux/etherdevice.h>
 #include <linux/timer.h>
-#ifdef CONFIG_DEBUG_FS
-#include <linux/debugfs.h>
+
+#include "dahdi/kernel.h"
+
+/* COMPILE TIME OPTIONS =================================================== */
+
+#define INTERRUPT 0
+#define WORKQUEUE 1
+#define TASKLET   2
+
+#ifndef DEFERRED_PROCESSING 
+#	define DEFERRED_PROCESSING WORKQUEUE
 #endif
 
-#include "dahdi/kernel.h"
-#include "wctc4xxp.h"
-#include "wcdte_commands.h"
-#include "wcdte_net.h"
-
-/* \todo Need to check these functions with more linux versions... */
-#undef CONFIG_DEBUG_FS
+#if DEFERRED_PROCESSING == INTERRUPT
+#	define ALLOC_FLAGS GFP_ATOMIC
+#elif DEFERRED_PROCESSING == TASKLET
+#	define ALLOC_FLAGS GFP_ATOMIC
+#else
+#	define ALLOC_FLAGS GFP_KERNEL
+#endif
+
+#define WARN() WARN_ON(1)
+
+#define DTE_PRINTK(_lvl, _fmt, _args...) \
+	   printk(KERN_##_lvl "%s: %s: " _fmt, THIS_MODULE->name, \
+	          (wc)->board_name, ## _args)
+
+#define DTE_DEBUG(_dbgmask, _fmt, _args...)                                 \
+	if ((debug & _dbgmask) == (_dbgmask)) {                             \
+		printk(KERN_DEBUG "%s: %s: " _fmt, THIS_MODULE->name,       \
+		       (wc)->board_name, ## _args);                         \
+	}                                                                   \
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
+#define WARN_ON_ONCE(__condition) do {         \
+	static int __once = 1;                 \
+	if (unlikely(__condition)) {           \
+		if (__once) {                  \
+			__once = 0;            \
+			WARN_ON(0);            \
+		}                              \
+	}                                      \
+} while(0) 
+#endif
 
 #define INVALID 999 /* Used to mark invalid channels, commands, etc.. */
 #define MAX_CHANNEL_PACKETS  5 /* Never let more than 5 outstanding packets exist for any channel. */
-
-#define USE_TDM_CONFIG
-#define QUIET_DSP
-
-#define WC_MAX_IFACES 128
-
-#if 0
-#define HERE() printk(KERN_DEBUG "HERE: %s:%d\n", __FILE__, __LINE__);
-#define ENTERING() printk(KERN_DEBUG "Entering %s \n", __FUNCTION__);
-#define LEAVING() printk(KERN_DEBUG "Leaving %s (%d)\n", __FUNCTION__, __LINE__);
-#else
-#define HERE() printk(KERN_DEBUG "HERE: %s:%d\n", __FILE__, __LINE__);
-// #define HERE() do {;} while (0)
-#define ENTERING() do {;} while (0)
-#define LEAVING() do {;} while (0)
-#endif
-
 
 #define G729_LENGTH	20
 #define G723_LENGTH	30
@@ -80,26 +99,799 @@
 #define G723_5K_BYTES	20	/* G.723.1 at 5.3kb/s */
 #define G723_SID_BYTES	4	/* G.723.1 SID frame */
 
-#define MDIO_SHIFT_CLK		0x10000
-#define MDIO_DATA_WRITE1 	0x20000
-#define MDIO_ENB		0x00000
-#define MDIO_ENB_IN		0x40000
-#define MDIO_DATA_READ		0x80000
-
-#define RCV_CSMENCAPS		1
-#define RCV_RTP			2
-#define RCV_CSMENCAPS_ACK	3
-#define RCV_OTHER		99
-
+#define MAX_CAPTURED_PACKETS 5000
+
+/* The following bit fields are used to set the various debug levels. */
+#define DTE_DEBUG_GENERAL          (1 << 0) /* 1  */
+#define DTE_DEBUG_CHANNEL_SETUP    (1 << 1) /* 2  */
+#define DTE_DEBUG_RTP_TX           (1 << 2) /* 4  */
+#define DTE_DEBUG_RTP_RX           (1 << 3) /* 8  */
+#define DTE_DEBUG_RX_TIMEOUT	   (1 << 4) /* 16 */
+#define DTE_DEBUG_NETWORK_IF       (1 << 5) /* 32 */
+#define DTE_DEBUG_NETWORK_EARLY    (1 << 6) /* 64 */
 
 int debug;
-static int debug_des;     /* Set the number of descriptor packet bytes to output on errors, 0 disables output */
-static int debug_des_cnt; /* Set the number of times descriptor packets are displayed before the output is disabled */
-static char *mode;
-static int debug_packets;
+char *mode;
+
+static spinlock_t wctc4xxp_list_lock;
+static struct list_head wctc4xxp_list;
+
+#define ETH_P_CSM_ENCAPS 0x889B
+
+struct rtphdr {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+	__u8    csrc_count:4;
+	__u8    extension:1;
+	__u8    padding:1;
+	__u8    ver:2;
+	__u8    type:7;
+	__u8 	marker:1;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+	__u8    ver:2;
+	__u8    padding:1;
+	__u8    extension:1;
+	__u8    csrc_count:4;
+	__u8 	marker:1;
+	__u8    type:7;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
+	__be16	seqno;
+	__be32  timestamp;
+	__be32  ssrc;
+} __attribute__((packed));
+
+struct rtp_packet {
+	struct ethhdr ethhdr;
+	struct iphdr  iphdr;
+	struct udphdr udphdr;
+	struct rtphdr rtphdr;
+	__u8   payload[0];
+}__attribute__((packed));
+
+/* Ethernet packet type for communication control information to the DTE. */
+struct csm_encaps_hdr {
+	struct ethhdr ethhdr;
+	/* CSM_ENCAPS HEADER */
+	__be16 op_code;
+	__u8   seq_num;
+	__u8   control;
+	__be16 channel;
+	/* COMMON PART OF PAYLOAD HEADER */
+	__u8   length;
+	__u8   index;
+	__u8   type;
+	__u8   class;
+	__le16 function;
+	__le16 reserved;
+	__le16 params[0];
+} __attribute__((packed));
+
+struct csm_create_channel_cmd {
+	struct csm_encaps_hdr hdr;
+	__le16 channel_type;
+	__le16 timeslot;
+} __attribute__((packed));
+
+#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 }
+
+#define CONTROL_PACKET_OPCODE  0x0001
+/* Control bits */
+#define LITTLE_ENDIAN   0x01
+#define SUPPRESS_ACK    0x40
+#define MESSAGE_PACKET  0x80
+
+#define SUPERVISOR_CHANNEL 0xffff
+
+/* Supervisor function codes */
+#define SUPVSR_CREATE_CHANNEL  0x0010
+
+#define CONFIG_CHANGE_TYPE        0x00 
+#define CONFIG_DEVICE_CLASS       0x06
+
+#define CMD_MSG_QUERY_CHANNEL_LEN 30
+#define CMD_MSG_QUERY_CHANNEL(s,t) { \
+	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
+	0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x01,0x06,0x10,0x00, 0x00,0x00, \
+	(t&0x00FF), ((t&0xFF00) >> 8) }
+
+#define CMD_MSG_TRANS_CONNECT_LEN 38
+#define CMD_MSG_TRANS_CONNECT(s,e,c1,c2,f1,f2) { \
+	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
+	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 }
+#define CMD_MSG_VOIP_DTMFOPT_LEN 32
+#define CMD_MSG_VOIP_DTMFOPT(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,0x02,0x80, 0x00,0x00, \
+	0x08,0x00, 0x00,0x00 }
+
+#define CMD_MSG_VOIP_TONECTL_LEN 32
+#define CMD_MSG_VOIP_TONECTL(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,0x5B,0x80, 0x00,0x00, \
+	0x00,0x00, 0x00,0x00 }
+
+#define SFRAME_SIZE 320 
+
+/* Transcoder buffer (tcb) */
+struct tcb {
+	/* First field so that is aligned by default. */
+	u8 cmd[SFRAME_SIZE];
+	struct list_head node;
+	unsigned long timeout;
+	unsigned long retries;
+	/* NOTE:  these flags aren't bit fields because some of the flags are
+	 * combinations of the other ones. */
+#define DO_NOT_AUTO_FREE        (1 << 0)
+#define TX_COMPLETE             (1 << 1)
+#define DO_NOT_CAPTURE          (1 << 2)
+#define __WAIT_FOR_ACK          (1 << 3)
+#define __WAIT_FOR_RESPONSE     (1 << 4) 
+#define DTE_CMD_TIMEOUT         (1 << 5)
+#define WAIT_FOR_ACK (__WAIT_FOR_ACK | DO_NOT_AUTO_FREE)
+#define WAIT_FOR_RESPONSE (__WAIT_FOR_RESPONSE | DO_NOT_AUTO_FREE)
+	unsigned long flags;
+	struct tcb *response;
+	struct completion complete;
+	struct timer_list timer;
+	void *data;
+	/* The number of bytes available in data. */
+	int data_len; 
+};
+
+static inline void *hdr_from_cmd(struct tcb *cmd) {
+	return cmd->data;
+}
+
+static inline void 
+initialize_cmd(struct tcb *cmd, unsigned long cmd_flags) 
+{
+	memset(cmd, 0, sizeof(*cmd));
+	INIT_LIST_HEAD(&cmd->node);
+	init_completion(&cmd->complete);
+	cmd->flags = cmd_flags;
+	cmd->data = &cmd->cmd[0];
+	cmd->data_len = SFRAME_SIZE;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+/*! Used to allocate commands to submit to the dte. */
+kmem_cache_t *cmd_cache;
+#else
+/*! Used to allocate commands to submit to the dte. */
+struct kmem_cache *cmd_cache;
+#endif
+
+static inline struct tcb *
+__alloc_cmd(unsigned alloc_flags, unsigned long cmd_flags)
+{
+	struct tcb *cmd;
+
+	cmd = kmem_cache_alloc(cmd_cache, alloc_flags);
+	if (likely(cmd)) {
+		initialize_cmd(cmd, cmd_flags);
+	}
+	return cmd;
+}
+
+static struct tcb *
+alloc_cmd(void)
+{
+	return __alloc_cmd(GFP_KERNEL, 0);
+}
+
+static void 
+__free_cmd(struct tcb *cmd)
+{
+	if (cmd->data != &cmd->cmd[0]) {
+		kfree(cmd->data);
+	}
+	kmem_cache_free(cmd_cache, cmd);
+	return;
+}
+
+static void 
+free_cmd(struct tcb *cmd)
+{
+	if (cmd->response) {
+		__free_cmd(cmd->response);
+	}
+	__free_cmd(cmd);
+}
+
+typedef enum { DECODER=0, ENCODER, } encode_t;
+
+struct channel_stats {
+	atomic_t packets_sent;
+	atomic_t packets_received;
+};
+
+struct channel_pvt {
+	spinlock_t lock;		/* Lock for this structure */
+	encode_t encoder;		/* If we're an encoder */
+	struct wcdte *wc;
+
+	unsigned int timestamp;
+	unsigned int seqno;
+
+	unsigned int cmd_seqno;
+
+	unsigned int timeslot_in_num;	/* DTE channel on which results will be received from */
+	unsigned int timeslot_out_num;	/* DTE channel to send data to */
+
+	unsigned int chan_in_num;	/* DTE channel on which results will be received from */
+	unsigned int chan_out_num;	/* DTE channel to send data to */
+	
+	struct channel_stats stats;
+
+	u16 last_dte_seqno;
+	unsigned int wctc4xxp_seqno_rcv;
+
+	unsigned char ssrc;
+	struct list_head rx_queue;	/* Transcoded packets for this channel. */
+};
+
+struct wcdte {
+	char board_name[40];
+	const char *variety;
+	int pos;
+	int cards;
+	struct list_head node;
+	spinlock_t reglock;
+	wait_queue_head_t waitq;
+	struct semaphore chansem;
+#define DTE_READY	1
+#define DTE_SHUTDOWN	2 
+	unsigned long flags;
+
+	spinlock_t cmd_list_lock;
+	/* This is a device-global list of commands that are waiting to be
+	 * transmited (and did not fit on the transmit descriptor ring) */
+	struct list_head cmd_list;
+	struct list_head waiting_for_response_list;
+
+	unsigned int seq_num;
+	unsigned char numchannels;
+	unsigned char complexname[40];
+
+	/* This section contains the members necessary to communicate with the
+	 * physical interface to the transcoding engine.  */
+	struct pci_dev *pdev;
+	unsigned int   intmask;
+	unsigned long  iobase;
+	struct wctc4xxp_descriptor_ring *txd;
+	struct wctc4xxp_descriptor_ring *rxd;
+	
+	struct dahdi_transcoder *uencode;
+	struct dahdi_transcoder *udecode;
+	struct channel_pvt *encoders;
+	struct channel_pvt *decoders;
+
+#if DEFERRED_PROCESSING == WORKQUEUE
+	struct work_struct deferred_work;
+#endif
+
+	/*
+	 * This section contains the members necessary for exporting the
+	 * network interface to the host system.  This is only used for
+	 * debugging purposes.
+	 *
+	 */
+	struct sk_buff_head captured_packets;
+	struct net_device *netdev;
+	struct net_device_stats net_stats;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+	struct napi_struct napi;
+#endif
+	struct timer_list watchdog;
+
+};
+
+static inline void wctc4xxp_set_ready(struct wcdte *wc) {
+	set_bit(DTE_READY, &wc->flags);
+}
+static inline int wctc4xxp_is_ready(struct wcdte *wc) {
+	return test_bit(DTE_READY, &wc->flags);
+}
+
+#if 1
+ /* \todo This macro is a candidate for removal.  It's still here because of
+ * how the commands are passed to this dahdi_send_cmd */
+#define wctc4xxp_send_cmd(wc, command) ({                                         \
+	int __res;                                                           \
+	u8 _cmd[] = command;                                                 \
+	struct tcb *cmd;                                                 \
+	if (!(cmd=__alloc_cmd(GFP_KERNEL, WAIT_FOR_RESPONSE)))               \
+		return -ENOMEM;                                              \
+	BUG_ON(sizeof(_cmd) > SFRAME_SIZE);                                  \
+	memcpy(cmd->data, _cmd, sizeof(_cmd));                               \
+	cmd->data_len = sizeof(_cmd);                                        \
+	__res = __wctc4xxp_send_cmd(wc, cmd);                                     \
+	__res;                                                               \
+})
+#define wctc4xxp_create_cmd(wc, command) ({                                       \
+	u8 _command[] = command;                                             \
+	struct tcb *_cmd;                                                \
+	if (!(_cmd=__alloc_cmd(GFP_KERNEL, WAIT_FOR_RESPONSE)))              \
+		return -ENOMEM;                                              \
+	BUG_ON(sizeof(_command) > SFRAME_SIZE);                              \
+	memcpy(_cmd->data, _command, sizeof(_command));                      \
+	_cmd->data_len = sizeof(_command);                                   \
+	_cmd;                                                                \
+})
+#endif
+
+#define DTE_FORMAT_ULAW   0x00
+#define DTE_FORMAT_G723_1 0x04
+#define DTE_FORMAT_ALAW   0x08
+#define DTE_FORMAT_G729A  0x12
+#define DTE_FORMAT_UNDEF  0xFF
+
+static inline u8 wctc4xxp_dahdifmt_to_dtefmt(unsigned int fmt)
+{
+	u8 pt;
+	
+	switch(fmt) {
+		case DAHDI_FORMAT_G723_1:
+			pt = DTE_FORMAT_G723_1;
+			break;
+		case DAHDI_FORMAT_ULAW:
+			pt = DTE_FORMAT_ULAW;
+			break;
+		case DAHDI_FORMAT_ALAW:
+			pt = DTE_FORMAT_ALAW;
+			break;
+		case DAHDI_FORMAT_G729A:
+			pt = DTE_FORMAT_G729A;
+			break;
+		default:
+			pt = DTE_FORMAT_UNDEF;
+			break;
+	}
+
+	return pt;
+}
+
+
+static struct sk_buff * 
+tcb_to_skb(struct net_device *netdev, const struct tcb *cmd)
+{
+	struct sk_buff *skb;
+	skb = alloc_skb(cmd->data_len, in_atomic() ? GFP_ATOMIC : GFP_KERNEL);
+	if (skb) {
+		skb->dev = netdev;
+		skb_put(skb, cmd->data_len);
+		memcpy(skb->data, cmd->data, cmd->data_len);
+		skb->protocol = eth_type_trans(skb,netdev);
+	}
+	return skb;
+}
+
+/** 
+ * wctc4xxp_skb_to_cmd - Convert a socket buffer (skb) to a tcb
+ * @wc: The transcoder that we're going to send this command to.
+ * @skb: socket buffer to convert.
+ *
+ */
+static struct tcb *
+wctc4xxp_skb_to_cmd(struct wcdte *wc, const struct sk_buff *skb)
+{
+	const unsigned long alloc_flags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
+	struct tcb *cmd;
+	/* const static char dev_mac[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55}; */
+	if ((cmd = __alloc_cmd(alloc_flags, 0))) {
+		int res;
+		cmd->data_len = skb->len;
+		if ((res = skb_copy_bits(skb, 0, cmd->data, cmd->data_len))) {
+			DTE_PRINTK(WARNING, 
+			   "Failed call to skb_copy_bits.\n");
+			free_cmd(cmd);
+			cmd = NULL;
+		}
+		/* When we set up our interface we indicated that we do not
+		 * support ARP.  Therefore, the destination MAC on packets
+		 * arriving from the kernel networking components are not
+		 * going to be correct. Let's fix that here.
+		 */
+		/* \todo let us just use whatever was in the packet already... */
+		/* memcpy(&cmd->cmd[6], dev_mac, sizeof(dev_mac)); */
+	}
+	return cmd;
+}
+
+static void 
+wctc4xxp_net_set_multi(struct net_device *netdev)
+{
+	struct wcdte *wc = netdev->priv;
+	DTE_DEBUG(DTE_DEBUG_GENERAL, "%s promiscuity:%d\n", 
+	   __FUNCTION__, netdev->promiscuity);
+}
+
+static int 
+wctc4xxp_net_up(struct net_device *netdev)
+{
+	struct wcdte *wc = netdev->priv;
+	DTE_DEBUG(DTE_DEBUG_GENERAL, "%s\n", __FUNCTION__);
+#if 1
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+	netif_poll_enable(netdev);
+#else
+	napi_enable(&wc->napi);
+#endif
+#endif
+	return 0;
+}
+
+static int 
+wctc4xxp_net_down(struct net_device *netdev)
+{
+	struct wcdte *wc = netdev->priv;
+	DTE_DEBUG(DTE_DEBUG_GENERAL, "%s\n", __FUNCTION__);
+#if 1
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+	netif_poll_disable(netdev);
+#else
+	napi_disable(&wc->napi);
+#endif
+#endif
+	return 0;
+}
+
+static void wctc4xxp_transmit_cmd(struct wcdte *, struct tcb *);
+
+static int 
+wctc4xxp_net_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct wcdte *wc = netdev->priv;
+	struct tcb *cmd;
+
+	/* We set DO_NOT_CAPTURE because this packet was already captured by
+	 * in code higher up in the networking stack.  We don't want to
+	 * capture it twice. 
+	 */
+	if ((cmd = wctc4xxp_skb_to_cmd(wc, skb))) {
+		cmd->flags |= DO_NOT_CAPTURE; 
+		wctc4xxp_transmit_cmd(wc, cmd);
+	}
+
+	dev_kfree_skb_any(skb);
+	return NETDEV_TX_OK;
+}
+
+static int 
+wctc4xxp_net_receive(struct wcdte *wc, int max)
+{
+	int count = 0;
+	struct sk_buff *skb;
+	WARN_ON(0 == max);
+	while ((skb = skb_dequeue(&wc->captured_packets))) {
+		netif_receive_skb(skb);
+		if (++count >= max) {
+			break;
+		}
+	}
+	return count;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+static int 
+wctc4xxp_poll(struct net_device *netdev, int *budget)
+{
+	struct wcdte *wc = netdev->priv;
+	int count = 0;
+	int quota = min(netdev->quota, *budget);
+
+	count = wctc4xxp_net_receive(wc, quota);
+
+	*budget -=       count;
+	netdev->quota -= count;
+
+	if (!skb_queue_len(&wc->captured_packets)) {
+		netif_rx_complete(netdev);
+		return 0;
+	} else {
+		return -1;
+	}
+}
+#else
+static int 
+wctc4xxp_poll(struct napi_struct *napi, int budget)
+{
+	struct wcdte *wc = container_of(napi, struct wcdte, napi);
+	int count;
+
+	count = wctc4xxp_net_receive(wc, budget);
+
+	if (!skb_queue_len(&wc->captured_packets)) {
+		netif_rx_complete(wc->netdev, &wc->napi);
+	}
+	return count;
+}
+#endif
+
+static struct net_device_stats *
+wctc4xxp_net_get_stats(struct net_device *netdev)
+{
+	struct wcdte *wc = netdev->priv;
+	return &wc->net_stats;
+}
+
+/* Wait until this device is put into promiscuous mode, or we timeout. */
+static void 
+wctc4xxp_net_waitfor_promiscuous(struct wcdte *wc)
+{
+	unsigned int seconds = 15;
+	unsigned long start = jiffies;
+	struct net_device *netdev = wc->netdev;
+
+	DTE_PRINTK(INFO, 
+	   "Waiting %d seconds for adapter to be placed in " \
+	   "promiscuous mode for early trace.\n", seconds);
+
+	while (!netdev->promiscuity) {
+		if (signal_pending(current)) {
+			DTE_PRINTK(INFO, 
+			   "Aborting wait due to signal.\n");
+			break;
+		}
+		msleep(100);
+		if (time_after(jiffies, start + (seconds * HZ))) {
+			DTE_PRINTK(INFO,
+			   "Aborting wait due to timeout.\n");
+			break;
+		}
+	}
+}
+
+static int  wctc4xxp_turn_off_booted_led(struct wcdte *wc);
+static void wctc4xxp_turn_on_booted_led(struct wcdte *wc);
+
+static int 
+wctc4xxp_net_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+	struct wcdte *wc = netdev->priv;
+	switch(cmd) {
+	case 0x89f0:
+		down(&wc->chansem);
+		wctc4xxp_turn_off_booted_led(wc);
+		break;
+	case 0x89f1:
+		wctc4xxp_turn_on_booted_led(wc);
+		up(&wc->chansem);
+		break;
+	default:
+		return -EOPNOTSUPP;
+	};
+	return 0;
+}
+
+/** 
+ * wctc4xxp_net_register - Register a new network interface.
+ * @wc: transcoder card to register the interface for.
+ *
+ * The network interface is primarily used for debugging in order to watch the
+ * traffic between the transcoder and the host.
+ * 
+ */
+static int 
+wctc4xxp_net_register(struct wcdte *wc)
+{
+	int res;
+	struct net_device *netdev;
+	const char our_mac[] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
+
+	if (!(netdev = alloc_netdev(0, wc->board_name, ether_setup))) {
+		return -ENOMEM;
+	}
+
+	memcpy(netdev->dev_addr, our_mac, sizeof(our_mac));
+	netdev->priv = wc;
+	netdev->set_multicast_list = &wctc4xxp_net_set_multi;
+	netdev->open = &wctc4xxp_net_up;
+	netdev->stop = &wctc4xxp_net_down;
+	netdev->hard_start_xmit = &wctc4xxp_net_hard_start_xmit;
+	netdev->get_stats = &wctc4xxp_net_get_stats;
+	netdev->do_ioctl = &wctc4xxp_net_ioctl;
+	netdev->promiscuity = 0;
+	netdev->flags |= IFF_NOARP;
+#	if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+	netdev->poll = &wctc4xxp_poll;
+	netdev->weight = 64;
+#	else
+	netif_napi_add(netdev, &wc->napi, &wctc4xxp_poll, 64);
+#	endif
+
+	if ((res = register_netdev(netdev))) {
+		DTE_PRINTK(WARNING, 
+		   "Failed to register network device %s.\n",
+		   wc->board_name);
+		goto error_sw;
+	}
+
+	wc->netdev = netdev;
+	skb_queue_head_init(&wc->captured_packets);
+
+	if (debug & DTE_DEBUG_NETWORK_EARLY) {
+		wctc4xxp_net_waitfor_promiscuous(wc);
+	}
+
+	DTE_PRINTK(DEBUG, 
+	   "Created network device %s for debug.\n", wc->board_name);
+	return 0;
+
+error_sw:
+	if (netdev) free_netdev(netdev);
+	return res;
+}
+
+static void 
+wctc4xxp_net_unregister(struct wcdte *wc)
+{
+	struct sk_buff *skb;
+	if (!wc->netdev) {
+		return;
+	}
+
+	unregister_netdev(wc->netdev);
+
+	while ((skb = skb_dequeue(&wc->captured_packets))) {
+		kfree_skb(skb);
+	}
+	
+	free_netdev(wc->netdev);
+	wc->netdev = NULL;
+}
+
+
+/**
+ * wctc4xxp_net_capture_cmd - Send a tcb to the network stack.
+ * @wc: transcoder that received the command.
+ * @cmd: command to send to network stack.
+ *
+ */
+static void 
+wctc4xxp_net_capture_cmd(struct wcdte *wc, const struct tcb *cmd)
+{
+	struct sk_buff *skb;
+	struct net_device *netdev = wc->netdev;
+
+	if (!netdev) {
+		return;
+	}
+
+	/* No need to capture if there isn't anyone listening. */
+	if (!(netdev->flags & IFF_UP)) {
+		return;
+	}
+	
+	if (skb_queue_len(&wc->captured_packets) > MAX_CAPTURED_PACKETS) {
+		WARN_ON_ONCE(1);
+		return;
+	}
+
+	if (!(skb = tcb_to_skb(netdev, cmd))) {
+		return;
+	}
+
+	skb_queue_tail(&wc->captured_packets, skb);
+#	if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+	netif_rx_schedule(netdev);
+#	else
+	netif_rx_schedule(netdev, &wc->napi);
+#	endif
+	return;
+}
+
 
 /*! In-memory structure shared by the host and the adapter. */
-struct dte_descriptor {
+struct wctc4xxp_descriptor {
 	__le32 des0;
 	__le32 des1;
 	__le32 buffer1;
@@ -110,15 +902,15 @@
 #define DRING_MASK (DRING_SIZE-1)
 #define MIN_PACKET_LEN  64
 
-struct dte_descriptor_ring {
+struct wctc4xxp_descriptor_ring {
 	/* Pointer to an array of descriptors to give to hardware. */
-	struct dte_descriptor* desc;
+	struct wctc4xxp_descriptor* desc;
 	/* Read completed buffers from the head. */
 	unsigned int 	head;
 	/* Write ready buffers to the tail. */
 	unsigned int 	tail;
 	/* Array to save the kernel virtual address of pending commands. */
-	struct dte_cmd *pending[DRING_SIZE];
+	struct tcb *pending[DRING_SIZE];
 	/* PCI Bus address of the descriptor list. */
 	dma_addr_t	desc_dma;
 	/*! either DMA_FROM_DEVICE or DMA_TO_DEVICE */
@@ -133,28 +925,29 @@
 	struct pci_dev  *pdev;
 };
 
-/* Returns the desriptor at index.
+/**
+ * wctc4xxp_descriptor - Returns the desriptor at index.
+ * @dr: The descriptor ring we're using.
+ * @index: index of the descriptor we want.
  * 
  * We need this function because we do not know what the padding on the
- * descriptors will be.
+ * descriptors will be.  Otherwise, we would just use an array.
  */
-static inline struct dte_descriptor *
-dte_descriptor(struct dte_descriptor_ring *dr, int index)
-{
-	struct dte_descriptor *d;
-	d = (struct dte_descriptor *)((u8*)dr->desc + 
-		((sizeof(*d) + dr->padding) * index));
-	return d;
+static inline struct wctc4xxp_descriptor *
+wctc4xxp_descriptor(struct wctc4xxp_descriptor_ring *dr, int index)
+{
+	return (struct wctc4xxp_descriptor *)((u8*)dr->desc + 
+		((sizeof(*dr->desc) + dr->padding) * index));
 }
 
 static int
-dte_initialize_descriptor_ring(struct pci_dev *pdev, struct dte_descriptor_ring *dr, 
+wctc4xxp_initialize_descriptor_ring(struct pci_dev *pdev, struct wctc4xxp_descriptor_ring *dr, 
 	u32 des1, unsigned int direction)
 {
 	int i; 
 	const u32 END_OF_RING = 0x02000000;
 	u8 cache_line_size = 0;
-	struct dte_descriptor *d;
+	struct wctc4xxp_descriptor *d;
 
 	BUG_ON(!pdev);
 	BUG_ON(!dr);
@@ -187,7 +980,7 @@
 
 	memset(dr->desc, 0, (sizeof(*d) + dr->padding) * DRING_SIZE);
 	for (i = 0; i < DRING_SIZE; ++i) {
-		d = dte_descriptor(dr, i);
+		d = wctc4xxp_descriptor(dr, i);
 		d->des1 = cpu_to_le32(des1);
 	}
 
@@ -203,24 +996,21 @@
 
 const unsigned int BUFFER1_SIZE_MASK = 0x7ff;
 
-/*! Submit a command to the descriptor list for processing by the DTE. */
 static int 
-dte_submit(struct dte_descriptor_ring* dr, struct dte_cmd *c)
-{
-	volatile struct dte_descriptor *d;
-	unsigned int tail = dr->tail;
+wctc4xxp_submit(struct wctc4xxp_descriptor_ring* dr, struct tcb *c)
+{
+	volatile struct wctc4xxp_descriptor *d;
 	unsigned int len;
 
 	WARN_ON(!c);
 	len = (c->data_len < MIN_PACKET_LEN) ? MIN_PACKET_LEN : c->data_len;
 	if (c->data_len > 1518) {
-		printk(KERN_ERR "Invalid frame size: %d.\n", c->data_len);
-		return -EBUSY;
+		WARN_ON_ONCE(!"Invalid command length passed\n");
+		c->data_len = 1518;
 	}
 
 	spin_lock_bh(&dr->lock);
-
-	d = dte_descriptor(dr, tail); 
+	d = wctc4xxp_descriptor(dr, dr->tail); 
 	WARN_ON(!d);
 	if (d->buffer1) {
 		spin_unlock_bh(&dr->lock);
@@ -233,24 +1023,21 @@
 	                            SFRAME_SIZE, dr->direction);
 
 	SET_OWNED(d); /* That's it until the hardware is done with it. */ 
-
-	dr->pending[tail] = c;
-	dr->tail = (++tail) & DRING_MASK; 
+	dr->pending[dr->tail] = c;
+	dr->tail = ++dr->tail & DRING_MASK;
 	++dr->count;
-
 	spin_unlock_bh(&dr->lock);
-
 	return 0;
 }
 
-static inline struct dte_cmd* 
-dte_retrieve(struct dte_descriptor_ring *dr)
-{
-	volatile struct dte_descriptor *d;
-	struct dte_cmd *c;
+static inline struct tcb* 
+wctc4xxp_retrieve(struct wctc4xxp_descriptor_ring *dr)
+{
+	volatile struct wctc4xxp_descriptor *d;
+	struct tcb *c;
 	unsigned int head = dr->head;
 	spin_lock_bh(&dr->lock);
-	d = dte_descriptor(dr, head);
+	d = wctc4xxp_descriptor(dr, head);
 	if (d->buffer1 && !OWNED(d)) {
 		pci_unmap_single(dr->pdev, d->buffer1, 
 		                 SFRAME_SIZE, dr->direction);
@@ -261,6 +1048,7 @@
 		--dr->count;
 		WARN_ON(!c);
 		c->data_len = (d->des0 >> 16) & BUFFER1_SIZE_MASK;
+		c->flags |= TX_COMPLETE;
 	} else {
 		c = NULL;
 	}
@@ -268,7 +1056,7 @@
 	return c;
 }
 
-static inline int dte_getcount(struct dte_descriptor_ring *dr) 
+static inline int wctc4xxp_getcount(struct wctc4xxp_descriptor_ring *dr) 
 {
 	int count;
 	spin_lock_bh(&dr->lock);
@@ -277,34 +1065,36 @@
 	return count;
 }
 
-static inline void __wcdte_setctl(struct wcdte *wc, unsigned int addr, unsigned int val)
+static inline void 
+__wctc4xxp_setctl(struct wcdte *wc, unsigned int addr, unsigned int val)
 {
 	outl(val, wc->iobase + addr);
 }
 
-static inline unsigned int __wcdte_getctl(struct wcdte *wc, unsigned int addr)
+static inline unsigned int 
+__wctc4xxp_getctl(struct wcdte *wc, unsigned int addr)
 {
 	return inl(wc->iobase + addr);
 }
 
-static inline void wcdte_setctl(struct wcdte *wc, unsigned int addr, unsigned int val)
+static inline void 
+wctc4xxp_setctl(struct wcdte *wc, unsigned int addr, unsigned int val)
 {
 	spin_lock_bh(&wc->reglock);
-	__wcdte_setctl(wc, addr, val);
+	__wctc4xxp_setctl(wc, addr, val);
 	spin_unlock_bh(&wc->reglock);
 }
 
-/* Instruct the DTE to read in the next rx descriptor */
-static inline void dte_receive_demand_poll(struct wcdte *wc) 
-{
-	__wcdte_setctl(wc, 0x0010, 0x00000000);
-}
-
-/* Instruct the DTE to read in the next tx descriptor */
-static inline void dte_transmit_demand_poll(struct wcdte *wc)
-{
-	// spin_lock_bh(&wc->reglock);
-	__wcdte_setctl(wc, 0x0008, 0x00000000);
+static inline void 
+wctc4xxp_receive_demand_poll(struct wcdte *wc) 
+{
+	__wctc4xxp_setctl(wc, 0x0010, 0x00000000);
+}
+
+static inline void 
+wctc4xxp_transmit_demand_poll(struct wcdte *wc)
+{
+	__wctc4xxp_setctl(wc, 0x0008, 0x00000000);
 
 	/* \todo Investigate why this register needs to be written twice in
 	 * order to get it to poll reliably.  So far, most of the problems
@@ -312,25 +1102,169 @@
 	 * packet sitting in the outbound descriptor list as opposed to any
 	 * problem with the dte firmware.
 	 */
-	__wcdte_setctl(wc, 0x0008, 0x00000000);
-	// spin_unlock_bh(&wc->reglock);
-}
-
+	__wctc4xxp_setctl(wc, 0x0008, 0x00000000);
+}
+
+/* Returns the size, in bytes, of a CSM_ENCAPS packet, given the number of
+ * parameters used. */
+#define SIZE_WITH_N_PARAMETERS(__n) (sizeof(struct csm_encaps_hdr) + ((__n) * (sizeof(u16))))
+
+/* There are 20 bytes in the ethernet header and the common CSM_ENCAPS header
+ * that we don't want in the length of the actual CSM_ENCAPS command */
+#define LENGTH_WITH_N_PARAMETERS(__n) (SIZE_WITH_N_PARAMETERS(__n) - 20)
+
+static const u8 dst_mac[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
+static const u8 src_mac[6] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
+
+static void 
+setup_common_header(struct wcdte *wc, struct csm_encaps_hdr *hdr)
+{
+	memcpy(hdr->ethhdr.h_dest, dst_mac, sizeof(dst_mac));
+	memcpy(hdr->ethhdr.h_source, src_mac, sizeof(src_mac));
+	hdr->ethhdr.h_proto = cpu_to_be16(ETH_P_CSM_ENCAPS);
+}
+
+static void 
+setup_supervisor_header(struct wcdte *wc, struct csm_encaps_hdr *hdr)
+{
+	setup_common_header(wc, hdr);
+
+	hdr->op_code = cpu_to_be16(CONTROL_PACKET_OPCODE);
+	hdr->control = LITTLE_ENDIAN;
+	hdr->seq_num = (wc->seq_num++)&0xf;
+	hdr->channel = cpu_to_be16(SUPERVISOR_CHANNEL);
+}
+
+static void  
+__wctc4xxp_create_channel_cmd(struct wcdte *wc, struct tcb *cmd, u16 timeslot)
+{
+	struct csm_create_channel_cmd *c; 
+	c = hdr_from_cmd(cmd);
+
+	BUG_ON(timeslot > 0x01ff);
+
+	setup_supervisor_header(wc, &c->hdr);
+
+	c->hdr.length =    LENGTH_WITH_N_PARAMETERS(2);
+	c->hdr.index =     0x0;
+	c->hdr.type  =     CONFIG_CHANGE_TYPE;
+	c->hdr.class =     CONFIG_DEVICE_CLASS;
+	c->hdr.function =  cpu_to_le16(SUPVSR_CREATE_CHANNEL);
+	c->hdr.reserved =  0x0000;
+
+	c->channel_type = cpu_to_le16(0x0002); /* Channel type is VoIP */
+	c->timeslot =     cpu_to_le16(timeslot);
+
+	cmd->flags |= WAIT_FOR_RESPONSE;
+	cmd->data_len = sizeof(*c);
+}
+
+struct tcb * 
+wctc4xxp_create_channel_cmd(struct wcdte *wc, u16 timeslot)
+{
+	struct tcb *cmd;
+	if (!(cmd = alloc_cmd())) {
+		return NULL;
+	}
+	__wctc4xxp_create_channel_cmd(wc, cmd, timeslot);
+	return cmd;
+}
+
+void 
+__wctc4xxp_create_set_arm_clk_cmd(struct wcdte *wc, struct tcb *cmd)
+{
+	struct csm_encaps_hdr *hdr = cmd->data;
+	BUG_ON(SIZE_WITH_N_PARAMETERS(2) > cmd->data_len);
+
+	setup_supervisor_header(wc, hdr);
+
+	hdr->length =		LENGTH_WITH_N_PARAMETERS(2);
+	hdr->index =		0x0;
+	hdr->type =		CONFIG_CHANGE_TYPE;
+	hdr->class =		CONFIG_DEVICE_CLASS;
+	hdr->function =		cpu_to_le16(0x0411);
+	hdr->reserved =		0x0000;
+	hdr->params[0] =	cpu_to_le16(0x012c);
+	hdr->params[1] =	cpu_to_le16(0x0000);
+
+	cmd->flags |= WAIT_FOR_RESPONSE;
+	cmd->data_len = SIZE_WITH_N_PARAMETERS(2);
+	return;
+}
+
+struct tcb *
+wctc4xxp_create_rtp_cmd(struct wcdte *wc, struct dahdi_transcoder_channel *dtc, size_t inbytes)
+{
+	const struct channel_pvt *cpvt = dtc->pvt;
+	struct rtp_packet *packet;
+	struct tcb *cmd;
+
+	if (!(cmd = alloc_cmd())) {
+		return NULL;
+	}
+
+	packet = cmd->data;
+
+	BUG_ON(cmd->data_len < sizeof(*packet));
+	
+	/* setup the ethernet header */
+	memcpy(packet->ethhdr.h_dest, dst_mac, sizeof(dst_mac));
+	memcpy(packet->ethhdr.h_source, src_mac, sizeof(src_mac));
+	packet->ethhdr.h_proto = cpu_to_be16(ETH_P_IP);
+	
+	/* setup the IP header */
+	packet->iphdr.ihl =	5;
+	packet->iphdr.version =	4;
+	packet->iphdr.tos =	0;
+	packet->iphdr.tot_len =	cpu_to_be16(inbytes+40);
+	packet->iphdr.id =	cpu_to_be16(cpvt->seqno);
+	packet->iphdr.frag_off=	cpu_to_be16(0x4000);
+	packet->iphdr.ttl =	64;
+	packet->iphdr.protocol=	0x11; /* UDP */
+	packet->iphdr.check =	0;
+	packet->iphdr.saddr =	cpu_to_be32(0xc0a80903);
+	packet->iphdr.daddr =	cpu_to_be32(0xc0a80903);
+	packet->iphdr.check =	ip_fast_csum((void*)&packet->iphdr, sizeof(struct iphdr));
+
+	/* setup the UDP header */
+	packet->udphdr.source =	cpu_to_be16(cpvt->timeslot_out_num + 0x5000);
+	packet->udphdr.dest =	cpu_to_be16(cpvt->timeslot_in_num + 0x5000);
+	packet->udphdr.len  =	cpu_to_be16(inbytes + sizeof(struct rtphdr) + sizeof(struct udphdr));
+	packet->udphdr.check =	0;
+
+	/* Setup the RTP header */
+	packet->rtphdr.ver =		2;
+	packet->rtphdr.padding =	0;
+	packet->rtphdr.extension =	0;
+	packet->rtphdr.csrc_count =	0;
+	packet->rtphdr.marker =		0;
+	packet->rtphdr.type =		wctc4xxp_dahdifmt_to_dtefmt(dtc->srcfmt);
+	packet->rtphdr.seqno =		cpu_to_be16(cpvt->seqno);
+	packet->rtphdr.timestamp =	cpu_to_be32(cpvt->timestamp);
+	packet->rtphdr.ssrc =		cpu_to_be32(cpvt->ssrc);
+
+	cmd->data_len = sizeof(*packet) + inbytes;
+
+	return cmd;
+}
 static void
-wcdte_cleanup_descriptor_ring(struct dte_descriptor_ring *dr) 
+wctc4xxp_cleanup_descriptor_ring(struct wctc4xxp_descriptor_ring *dr) 
 {

[... 2361 lines stripped ...]



More information about the dahdi-commits mailing list