diff options
author | mogorman <mogorman@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2006-12-11 19:45:18 +0000 |
---|---|---|
committer | mogorman <mogorman@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2006-12-11 19:45:18 +0000 |
commit | 2f198d98a8150963b7154c18930173b8b871f6c3 (patch) | |
tree | 19e2a7ec583c6741bd008c01b7d3b167a46ab37b /ztcodec_dte.c | |
parent | 1bfb68dfe23e791a6dacc7b59a65e6f5341c4973 (diff) |
updates for dynamic channel creation on transcoder card.
from jsloan's branch
git-svn-id: http://svn.digium.com/svn/zaptel/trunk@1703 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'ztcodec_dte.c')
-rw-r--r-- | ztcodec_dte.c | 855 |
1 files changed, 536 insertions, 319 deletions
diff --git a/ztcodec_dte.c b/ztcodec_dte.c index 8db9a74..da43dfe 100644 --- a/ztcodec_dte.c +++ b/ztcodec_dte.c @@ -23,6 +23,7 @@ * */ + #include <linux/kernel.h> #include <linux/errno.h> #include <linux/module.h> @@ -37,6 +38,9 @@ #include <linux/mman.h> #include <linux/delay.h> #include <asm/io.h> +#include <asm/semaphore.h> +#include <linux/jiffies.h> +#include <linux/workqueue.h> #ifdef CONFIG_DEVFS_FS #include <linux/devfs_fs_kernel.h> #endif @@ -45,9 +49,7 @@ #else #include <linux/zaptel.h> #endif -#ifdef LINUX26 #include <linux/moduleparam.h> -#endif #include "dte_firm.h" @@ -59,6 +61,7 @@ #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 #define DTE_FORMAT_ULAW 0x00 @@ -67,19 +70,21 @@ #define DTE_FORMAT_G729A 0x12 #define DTE_FORMAT_UNDEF 0xFF -/* #define COMPLEX_CODEC DTE_FORMAT_G723_1 */ -#define COMPLEX_CODEC DTE_FORMAT_G729A -#define SIMPLE_CODEC DTE_FORMAT_ULAW +#define G729_LENGTH 20 +#define G723_LENGTH 30 -#define SAMPLE_LENGTH 20 +#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 PACKET_OUT_SIZE 160 /* g.729 */ -/* #define PACKET_OUT_SIZE 240 */ /* 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 @@ -95,126 +100,179 @@ -#define RCV_CSMENCAPS 1 -#define RCV_RTP 2 -#define RCV_OTHER 99 +#define RCV_CSMENCAPS 1 +#define RCV_RTP 2 +#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, 0x01, 0xFF,0xFF, 0x0A, 0x01, 0x00,0x06,0x17,0x04, 0xFF,0xFF, 0x04,0x00} - +#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, 0x01, 0xFF,0xFF, 0x0A, 0x02, 0x00,0x06,0x05,0x04, 0xFF,0xFF, 0x04,0x00} - +#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, 0x01, 0xFF,0xFF, 0x10, p1, 0x00,0x06,0x07,0x04, 0xFF,0xFF, p2,0x83, 0x00,0x0C, 0x00,0x00, p3,0x00} - +#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, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x35,0x04, 0xFF,0xFF, 0x00,0x00} - - - +#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, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x1B,0x04, 0xFF,0xFF, 0x00,0x00} - - - - +#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, 0x01, 0xFF,0xFF, 0x0C, 0x00, 0x00,0x06,0x11,0x04, 0x00,0x00, 0x2C,0x01, 0x00,0x00} - +#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, 0x01, 0xFF,0xFF, 0x0C, 0x00, 0x00,0x06,0x12,0x04, 0x00,0x00, 0x2C,0x01, 0x00,0x00} - - - -#define CMD_MSG_ACK_LEN 20 -#define CMD_MSG_ACK(s,c1,c2) {0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, 0x00,0x01, s, 0xE0, c1, c2} - +#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, 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_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, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x02,0x03, 0xFF,0xFF, 0x00,0x02} - - +#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, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x05,0x01, 0xFF,0xFF, 0x01,0x00} - +#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, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x04,0x03, 0xFF,0xFF, 0x01,0xFF} - -#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, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x13,0x00, 0xFF,0xFF, p1,0x00} - +#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, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x06,0x03, 0xFF,0xFF, 0x02,0x00} - - - - +#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,t1,t2) {0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, 0x00,0x01, s, 0x01, 0xFF,0xFF, 0x0C, 0x00, 0x00,0x06,0x10,0x00, 0x00,0x00, 0x02,0x00, t1, t2} - - +#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,c1,c2,s1,s2,s3,s4) {0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, 0x00,0x01, s, 0x01, c1,c2, 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, s1,s2, s3,s4, 0x00,0x00, 0x00,0x00} - +#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,c1,c2,t,w) {0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, 0x00,0x01, s, 0x01, c1,c2, 0x12, 0x00, 0x00,0x02,0x01,0x80, 0x00,0x00, 0x31,t, 0x00,0x1C, 0x04,0x00, 0x00,0x00, w,0x00, 0x80,0x11} - -#define CMD_MSG_TRANS_CONNECT_LEN 38 -#define CMD_MSG_TRANS_CONNECT(s,e,c1,c2,c3,c4) {0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, 0x00,0x01, s, 0x01, 0xFF,0xFF, 0x12, 0x00, 0x00,0x06,0x22,0x93, 0x00,0x00, e,0x00, c1,c2, COMPLEX_CODEC,0x00, c3,c4, 0x00,0x00} - - +#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,c1,c2,f) {0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, 0x00,0x01, s, 0x01, c1,c2, 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(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,c1,c2,f) {0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, 0x00,0x01, s, 0x01, c1,c2, 0x0A, 0x00, 0x00,0x02,0x00,0x80, 0x00,0x00, 0x00,0x00, 0x00,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, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x0F,0x04, 0xFF,0xFF, 0x05,0x00} - - +#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 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); \ - do { \ - ret = wcdte_waitfor_csmencaps(wc); \ - if (ret == 1) \ - return(1); \ - } while ((wc->last_rcommand != hex) && (ret != 2)); \ + __transmit_demand(wc); \ + up(&wc->cmdqsem); \ + ret = wcdte_waitfor_csmencaps(wc, RCV_CSMENCAPS, 0); \ + if (ret == 1) \ + return(1); \ } while (ret == 2); \ }) - - /* define NOT_BLI to use a faster but not bit-level identical version */ /* #define NOT_BLI */ @@ -234,7 +292,6 @@ struct cmdq { unsigned int cmd[MAX_COMMAND_LEN]; }; - struct wcdte { struct pci_dev *dev; char *variety; @@ -250,13 +307,24 @@ struct wcdte { spinlock_t reglock; wait_queue_head_t regq; int rcvflags; - + + struct semaphore chansem; + struct semaphore cmdqsem; struct cmdq cmdq[MAX_COMMANDS]; unsigned int cmdq_wndx; unsigned int cmdq_rndx; + + unsigned int last_command_sent; unsigned int last_rcommand; + unsigned int last_rparm2; unsigned int seq_num; + unsigned int ztsnd_rtx; + unsigned int ztsnd_0010_rtx; + + unsigned char numchannels; + unsigned char complexname[40]; + unsigned long iobase; dma_addr_t readdma; dma_addr_t writedma; @@ -265,10 +333,16 @@ struct wcdte { volatile unsigned int *readchunk; /* Double-word aligned read memory */ volatile unsigned int *descripchunk; /* Descriptors */ + int wqueints; + struct workqueue_struct *dte_wq; + struct work_struct dte_work; + struct zt_transcoder *uencode; struct zt_transcoder *udecode; }; +static void dte_wque_run(struct wcdte *wc); + struct wcdte_desc { char *name; int flags; @@ -296,9 +370,12 @@ struct dte_state { unsigned int timestamp; unsigned int seqno; - unsigned int phys_in_chan; /* DTE chennel on which results we be received from */ - unsigned int phys_out_chan; /* DTE channel to send data to */ + 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,12 +384,17 @@ struct dte_state { }; -static int numchannels = NUM_CHANNELS - 1; 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; +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); static void dte_init_state(struct dte_state *state_ptr, int encoder, unsigned int channel, struct wcdte *wc) @@ -326,19 +408,22 @@ static void dte_init_state(struct dte_state *state_ptr, int encoder, unsigned in 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 == 1) { - state_ptr->phys_in_chan = channel * 2; - state_ptr->phys_out_chan = channel * 2 + 1; + state_ptr->timeslot_in_num = channel * 2; + state_ptr->timeslot_out_num = channel * 2 + 1; } else { - state_ptr->phys_in_chan = channel * 2 + 1; - state_ptr->phys_out_chan = channel * 2; + state_ptr->timeslot_in_num = channel * 2 + 1; + state_ptr->timeslot_out_num = channel * 2; } } -static unsigned int dte_fmt_to_pt(unsigned int fmt) +static unsigned int wcdte_zapfmt_to_dtefmt(unsigned int fmt) { unsigned int pt; @@ -414,8 +499,8 @@ static inline int __transmit_demand(struct wcdte *wc) int o2,i,j; unsigned int reg, xmt_length; - reg = __wcdte_getctl(wc, 0x0028) & 0x00700000; - + reg = wcdte_getctl(wc, 0x0028) & 0x00700000; + /* Already transmiting, no need to demand another */ if (!((reg == 0) || (reg = 6))) return(1); @@ -449,10 +534,18 @@ static inline int __transmit_demand(struct wcdte *wc) 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); - __wcdte_setctl(wc, 0x0008, 0x00000000); /* Transmit Poll Demand */ + wcdte_setctl(wc, 0x0008, 0x00000000); /* Transmit Poll Demand */ wc->tdbl = (wc->tdbl + 1) % ERING_SIZE; @@ -463,18 +556,18 @@ static inline int __transmit_demand(struct wcdte *wc) static inline int transmit_demand(struct wcdte *wc) { - unsigned long flags; int val; - spin_lock_irqsave(&wc->reglock, flags); + down(&wc->cmdqsem); val = __transmit_demand(wc); - spin_unlock_irqrestore(&wc->reglock, flags); + up(&wc->cmdqsem); return val; } static int dte_operation(struct zt_transcoder_channel *ztc, int op) { - struct dte_state *st = ztc->pvt; + struct zt_transcoder_channel *compl_ztc; + struct dte_state *st = ztc->pvt, *compl_st; struct zt_transcode_header *zth = ztc->tch; struct wcdte *wc = st->wc; unsigned char *chars; @@ -482,18 +575,74 @@ static int dte_operation(struct zt_transcoder_channel *ztc, int op) unsigned int timestamp_inc = 0; int i = 0; int res = 0; - unsigned long flags; - unsigned int ipchksum; + unsigned int ipchksum, ndx; switch(op) { case ZT_TCOP_RESET: + down(&wc->chansem); + if (ztc->chan_built == 0) + { + if (st->encoder == 1) + wcdte_create_channel(wc, wcdte_zapfmt_to_dtefmt(zth->srcfmt), wcdte_zapfmt_to_dtefmt(zth->dstfmt), + st->timeslot_in_num, st->timeslot_out_num, &(st->chan_in_num), &(st->chan_out_num)); + else + wcdte_create_channel(wc, wcdte_zapfmt_to_dtefmt(zth->dstfmt), wcdte_zapfmt_to_dtefmt(zth->srcfmt), + st->timeslot_out_num, st->timeslot_in_num, &(st->chan_out_num), &(st->chan_in_num)); + /* 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_TRANSCODE: + case ZT_TCOP_RELEASE: + down(&wc->chansem); + ndx = st->timeslot_in_num/2; + + if (st->encoder == 1) + compl_ztc = &(wc->udecode->channels[ndx]); + else + compl_ztc = &(wc->uencode->channels[ndx]); + + /* If the channel complement (other half of the encoder/decoder pair) is not being used... */ + if ((compl_ztc->flags & ZT_TC_FLAG_BUSY) == 0) + { + if (st->encoder == 1) + wcdte_destroy_channel(wc, st->chan_in_num, st->chan_out_num); + else + wcdte_destroy_channel(wc, st->chan_out_num, st->chan_in_num); - spin_lock_irqsave(&wc->reglock, flags); + /* Mark this channel as not built */ + ztc->chan_built = 0; + ztc->built_fmts = 0; + st->chan_in_num = 999; + st->chan_out_num = 999; + + /* Mark the channel complement as not built */ + compl_ztc->chan_built = 0; + compl_ztc->built_fmts = 0; + compl_st = compl_ztc->pvt; + compl_st->chan_in_num = 999; + compl_st->chan_out_num = 999; + } + st->dte_seqno_rcv = 0; + up(&wc->chansem); + break; + case ZT_TCOP_TRANSCODE: - if ( (((zth->srcfmt == ZT_FORMAT_ULAW) || (zth->srcfmt == ZT_FORMAT_ALAW)) && (zth->srclen >= 160)) - || ((zth->srcfmt == ZT_FORMAT_G729A) && (zth->srclen >= 20)) - || ((zth->srcfmt == ZT_FORMAT_G723_1) && (zth->srclen >= 24)) ) + 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 { @@ -501,42 +650,48 @@ static int dte_operation(struct zt_transcoder_channel *ztc, int op) if ((zth->srcfmt == ZT_FORMAT_ULAW) || (zth->srcfmt == ZT_FORMAT_ALAW)) { - inbytes = 160; /* 80; */ - timestamp_inc = 160; /* 80; */ + 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; + } + } else if (zth->srcfmt == ZT_FORMAT_G729A) { - inbytes = 20; /* 10; */ - timestamp_inc = 160; /* 80; */ + inbytes = G729_BYTES; + timestamp_inc = G729_SAMPLES; } else if (zth->srcfmt == ZT_FORMAT_G723_1) { - inbytes = 24; - timestamp_inc = 240; + inbytes = G723_BYTES; + timestamp_inc = G723_SAMPLES; } zth->srclen -= inbytes; { unsigned char fifo[OTHER_CMD_LEN] = CMD_MSG_IP_UDP_RTP( - ((inbytes+40) >> 8) & 0xFF, - (inbytes+40) & 0xFF, - st->seqno & 0xFF, + ((inbytes+40) >> 8) & 0xFF, + (inbytes+40) & 0xFF, + st->seqno & 0xFF, 0x00, 0x00, - (((st->phys_out_chan) >> 8)+0x50) & 0xFF, - (st->phys_out_chan) & 0xFF, - (((st->phys_in_chan) >> 8)+0x50) & 0xFF, - (st->phys_in_chan) & 0xFF, - ((inbytes+20) >> 8) & 0xFF, - (inbytes+20) & 0xFF, + (((st->timeslot_out_num) >> 8)+0x50) & 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, - dte_fmt_to_pt(zth->srcfmt), - ((st->seqno) >> 8) & 0xFF, - (st->seqno) & 0xFF, - ((st->timestamp) >> 24) & 0xFF, - ((st->timestamp) >> 16) & 0xFF, - ((st->timestamp) >> 8) & 0xFF, - (st->timestamp) & 0xFF); + 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]; @@ -553,6 +708,8 @@ static int dte_operation(struct zt_transcoder_channel *ztc, int op) for (i = 0; i < inbytes; i++) fifo[i+CMD_MSG_IP_UDP_RTP_LEN]= chars[i]; + down(&wc->cmdqsem); + if ( (((wc->cmdq_wndx + 1) % MAX_COMMANDS) == wc->cmdq_rndx) && debug ) printk("wcdte error: cmdq is full.\n"); else @@ -563,26 +720,24 @@ static int dte_operation(struct zt_transcoder_channel *ztc, int op) wc->cmdq_wndx = (wc->cmdq_wndx + 1) % MAX_COMMANDS; } + __transmit_demand(wc); + up(&wc->cmdqsem); } st->packets_sent++; - __transmit_demand(wc); zth->srcoffset += inbytes; - } while ( (((zth->srcfmt == ZT_FORMAT_ULAW) || (zth->srcfmt == ZT_FORMAT_ALAW)) && (zth->srclen >= 160)) - || ((zth->srcfmt == ZT_FORMAT_G729A) && (zth->srclen >= 20)) - || ((zth->srcfmt == ZT_FORMAT_G723_1) && (zth->srclen >= 24)) ); + } 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); } - spin_unlock_irqrestore(&wc->reglock, flags); - - res = 0; break; } @@ -601,7 +756,7 @@ static inline void wcdte_receiveprep(struct wcdte *wc, int dbl) struct dte_state *st = NULL; int o2,i; unsigned char rseq, rcodec; - unsigned int reg, rchannel, rlen, rtp_rseq, rtp_eseq; + unsigned int rcommand, rchannel, rlen, rtp_rseq, rtp_eseq; unsigned char *chars = NULL; unsigned int ztc_ndx; @@ -611,26 +766,29 @@ static inline void wcdte_receiveprep(struct wcdte *wc, int dbl) o2 = dbl * 4; o2 += ERING_SIZE * 4; - - reg = wcdte_getctl(wc, 0x0001); - /* Control in packet */ if ((readchunk[12] == 0x88) && (readchunk[13] == 0x9B)) { - wc->rcvflags = RCV_CSMENCAPS; - wc->last_rcommand = readchunk[24] | (readchunk[25] << 8); - + 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) { + rcommand = readchunk[24] | (readchunk[25] << 8); rchannel = readchunk[18] | (readchunk[19] << 8); rseq = readchunk[16]; + down(&wc->cmdqsem); if ( (((wc->cmdq_wndx + 1) % MAX_COMMANDS) == wc->cmdq_rndx) && debug ) printk("wcdte error: cmdq is full (rndx = %d, wndx = %d).\n", wc->cmdq_rndx, wc->cmdq_wndx); else { - unsigned char fifo[OTHER_CMD_LEN] = CMD_MSG_ACK((rseq++)&0x0F, rchannel&0x00FF, (rchannel>>8)&0x00FF); + 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++) @@ -638,7 +796,19 @@ static inline void wcdte_receiveprep(struct wcdte *wc, int dbl) wc->cmdq_wndx = (wc->cmdq_wndx + 1) % MAX_COMMANDS; } - transmit_demand(wc); + __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); } } @@ -646,8 +816,6 @@ static inline void wcdte_receiveprep(struct wcdte *wc, int dbl) else if ((readchunk[12] == 0x08) && (readchunk[13] == 0x00) && (readchunk[50] == 0x12) && (readchunk[51] == 0x34) && (readchunk[52] = 0x56) && (readchunk[53] == 0x78)) { - wc->rcvflags = RCV_RTP; - rchannel = (readchunk[37] | (readchunk[36] << 8)) - 0x5000; rlen = (readchunk[39] | (readchunk[38] << 8)) - 20; rtp_rseq = (readchunk[45] | (readchunk[44] << 8)); @@ -655,10 +823,10 @@ static inline void wcdte_receiveprep(struct wcdte *wc, int dbl) ztc_ndx = rchannel/2; - if (ztc_ndx >= numchannels) + if (ztc_ndx >= wc->numchannels) { if (debug) - printk("wcdte error: Invalid channel number received (ztc_ndx = %d) (numchannels = %d)\n", ztc_ndx, numchannels); + printk("wcdte error: Invalid channel number received (ztc_ndx = %d) (numchannels = %d)\n", ztc_ndx, wc->numchannels); rcodec = DTE_FORMAT_UNDEF; } @@ -712,8 +880,7 @@ static inline void wcdte_receiveprep(struct wcdte *wc, int dbl) if (rcodec == 0x00) /* ulaw */ { - if (zt_tc_sanitycheck(zth, rlen) && (rlen == 160)) - { + if (zt_tc_sanitycheck(zth, rlen) && ((zth->srcfmt == ZT_FORMAT_G729A && rlen == G729_SAMPLES) || (zth->srcfmt == ZT_FORMAT_G723_1 && rlen == G723_SAMPLES))) { for (i = 0; i < rlen; i++) chars[i] = readchunk[i+54]; @@ -723,16 +890,12 @@ static inline void wcdte_receiveprep(struct wcdte *wc, int dbl) } else { ztc->errorstatus = -EOVERFLOW; } - - if (!(zth->dstsamples % PACKET_OUT_SIZE)) - { - zt_transcoder_alert(ztc); - } + zt_transcoder_alert(ztc); } else if (rcodec == 0x08) /* alaw */ { - if (zt_tc_sanitycheck(zth, rlen) && (rlen == 160)) - { + if (zt_tc_sanitycheck(zth, rlen) && ((zth->srcfmt == ZT_FORMAT_G729A && rlen == G729_SAMPLES) || (zth->srcfmt == ZT_FORMAT_G723_1 && rlen == G723_SAMPLES))) { + for (i = 0; i < rlen; i++) chars[i] = readchunk[i+54]; @@ -742,32 +905,30 @@ static inline void wcdte_receiveprep(struct wcdte *wc, int dbl) } else { ztc->errorstatus = -EOVERFLOW; } - zt_transcoder_alert(ztc); - } else if (rcodec == 0x04) /* g.723.1 */ { - if (zt_tc_sanitycheck(zth, rlen) && (rlen == 24)) + if (zt_tc_sanitycheck(zth, rlen) && (rlen == G723_BYTES)) { for (i = 0; i < rlen; i++) chars[i] = readchunk[i+54]; zth->dstlen += rlen; - zth->dstsamples = zth->dstlen * 10; + zth->dstsamples = zth->dstlen * 12; } else { ztc->errorstatus = -EOVERFLOW; } - if (!(zth->dstsamples % PACKET_OUT_SIZE)) + if (!(zth->dstsamples % G723_SAMPLES)) { zt_transcoder_alert(ztc); } } else if (rcodec == 0x12) /* g.729a */ { - if (zt_tc_sanitycheck(zth, rlen) && (rlen == 20)) + if (zt_tc_sanitycheck(zth, rlen) && (rlen == G729_BYTES)) { for (i = 0; i < rlen; i++) chars[i] = readchunk[i+54]; @@ -779,20 +940,12 @@ static inline void wcdte_receiveprep(struct wcdte *wc, int dbl) ztc->errorstatus = -EOVERFLOW; } - if (!(zth->dstsamples % PACKET_OUT_SIZE)) + if (!(zth->dstsamples % G729_SAMPLES)) { zt_transcoder_alert(ztc); } } } - - - - else - wc->rcvflags = RCV_OTHER; - - wake_up_interruptible(&wc->regq); - } @@ -854,46 +1007,46 @@ static void wcdte_init_descriptors(struct wcdte *wc) } } -#ifdef LINUX26 -static irqreturn_t wcdte_interrupt(int irq, void *dev_id, struct pt_regs *regs) -#else -static void wcdte_interrupt(int irq, void *dev_id, struct pt_regs *regs) -#endif +static void dte_wque_run(struct wcdte *wc) { - struct wcdte *wc = dev_id; - unsigned int ints; int res; - /* Read and clear interrupts */ - ints = wcdte_getctl(wc, 0x0028); - wcdte_setctl(wc, 0x0028, ints); - - if (!ints) -#ifdef LINUX26 - return IRQ_NONE; -#else - return; -#endif - ints &= wc->intmask; - - /* Handle RX interrupts */ - if (ints & 0x00000040) { + if (wc->wqueints & 0x00000040) { /* Loop descriptors is available */ do { res = wcdte_check_descriptor(wc); } while(res); } - + /* Handle TX interrupts */ - if (ints & 0x00000001) + if (wc->wqueints & 0x00000001) { wc->txints++; transmit_demand(wc); wc->intcount++; } +} + +static irqreturn_t wcdte_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct wcdte *wc = dev_id; + unsigned int ints; + + /* Read and clear interrupts */ + ints = wcdte_getctl(wc, 0x0028); + wcdte_setctl(wc, 0x0028, ints); + + if (!ints) + return IRQ_NONE; + ints &= wc->intmask; + if (ints & 0x00000041) { + wc->wqueints = ints; + queue_work(wc->dte_wq, &wc->dte_work); + } + if ((ints & 0x00008000) && debug) - printk("wcdte: Abormal Interrupt: "); + printk("wcdte: Abnormal Interrupt: "); if ((ints & 0x00002000) && debug) printk("wcdte: Fatal Bus Error INT\n"); @@ -916,9 +1069,7 @@ static void wcdte_interrupt(int irq, void *dev_id, struct pt_regs *regs) if ((ints & 0x00000002) && debug) printk("wcdte: Transmit Processor Stopped INT\n"); -#ifdef LINUX26 return IRQ_RETVAL(1); -#endif } @@ -1008,20 +1159,20 @@ static void wcdte_disable_interrupts(struct wcdte *wc) } -static int wcdte_waitfor_csmencaps(struct wcdte *wc) +static long timeout = 1 * HZ; /* 1 sec */ + +static int wcdte_waitfor_csmencaps(struct wcdte *wc, unsigned int mask, int use_mask) { int ret; -#ifdef LINUX26 - ret = wait_event_interruptible_timeout(wc->regq, wc->rcvflags != 0, (1*HZ)); -#else - /* Since timeout versions of wait_event... don't exist, */ - /* make a success ret look like ir didn't timeout */ - /* It may be good to look for a 2.4 compatible timeout mechanism */ - ret = wait_event_interruptible(wc->regq, wc->rcvflags != 0); - if (ret == 0) - ret = 1; -#endif + + if (use_mask) + ret = wait_event_interruptible_timeout(wc->regq, (wc->rcvflags == mask), timeout); + else + ret = wait_event_interruptible_timeout(wc->regq, (wc->last_rcommand == wc->last_command_sent), timeout); + wc->rcvflags = 0; + wc->last_rcommand = 0; + wc->last_command_sent = 0; if (ret < 0) { @@ -1032,16 +1183,9 @@ static int wcdte_waitfor_csmencaps(struct wcdte *wc) if (ret == 0) { if (debug) - printk("wcdte error: Waitfor CSMENCAPS ACK timed out (ret = %d)\n", ret); + printk("wcdte error: Waitfor CSMENCAPS response timed out (ret = %d)\n", ret); return(2); } - - if (wc->rcvflags != RCV_CSMENCAPS) - { - printk("wcdte error: DTE processor failed to respond\n"); - return(1); - } - wc->rcvflags = 0; return(0); } @@ -1085,11 +1229,11 @@ static int wcdte_boot_processor(struct wcdte *wc) reg = wcdte_getctl(wc, 0x00fc); if (debug) - printk("LINK STATUS: reg(0xfc) = %X\n", reg); + printk("wcdte: LINK STATUS: reg(0xfc) = %X\n", reg); reg = wcdte_getctl(wc, 0x00A0); - byteloc = 0; + byteloc = 17; j = 0; do @@ -1099,6 +1243,7 @@ static int wcdte_boot_processor(struct wcdte *wc) length = (wcdte_firmware[byteloc] << 8) | wcdte_firmware[byteloc+1]; byteloc += 2; + down(&wc->cmdqsem); if ( (((wc->cmdq_wndx + 1) % MAX_COMMANDS) == wc->cmdq_rndx) && debug ) printk("wcdte error: cmdq is full.\n"); else @@ -1108,10 +1253,11 @@ static int wcdte_boot_processor(struct wcdte *wc) wc->cmdq[wc->cmdq_wndx].cmd[i] = wcdte_firmware[byteloc++]; wc->cmdq_wndx = (wc->cmdq_wndx + 1) % MAX_COMMANDS; } - - transmit_demand(wc); + + __transmit_demand(wc); + up(&wc->cmdqsem); - ret = wcdte_waitfor_csmencaps(wc); + ret = wcdte_waitfor_csmencaps(wc, RCV_CSMENCAPS_ACK, 1); if (ret == 1) return(1); else if (ret == 2) /* Retransmit if dte processor times out */ @@ -1121,7 +1267,7 @@ static int wcdte_boot_processor(struct wcdte *wc) } while (byteloc < sizeof(wcdte_firmware)-20); /* Waitfor code to start */ - if (wcdte_waitfor_csmencaps(wc)) + if (wcdte_waitfor_csmencaps(wc, RCV_CSMENCAPS, 1)) return(1); /* Turn on booted LED */ @@ -1133,71 +1279,99 @@ static int wcdte_boot_processor(struct wcdte *wc) return(0); } +static int wcdte_create_channel(struct wcdte *wc, int simple, int complicated, int part1_id, int part2_id, unsigned int *dte_chan1, unsigned int *dte_chan2) +{ + int length = 0; + unsigned char chan1, chan2; + if(complicated == DTE_FORMAT_G729A) + length = G729_LENGTH; + else if (complicated == DTE_FORMAT_G723_1) + length = G723_LENGTH; + + /* Create complex channel */ + zt_send_cmd(wc, CMD_MSG_CREATE_CHANNEL(wc->seq_num++, part1_id), CMD_MSG_CREATE_CHANNEL_LEN, 0x0010); + chan1 = wc->last_rparm2; + + /* Create simple channel */ + zt_send_cmd(wc, CMD_MSG_CREATE_CHANNEL(wc->seq_num++, part2_id), CMD_MSG_CREATE_CHANNEL_LEN, 0x0010); + chan2 = wc->last_rparm2; + + /* Configure complex channel */ + zt_send_cmd(wc, CMD_MSG_SET_IP_HDR_CHANNEL(wc->seq_num++, chan1, part2_id, part1_id), CMD_MSG_SET_IP_HDR_CHANNEL_LEN, 0x9000); + zt_send_cmd(wc, CMD_MSG_VOIP_VCEOPT(wc->seq_num++, chan1, length, 0), CMD_MSG_VOIP_VCEOPT_LEN, 0x8001); + + /* Configure simple channel */ + zt_send_cmd(wc, CMD_MSG_SET_IP_HDR_CHANNEL(wc->seq_num++, chan2, part1_id, part2_id), CMD_MSG_SET_IP_HDR_CHANNEL_LEN, 0x9000); + zt_send_cmd(wc, CMD_MSG_VOIP_VCEOPT(wc->seq_num++, chan2, length, 0), CMD_MSG_VOIP_VCEOPT_LEN, 0x8001); + + zt_send_cmd(wc, CMD_MSG_TRANS_CONNECT(wc->seq_num++, 1, chan1, chan2, complicated, simple), CMD_MSG_TRANS_CONNECT_LEN, 0x9322); + zt_send_cmd(wc, CMD_MSG_VOIP_INDCTRL(wc->seq_num++, chan1), CMD_MSG_VOIP_INDCTRL_LEN, 0x8084); + zt_send_cmd(wc, CMD_MSG_VOIP_INDCTRL(wc->seq_num++, chan2), CMD_MSG_VOIP_INDCTRL_LEN, 0x8084); + zt_send_cmd(wc, CMD_MSG_VOIP_VOPENA(wc->seq_num++, chan1, complicated), CMD_MSG_VOIP_VOPENA_LEN, 0x8000); + zt_send_cmd(wc, CMD_MSG_VOIP_VOPENA(wc->seq_num++, chan2, simple), CMD_MSG_VOIP_VOPENA_LEN, 0x8000); + debug_packets = 0; + + *dte_chan1 = chan1; + *dte_chan2 = chan2; + + return 1; +} -static int wcdte_setup_channels(struct wcdte *wc) +static int wcdte_destroy_channel(struct wcdte *wc, unsigned int chan1, unsigned int chan2) { - int i, j, ret; - unsigned int part1_id, part2_id; + + /* Turn off both channels */ + zt_send_cmd(wc, CMD_MSG_VOIP_VOPENA_CLOSE(wc->seq_num++, chan1), CMD_MSG_VOIP_VOPENA_CLOSE_LEN, 0x8000); + zt_send_cmd(wc, CMD_MSG_VOIP_VOPENA_CLOSE(wc->seq_num++, chan2), CMD_MSG_VOIP_VOPENA_CLOSE_LEN, 0x8000); + + /* Disconnect the channels */ + zt_send_cmd(wc, CMD_MSG_TRANS_CONNECT(wc->seq_num++, 0, chan1, chan2, 0, 0), CMD_MSG_TRANS_CONNECT_LEN, 0x9322); + + /* Remove the channels */ + zt_send_cmd(wc, CMD_MSG_DESTROY_CHANNEL(wc->seq_num++, chan1), CMD_MSG_DESTROY_CHANNEL_LEN, 0x0011); + zt_send_cmd(wc, CMD_MSG_DESTROY_CHANNEL(wc->seq_num++, chan2), CMD_MSG_DESTROY_CHANNEL_LEN, 0x0011); + + debug_packets=0; + + return 1; +} +static int wcdte_setup_channels(struct wcdte *wc) +{ #ifndef USE_TEST_HW - zt_send_cmd(wc, CMD_MSG_SET_ARM_CLK((wc->seq_num++)&0x0F), CMD_MSG_SET_ARM_CLK_LEN, 0x0411); - zt_send_cmd(wc, CMD_MSG_SET_SPU_CLK((wc->seq_num++)&0x0F), CMD_MSG_SET_SPU_CLK_LEN, 0x0412); + zt_send_cmd(wc, CMD_MSG_SET_ARM_CLK(wc->seq_num++), CMD_MSG_SET_ARM_CLK_LEN, 0x0411); + zt_send_cmd(wc, CMD_MSG_SET_SPU_CLK(wc->seq_num++), CMD_MSG_SET_SPU_CLK_LEN, 0x0412); #endif #ifdef USE_TDM_CONFIG - zt_send_cmd(wc, CMD_MSG_TDM_SELECT_BUS_MODE((wc->seq_num++)&0x0F), CMD_MSG_TDM_SELECT_BUS_MODE_LEN, 0x0417); - zt_send_cmd(wc, CMD_MSG_TDM_ENABLE_BUS((wc->seq_num++)&0x0F), CMD_MSG_TDM_ENABLE_BUS_LEN, 0x0405); - zt_send_cmd(wc, CMD_MSG_SUPVSR_SETUP_TDM_PARMS((wc->seq_num++)&0x0F, 0x03, 0x20, 0x00), CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN, 0x0407); - zt_send_cmd(wc, CMD_MSG_SUPVSR_SETUP_TDM_PARMS((wc->seq_num++)&0x0F, 0x04, 0x80, 0x04), CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN, 0x0407); - zt_send_cmd(wc, CMD_MSG_SUPVSR_SETUP_TDM_PARMS((wc->seq_num++)&0x0F, 0x05, 0x20, 0x08), CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN, 0x0407); - zt_send_cmd(wc, CMD_MSG_SUPVSR_SETUP_TDM_PARMS((wc->seq_num++)&0x0F, 0x06, 0x80, 0x0C), CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN, 0x0407); + zt_send_cmd(wc, CMD_MSG_TDM_SELECT_BUS_MODE(wc->seq_num++), CMD_MSG_TDM_SELECT_BUS_MODE_LEN, 0x0417); + zt_send_cmd(wc, CMD_MSG_TDM_ENABLE_BUS(wc->seq_num++), CMD_MSG_TDM_ENABLE_BUS_LEN, 0x0405); + zt_send_cmd(wc, CMD_MSG_SUPVSR_SETUP_TDM_PARMS(wc->seq_num++, 0x03, 0x20, 0x00), CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN, 0x0407); + zt_send_cmd(wc, CMD_MSG_SUPVSR_SETUP_TDM_PARMS(wc->seq_num++, 0x04, 0x80, 0x04), CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN, 0x0407); + zt_send_cmd(wc, CMD_MSG_SUPVSR_SETUP_TDM_PARMS(wc->seq_num++, 0x05, 0x20, 0x08), CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN, 0x0407); + zt_send_cmd(wc, CMD_MSG_SUPVSR_SETUP_TDM_PARMS(wc->seq_num++, 0x06, 0x80, 0x0C), CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN, 0x0407); #endif - zt_send_cmd(wc, CMD_MSG_SET_ETH_HEADER((wc->seq_num++)&0x0F), CMD_MSG_SET_ETH_HEADER_LEN, 0x0100); - zt_send_cmd(wc, CMD_MSG_IP_SERVICE_CONFIG((wc->seq_num++)&0x0F), CMD_MSG_IP_SERVICE_CONFIG_LEN, 0x0302); - zt_send_cmd(wc, CMD_MSG_ARP_SERVICE_CONFIG((wc->seq_num++)&0x0F), CMD_MSG_ARP_SERVICE_CONFIG_LEN, 0x0105); - zt_send_cmd(wc, CMD_MSG_ICMP_SERVICE_CONFIG((wc->seq_num++)&0x0F), CMD_MSG_ICMP_SERVICE_CONFIG_LEN, 0x0304); + zt_send_cmd(wc, CMD_MSG_SET_ETH_HEADER(wc->seq_num++), CMD_MSG_SET_ETH_HEADER_LEN, 0x0100); + zt_send_cmd(wc, CMD_MSG_IP_SERVICE_CONFIG(wc->seq_num++), CMD_MSG_IP_SERVICE_CONFIG_LEN, 0x0302); + zt_send_cmd(wc, CMD_MSG_ARP_SERVICE_CONFIG(wc->seq_num++), CMD_MSG_ARP_SERVICE_CONFIG_LEN, 0x0105); + zt_send_cmd(wc, CMD_MSG_ICMP_SERVICE_CONFIG(wc->seq_num++), CMD_MSG_ICMP_SERVICE_CONFIG_LEN, 0x0304); #ifdef USE_TDM_CONFIG - zt_send_cmd(wc, CMD_MSG_DEVICE_SET_COUNTRY_CODE((wc->seq_num++)&0x0F), CMD_MSG_DEVICE_SET_COUNTRY_CODE_LEN, 0x041B); + zt_send_cmd(wc, CMD_MSG_DEVICE_SET_COUNTRY_CODE(wc->seq_num++), CMD_MSG_DEVICE_SET_COUNTRY_CODE_LEN, 0x041B); #endif - zt_send_cmd(wc, CMD_MSG_SPU_FEATURES_CONTROL((wc->seq_num++)&0x0F, 0x02), CMD_MSG_SPU_FEATURES_CONTROL_LEN, 0x0013); - zt_send_cmd(wc, CMD_MSG_IP_OPTIONS((wc->seq_num++)&0x0F), CMD_MSG_IP_OPTIONS_LEN, 0x0306); - zt_send_cmd(wc, CMD_MSG_SPU_FEATURES_CONTROL((wc->seq_num++)&0x0F, 0x04), CMD_MSG_SPU_FEATURES_CONTROL_LEN, 0x0013); + zt_send_cmd(wc, CMD_MSG_SPU_FEATURES_CONTROL(wc->seq_num++, 0x02), CMD_MSG_SPU_FEATURES_CONTROL_LEN, 0x0013); + zt_send_cmd(wc, CMD_MSG_IP_OPTIONS(wc->seq_num++), CMD_MSG_IP_OPTIONS_LEN, 0x0306); + zt_send_cmd(wc, CMD_MSG_SPU_FEATURES_CONTROL(wc->seq_num++, 0x04), CMD_MSG_SPU_FEATURES_CONTROL_LEN, 0x0013); #ifdef USE_TDM_CONFIG - zt_send_cmd(wc, CMD_MSG_TDM_OPT((wc->seq_num++)&0x0F), CMD_MSG_TDM_OPT_LEN, 0x0435); + zt_send_cmd(wc, CMD_MSG_TDM_OPT(wc->seq_num++), CMD_MSG_TDM_OPT_LEN, 0x0435); #endif - - part1_id = 0; - part2_id = 1; - for(j = 0; j < NUM_CHANNELS; j++) - { - /* Create complex channel */ - zt_send_cmd(wc, CMD_MSG_CREATE_CHANNEL((wc->seq_num++)&0x0F, (part1_id&0x00FF), (part1_id&0xFF00) >> 8), CMD_MSG_CREATE_CHANNEL_LEN, 0x0010); - zt_send_cmd(wc, CMD_MSG_SET_IP_HDR_CHANNEL((wc->seq_num++)&0x0F, (part1_id&0xFF00) >> 8, (part1_id&0x00FF),((part2_id&0xFF00) >> 8) + 0x50, (part2_id&0x00FF), ((part1_id&0xFF00) >> 8) + 0x50, (part1_id&0x00FF)), CMD_MSG_SET_IP_HDR_CHANNEL_LEN, 0x9000); - zt_send_cmd(wc, CMD_MSG_VOIP_VCEOPT((wc->seq_num++)&0x0F, (part1_id&0xFF00) >> 8, (part1_id&0x00FF), SAMPLE_LENGTH, 0), CMD_MSG_VOIP_VCEOPT_LEN, 0x8001); - - /* Create simple channel */ - zt_send_cmd(wc, CMD_MSG_CREATE_CHANNEL((wc->seq_num++)&0x0F, (part2_id&0x00FF), (part2_id&0xFF00) >> 8), CMD_MSG_CREATE_CHANNEL_LEN, 0x0010); - zt_send_cmd(wc, CMD_MSG_SET_IP_HDR_CHANNEL((wc->seq_num++)&0x0F, (part2_id&0xFF00) >> 8, (part2_id&0x00FF),((part1_id&0xFF00) >> 8) + 0x50, (part1_id&0x00FF), ((part2_id&0xFF00) >> 8) + 0x50, (part2_id&0x00FF)), CMD_MSG_SET_IP_HDR_CHANNEL_LEN, 0x9000); - zt_send_cmd(wc, CMD_MSG_VOIP_VCEOPT((wc->seq_num++)&0x0F, (part2_id&0xFF00) >> 8, (part2_id&0x00FF), SAMPLE_LENGTH, 0), CMD_MSG_VOIP_VCEOPT_LEN, 0x8001); - - - zt_send_cmd(wc, CMD_MSG_TRANS_CONNECT((wc->seq_num++)&0x0F, 1, (part1_id&0x00FF), (part1_id&0xFF00) >> 8, (part2_id&0x00FF), (part2_id&0xFF00) >> 8), CMD_MSG_TRANS_CONNECT_LEN, 0x9322); - zt_send_cmd(wc, CMD_MSG_VOIP_VOPENA((wc->seq_num++)&0x0F, (part1_id&0xFF00) >> 8, (part1_id&0x00FF), COMPLEX_CODEC), CMD_MSG_VOIP_VOPENA_LEN, 0x8000); - zt_send_cmd(wc, CMD_MSG_VOIP_VOPENA((wc->seq_num++)&0x0F, (part2_id&0xFF00) >> 8, (part2_id&0x00FF), SIMPLE_CODEC), CMD_MSG_VOIP_VOPENA_LEN, 0x8000); - - part1_id += 2; - part2_id += 2; - } - - if (debug) - zt_send_cmd(wc, CMD_MSG_DEVICE_STATUS_CONFIG((wc->seq_num++)&0x0F), CMD_MSG_DEVICE_STATUS_CONFIG_LEN, 0x040F); + timeout = HZ/100 + 1; /* 10msec */ return(0); } @@ -1210,6 +1384,8 @@ static int __devinit wcdte_init_one(struct pci_dev *pdev, const struct pci_devic struct wcdte_desc *d = (struct wcdte_desc *)ent->driver_data; int x; static int initd_ifaces=0; + unsigned char g729_numchannels, g723_numchannels, min_numchannels, dte_firmware_ver; + unsigned int complexfmts; if(initd_ifaces){ memset((void *)ifaces,0,(sizeof(struct wcdte *))*WC_MAX_IFACES); @@ -1218,7 +1394,7 @@ static int __devinit wcdte_init_one(struct pci_dev *pdev, const struct pci_devic for (x=0;x<WC_MAX_IFACES;x++) if (!ifaces[x]) break; if (x >= WC_MAX_IFACES) { - printk("Too many interfaces\n"); + printk("wcdte: Too many interfaces\n"); return -EIO; } @@ -1231,6 +1407,8 @@ static int __devinit wcdte_init_one(struct pci_dev *pdev, const struct pci_devic ifaces[x] = wc; memset(wc, 0, sizeof(struct wcdte)); spin_lock_init(&wc->reglock); + sema_init(&wc->chansem, 1); + sema_init(&wc->cmdqsem, 1); wc->cards = NUM_CARDS; wc->iobase = pci_resource_start(pdev, 0); wc->dev = pdev; @@ -1240,10 +1418,14 @@ static int __devinit wcdte_init_one(struct pci_dev *pdev, const struct pci_devic wc->tdbl = 0; wc->rdbl = 0; wc->rcvflags = 0; + wc->last_command_sent = 0; wc->last_rcommand = 0; + wc->last_rparm2 = 0; wc->cmdq_wndx = 0; wc->cmdq_rndx = 0; wc->seq_num = 6; + wc->ztsnd_rtx = 0; + wc->ztsnd_0010_rtx = 0; /* Keep track of whether we need to free the region */ if (request_region(wc->iobase, 0xff, "wcdte")) @@ -1269,14 +1451,53 @@ static int __devinit wcdte_init_one(struct pci_dev *pdev, const struct pci_devic memset((void *)wc->readchunk, 0x00, SFRAME_SIZE * 2); init_waitqueue_head(&wc->regq); + + /* Initialize the work queue */ + wc->dte_wq = create_workqueue("tc400b"); + INIT_WORK(&wc->dte_work, (void (*)(void *))dte_wque_run, wc); + + g729_numchannels = wcdte_firmware[1]; + g723_numchannels = wcdte_firmware[2]; + dte_firmware_ver = wcdte_firmware[0]; + + if (g723_numchannels < g729_numchannels) + min_numchannels = g723_numchannels; + else + min_numchannels = g729_numchannels; /* Setup Encoders nad Decoders */ - uencode = zt_transcoder_alloc(numchannels); - udecode = zt_transcoder_alloc(numchannels); - encoders = vmalloc(sizeof(struct dte_state) * numchannels); - decoders = vmalloc(sizeof(struct dte_state) * numchannels); - memset(encoders, 0, sizeof(struct dte_state) * numchannels); - memset(decoders, 0, sizeof(struct dte_state) * numchannels); + + if (!mode) + { + sprintf(wc->complexname, "g.729a / g.723.1 5.3kbps"); + complexfmts = ZT_FORMAT_G729A | ZT_FORMAT_G723_1; + wc->numchannels = min_numchannels; + } + else if (mode[3] == '9') /* "g729" */ + { + sprintf(wc->complexname, "g.729a"); + complexfmts = ZT_FORMAT_G729A; + wc->numchannels = g729_numchannels; + } + else if (mode[3] == '3') /* "g723" */ + { + sprintf(wc->complexname, "g.723.1 5.3kbps"); + complexfmts = ZT_FORMAT_G723_1; + wc->numchannels = g723_numchannels; + } + else + { + sprintf(wc->complexname, "g.729a / g.723.1 5.3kbps"); + complexfmts = ZT_FORMAT_G729A | ZT_FORMAT_G723_1; + wc->numchannels = min_numchannels; + } + + uencode = zt_transcoder_alloc(wc->numchannels); + udecode = zt_transcoder_alloc(wc->numchannels); + encoders = vmalloc(sizeof(struct dte_state) * wc->numchannels); + decoders = vmalloc(sizeof(struct dte_state) * wc->numchannels); + memset(encoders, 0, sizeof(struct dte_state) * wc->numchannels); + memset(decoders, 0, sizeof(struct dte_state) * wc->numchannels); if (!uencode || !udecode || !encoders || !decoders) { if (uencode) zt_transcoder_free(uencode); @@ -1291,14 +1512,12 @@ static int __devinit wcdte_init_one(struct pci_dev *pdev, const struct pci_devic sprintf(udecode->name, "DTE Decoder"); sprintf(uencode->name, "DTE Encoder"); -/* udecode->srcfmts = uencode->dstfmts = ZT_FORMAT_G729A | ZT_FORMAT_G723_1; */ -/* udecode->dstfmts = uencode->srcfmts = ZT_FORMAT_ULAW | ZT_FORMAT_ALAW; */ - udecode->srcfmts = uencode->dstfmts = ZT_FORMAT_G729A; - udecode->dstfmts = uencode->srcfmts = ZT_FORMAT_ULAW; - + udecode->srcfmts = uencode->dstfmts = complexfmts; + udecode->dstfmts = uencode->srcfmts = ZT_FORMAT_ULAW | ZT_FORMAT_ALAW; + udecode->operation = uencode->operation = dte_operation; - for (x=0;x<numchannels;x++) { + for (x=0;x<wc->numchannels;x++) { dte_init_state(encoders + x, 1, x, wc); encoders[x].encoder = 1; decoders[x].encoder = 0; @@ -1313,8 +1532,7 @@ static int __devinit wcdte_init_one(struct pci_dev *pdev, const struct pci_devic zt_transcoder_register(uencode); zt_transcoder_register(udecode); - printk("Zaptel DTE (G.729/G.723) Transcoder support LOADED\n"); - + printk("Zaptel DTE (%s) Transcoder support LOADED (firm ver = %d)\n", wc->complexname, dte_firmware_ver); /* Enable bus mastering */ @@ -1348,13 +1566,12 @@ static int __devinit wcdte_init_one(struct pci_dev *pdev, const struct pci_devic } - /* Enable interrupts */ wcdte_enable_interrupts(wc); /* Start DMA */ wcdte_start_dma(wc); - + if (wcdte_boot_processor(wc)) { /* Set Reset Low */ @@ -1385,9 +1602,9 @@ static int __devinit wcdte_init_one(struct pci_dev *pdev, const struct pci_devic reg = wcdte_getctl(wc, 0x00fc); if (debug) - printk("(post-boot) Reg fc is %08x\n", reg); + printk("wcdte debug: (post-boot) Reg fc is %08x\n", reg); - printk("Found a Wildcard TC: %s \n", wc->variety); + printk("Found and successfully installed a Wildcard TC: %s \n", wc->variety); res = 0; } else res = -ENOMEM; @@ -1405,10 +1622,31 @@ static void wcdte_release(struct wcdte *wc) static void __devexit wcdte_remove_one(struct pci_dev *pdev) { + int i; struct wcdte *wc = pci_get_drvdata(pdev); + struct zt_transcoder_channel *ztc_en, *ztc_de; + struct dte_state *st_en, *st_de; if (wc) { - + + if (debug) + { + printk("wcdte debug: wc->ztsnd_rtx = %d\n", wc->ztsnd_rtx); + printk("wcdte debug: wc->ztsnd_0010_rtx = %d\n", wc->ztsnd_0010_rtx); + + for(i = 0; i < wc->numchannels; i++) + { + ztc_en = &(wc->uencode->channels[i]); + st_en = ztc_en->pvt; + + ztc_de = &(wc->udecode->channels[i]); + st_de = ztc_de->pvt; + + printk("wcdte debug: en[%d] snt = %d, rcv = %d [%d]\n", i, st_en->packets_sent, st_en->packets_received, st_en->packets_sent - st_en->packets_received); + printk("wcdte debug: de[%d] snt = %d, rcv = %d [%d]\n", i, st_de->packets_sent, st_de->packets_received, st_de->packets_sent - st_de->packets_received); + } + } + zt_transcoder_unregister(wc->udecode); zt_transcoder_unregister(wc->uencode); zt_transcoder_free(wc->uencode); @@ -1421,6 +1659,9 @@ static void __devexit wcdte_remove_one(struct pci_dev *pdev) /* In case hardware is still there */ wcdte_disable_interrupts(wc); + + /* Kill workqueue */ + destroy_workqueue(wc->dte_wq); /* Immediately free resources */ pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); @@ -1436,7 +1677,7 @@ static struct pci_device_id wcdte_pci_tbl[] = { #ifndef USE_TEST_HW { 0xd161, 0x3400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcdte }, /* digium board */ #else - { 0x1317, 0x0985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcdte }, /*reference board */ + { 0x1317, 0x0985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcdte }, /* reference board */ #endif { 0 } }; @@ -1447,11 +1688,7 @@ MODULE_DEVICE_TABLE(pci, wcdte_pci_tbl); static struct pci_driver wcdte_driver = { name: "ztcodec_dte", probe: wcdte_init_one, -#ifdef LINUX26 remove: __devexit_p(wcdte_remove_one), -#else - remove: wcdte_remove_one, -#endif suspend: NULL, resume: NULL, id_table: wcdte_pci_tbl, @@ -1470,32 +1707,12 @@ int ztdte_init(void) void ztdte_cleanup(void) { -// int i; - -#if 0 - if (debug) - { - for(i = 0; i < NUM_CHANNELS; i++) - { - printk("encoder[%d] packets_sent = %d, packets_received = %d [%d]\n", i, encoders[i].packets_sent, encoders[i].packets_received, encoders[i].packets_sent - encoders[i].packets_received); - printk("decoder[%d] packets_sent = %d, packets_received = %d [%d]\n", i, decoders[i].packets_sent, decoders[i].packets_received, decoders[i].packets_sent - decoders[i].packets_received); - } - } -#endif - pci_unregister_driver(&wcdte_driver); - - printk("Zaptel DTE (G.729/G.723) Transcoder support unloaded.\n"); - + printk("Zaptel DTE Transcoder support unloaded.\n"); } -#ifdef LINUX26 module_param(debug, int, 0600); -module_param(numchannels, int, 0600); -#else -MODULE_PARM(debug, "i"); -MODULE_PARM(numchannels, "i"); -#endif +module_param(mode, charp, 0600); MODULE_DESCRIPTION("Zaptel DTE (G.729/G.723) Transcoder Support"); MODULE_AUTHOR("John Sloan <jsloan@digium.com>"); #ifdef MODULE_LICENSE |