[zaptel-commits] kpfleming: branch group/transcoder-rework r2126 -
in /team/group/transcoder-r...
zaptel-commits at lists.digium.com
zaptel-commits at lists.digium.com
Thu Feb 8 09:46:55 MST 2007
Author: kpfleming
Date: Thu Feb 8 10:46:54 2007
New Revision: 2126
URL: http://svn.digium.com/view/zaptel?view=rev&rev=2126
Log:
bring back the not-quite-working-but-otherwise-much-improved driver :-)
Modified:
team/group/transcoder-rework/wctc4xxp/base.c
team/group/transcoder-rework/zaptel.h
team/group/transcoder-rework/zttranscode.c
Modified: team/group/transcoder-rework/wctc4xxp/base.c
URL: http://svn.digium.com/view/zaptel/team/group/transcoder-rework/wctc4xxp/base.c?view=diff&rev=2126&r1=2125&r2=2126
==============================================================================
--- team/group/transcoder-rework/wctc4xxp/base.c (original)
+++ team/group/transcoder-rework/wctc4xxp/base.c Thu Feb 8 10:46:54 2007
@@ -1,9 +1,10 @@
/*
- * Wildcard TC400B Driver
+ * Wildcard TC400B Interface Driver for Zapata Telephony interface
*
* Written by John Sloan <jsloan at digium.com>
+ * and Kevin P. Fleming <kpfleming at digium.com>
*
- * Copyright (C) 2006, Digium, Inc.
+ * Copyright (C) 2006-2007, Digium, Inc.
*
* All rights reserved.
*
@@ -23,7 +24,6 @@
*
*/
-
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/module.h>
@@ -34,7 +34,6 @@
#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>
@@ -43,30 +42,30 @@
#include <linux/workqueue.h>
#include <linux/moduleparam.h>
#include <linux/firmware.h>
-#ifdef CONFIG_DEVFS_FS
-#include <linux/devfs_fs_kernel.h>
-#endif
+#include <linux/list.h>
+
#ifdef STANDALONE_ZAPATA
#include "zaptel.h"
#else
#include <linux/zaptel.h>
#endif
-#ifdef HOTPLUG_FIRMWARE
-static const char *dte_firmware = "tc400m-firmware.bin";
+#if defined(HOTPLUG_FIRMWARE)
+static const char *tc400m_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 128
-
-#define NUM_CARDS 24
-#define NUM_EC 4
+#define WC_MAX_IFACES 8
/* NUM_CHANNELS must be checked if new firmware (dte_firm.h) is used */
#define NUM_CHANNELS 97
@@ -80,30 +79,22 @@
#define G729_LENGTH 20
#define G723_LENGTH 30
-#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 G729_SAMPLES 160
+#define G723_SAMPLES 240
+
+#define G729_BYTES 20
+#define G723_BYTES 20
+
+/* 274 for 30ms ulaw, 194 for 20ms ulaw */
#define OTHER_CMD_LEN 300
-#define MAX_COMMAND_LEN BOOT_CMD_LEN /* Must be the larger of BOOT_CMD_LEN or OTHER_CMD_LEN */
+#define MAX_COMMAND_LEN 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
@@ -117,182 +108,130 @@
#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 {
- unsigned int cmdlen;
- unsigned int cmd[MAX_COMMAND_LEN];
+ struct list_head list;
+ size_t cmdspace;
+ size_t cmdlen;
+ u8 cmd[0];
};
+
+#define MAX_PACKET_SIZE 1500
+#define MAX_TOTAL_CMDQ 40
struct wcdte {
struct pci_dev *dev;
- char *variety;
+ const char *variety;
unsigned int intcount;
unsigned int rxints;
unsigned int txints;
@@ -301,16 +240,15 @@
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 cmdq cmdq[MAX_COMMANDS];
- unsigned int cmdq_wndx;
- unsigned int cmdq_rndx;
+ struct list_head pending_cmdq;
+ struct list_head free_cmdq;
+ u32 total_cmdq; /* total of all cmdq entries, both pending and free */
unsigned int last_command_sent;
unsigned int last_rcommand;
@@ -321,16 +259,16 @@
unsigned int ztsnd_rtx;
unsigned int ztsnd_0010_rtx;
- unsigned char numchannels;
+ unsigned int numchannels;
unsigned char complexname[40];
unsigned long iobase;
- 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 */
+ 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 */
int wqueints;
struct workqueue_struct *dte_wq;
@@ -341,37 +279,26 @@
};
struct wcdte_desc {
- char *name;
+ const char *name;
int flags;
};
-static struct wcdte_desc wcdte = { "Wildcard TC400P+TC400M", 0 };
+static const 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; /* If we're an encoder */
+ int encoder;
struct wcdte *wc;
unsigned int timestamp;
unsigned int seqno;
- 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 timeslot_in_num;
+ unsigned int timeslot_out_num;
+
+ unsigned int chan_in_num;
+ unsigned int chan_out_num;
unsigned int packets_sent;
unsigned int packets_received;
@@ -380,21 +307,17 @@
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;
-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 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);
/* Sanity check values */
-static inline int zt_tc_sanitycheck(struct zt_transcode_header *zth, unsigned int outbytes)
+static inline int sanitycheck(struct zt_transcode_header *zth, unsigned int outbytes)
{
if (zth->dstoffset >= sizeof(zth->dstdata))
return 0;
@@ -413,23 +336,136 @@
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 == 1)
- {
+ if (encoder) {
state_ptr->timeslot_in_num = channel * 2;
state_ptr->timeslot_out_num = channel * 2 + 1;
} else {
@@ -438,138 +474,141 @@
}
}
-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)
+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)
{
outl(val, wc->iobase + addr);
}
-static inline unsigned int __wcdte_getctl(struct wcdte *wc, unsigned int addr)
+static inline unsigned int __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 setctl(struct wcdte *wc, unsigned int addr, unsigned int val)
{
unsigned long flags;
+
spin_lock_irqsave(&wc->reglock, flags);
- __wcdte_setctl(wc, addr, val);
+ __setctl(wc, addr, val);
spin_unlock_irqrestore(&wc->reglock, flags);
}
-static inline void wcdte_reinit_descriptor(struct wcdte *wc, int tx, int dbl, char *s)
-{
- int o2 = 0;
- o2 += dbl * 4;
+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;
if (!tx)
o2 += ERING_SIZE * 4;
wc->descripchunk[o2] = cpu_to_le32(0x80000000);
- 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;
+ 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);
+
+ memcpy((void *) writechunk, data, length);
+ if (length < xmt_length)
+ memset((void *) writechunk + length, 0, xmt_length - length);
+
+ wc->descripchunk[o2] = cpu_to_le32(0x80000000);
+ setctl(wc, 0x0008, 0x00000000); /* Transmit Poll Demand */
+
+ wc->tdbl = (wc->tdbl + 1) % ERING_SIZE;
}
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);
-
+ int i;
+ unsigned int reg;
+ struct cmdq *cmdq;
+
+ reg = getctl(wc, 0x0028) & 0x00700000;
+
/* 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);
-
- 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]);
+ 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");
}
- wc->cmdq[wc->cmdq_rndx].cmdlen = 0;
-
- wc->descripchunk[o2] = cpu_to_le32(0x80000000);
- wcdte_setctl(wc, 0x0008, 0x00000000); /* Transmit Poll Demand */
-
- wc->tdbl = (wc->tdbl + 1) % ERING_SIZE;
-
- wc->cmdq_rndx = (wc->cmdq_rndx + 1) % MAX_COMMANDS;
-
- return(0);
+ 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;
}
static inline int transmit_demand(struct wcdte *wc)
{
int val;
+
down(&wc->cmdqsem);
val = __transmit_demand(wc);
up(&wc->cmdqsem);
+
return val;
}
@@ -582,63 +621,61 @@
unsigned char *chars;
unsigned int inbytes = 0;
unsigned int timestamp_inc = 0;
- int i = 0;
int res = 0;
- unsigned int ipchksum, ndx;
- switch(op) {
+ u32 ipchksum;
+
+ switch (op) {
case ZT_TCOP_ALLOCATE:
+ if (ztc->flags.chan_built)
+ break;
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;
- }
+ 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;
up(&wc->chansem);
break;
case ZT_TCOP_RELEASE:
down(&wc->chansem);
- ndx = st->timeslot_in_num/2;
- if (st->encoder == 1)
- compl_ztc = &(wc->udecode->channels[ndx]);
+ if (st->encoder)
+ compl_ztc = &(wc->udecode->channels[st->timeslot_in_num >> 1]);
else
- compl_ztc = &(wc->uencode->channels[ndx]);
+ compl_ztc = &(wc->uencode->channels[st->timeslot_in_num >> 1]);
/* 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);
+ if (!compl_ztc->flags.busy) {
+ if (st->encoder)
+ destroy_channel(wc, st->chan_in_num, st->chan_out_num);
else
- wcdte_destroy_channel(wc, st->chan_out_num, st->chan_in_num);
+ destroy_channel(wc, st->chan_out_num, st->chan_in_num);
/* Mark this channel as not built */
- ztc->chan_built = 0;
+ ztc->flags.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->flags.chan_built = 0;
compl_ztc->built_fmts = 0;
compl_st = compl_ztc->pvt;
compl_st->chan_in_num = 999;
@@ -648,61 +685,66 @@
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)) )
- {
- 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;
+ 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;
}
-
- } else if (zth->srcfmt == ZT_FORMAT_G729A)
- {
+ break;
+ case ZT_FORMAT_G729A:
inbytes = G729_BYTES;
timestamp_inc = G729_SAMPLES;
- } else if (zth->srcfmt == ZT_FORMAT_G723_1)
- {
+ break;
+ case ZT_FORMAT_G723_1:
inbytes = G723_BYTES;
timestamp_inc = G723_SAMPLES;
+ break;
}
zth->srclen -= inbytes;
-
+
{
- unsigned char fifo[OTHER_CMD_LEN] = CMD_MSG_IP_UDP_RTP(
- ((inbytes+40) >> 8) & 0xFF,
- (inbytes+40) & 0xFF,
- st->seqno & 0xFF,
- 0x00,
- 0x00,
+ u8 fifo[] = 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,
- 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];
+ (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];
while (ipchksum >> 16)
ipchksum = (ipchksum & 0xFFFF) + (ipchksum >> 16);
ipchksum = (~ipchksum) & 0xFFFF;
@@ -713,273 +755,198 @@
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;
}
- 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)) );
-
+ } 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 wcdte_stop_dma(struct wcdte *wc);
-
-static inline void wcdte_receiveprep(struct wcdte *wc, int dbl)
-{
- volatile unsigned char *readchunk;
+static void stop_dma(struct wcdte *wc);
+
+static inline void receiveprep(struct wcdte *wc, int dbl)
+{
+ volatile u8 *readchunk = wc->readchunk + (dbl * SFRAME_SIZE);
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;
- unsigned char *chars = NULL;
+ u8 *chars = NULL;
unsigned int ztc_ndx;
-
- readchunk = (volatile unsigned char *)wc->readchunk;
- readchunk += dbl * SFRAME_SIZE;
o2 = dbl * 4;
o2 += ERING_SIZE * 4;
- /* Control in packet */
- if ((readchunk[12] == 0x88) && (readchunk[13] == 0x9B))
- {
- if (debug_packets)
- {
- printk("wcdte debug: RX: ");
- for (i=0; i<debug_packets; i++)
+ 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++)
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];
+ {
+ u8 fifo[] = CMD_MSG_ACK(rseq++, rchannel);
- 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++, 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;
+ 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);
}
-
- __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
- {
+ } else {
wc->rcvflags = RCV_CSMENCAPS_ACK;
wake_up_interruptible(&wc->regq);
}
- }
-
- /* IP/UDP in packet */
- else if ((readchunk[12] == 0x08) && (readchunk[13] == 0x00)
- && (readchunk[50] == 0x12) && (readchunk[51] == 0x34) && (readchunk[52] = 0x56) && (readchunk[53] == 0x78))
- {
+ } else if ((readchunk[12] == 0x08) && (readchunk[13] == 0x00) &&
+ (readchunk[50] == 0x12) && (readchunk[51] == 0x34) &&
+ (readchunk[52] = 0x56) && (readchunk[53] == 0x78)) {
+ /* IP/UDP in packet */
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/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);
+ 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);
rcodec = DTE_FORMAT_UNDEF;
}
- if ((rcodec == 0x00) || (rcodec == 0x08)) /* ulaw or alaw (decoders) */
- {
+ switch (rcodec) {
+ case 0x00: /* ulaw */
+ case 0x08: /* alaw */
ztc = &(wc->udecode->channels[ztc_ndx]);
- 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 {
- chars = (unsigned char *)(zth->dstdata + zth->dstoffset + zth->dstlen);
- st->packets_received++;
- }
-
+ break;
+ case 0x04: /* g.723.1 */
+ case 0x12: /* g.729 */
[... 1826 lines stripped ...]
More information about the zaptel-commits
mailing list