[zaptel-commits] kpfleming: branch 1.2 r2092 - in /branches/1.2: ./
wctc4xxp/
zaptel-commits at lists.digium.com
zaptel-commits at lists.digium.com
Tue Feb 6 14:57:39 MST 2007
Author: kpfleming
Date: Tue Feb 6 15:57:38 2007
New Revision: 2092
URL: http://svn.digium.com/view/zaptel?view=rev&rev=2092
Log:
revert transcoder driver to last version that passed PQ testing... improved version will come back once testing has been completed and bugs are found/fixed
Modified:
branches/1.2/wctc4xxp/base.c
branches/1.2/zaptel.h
branches/1.2/zttranscode.c
Modified: branches/1.2/wctc4xxp/base.c
URL: http://svn.digium.com/view/zaptel/branches/1.2/wctc4xxp/base.c?view=diff&rev=2092&r1=2091&r2=2092
==============================================================================
--- branches/1.2/wctc4xxp/base.c (original)
+++ branches/1.2/wctc4xxp/base.c Tue Feb 6 15:57:38 2007
@@ -1,10 +1,9 @@
/*
- * Wildcard TC400B Interface Driver for Zapata Telephony interface
+ * Wildcard TC400B Driver
*
* Written by John Sloan <jsloan at digium.com>
- * and Kevin P. Fleming <kpfleming at digium.com>
*
- * Copyright (C) 2006-2007, Digium, Inc.
+ * Copyright (C) 2006, Digium, Inc.
*
* All rights reserved.
*
@@ -24,6 +23,7 @@
*
*/
+
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/module.h>
@@ -34,6 +34,7 @@
#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
#include <linux/mman.h>
#include <linux/delay.h>
#include <asm/io.h>
@@ -42,30 +43,30 @@
#include <linux/workqueue.h>
#include <linux/moduleparam.h>
#include <linux/firmware.h>
-#include <linux/list.h>
-
+#ifdef CONFIG_DEVFS_FS
+#include <linux/devfs_fs_kernel.h>
+#endif
#ifdef STANDALONE_ZAPATA
#include "zaptel.h"
#else
#include <linux/zaptel.h>
#endif
-#if defined(HOTPLUG_FIRMWARE)
-static const char *tc400m_firmware = "tc400m-firmware.bin";
+#ifdef HOTPLUG_FIRMWARE
+static const char *dte_firmware = "tc400m-firmware.bin";
#else
extern u8 _binary_tc400m_firmware_bin_start[];
extern void _binary_tc400m_firmware_bin_size;
#endif
-static struct pci_driver driver;
-
-#define module_printk(fmt, args...) printk("%s: " fmt, driver.name, ## args)
-#define debug_printk(test, fmt, args...) if (debug && (test)) printk("%s (%s): " fmt, driver.name, __FUNCTION__, ## args)
/* #define USE_TEST_HW */
#define USE_TDM_CONFIG
-#define WC_MAX_IFACES 8
+#define WC_MAX_IFACES 128
+
+#define NUM_CARDS 24
+#define NUM_EC 4
/* NUM_CHANNELS must be checked if new firmware (dte_firm.h) is used */
#define NUM_CHANNELS 97
@@ -79,22 +80,30 @@
#define G729_LENGTH 20
#define G723_LENGTH 30
-#define G729_SAMPLES 160
-#define G723_SAMPLES 240
-
-#define G729_BYTES 20
-#define G723_BYTES 20
-
-/* 274 for 30ms ulaw, 194 for 20ms ulaw */
+#define G729_SAMPLES 160 /* g.729 */
+#define G723_SAMPLES 240 /* g.723 */
+
+#define G729_BYTES 20 /* g.729 */
+#define G723_BYTES 20 /* g.723 */
+
+
+
+#define ACK_SPACE 20
+
+#define MAX_COMMANDS (NUM_CHANNELS + ACK_SPACE)
+#define MAX_RCV_COMMANDS 16
+
+/* 1432 for boot, 274 for 30msec ulaw, 194 for 20mec ulaw */
+#define BOOT_CMD_LEN 1500
#define OTHER_CMD_LEN 300
-#define MAX_COMMAND_LEN OTHER_CMD_LEN
+#define MAX_COMMAND_LEN BOOT_CMD_LEN /* Must be the larger of BOOT_CMD_LEN or OTHER_CMD_LEN */
#define ERING_SIZE (NUM_CHANNELS / 2) /* Maximum ring size */
#define SFRAME_SIZE MAX_COMMAND_LEN
-#define PCI_WINDOW_SIZE ((2 * 2 * ERING_SIZE * SFRAME_SIZE) + (2 * ERING_SIZE * 4))
+#define PCI_WINDOW_SIZE ((2* 2 * ERING_SIZE * SFRAME_SIZE) + (2 * ERING_SIZE * 4))
#define MDIO_SHIFT_CLK 0x10000
#define MDIO_DATA_WRITE0 0x00000
@@ -108,130 +117,182 @@
#define RCV_CSMENCAPS_ACK 3
#define RCV_OTHER 99
+
/* TDM Commands */
+#define CMD_MSG_TDM_SELECT_BUS_MODE_LEN 30
#define CMD_MSG_TDM_SELECT_BUS_MODE(s) { \
0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x01, 0x00,0x06,0x17,0x04, 0xFF,0xFF, \
0x04,0x00 }
+#define CMD_MSG_TDM_ENABLE_BUS_LEN 30
#define CMD_MSG_TDM_ENABLE_BUS(s) { \
0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x02, 0x00,0x06,0x05,0x04, 0xFF,0xFF, \
0x04,0x00 }
+#define CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN 34
#define CMD_MSG_SUPVSR_SETUP_TDM_PARMS(s,p1,p2,p3) { \
0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x10, p1, 0x00,0x06,0x07,0x04, 0xFF,0xFF, \
p2,0x83, 0x00,0x0C, 0x00,0x00, p3,0x00 }
+#define CMD_MSG_TDM_OPT_LEN 30
#define CMD_MSG_TDM_OPT(s) { \
0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x35,0x04, 0xFF,0xFF, \
0x00,0x00 }
+#define CMD_MSG_DEVICE_SET_COUNTRY_CODE_LEN 30
#define CMD_MSG_DEVICE_SET_COUNTRY_CODE(s) { \
0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x1B,0x04, 0xFF,0xFF, \
0x00,0x00 }
/* CPU Commands */
+#define CMD_MSG_SET_ARM_CLK_LEN 32
#define CMD_MSG_SET_ARM_CLK(s) { \
0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0C, 0x00, 0x00,0x06,0x11,0x04, 0x00,0x00, \
0x2C,0x01, 0x00,0x00 }
+#define CMD_MSG_SET_SPU_CLK_LEN 32
#define CMD_MSG_SET_SPU_CLK(s) { \
0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0C, 0x00, 0x00,0x06,0x12,0x04, 0x00,0x00, \
0x2C,0x01, 0x00,0x00 }
+#define CMD_MSG_SPU_FEATURES_CONTROL_LEN 30
#define CMD_MSG_SPU_FEATURES_CONTROL(s,p1) { \
0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x13,0x00, 0xFF,0xFF, \
p1,0x00 }
+#define CMD_MSG_DEVICE_STATUS_CONFIG_LEN 30
#define CMD_MSG_DEVICE_STATUS_CONFIG(s) { \
0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x0F,0x04, 0xFF,0xFF, \
0x05,0x00 }
/* General IP/RTP Commands */
+#define CMD_MSG_SET_ETH_HEADER_LEN 44
#define CMD_MSG_SET_ETH_HEADER(s) { \
0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x18, 0x00, 0x00,0x06,0x00,0x01, 0xFF,0xFF, \
0x01,0x00, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x00,0x11,0x22,0x33,0x44,0x55, 0x08,0x00 }
+#define CMD_MSG_IP_SERVICE_CONFIG_LEN 30
#define CMD_MSG_IP_SERVICE_CONFIG(s) { \
0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x02,0x03, 0xFF,0xFF, \
0x00,0x02 }
+#define CMD_MSG_ARP_SERVICE_CONFIG_LEN 30
#define CMD_MSG_ARP_SERVICE_CONFIG(s) { \
0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x05,0x01, 0xFF,0xFF, \
0x01,0x00 }
+#define CMD_MSG_ICMP_SERVICE_CONFIG_LEN 30
#define CMD_MSG_ICMP_SERVICE_CONFIG(s) { \
0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x04,0x03, 0xFF,0xFF, \
0x01,0xFF }
+#define CMD_MSG_IP_OPTIONS_LEN 30
#define CMD_MSG_IP_OPTIONS(s) { \
0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x06,0x03, 0xFF,0xFF, \
0x02,0x00 }
/* Supervisor channel commands */
+#define CMD_MSG_CREATE_CHANNEL_LEN 32
#define CMD_MSG_CREATE_CHANNEL(s,t) { \
0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0C, 0x00, 0x00,0x06,0x10,0x00, 0x00,0x00, \
0x02,0x00, (t&0x00FF), ((t&0xFF00) >> 8) }
+#define CMD_MSG_TRANS_CONNECT_LEN 38
#define CMD_MSG_TRANS_CONNECT(s,e,c1,c2,f1,f2) { \
0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x12, 0x00, 0x00,0x06,0x22,0x93, 0x00,0x00, \
e,0x00, (c1&0x00FF),((c1&0xFF00)>>8), f1,0x00, (c2&0x00FF),((c2&0xFF00)>>8), f2,0x00 }
+#define CMD_MSG_DESTROY_CHANNEL_LEN 32
#define CMD_MSG_DESTROY_CHANNEL(s,t) { \
0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x11,0x00, 0x00,0x00, \
(t&0x00FF),((t&0xFF00)>>8), 0x00, 0x00 }
/* Individual channel config commands */
+#define CMD_MSG_SET_IP_HDR_CHANNEL_LEN 58
#define CMD_MSG_SET_IP_HDR_CHANNEL(s,c,t2,t1) { \
0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
0x00,0x01, s&0x0F, 0x01, ((c&0xFF00) >> 8),(c&0x00FF), 0x26, 0x00, 0x00,0x02,0x00,0x90, 0x00,0x00, \
0x00,0x00, 0x45,0x00, 0x00,0x00, 0x00,0x00, 0x40,0x00, 0x80,0x11, 0x00,0x00, \
0xC0,0xA8,0x09,0x03, 0xC0,0xA8,0x09,0x03, \
((t2&0xFF00)>>8)+0x50,(t2&0x00FF), ((t1&0xFF00)>>8)+0x50,(t1&0x00FF), 0x00,0x00, 0x00,0x00 }
+#define CMD_MSG_VOIP_VCEOPT_LEN 40
#define CMD_MSG_VOIP_VCEOPT(s,c,l,w) { \
0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x12, 0x00, 0x00,0x02,0x01,0x80, 0x00,0x00, \
0x21,l, 0x00,0x1C, 0x04,0x00, 0x00,0x00, w,0x00, 0x80,0x11 }
+#define CMD_MSG_VOIP_VOPENA_LEN 44
#define CMD_MSG_VOIP_VOPENA(s,c,f) { \
0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x16, 0x00, 0x00,0x02,0x00,0x80, 0x00,0x00, \
0x01,0x00, 0x80,f, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x12,0x34, 0x56,0x78, 0x00,0x00 }
+#define CMD_MSG_VOIP_VOPENA_CLOSE_LEN 32
#define CMD_MSG_VOIP_VOPENA_CLOSE(s,c) { \
0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x0A, 0x00, 0x00,0x02,0x00,0x80, 0x00,0x00, \
0x00,0x00, 0x00,0x00 }
+#define CMD_MSG_VOIP_INDCTRL_LEN 32
#define CMD_MSG_VOIP_INDCTRL(s,c) {0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x0A, 0x00, 0x00,0x02,0x84,0x80, 0x00,0x00, \
0x07,0x00, 0x00,0x00 }
/* CPU ACK command */
+#define CMD_MSG_ACK_LEN 20
#define CMD_MSG_ACK(s,c) { \
0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
0x00,0x01, s, 0xE0, (c&0x00FF), ((c>>8)&0x00FF) }
/* Wrapper for RTP packets */
+#define CMD_MSG_IP_UDP_RTP_LEN 54
#define CMD_MSG_IP_UDP_RTP(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16,p17,p18,p19,p20) { \
0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x08,0x00, \
0x45,0x00, p1,p2, 0x00,p3, 0x40,0x00, 0x80,0x11, p4,p5, \
0xC0,0xA8,0x09,0x03, 0xC0,0xA8,0x09,0x03, p6,p7, p8,p9, p10,p11, p12,p13, \
0x80,p14, p15,p16, p17,p18,p19,p20, 0x12,0x34,0x56,0x78}
+
+#define zt_send_cmd(wc, command, length, hex) \
+ ({ \
+ int ret = 0; \
+ do { \
+ if (ret == 2) \
+ { \
+ wc->ztsnd_rtx++; \
+ if (hex == 0x0010) \
+ wc->ztsnd_0010_rtx++; \
+ } \
+ down(&wc->cmdqsem); \
+ wc->last_command_sent = hex; \
+ if ( (((wc->cmdq_wndx + 1) % MAX_COMMANDS) == wc->cmdq_rndx) && debug ) \
+ printk("wcdte error: cmdq is full.\n"); \
+ else { \
+ unsigned char fifo[OTHER_CMD_LEN] = command; \
+ int i; \
+ wc->cmdq[wc->cmdq_wndx].cmdlen = length; \
+ for (i = 0; i < length; i++) \
+ wc->cmdq[wc->cmdq_wndx].cmd[i] = fifo[i]; \
+ wc->cmdq_wndx = (wc->cmdq_wndx + 1) % MAX_COMMANDS; \
+ } \
+ __transmit_demand(wc); \
+ up(&wc->cmdqsem); \
+ ret = wcdte_waitfor_csmencaps(wc, RCV_CSMENCAPS, 0); \
+ if (ret == 1) \
+ return(1); \
+ } while (ret == 2); \
+ })
+
+
struct cmdq {
- struct list_head list;
- size_t cmdspace;
- size_t cmdlen;
- u8 cmd[0];
+ unsigned int cmdlen;
+ unsigned int cmd[MAX_COMMAND_LEN];
};
-
-#define MAX_PACKET_SIZE 1500
-#define MAX_TOTAL_CMDQ 40
struct wcdte {
struct pci_dev *dev;
- const char *variety;
+ char *variety;
unsigned int intcount;
unsigned int rxints;
unsigned int txints;
@@ -240,15 +301,16 @@
int freeregion;
int rdbl;
int tdbl;
+ int cards;
spinlock_t reglock;
wait_queue_head_t regq;
int rcvflags;
struct semaphore chansem;
struct semaphore cmdqsem;
- struct list_head pending_cmdq;
- struct list_head free_cmdq;
- u32 total_cmdq; /* total of all cmdq entries, both pending and free */
+ struct cmdq cmdq[MAX_COMMANDS];
+ unsigned int cmdq_wndx;
+ unsigned int cmdq_rndx;
unsigned int last_command_sent;
unsigned int last_rcommand;
@@ -259,16 +321,16 @@
unsigned int ztsnd_rtx;
unsigned int ztsnd_0010_rtx;
- unsigned int numchannels;
+ unsigned char numchannels;
unsigned char complexname[40];
unsigned long iobase;
- dma_addr_t readdma;
- dma_addr_t writedma;
- dma_addr_t descripdma;
- volatile u8 *writechunk; /* write buffers */
- volatile u8 *readchunk; /* read buffers */
- volatile u32 *descripchunk; /* descriptors */
+ dma_addr_t readdma;
+ dma_addr_t writedma;
+ dma_addr_t descripdma;
+ volatile unsigned int *writechunk; /* Double-word aligned write memory */
+ volatile unsigned int *readchunk; /* Double-word aligned read memory */
+ volatile unsigned int *descripchunk; /* Descriptors */
int wqueints;
struct workqueue_struct *dte_wq;
@@ -278,27 +340,40 @@
struct zt_transcoder *udecode;
};
+static void dte_wque_run(struct wcdte *wc);
+
struct wcdte_desc {
- const char *name;
+ char *name;
int flags;
};
-static const struct wcdte_desc wcdte = { "Wildcard TC400P+TC400M", 0 };
+static struct wcdte_desc wcdte = { "Wildcard TC400P+TC400M", 0 };
static struct wcdte *ifaces[WC_MAX_IFACES];
+
+
+/*
+ * The following is the definition of the state structure
+ * used by the G.721/G.723 encoder and decoder to preserve their internal
+ * state between successive calls. The meanings of the majority
+ * of the state structure fields are explained in detail in the
+ * CCITT Recommendation G.721. The field names are essentially indentical
+ * to variable names in the bit level description of the coding algorithm
+ * included in this Recommendation.
+ */
struct dte_state {
- int encoder;
+ int encoder; /* If we're an encoder */
struct wcdte *wc;
unsigned int timestamp;
unsigned int seqno;
- unsigned int timeslot_in_num;
- unsigned int timeslot_out_num;
-
- unsigned int chan_in_num;
- unsigned int chan_out_num;
+ unsigned int timeslot_in_num; /* DTE chennel on which results we be received from */
+ unsigned int timeslot_out_num; /* DTE channel to send data to */
+
+ unsigned int chan_in_num; /* DTE chennel on which results we be received from */
+ unsigned int chan_out_num; /* DTE channel to send data to */
unsigned int packets_sent;
unsigned int packets_received;
@@ -307,17 +382,21 @@
unsigned int dte_seqno_rcv;
};
+
+static struct zt_transcoder *uencode;
+static struct zt_transcoder *udecode;
+static struct dte_state *encoders;
+static struct dte_state *decoders;
static int debug = 0;
-static char *mode[2] = { "g729", "g723" };
-static int mode_count = 2;
-u32 debug_packets = 0;
-u32 debug_cmd_packets = 0;
-
-static int create_channel(struct wcdte *wc, int simple, int complicated, int part1_id, int part2_id, unsigned int *dte_chan1, unsigned int *dte_chan2);
-static int destroy_channel(struct wcdte *wc, unsigned int chan1, unsigned int chan2);
+static char *mode;
+int debug_packets = 0;
+
+
+static int wcdte_create_channel(struct wcdte *wc, int simple, int complicated, int part1_id, int part2_id, unsigned int *dte_chan1, unsigned int *dte_chan2);
+static int wcdte_destroy_channel(struct wcdte *wc, unsigned int chan1, unsigned int chan2);
/* Sanity check values */
-static inline int sanitycheck(struct zt_transcode_header *zth, unsigned int outbytes)
+static inline int zt_tc_sanitycheck(struct zt_transcode_header *zth, unsigned int outbytes)
{
if (zth->dstoffset >= sizeof(zth->dstdata))
return 0;
@@ -336,136 +415,23 @@
return 1;
}
-static void dump_cmdq(struct wcdte *wc)
-{
- struct cmdq *cmdq;
-
- debug_printk(1, "pending_cmdq: ");
- list_for_each_entry(cmdq, &wc->pending_cmdq, list)
- printk("%p(%zd) ", cmdq, cmdq->cmdspace);
- printk("\n");
-
- debug_printk(1, "free_cmdq: ");
- list_for_each_entry(cmdq, &wc->free_cmdq, list)
- printk("%p(%zd) ", cmdq, cmdq->cmdspace);
- printk("\n");
-}
-
-static struct cmdq *get_free_cmdq(struct wcdte *wc, size_t size_needed)
-{
- struct cmdq *winner = NULL;
- struct cmdq *candidate = NULL;
- size_t candidate_size = MAX_PACKET_SIZE;
- struct cmdq *smallest_seen = NULL;
- size_t smallest_seen_size = MAX_PACKET_SIZE;
- struct cmdq *entry;
-
- size_needed = ((size_needed / 16) + 1) * 16;
-
- if (size_needed > MAX_PACKET_SIZE)
- return NULL;
-
- list_for_each_entry(entry, &wc->free_cmdq, list) {
- if (entry->cmdspace == size_needed) {
- winner = entry;
- break;
- } else if ((entry->cmdspace > size_needed) &&
- (entry->cmdspace < candidate_size)) {
- candidate = entry;
- candidate_size = entry->cmdspace;
- } else if (entry->cmdspace < smallest_seen_size) {
- smallest_seen = entry;
- smallest_seen_size = entry->cmdspace;
- }
- }
-
- /* at this point, we either have a winner, a candidate,
- a potentially freeable too-small entry, or nothing...
- deal with the results
- */
-
- if (winner) {
- list_del_init(&winner->list);
- return winner;
- } else if (candidate) {
- list_del_init(&candidate->list);
- return candidate;
- } else if (wc->total_cmdq < MAX_TOTAL_CMDQ) {
- /* we can make a new entry */
- if (debug)
- dump_cmdq(wc);
- if ((winner = kmalloc(sizeof(*winner) + size_needed, GFP_KERNEL))) {
- debug_printk(1, "created a '%zd' byte cmdq entry at '%p'\n", size_needed, winner);
- winner->cmdspace = size_needed;
- INIT_LIST_HEAD(&winner->list);
- }
- return winner;
- } else if (smallest_seen) {
- /* we can't allocate new entries, but we have a
- too-small entry we can free and replace */
- if (debug)
- dump_cmdq(wc);
- list_del(&smallest_seen->list);
- kfree(smallest_seen);
- if ((winner = kmalloc(sizeof(*winner) + size_needed, GFP_KERNEL))) {
- debug_printk(1, "replaced a '%zd' byte cmdq entry at '%p' with a '%zd' byte one at '%p'\n", smallest_seen_size, smallest_seen, size_needed, winner);
- winner->cmdspace = size_needed;
- INIT_LIST_HEAD(&winner->list);
- }
- return winner;
- } else {
- /* we failed */
- module_printk("no cmdq entries available; limit of %d reached\n", MAX_TOTAL_CMDQ);
- return NULL;
- }
-}
-
-static int queue_cmd(struct wcdte *wc, u8 *data, size_t length)
-{
- struct cmdq *cmdq = get_free_cmdq(wc, length);
-
- if (!cmdq)
- return -1;
-
- cmdq->cmdlen = length;
- memcpy(cmdq->cmd, data, length);
- list_add_tail(&cmdq->list, &wc->pending_cmdq);
-
- return 0;
-}
-
-#define send_cmd(wc, command, length, hex) \
- ({ \
- int ret = 0; \
- u8 fifo[] = command; \
- do { \
- if (ret == 2) { \
- wc->ztsnd_rtx++; \
- if (hex == 0x0010) \
- wc->ztsnd_0010_rtx++; \
- } \
- down(&wc->cmdqsem); \
- queue_cmd(wc, fifo, sizeof(fifo)); \
- wc->last_command_sent = hex; \
- __transmit_demand(wc); \
- up(&wc->cmdqsem); \
- ret = waitfor_csmencaps(wc, RCV_CSMENCAPS, 0); \
- if (ret == 1) \
- return 1; \
- } while (ret == 2); \
- })
-
static void dte_init_state(struct dte_state *state_ptr, int encoder, unsigned int channel, struct wcdte *wc)
{
- memset(state_ptr, 0, sizeof(*state_ptr));
-
state_ptr->encoder = encoder;
state_ptr->wc = wc;
+ state_ptr->timestamp = 0;
+ state_ptr->seqno = 0;
+
+ state_ptr->packets_sent = 0;
+ state_ptr->packets_received = 0;
+ state_ptr->last_dte_seqno = 0;
+ state_ptr->dte_seqno_rcv = 0;
state_ptr->chan_in_num = 999;
state_ptr->chan_out_num = 999;
- if (encoder) {
+ if (encoder == 1)
+ {
state_ptr->timeslot_in_num = channel * 2;
state_ptr->timeslot_out_num = channel * 2 + 1;
} else {
@@ -474,141 +440,138 @@
}
}
-static inline unsigned int zapfmt_to_dtefmt(unsigned int fmt)
-{
- switch (fmt) {
- case ZT_FORMAT_G723_1:
- return DTE_FORMAT_G723_1;
- case ZT_FORMAT_ULAW:
- return DTE_FORMAT_ULAW;
- case ZT_FORMAT_ALAW:
- return DTE_FORMAT_ALAW;
- case ZT_FORMAT_G729A:
- return DTE_FORMAT_G729A;
- default:
- return DTE_FORMAT_UNDEF;
- }
-}
-
-static inline void __setctl(struct wcdte *wc, unsigned int addr, unsigned int val)
+static unsigned int wcdte_zapfmt_to_dtefmt(unsigned int fmt)
+{
+ unsigned int pt;
+
+ switch(fmt)
+ {
+ case ZT_FORMAT_G723_1:
+ pt = DTE_FORMAT_G723_1;
+ break;
+ case ZT_FORMAT_ULAW:
+ pt = DTE_FORMAT_ULAW;
+ break;
+ case ZT_FORMAT_ALAW:
+ pt = DTE_FORMAT_ALAW;
+ break;
+ case ZT_FORMAT_G729A:
+ pt = DTE_FORMAT_G729A;
+ break;
+ default:
+ pt = DTE_FORMAT_UNDEF;
+ }
+
+ return(pt);
+}
+
+static inline void __wcdte_setctl(struct wcdte *wc, unsigned int addr, unsigned int val)
{
outl(val, wc->iobase + addr);
}
-static inline unsigned int __getctl(struct wcdte *wc, unsigned int addr)
+static inline unsigned int __wcdte_getctl(struct wcdte *wc, unsigned int addr)
{
return inl(wc->iobase + addr);
}
-static inline void setctl(struct wcdte *wc, unsigned int addr, unsigned int val)
+static inline void wcdte_setctl(struct wcdte *wc, unsigned int addr, unsigned int val)
{
unsigned long flags;
-
spin_lock_irqsave(&wc->reglock, flags);
- __setctl(wc, addr, val);
+ __wcdte_setctl(wc, addr, val);
spin_unlock_irqrestore(&wc->reglock, flags);
}
-static inline unsigned int getctl(struct wcdte *wc, unsigned int addr)
-{
- unsigned long flags;
- unsigned int val;
-
- spin_lock_irqsave(&wc->reglock, flags);
- val = __getctl(wc, addr);
- spin_unlock_irqrestore(&wc->reglock, flags);
-
- return val;
-}
-
-static inline void reinit_descriptor(struct wcdte *wc, int tx, int dbl, char *s)
-{
- unsigned int o2;
-
- o2 = dbl * 4;
+static inline void wcdte_reinit_descriptor(struct wcdte *wc, int tx, int dbl, char *s)
+{
+ int o2 = 0;
+ o2 += dbl * 4;
if (!tx)
o2 += ERING_SIZE * 4;
wc->descripchunk[o2] = cpu_to_le32(0x80000000);
- setctl(wc, 0x0008, 0x00000000);
-}
-
-static inline void __transmit_one(struct wcdte *wc, u8 *data, size_t length)
-{
- u32 o2 = wc->tdbl * 4;
- volatile u8 *writechunk = (volatile u8 *) wc->writechunk + (wc->tdbl * SFRAME_SIZE);
- size_t xmt_length;
-
- /* Yes... this is a busy loop, that is not interruptible. However, it is
- highly unlikely (and testing proves) that the wait for a descriptor
- to become available will ever be long enough for this to be an issue.
- */
- do {} while ((le32_to_cpu(wc->descripchunk[o2]) & 0x80000000));
-
- xmt_length = max(length, (size_t) 64);
-
- wc->descripchunk[o2 + 1] = cpu_to_le32((le32_to_cpu(wc->descripchunk[o2 + 1]) & 0xFBFFF800) | xmt_length);
+ wcdte_setctl(wc, 0x0008, 0x00000000);
+}
+
+static inline unsigned int wcdte_getctl(struct wcdte *wc, unsigned int addr)
+{
+ unsigned long flags;
+ unsigned int val;
+ spin_lock_irqsave(&wc->reglock, flags);
+ val = __wcdte_getctl(wc, addr);
+ spin_unlock_irqrestore(&wc->reglock, flags);
+ return val;
+}
+
+static inline int __transmit_demand(struct wcdte *wc)
+{
+ volatile unsigned char *writechunk;
+ int o2,i,j;
+ unsigned int reg, xmt_length;
+
+ reg = wcdte_getctl(wc, 0x0028) & 0x00700000;
+
+ /* Already transmiting, no need to demand another */
+ if (!((reg == 0) || (reg = 6)))
+ return(1);
+
+ /* Nothing to transmit */
+ if (wc->cmdq_rndx == wc->cmdq_wndx)
+ return(1);
+
+ /* Nothing to transmit */
+ if (wc->cmdq[wc->cmdq_rndx].cmdlen == 0 )
+ return(1);
+
+ writechunk = (volatile unsigned char *)(wc->writechunk);
+
+ writechunk += wc->tdbl * SFRAME_SIZE;
+
+ o2 = wc->tdbl * 4;
+
+ do
+ {
+ } while ((le32_to_cpu(wc->descripchunk[o2]) & 0x80000000));
+
+ xmt_length = wc->cmdq[wc->cmdq_rndx].cmdlen;
+ if (xmt_length < 64)
+ xmt_length = 64;
+
+ wc->descripchunk[o2+1] = cpu_to_le32((le32_to_cpu(wc->descripchunk[o2+1]) & 0xFBFFF800) | xmt_length);
- memcpy((void *) writechunk, data, length);
- if (length < xmt_length)
- memset((void *) writechunk + length, 0, xmt_length - length);
+ for(i = 0; i < wc->cmdq[wc->cmdq_rndx].cmdlen; i++)
+ writechunk[i] = wc->cmdq[wc->cmdq_rndx].cmd[i];
+ for (j = i; j < xmt_length; j++)
+ writechunk[j] = 0;
+
+ if (debug_packets && (writechunk[12] == 0x88) && (writechunk[13] == 0x9B))
+ {
+ printk("wcdte debug: TX: ");
+ for (i=0; i<debug_packets; i++)
+ printk("%02X ", writechunk[i]);
+ printk("\n");
+ }
+
+ wc->cmdq[wc->cmdq_rndx].cmdlen = 0;
wc->descripchunk[o2] = cpu_to_le32(0x80000000);
- setctl(wc, 0x0008, 0x00000000); /* Transmit Poll Demand */
+ wcdte_setctl(wc, 0x0008, 0x00000000); /* Transmit Poll Demand */
wc->tdbl = (wc->tdbl + 1) % ERING_SIZE;
-}
-
-static inline int __transmit_demand(struct wcdte *wc)
-{
- int i;
- unsigned int reg;
- struct cmdq *cmdq;
-
- reg = getctl(wc, 0x0028) & 0x00700000;
-
- /* Nothing to transmit */
- if (list_empty(&wc->pending_cmdq))
- return 1;
-
- /* pop the first entry off the list */
- cmdq = list_entry(wc->pending_cmdq.next, struct cmdq, list);
- list_del_init(&cmdq->list);
-
- debug_printk(1, "transmitting command at '%p' of '%zd' bytes\n", cmdq, cmdq->cmdlen);
-
- __transmit_one(wc, cmdq->cmd, cmdq->cmdlen);
-
- if (debug_packets) {
- debug_printk(1, "TX: ");
- for (i = 0; i < min((size_t) debug_packets, cmdq->cmdlen); i++)
- printk("%02X ", cmdq->cmd[i]);
- printk("\n");
- }
-
- if (debug_cmd_packets &&
- (cmdq->cmd[12] == 0x88) &&
- (cmdq->cmd[13] == 0x9B)) {
- debug_printk(1, "TX: ");
- for (i = 0; i < min((size_t) debug_cmd_packets, cmdq->cmdlen); i++)
- printk("%02X ", cmdq->cmd[i]);
- printk("\n");
- }
-
- list_add_tail(&cmdq->list, &wc->free_cmdq);
-
- return 0;
+
+ wc->cmdq_rndx = (wc->cmdq_rndx + 1) % MAX_COMMANDS;
+
+ return(0);
}
static inline int transmit_demand(struct wcdte *wc)
{
int val;
-
down(&wc->cmdqsem);
val = __transmit_demand(wc);
up(&wc->cmdqsem);
-
return val;
}
@@ -621,61 +584,63 @@
unsigned char *chars;
unsigned int inbytes = 0;
unsigned int timestamp_inc = 0;
+ int i = 0;
int res = 0;
- u32 ipchksum;
-
- switch (op) {
+ unsigned int ipchksum, ndx;
+ switch(op) {
case ZT_TCOP_ALLOCATE:
- if (ztc->flags.chan_built)
- break;
down(&wc->chansem);
- if (st->encoder)
- create_channel(wc, zapfmt_to_dtefmt(zth->srcfmt), zapfmt_to_dtefmt(zth->dstfmt),
- st->timeslot_in_num, st->timeslot_out_num, &(st->chan_in_num),
- &(st->chan_out_num));
- else
- create_channel(wc, zapfmt_to_dtefmt(zth->dstfmt), zapfmt_to_dtefmt(zth->srcfmt),
- st->timeslot_out_num, st->timeslot_in_num, &(st->chan_out_num),
- &(st->chan_in_num));
- /* Mark this channel as built */
- ztc->flags.chan_built = 1;
- ztc->built_fmts = zth->dstfmt | zth->srcfmt;
-
- /* Mark the channel complement (other half of encoder/decoder pair) as built */
- if (st->encoder)
- compl_ztc = &(wc->udecode->channels[st->timeslot_in_num >> 1]);
- else
- compl_ztc = &(wc->uencode->channels[st->timeslot_in_num >> 1]);
- compl_ztc->flags.chan_built = 1;
- compl_ztc->built_fmts = zth->dstfmt | zth->srcfmt;
- compl_st = compl_ztc->pvt;
- compl_st->chan_in_num = st->chan_out_num;
- compl_st->chan_out_num = st->chan_in_num;
+ if (ztc->chan_built == 0)
+ {
+ if (st->encoder == 1)
+ wcdte_create_channel(wc, wcdte_zapfmt_to_dtefmt(zth->srcfmt), wcdte_zapfmt_to_dtefmt(zth->dstfmt),
+ st->timeslot_in_num, st->timeslot_out_num, &(st->chan_in_num), &(st->chan_out_num));
+ else
+ wcdte_create_channel(wc, wcdte_zapfmt_to_dtefmt(zth->dstfmt), wcdte_zapfmt_to_dtefmt(zth->srcfmt),
+ st->timeslot_out_num, st->timeslot_in_num, &(st->chan_out_num), &(st->chan_in_num));
+ /* Mark this channel as built */
+ ztc->chan_built = 1;
+ ztc->built_fmts = zth->dstfmt | zth->srcfmt;
+
+ /* Mark the channel complement (other half of encoder/decoder pair) as built */
+ ndx = st->timeslot_in_num/2;
+ if (st->encoder == 1)
+ compl_ztc = &(wc->udecode->channels[ndx]);
+ else
+ compl_ztc = &(wc->uencode->channels[ndx]);
+ compl_ztc->chan_built = 1;
+ compl_ztc->built_fmts = zth->dstfmt | zth->srcfmt;
+ compl_st = compl_ztc->pvt;
+ compl_st->chan_in_num = st->chan_out_num;
+ compl_st->chan_out_num = st->chan_in_num;
+ }
up(&wc->chansem);
break;
case ZT_TCOP_RELEASE:
down(&wc->chansem);
+ ndx = st->timeslot_in_num/2;
- if (st->encoder)
- compl_ztc = &(wc->udecode->channels[st->timeslot_in_num >> 1]);
+ if (st->encoder == 1)
+ compl_ztc = &(wc->udecode->channels[ndx]);
else
- compl_ztc = &(wc->uencode->channels[st->timeslot_in_num >> 1]);
+ compl_ztc = &(wc->uencode->channels[ndx]);
/* If the channel complement (other half of the encoder/decoder pair) is not being used... */
- if (!compl_ztc->flags.busy) {
- if (st->encoder)
- destroy_channel(wc, st->chan_in_num, st->chan_out_num);
+ if ((compl_ztc->flags & ZT_TC_FLAG_BUSY) == 0)
+ {
+ if (st->encoder == 1)
+ wcdte_destroy_channel(wc, st->chan_in_num, st->chan_out_num);
else
- destroy_channel(wc, st->chan_out_num, st->chan_in_num);
+ wcdte_destroy_channel(wc, st->chan_out_num, st->chan_in_num);
/* Mark this channel as not built */
- ztc->flags.chan_built = 0;
+ ztc->chan_built = 0;
ztc->built_fmts = 0;
st->chan_in_num = 999;
st->chan_out_num = 999;
/* Mark the channel complement as not built */
- compl_ztc->flags.chan_built = 0;
+ compl_ztc->chan_built = 0;
compl_ztc->built_fmts = 0;
compl_st = compl_ztc->pvt;
compl_st->chan_in_num = 999;
@@ -685,66 +650,61 @@
up(&wc->chansem);
break;
case ZT_TCOP_TRANSCODE:
- if ((((zth->srcfmt == ZT_FORMAT_ULAW) || (zth->srcfmt == ZT_FORMAT_ALAW)) &&
- ((zth->dstfmt == ZT_FORMAT_G729A && zth->srclen >= G729_SAMPLES) ||
- (zth->dstfmt == ZT_FORMAT_G723_1 && zth->srclen >= G723_SAMPLES))) ||
- ((zth->srcfmt == ZT_FORMAT_G729A) && (zth->srclen >= G729_BYTES)) ||
- ((zth->srcfmt == ZT_FORMAT_G723_1) && (zth->srclen >= G723_BYTES))) {
- struct cmdq *cmdq;
-
- do {
- chars = (u8 *)(zth->srcdata + zth->srcoffset);
-
- switch (zth->srcfmt) {
- case ZT_FORMAT_ULAW:
- case ZT_FORMAT_ALAW:
- switch (zth->dstfmt) {
- case ZT_FORMAT_G729A:
- inbytes = G729_SAMPLES;
- timestamp_inc = G729_SAMPLES;
- break;
- case ZT_FORMAT_G723_1:
- inbytes = G723_SAMPLES;
- timestamp_inc = G723_SAMPLES;
- break;
+ if ( (((zth->srcfmt == ZT_FORMAT_ULAW) || (zth->srcfmt == ZT_FORMAT_ALAW)) && ((zth->dstfmt == ZT_FORMAT_G729A && zth->srclen >= G729_SAMPLES) ||(zth->dstfmt == ZT_FORMAT_G723_1 && zth->srclen >= G723_SAMPLES)) )
+ || ((zth->srcfmt == ZT_FORMAT_G729A) && (zth->srclen >= G729_BYTES))
+ || ((zth->srcfmt == ZT_FORMAT_G723_1) && (zth->srclen >= G723_BYTES)) )
+ {
+ do
+ {
+ chars = (unsigned char *)(zth->srcdata + zth->srcoffset);
+
+ if ((zth->srcfmt == ZT_FORMAT_ULAW) || (zth->srcfmt == ZT_FORMAT_ALAW))
+ {
+ if (zth->dstfmt == ZT_FORMAT_G729A) {
+ inbytes = G729_SAMPLES;
+ timestamp_inc = G729_SAMPLES;
+ } else if (zth->dstfmt == ZT_FORMAT_G723_1) {
+ inbytes = G723_SAMPLES;
+ timestamp_inc = G723_SAMPLES;
}
- break;
- case ZT_FORMAT_G729A:
+
+ } else if (zth->srcfmt == ZT_FORMAT_G729A)
+ {
inbytes = G729_BYTES;
timestamp_inc = G729_SAMPLES;
- break;
- case ZT_FORMAT_G723_1:
+ } else if (zth->srcfmt == ZT_FORMAT_G723_1)
+ {
inbytes = G723_BYTES;
timestamp_inc = G723_SAMPLES;
- break;
}
zth->srclen -= inbytes;
-
+
{
- u8 fifo[] = CMD_MSG_IP_UDP_RTP(
- ((inbytes+40) >> 8) & 0xFF,
- (inbytes+40) & 0xFF,
- st->seqno & 0xFF,
- 0x00,
- 0x00,
+ unsigned char fifo[OTHER_CMD_LEN] = CMD_MSG_IP_UDP_RTP(
+ ((inbytes+40) >> 8) & 0xFF,
+ (inbytes+40) & 0xFF,
+ st->seqno & 0xFF,
+ 0x00,
+ 0x00,
(((st->timeslot_out_num) >> 8)+0x50) & 0xFF,
- (st->timeslot_out_num) & 0xFF,
+ (st->timeslot_out_num) & 0xFF,
(((st->timeslot_in_num) >> 8)+0x50) & 0xFF,
- (st->timeslot_in_num) & 0xFF,
- ((inbytes+20) >> 8) & 0xFF,
- (inbytes+20) & 0xFF,
- 0x00,
- 0x00,
- zapfmt_to_dtefmt(zth->srcfmt),
- ((st->seqno) >> 8) & 0xFF,
- (st->seqno) & 0xFF,
- ((st->timestamp) >> 24) & 0xFF,
- ((st->timestamp) >> 16) & 0xFF,
- ((st->timestamp) >> 8) & 0xFF,
- (st->timestamp) & 0xFF);
-
- ipchksum = 0x9869 + (fifo[16] << 8) + fifo[17] + (fifo[18] << 8) + fifo[19];
+ (st->timeslot_in_num) & 0xFF,
+ ((inbytes+20) >> 8) & 0xFF,
+ (inbytes+20) & 0xFF,
+ 0x00,
+ 0x00,
+ wcdte_zapfmt_to_dtefmt(zth->srcfmt),
+ ((st->seqno) >> 8) & 0xFF,
+ (st->seqno) & 0xFF,
+ ((st->timestamp) >> 24) & 0xFF,
+ ((st->timestamp) >> 16) & 0xFF,
+ ((st->timestamp) >> 8) & 0xFF,
+ (st->timestamp) & 0xFF);
+
+ ipchksum = 0x9869 + (fifo[16] << 8) + fifo[17]
+ + (fifo[18] << 8) + fifo[19];
while (ipchksum >> 16)
ipchksum = (ipchksum & 0xFFFF) + (ipchksum >> 16);
ipchksum = (~ipchksum) & 0xFFFF;
@@ -755,198 +715,273 @@
st->seqno += 1;
st->timestamp += timestamp_inc;
+ for (i = 0; i < inbytes; i++)
+ fifo[i+CMD_MSG_IP_UDP_RTP_LEN]= chars[i];
+
down(&wc->cmdqsem);
-
- if (!(cmdq = get_free_cmdq(wc, sizeof(fifo) + inbytes))) {
- up(&wc->cmdqsem);
- res = -EIO;
- break;
+
+ if ( (((wc->cmdq_wndx + 1) % MAX_COMMANDS) == wc->cmdq_rndx) && debug )
+ printk("wcdte error: cmdq is full.\n");
+ else
+ {
+ wc->cmdq[wc->cmdq_wndx].cmdlen = CMD_MSG_IP_UDP_RTP_LEN+inbytes;
+ for (i = 0; i < CMD_MSG_IP_UDP_RTP_LEN+inbytes; i++)
+ wc->cmdq[wc->cmdq_wndx].cmd[i] = fifo[i];
+ wc->cmdq_wndx = (wc->cmdq_wndx + 1) % MAX_COMMANDS;
}
-
- memcpy(cmdq->cmd, fifo, sizeof(fifo));
- memcpy(cmdq->cmd + sizeof(fifo), chars, inbytes);
- cmdq->cmdlen = sizeof(fifo) + inbytes;
- list_add_tail(&cmdq->list, &wc->pending_cmdq);
+
__transmit_demand(wc);
up(&wc->cmdqsem);
- st->packets_sent++;
- zth->srcoffset += inbytes;
}
- } while ((((zth->srcfmt == ZT_FORMAT_ULAW) || (zth->srcfmt == ZT_FORMAT_ALAW)) &&
- ((zth->dstfmt == ZT_FORMAT_G729A && zth->srclen >= G729_SAMPLES) ||
- (zth->dstfmt == ZT_FORMAT_G723_1 && zth->srclen >= G723_SAMPLES))) ||
- ((zth->srcfmt == ZT_FORMAT_G729A) && (zth->srclen >= G729_BYTES)) ||
- ((zth->srcfmt == ZT_FORMAT_G723_1) && (zth->srclen >= G723_BYTES)));
+ st->packets_sent++;
+
+
+
+ zth->srcoffset += inbytes;
+
+
+ } while ((((zth->srcfmt == ZT_FORMAT_ULAW) || (zth->srcfmt == ZT_FORMAT_ALAW)) && ((zth->dstfmt == ZT_FORMAT_G729A && zth->srclen >= G729_SAMPLES) ||(zth->dstfmt == ZT_FORMAT_G723_1 && zth->srclen >= G723_SAMPLES)) )
+ || ((zth->srcfmt == ZT_FORMAT_G729A) && (zth->srclen >= G729_BYTES))
+ || ((zth->srcfmt == ZT_FORMAT_G723_1) && (zth->srclen >= G723_BYTES)) );
+
} else {
zt_transcoder_alert(ztc);
- res = -EINVAL;
}
+ res = 0;
break;
}
-
return res;
}
-static void stop_dma(struct wcdte *wc);
-
-static inline void receiveprep(struct wcdte *wc, int dbl)
-{
- volatile u8 *readchunk = wc->readchunk + (dbl * SFRAME_SIZE);
+static void wcdte_stop_dma(struct wcdte *wc);
+
+static inline void wcdte_receiveprep(struct wcdte *wc, int dbl)
+{
+ volatile unsigned char *readchunk;
struct zt_transcoder_channel *ztc = NULL;
struct zt_transcode_header *zth = NULL;
struct dte_state *st = NULL;
- int o2, i;
+ int o2,i;
unsigned char rseq, rcodec;
unsigned int rcommand, rchannel, rlen, rtp_rseq, rtp_eseq;
- u8 *chars = NULL;
+ unsigned char *chars = NULL;
unsigned int ztc_ndx;
+
+ readchunk = (volatile unsigned char *)wc->readchunk;
+ readchunk += dbl * SFRAME_SIZE;
o2 = dbl * 4;
o2 += ERING_SIZE * 4;
- if (debug_packets) {
- debug_printk(1, "RX: ");
- for (i = 0; i < debug_packets; i++)
- printk("%02X ", readchunk[i]);
- printk("\n");
- }
-
- if ((readchunk[12] == 0x88) && (readchunk[13] == 0x9B)) {
- /* Control in packet */
- if (debug_cmd_packets) {
- debug_printk(1, "RX: ");
- for (i = 0; i < debug_cmd_packets; i++)
+ /* Control in packet */
+ if ((readchunk[12] == 0x88) && (readchunk[13] == 0x9B))
+ {
+ if (debug_packets)
+ {
+ printk("wcdte debug: RX: ");
+ for (i=0; i<debug_packets; i++)
printk("%02X ", readchunk[i]);
printk("\n");
}
/* See if message must be ACK'd */
- if ((readchunk[17] & 0xC0) == 0) {
+ if ((readchunk[17] & 0xC0) == 0)
+ {
rcommand = readchunk[24] | (readchunk[25] << 8);
rchannel = readchunk[18] | (readchunk[19] << 8);
rseq = readchunk[16];
+
+ down(&wc->cmdqsem);
+ if ( (((wc->cmdq_wndx + 1) % MAX_COMMANDS) == wc->cmdq_rndx) && debug )
+ printk("wcdte error: cmdq is full (rndx = %d, wndx = %d).\n", wc->cmdq_rndx, wc->cmdq_wndx);
+ else
{
- u8 fifo[] = CMD_MSG_ACK(rseq++, rchannel);
-
- down(&wc->cmdqsem);
- queue_cmd(wc, fifo, sizeof(fifo));
- __transmit_demand(wc);
- wc->rcvflags = RCV_CSMENCAPS;
- wc->last_rcommand = rcommand;
- wc->last_rparm2 = readchunk[30] | (readchunk[31] << 8);
- wake_up_interruptible(&wc->regq);
- up(&wc->cmdqsem);
- }
- } else {
+ unsigned char fifo[OTHER_CMD_LEN] = CMD_MSG_ACK(rseq++, rchannel);
+
+ wc->cmdq[wc->cmdq_wndx].cmdlen = CMD_MSG_ACK_LEN;
+ for (i = 0; i < wc->cmdq[wc->cmdq_wndx].cmdlen; i++)
+ wc->cmdq[wc->cmdq_wndx].cmd[i] = fifo[i];
+ wc->cmdq_wndx = (wc->cmdq_wndx + 1) % MAX_COMMANDS;
+ }
+
+ __transmit_demand(wc);
+
+
+ wc->rcvflags = RCV_CSMENCAPS;
+ wc->last_rcommand = rcommand;
+ wc->last_rparm2 = readchunk[30] | (readchunk[31] << 8);
+ wake_up_interruptible(&wc->regq);
+ up(&wc->cmdqsem);
+ }
+ else
+ {
wc->rcvflags = RCV_CSMENCAPS_ACK;
wake_up_interruptible(&wc->regq);
}
- } else if ((readchunk[12] == 0x08) && (readchunk[13] == 0x00) &&
- (readchunk[50] == 0x12) && (readchunk[51] == 0x34) &&
- (readchunk[52] = 0x56) && (readchunk[53] == 0x78)) {
- /* IP/UDP in packet */
+ }
+
+ /* IP/UDP in packet */
+ else if ((readchunk[12] == 0x08) && (readchunk[13] == 0x00)
+ && (readchunk[50] == 0x12) && (readchunk[51] == 0x34) && (readchunk[52] = 0x56) && (readchunk[53] == 0x78))
+ {
rchannel = (readchunk[37] | (readchunk[36] << 8)) - 0x5000;
rlen = (readchunk[39] | (readchunk[38] << 8)) - 20;
rtp_rseq = (readchunk[45] | (readchunk[44] << 8));
rcodec = readchunk[43];
- ztc_ndx = rchannel >> 1;
-
- if (ztc_ndx >= wc->numchannels) {
- debug_printk(1, "Invalid channel number received (ztc_ndx = %d) (numchannels = %d)\n", ztc_ndx, wc->numchannels);
+ ztc_ndx = rchannel/2;
+
+ if (ztc_ndx >= wc->numchannels)
+ {
+ if (debug)
+ printk("wcdte error: Invalid channel number received (ztc_ndx = %d) (numchannels = %d)\n", ztc_ndx, wc->numchannels);
rcodec = DTE_FORMAT_UNDEF;
}
- switch (rcodec) {
- case 0x00: /* ulaw */
- case 0x08: /* alaw */
+ if ((rcodec == 0x00) || (rcodec == 0x08)) /* ulaw or alaw (decoders) */
+ {
ztc = &(wc->udecode->channels[ztc_ndx]);
- break;
- case 0x04: /* g.723.1 */
- case 0x12: /* g.729 */
+ zth = ztc->tch;
+ st = ztc->pvt;
+
+ if (zth == NULL)
+ {
+ if (debug)
+ printk("wcdte error: Tried to put DTE data into a freed zth header!\n");
+ rcodec = DTE_FORMAT_UNDEF;
+ } else {
[... 1815 lines stripped ...]
More information about the zaptel-commits
mailing list