[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