No subject


Thu Jul 12 09:23:04 CDT 2007


- DAHDI_TRANSCODE_OP is no longer supported, instead use DAHDI_TC_ALLOCATE,
  DAHDI_TC_GETINFO, and write/read.
- Memory and stack usage is reduced (stack usage could still be reduced some
  more by continuing the process of getting rid of the users of
  wctc4xxp_send_cmd and wctc4xxp_create_cmd).
- If more than one card is in the system channels will be allocated in a
  round-robin fashion from all available cards, reducing contention for the
  supervisor channel.
- There is no longer a tc400b workqueue created that will not show up in the
  process list.
- Commands and their responses are now explicitly matched up which elimated
  certain errors caused by unsolicited messages from the transcoder confusing
  the driver.
- There is now an option to export a network interface for capturing traffic
  to/from the hardware transcoder.
- codec_test has been removed from the dadhi/linux package.


Removed:
    linux/trunk/drivers/dahdi/wctc4xxp/codec_test.c
Modified:
    linux/trunk/drivers/dahdi/dahdi-base.c
    linux/trunk/drivers/dahdi/dahdi_transcode.c
    linux/trunk/drivers/dahdi/wctc4xxp/Kbuild
    linux/trunk/drivers/dahdi/wctc4xxp/Makefile
    linux/trunk/drivers/dahdi/wctc4xxp/base.c
    linux/trunk/include/dahdi/kernel.h
    linux/trunk/include/dahdi/user.h

Modified: linux/trunk/drivers/dahdi/dahdi-base.c
URL: http://svn.digium.com/view/dahdi/linux/trunk/drivers/dahdi/dahdi-base.c?view=diff&rev=4717&r1=4716&r2=4717
==============================================================================
--- linux/trunk/drivers/dahdi/dahdi-base.c (original)
+++ linux/trunk/drivers/dahdi/dahdi-base.c Wed Aug  6 13:09:58 2008
@@ -2620,30 +2620,29 @@
 static int dahdi_open(struct inode *inode, struct file *file)
 {
 	int unit = UNIT(file);
-	int ret = -ENXIO;
 	struct dahdi_chan *chan;
 	/* Minor 0: Special "control" descriptor */
 	if (!unit)
 		return dahdi_ctl_open(inode, file);
 	if (unit == 250) {
-		if (!dahdi_transcode_fops)
-			request_module("dahdi_transcode");
+		if (!dahdi_transcode_fops) {
+			if (request_module("dahdi_transcode")) {
+				return -ENXIO;
+			}
+		}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+		__MOD_INC_USE_COUNT (dahdi_transcode_fops->owner);
+#else
+		if (!try_module_get(dahdi_transcode_fops->owner)) {
+			return -ENXIO;
+		}
+#endif
 		if (dahdi_transcode_fops && dahdi_transcode_fops->open) {
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-			if (dahdi_transcode_fops->owner) {
-				__MOD_INC_USE_COUNT (dahdi_transcode_fops->owner);
-#else
-			if (try_module_get(dahdi_transcode_fops->owner)) {
-#endif
-				ret = dahdi_transcode_fops->open(inode, file);
-				if (ret)
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-					__MOD_DEC_USE_COUNT (dahdi_transcode_fops->owner);
-#else
-					module_put(dahdi_transcode_fops->owner);
-#endif
-			}
-			return ret;
+			return dahdi_transcode_fops->open(inode, file);
+		} else {
+			/* dahdi_transcode module should have exported a
+			 * file_operations table. */
+			 WARN_ON(1);
 		}
 		return -ENXIO;
 	}
@@ -3163,14 +3162,11 @@
 		return dahdi_timer_release(inode, file);
 	}
 	if (unit == 250) {
-		res = dahdi_transcode_fops->release(inode, file);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-		if (dahdi_transcode_fops->owner)
-			__MOD_DEC_USE_COUNT (dahdi_transcode_fops->owner);
-#else
-		module_put(dahdi_transcode_fops->owner);
-#endif
-		return res;
+		/* We should not be here because the dahdi_transcode.ko module
+		 * should have updated the file_operations for this file
+		 * handle when the file was opened. */
+		WARN_ON(1);
+		return -EFAULT;
 	}
 	if (unit == 254) {
 		chan = file->private_data;
@@ -5249,8 +5245,12 @@
 	if (!unit)
 		return dahdi_ctl_ioctl(inode, file, cmd, data);
 
-	if (unit == 250)
-		return dahdi_transcode_fops->ioctl(inode, file, cmd, data);
+	if (unit == 250) {
+		/* dahdi_transcode should have updated the file_operations on
+		 * this file object on open, so we shouldn't be here. */
+		WARN_ON(1);
+		return -EFAULT;
+	}
 
 	if (unit == 253) {
 		timer = file->private_data;

Modified: linux/trunk/drivers/dahdi/dahdi_transcode.c
URL: http://svn.digium.com/view/dahdi/linux/trunk/drivers/dahdi/dahdi_transcode.c?view=diff&rev=4717&r1=4716&r2=4717
==============================================================================
--- linux/trunk/drivers/dahdi/dahdi_transcode.c (original)
+++ linux/trunk/drivers/dahdi/dahdi_transcode.c Wed Aug  6 13:09:58 2008
@@ -3,7 +3,7 @@
  *
  * Written by Mark Spencer <markster at digium.com>
  *
- * Copyright (C) 2006-2007, Digium, Inc.
+ * Copyright (C) 2006-2008, Digium, Inc.
  *
  * All rights reserved.
  *
@@ -21,6 +21,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
+ *
  */
 
 #include <linux/kernel.h>
@@ -35,13 +36,18 @@
 #include <linux/vmalloc.h>
 #include <linux/mm.h>
 #include <linux/page-flags.h>
-#include <linux/moduleparam.h>
 #include <asm/io.h>
-
+#ifdef CONFIG_DEVFS_FS
+#include <linux/devfs_fs_kernel.h>
+#endif
+#ifdef STANDALONE_ZAPATA
+#include "dahdi/kernel.h"
+#else
 #include <dahdi/kernel.h>
-
-static int debug = 0;
-static struct dahdi_transcoder *trans;
+#endif
+
+static int debug;
+LIST_HEAD(trans);
 static spinlock_t translock = SPIN_LOCK_UNLOCKED;
 
 EXPORT_SYMBOL(dahdi_transcoder_register);
@@ -52,387 +58,375 @@
 
 struct dahdi_transcoder *dahdi_transcoder_alloc(int numchans)
 {
-	struct dahdi_transcoder *ztc;
+	struct dahdi_transcoder *tc;
 	unsigned int x;
-	size_t size = sizeof(*ztc) + (sizeof(ztc->channels[0]) * numchans);
-
-	if (!(ztc = kmalloc(size, GFP_KERNEL)))
+	size_t size = sizeof(*tc) + (sizeof(tc->channels[0]) * numchans);
+
+	if (!(tc = kmalloc(size, GFP_KERNEL)))
 		return NULL;
 
-	memset(ztc, 0, size);
-	strcpy(ztc->name, "<unspecified>");
-	ztc->numchannels = numchans;
-	for (x=0;x<ztc->numchannels;x++) {
-		init_waitqueue_head(&ztc->channels[x].ready);
-		ztc->channels[x].parent = ztc;
-		ztc->channels[x].offset = x;
-		ztc->channels[x].chan_built = 0;
-		ztc->channels[x].built_fmts = 0;
-	}
-
-	return ztc;
-}
-
-static int schluffen(wait_queue_head_t *q)
-{
-	DECLARE_WAITQUEUE(wait, current);
-
-	add_wait_queue(q, &wait);
-	current->state = TASK_INTERRUPTIBLE;
-
-	if (!signal_pending(current))
-		schedule();
-
-	current->state = TASK_RUNNING;
-	remove_wait_queue(q, &wait);
-
-	if (signal_pending(current))
-		return -ERESTARTSYS;
-
-	return 0;
-}
-
-void dahdi_transcoder_free(struct dahdi_transcoder *ztc)
-{
-	kfree(ztc);
+	memset(tc, 0, size);
+	strcpy(tc->name, "<unspecified>");
+	tc->numchannels = numchans;
+	for (x=0;x<tc->numchannels;x++) {
+		init_waitqueue_head(&tc->channels[x].ready);
+		INIT_LIST_HEAD(&tc->node);
+		tc->channels[x].parent = tc;
+	}
+
+	WARN_ON(!dahdi_transcode_fops);
+	/* Individual transcoders should supply their own file_operations for
+	 * write and read.  But they will by default use the file_operations
+	 * provided by the dahdi_transcode layer.  */
+	memcpy(&tc->fops, dahdi_transcode_fops, sizeof(*dahdi_transcode_fops));
+	return tc;
+}
+
+void dahdi_transcoder_free(struct dahdi_transcoder *tc)
+{
+	kfree(tc);
+}
+
+/* Returns 1 if the item is on the list pointed to by head, otherwise, returns
+ * 0 */
+static int is_on_list(struct list_head *entry, struct list_head *head)
+{
+	struct list_head *cur;
+	list_for_each(cur, head) {
+		if (cur == entry) return 1;
+	}
+	return 0;
 }
 
 /* Register a transcoder */
 int dahdi_transcoder_register(struct dahdi_transcoder *tc)
 {
-	struct dahdi_transcoder *cur;
-	int res = -EBUSY;
-
 	spin_lock(&translock);
-	for (cur = trans; cur; cur = cur->next) {
-		if (cur == tc) {
-			spin_unlock(&translock);
-			return res;
-		}
-	}
-
-	tc->next = trans;
-	trans = tc;
-	printk(KERN_INFO "Registered codec translator '%s' with %d transcoders (srcs=%08x, dsts=%08x)\n", 
+	BUG_ON(is_on_list(&tc->node, &trans));
+	list_add_tail(&tc->node, &trans);
+	spin_unlock(&translock);
+
+	printk(KERN_INFO "%s: Registered codec translator '%s' " \
+	       "with %d transcoders (srcs=%08x, dsts=%08x)\n", 
+	       THIS_MODULE->name, tc->name, tc->numchannels, 
+	       tc->srcfmts, tc->dstfmts);
+
+	return 0;
+}
+
+/* Unregister a transcoder */
+int dahdi_transcoder_unregister(struct dahdi_transcoder *tc) 
+{
+	int res = -EINVAL;
+
+	/* \todo Perhaps we should check to make sure there isn't a channel
+	 * that is still in use? */
+
+	spin_lock(&translock);
+	if (!is_on_list(&tc->node, &trans)) {
+		spin_unlock(&translock);
+		printk(KERN_WARNING "%s: Failed to unregister %s, which is " \
+		       "not currently registerd.\n", THIS_MODULE->name, tc->name);
+		return -EINVAL;
+	}
+	list_del_init(&tc->node);
+	spin_unlock(&translock);
+
+	printk(KERN_INFO "Unregistered codec translator '%s' with %d " \
+	       "transcoders (srcs=%08x, dsts=%08x)\n", 
 	       tc->name, tc->numchannels, tc->srcfmts, tc->dstfmts);
 	res = 0;
-	spin_unlock(&translock);
 
 	return res;
 }
 
-/* Unregister a transcoder */
-int dahdi_transcoder_unregister(struct dahdi_transcoder *tc) 
-{
-	struct dahdi_transcoder *cur, *prev;
-	int res = -EINVAL;
-
-	spin_lock(&translock);
-	for (cur = trans, prev = NULL; cur; prev = cur, cur = cur->next) {
-		if (cur == tc)
-			break;
-	}
-
-	if (!cur) {
-		spin_unlock(&translock);
-		return res;
-	}
-
-	if (prev)
-		prev->next = tc->next;
-	else
-		trans = tc->next;
-	tc->next = NULL;
-	printk(KERN_INFO "Unregistered codec translator '%s' with %d transcoders (srcs=%08x, dsts=%08x)\n", 
-	       tc->name, tc->numchannels, tc->srcfmts, tc->dstfmts);
-	res = 0;
-	spin_unlock(&translock);
-
-	return res;
-}
-
 /* Alert a transcoder */
-int dahdi_transcoder_alert(struct dahdi_transcoder_channel *ztc)
-{
-	if (debug)
-		printk(KERN_DEBUG "DAHDI Transcoder Alert!\n");
-	if (ztc->tch)
-		ztc->tch->status &= ~DAHDI_TC_FLAG_BUSY;
-	wake_up_interruptible(&ztc->ready);
-
+int dahdi_transcoder_alert(struct dahdi_transcoder_channel *chan)
+{
+	wake_up_interruptible(&chan->ready);
 	return 0;
 }
 
 static int dahdi_tc_open(struct inode *inode, struct file *file)
 {
-	struct dahdi_transcoder_channel *ztc;
-	struct dahdi_transcode_header *zth;
-	struct page *page;
-
-	if (!(ztc = kmalloc(sizeof(*ztc), GFP_KERNEL)))
-		return -ENOMEM;
-
-	if (!(zth = kmalloc(sizeof(*zth), GFP_KERNEL | GFP_DMA))) {
-		kfree(ztc);
-		return -ENOMEM;
-	}
-	
-	memset(ztc, 0, sizeof(*ztc));
-	memset(zth, 0, sizeof(*zth));
-	ztc->flags = DAHDI_TC_FLAG_TRANSIENT | DAHDI_TC_FLAG_BUSY;
-	ztc->tch = zth;
-	if (debug)
-		printk(KERN_DEBUG "Allocated Transcoder Channel, header is at %p!\n", zth);
-	zth->magic = DAHDI_TRANSCODE_MAGIC;
-	file->private_data = ztc;
-	for (page = virt_to_page(zth);
-	     page < virt_to_page((unsigned long) zth + sizeof(*zth));
-	     page++)
-		SetPageReserved(page);
-
-	return 0;
-}
-
-static void ztc_release(struct dahdi_transcoder_channel *ztc)
-{
-	struct dahdi_transcode_header *zth = ztc->tch;
-	struct page *page;
-
-	if (!ztc)
-		return;
-
-	ztc->flags &= ~(DAHDI_TC_FLAG_BUSY);
-
-	if(ztc->tch) {
-		for (page = virt_to_page(zth);
-		     page < virt_to_page((unsigned long) zth + sizeof(*zth));
-		     page++)
-			ClearPageReserved(page);
-		kfree(ztc->tch);
-	}
-
-	ztc->tch = NULL;
-	/* Actually reset the transcoder channel */
-	if (ztc->flags & DAHDI_TC_FLAG_TRANSIENT)
-		kfree(ztc);
-	if (debug)
-		printk(KERN_DEBUG "Released Transcoder!\n");
+	const struct file_operations *original_fops;	
+	BUG_ON(!dahdi_transcode_fops);
+	original_fops = file->f_op;
+	file->f_op = dahdi_transcode_fops;
+	file->private_data = NULL;
+	/* Under normal operation, this releases the reference on the DAHDI
+	 * module that was created when the file was opened. dahdi_open is
+	 * responsible for taking a reference out on this module before
+	 * calling this function. */
+	module_put(original_fops->owner);
+	return 0;
+}
+
+static void dtc_release(struct dahdi_transcoder_channel *chan)
+{
+	BUG_ON(!chan);
+	if (chan->parent && chan->parent->release) {
+		chan->parent->release(chan);
+	}
+	dahdi_tc_clear_busy(chan);
 }
 
 static int dahdi_tc_release(struct inode *inode, struct file *file)
 {
-	ztc_release(file->private_data);
-
-	return 0;
-}
-
-static int do_reset(struct dahdi_transcoder_channel **ztc)
-{
-	struct dahdi_transcoder_channel *newztc = NULL, *origztc = NULL;
-	struct dahdi_transcode_header *zth = (*ztc)->tch;
+	struct dahdi_transcoder_channel *chan = file->private_data;
+	/* There will not be a transcoder channel associated with this file if
+	 * the ALLOCATE ioctl never succeeded. 
+	 */
+	if (chan) {
+		dtc_release(chan);
+	}
+	return 0;
+}
+
+/* Find a free channel on the transcoder and mark it busy. */
+static inline struct dahdi_transcoder_channel *
+get_free_channel(struct dahdi_transcoder *tc)
+
+{
+	struct dahdi_transcoder_channel *chan;
+	int i;
+	/* Should be called with the translock held. */
+	WARN_ON(!spin_is_locked(&translock));
+
+	for (i = 0; i < tc->numchannels; i++) {
+		chan = &tc->channels[i];
+		if (!dahdi_tc_is_busy(chan)) {
+			dahdi_tc_set_busy(chan);
+			return chan;
+		}
+	}
+	return NULL;
+}
+
+/* Search the list for a transcoder that supports the specified format, and
+ * allocate and return an available channel on it.   
+ *
+ * Returns either a pointer to the allocated channel, -EBUSY if the format is
+ * supported but all the channels are busy, or -ENODEV if there are not any
+ * transcoders that support the formats.
+ */
+static struct dahdi_transcoder_channel *
+__find_free_channel(struct list_head *list, const struct dahdi_transcoder_formats *fmts)
+{
 	struct dahdi_transcoder *tc;
-	unsigned int x;
+	struct dahdi_transcoder_channel *chan = NULL;
 	unsigned int match = 0;
 
-	if (((*ztc)->srcfmt != zth->srcfmt) ||
-	    ((*ztc)->dstfmt != zth->dstfmt)) {
-		/* Find new transcoder */
-		spin_lock(&translock);
-		for (tc = trans; tc && !newztc; tc = tc->next) {
-			if (!(tc->srcfmts & zth->srcfmt))
-				continue;
-
-			if (!(tc->dstfmts & zth->dstfmt))
-				continue;
-
-			match = 1;
-			for (x = 0; x < tc->numchannels; x++) {
-				if (tc->channels[x].flags & DAHDI_TC_FLAG_BUSY)
-					continue;
-				if ((tc->channels[x].chan_built) && ((zth->srcfmt | zth->dstfmt) != tc->channels[x].built_fmts))
-					continue;
-
-				newztc = &tc->channels[x];
-				newztc->flags = DAHDI_TC_FLAG_BUSY;
-				break;
+	list_for_each_entry(tc, list, node) {
+		if ((tc->dstfmts & fmts->dstfmt)) {
+			/* We found a transcoder that can handle our formats.
+			 * Now look for an available channel. */
+			match = 1; 
+			if ((chan = get_free_channel(tc))) {
+				/* transcoder tc has a free channel.  In order
+				 * to spread the load among available
+				 * transcoders (when there are more than one
+				 * transcoder in the system) we'll move tc 
+				 * to the end of the list. */
+				list_move_tail(&tc->node, list);
+				return chan;
 			}
 		}
-		spin_unlock(&translock);
-
-		if (!newztc)
-			return match ? -EBUSY : -ENOSYS;
-
-		/* Move transcoder header over */
-		origztc = (*ztc);
-		(*ztc) = newztc;
-		(*ztc)->tch = origztc->tch;
-		origztc->tch = NULL;
-		(*ztc)->flags |= (origztc->flags & ~(DAHDI_TC_FLAG_TRANSIENT));
-		ztc_release(origztc);
+	}
+	return (void*)((match) ? -EBUSY : -ENODEV);
+}
+
+static long dahdi_tc_allocate(struct file *file, unsigned long data)
+{
+	struct dahdi_transcoder_channel *chan = NULL;
+	struct dahdi_transcoder_formats fmts;
+	
+	if (copy_from_user(&fmts, 
+		(struct dahdi_transcoder_formats*) data, sizeof(fmts))) {
+		return -EFAULT;
+	}
+
+	spin_lock(&translock);
+	chan = __find_free_channel(&trans, &fmts);
+	spin_unlock(&translock);
+
+	if (IS_ERR(chan)) {
+		return PTR_ERR(chan);
+	}
+
+	/* Every transcoder channel must be associated with a parent
+	 * transcoder. */
+	BUG_ON(!chan->parent);
+
+	chan->srcfmt = fmts.srcfmt;
+	chan->dstfmt = fmts.dstfmt;
+
+	if (file->private_data) {
+		/* This open file is moving to a new channel. Cleanup and
+		 * close the old channel here.  */
+		dtc_release(file->private_data);
+	}
+
+	file->private_data = chan;
+	if (chan->parent->fops.owner != file->f_op->owner) {
+		if (!try_module_get(chan->parent->fops.owner)) {
+			/* Failed to get a reference on the driver for the
+			 * actual transcoding hardware.  */
+			return -EINVAL;
+		}
+		/* Release the reference on the existing driver. */
+		module_put(file->f_op->owner);
+		file->f_op = &chan->parent->fops;
+	}
+
+	if (file->f_flags & O_NONBLOCK) {
+		dahdi_tc_set_nonblock(chan);
+	} else {
+		dahdi_tc_clear_nonblock(chan); 
 	}
 
 	/* Actually reset the transcoder channel */
-	if ((*ztc)->parent && ((*ztc)->parent->operation))
-		return (*ztc)->parent->operation((*ztc), DAHDI_TCOP_ALLOCATE);
+	if (chan->parent->allocate)
+		return chan->parent->allocate(chan);
 
 	return -EINVAL;
 }
 
-static int wait_busy(struct dahdi_transcoder_channel *ztc)
-{
-	int ret;
-
-	for (;;) {
-		if (!(ztc->tch->status & DAHDI_TC_FLAG_BUSY))
-			return 0;
-		if ((ret = schluffen(&ztc->ready)))
-			return ret;
-	}
-}
-
-static int dahdi_tc_getinfo(unsigned long data)
-{
-	struct dahdi_transcode_info info;
+static long dahdi_tc_getinfo(unsigned long data)
+{
+	struct dahdi_transcoder_info info;
 	unsigned int x;
-	struct dahdi_transcoder *tc;
+	struct dahdi_transcoder *cur;
+	struct dahdi_transcoder *tc = NULL;
 	
-	if (copy_from_user(&info, (struct dahdi_transcode_info *) data, sizeof(info)))
+	if (copy_from_user(&info, (const void *) data, sizeof(info))) {
 		return -EFAULT;
-
+	}
+
+	x = 0;
 	spin_lock(&translock);
-	for (tc = trans, x = info.tcnum; tc && x; tc = tc->next, x--);
+	list_for_each_entry(cur, &trans, node) {
+		if (x++ == info.tcnum) {
+			tc = cur;
+			break;
+		} 
+	}
 	spin_unlock(&translock);
 
-	if (!tc)
+	if (!tc) {
 		return -ENOSYS;
+	}
 
 	dahdi_copy_string(info.name, tc->name, sizeof(info.name));
 	info.numchannels = tc->numchannels;
 	info.srcfmts = tc->srcfmts;
 	info.dstfmts = tc->dstfmts;
 
-	return copy_to_user((struct dahdi_transcode_info *) data, &info, sizeof(info)) ? -EFAULT : 0;
+	return copy_to_user((void *) data, &info, sizeof(info)) ? -EFAULT : 0;
+}
+
+static ssize_t dahdi_tc_write(struct file *file, __user const char *usrbuf, size_t count, loff_t *ppos)
+{
+	if (file->private_data) {
+		/* file->private_data will not be NULL if DAHDI_TC_ALLOCATE was
+		 * called, and therefore indicates that the transcoder driver
+		 * did not export a read function. */
+		WARN_ON(1);
+		return -ENOSYS;
+	} else {
+		printk(KERN_INFO "%s: Attempt to write to unallocated " \
+		       "channel.\n", THIS_MODULE->name);
+		return -EINVAL;
+	}
+}
+
+static ssize_t dahdi_tc_read(struct file *file, __user char *usrbuf, size_t count, loff_t *ppos)
+{
+	if (file->private_data) {
+		/* file->private_data will not be NULL if DAHDI_TC_ALLOCATE was
+		 * called, and therefore indicates that the transcoder driver
+		 * did not export a write function. */
+		WARN_ON(1);
+		return -ENOSYS;
+	} else {
+		printk(KERN_INFO "%s: Attempt to read from unallocated " \
+		       "channel.\n", THIS_MODULE->name);
+		return -EINVAL;
+	}
+}
+
+static long dahdi_tc_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long data)
+{
+	switch (cmd) {
+	case DAHDI_TC_ALLOCATE:
+		return dahdi_tc_allocate(file, data);
+	case DAHDI_TC_GETINFO:
+		return dahdi_tc_getinfo(data);
+	case DAHDI_TRANSCODE_OP:
+		/* This is a deprecated call from the previous transcoder
+		 * interface, which was all routed through the dahdi_ioctl in
+		 * dahdi-base.c, and this ioctl request was used to indicate
+		 * that the call should be forwarded to this function. Now
+		 * when the file is opened, the f_ops pointer is updated to
+		 * point directly to this function, and we don't need a
+		 * general indication that the ioctl is destined for the
+		 * transcoder.  
+		 *
+		 * I'm keeping this ioctl here in order to explain why there
+		 * might be a hole in the ioctl numbering scheme in the header
+		 * files.
+		 */
+		printk(KERN_WARNING "%s: DAHDI_TRANSCODE_OP is no longer " \
+		   "supported. Please call DAHDI_TC ioctls directly.\n",
+		   THIS_MODULE->name);
+		return -EINVAL;
+	default:
+		return -EINVAL;
+	};
 }
 
 static int dahdi_tc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data)
 {
-	int op;
+	return (int)dahdi_tc_unlocked_ioctl(file, cmd, data);
+}
+
+static int dahdi_tc_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	printk(KERN_ERR "%s: mmap interface deprecated.\n", THIS_MODULE->name);
+	return -ENOSYS;
+}
+
+static unsigned int dahdi_tc_poll(struct file *file, struct poll_table_struct *wait_table)
+{
 	int ret;
-	struct dahdi_transcoder_channel *ztc = file->private_data;
-
-	if (cmd != DAHDI_TRANSCODE_OP)
-		return -ENOSYS;
-
-	if (get_user(op, (int *) data))
-		return -EFAULT;
-
-	if (debug)
-		printk(KERN_DEBUG "DAHDI Transcode ioctl op = %d!\n", op);
-
-	switch(op) {
-	case DAHDI_TCOP_GETINFO:
-		ret = dahdi_tc_getinfo(data);
-		break;
-	case DAHDI_TCOP_ALLOCATE:
-		/* Reset transcoder, possibly changing who we point to */
-		ret = do_reset(&ztc);
-		file->private_data = ztc;
-		break;
-	case DAHDI_TCOP_RELEASE:
-		ret = ztc->parent->operation(ztc, DAHDI_TCOP_RELEASE);
-		break;
-	case DAHDI_TCOP_TEST:
-		ret = ztc->parent->operation(ztc, DAHDI_TCOP_TEST);
-		break;
-	case DAHDI_TCOP_TRANSCODE:
-		if (!ztc->parent->operation)
-			return -EINVAL;
-
-		ztc->tch->status |= DAHDI_TC_FLAG_BUSY;
-		if (!(ret = ztc->parent->operation(ztc, DAHDI_TCOP_TRANSCODE))) {
-			/* Wait for busy to go away if we're not non-blocking */
-			if (!(file->f_flags & O_NONBLOCK)) {
-				if (!(ret = wait_busy(ztc)))
-					ret = ztc->errorstatus;
-			}
-		} else
-			ztc->tch->status &= ~DAHDI_TC_FLAG_BUSY;
-		break;
-	default:
-		ret = -ENOSYS;
-	}
-
+	struct dahdi_transcoder_channel *chan = file->private_data;
+
+	if (!chan) {
+		/* This is because the DAHDI_TC_ALLOCATE ioctl was not called
+		 * before calling poll, which is invalid. */
+		return -EINVAL;
+	}
+
+	poll_wait(file, &chan->ready, wait_table);
+
+	ret =  dahdi_tc_is_busy(chan)         ? 0       : POLLPRI;
+	ret |= dahdi_tc_is_built(chan)        ? POLLOUT : 0;
+	ret |= dahdi_tc_is_data_waiting(chan) ? POLLIN  : 0;
 	return ret;
 }
 
-static int dahdi_tc_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct dahdi_transcoder_channel *ztc = file->private_data;
-	unsigned long physical;
-	int res;
-
-	if (!ztc)
-		return -EINVAL;
-
-	/* Do not allow an offset */
-	if (vma->vm_pgoff) {
-		if (debug)
-			printk(KERN_DEBUG "zttranscode: Attempted to mmap with offset!\n");
-		return -EINVAL;
-	}
-
-	if ((vma->vm_end - vma->vm_start) != sizeof(struct dahdi_transcode_header)) {
-		if (debug)
-			printk(KERN_DEBUG "zttranscode: Attempted to mmap with size %d != %zd!\n", (int) (vma->vm_end - vma->vm_start), sizeof(struct dahdi_transcode_header));
-		return -EINVAL;
-	}
-
-	physical = (unsigned long) virt_to_phys(ztc->tch);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
-	res = remap_pfn_range(vma, vma->vm_start, physical >> PAGE_SHIFT, sizeof(struct dahdi_transcode_header), PAGE_SHARED);
-#else
-  #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-	res = remap_page_range(vma->vm_start, physical, sizeof(struct dahdi_transcode_header), PAGE_SHARED);
-  #else
-	res = remap_page_range(vma, vma->vm_start, physical, sizeof(struct dahdi_transcode_header), PAGE_SHARED);
-  #endif
+static struct file_operations __dahdi_transcode_fops = {
+	owner:   THIS_MODULE,
+	open:    dahdi_tc_open,
+	release: dahdi_tc_release,
+	ioctl:   dahdi_tc_ioctl,
+	read:    dahdi_tc_read,
+	write:   dahdi_tc_write,
+	poll:    dahdi_tc_poll,
+	mmap:    dahdi_tc_mmap,
+#if HAVE_UNLOCKED_IOCTL
+	unlocked_ioctl: dahdi_tc_unlocked_ioctl,
 #endif
-	if (res) {
-		if (debug)
-			printk(KERN_DEBUG "zttranscode: remap failed!\n");
-		return -EAGAIN;
-	}
-
-	if (debug)
-		printk(KERN_DEBUG "zttranscode: successfully mapped transcoder!\n");
-
-	return 0;
-}
-
-static unsigned int dahdi_tc_poll(struct file *file, struct poll_table_struct *wait_table)
-{
-	struct dahdi_transcoder_channel *ztc = file->private_data;
-
-	if (!ztc)
-		return -EINVAL;
-
-	poll_wait(file, &ztc->ready, wait_table);
-	return ztc->tch->status & DAHDI_TC_FLAG_BUSY ? 0 : POLLPRI;
-}
-
-static struct file_operations __dahdi_transcode_fops = {
-	owner: THIS_MODULE,
-	llseek: NULL,
-	open: dahdi_tc_open,
-	release: dahdi_tc_release,
-	ioctl: dahdi_tc_ioctl,
-	read: NULL,
-	write: NULL,
-	poll: dahdi_tc_poll,
-	mmap: dahdi_tc_mmap,
-	flush: NULL,
-	fsync: NULL,
-	fasync: NULL,
 };
 
 static struct dahdi_chardev transcode_chardev = {
@@ -445,7 +439,7 @@
 	int res;
 
 	if (dahdi_transcode_fops) {
-		printk(KERN_NOTICE "Whoa, dahdi_transcode_fops already set?!\n");
+		printk(KERN_WARNING "dahdi_transcode_fops already set.\n");
 		return -EBUSY;
 	}
 
@@ -454,8 +448,7 @@
 	if ((res = dahdi_register_chardev(&transcode_chardev)))
 		return res;
 
-	printk(KERN_INFO "DAHDI Transcoder support loaded\n");
-
+	printk(KERN_INFO "%s: Loaded.\n", THIS_MODULE->name);
 	return 0;
 }
 
@@ -465,14 +458,15 @@
 
 	dahdi_transcode_fops = NULL;
 
-	printk(KERN_INFO "DAHDI Transcoder support unloaded\n");
+	printk(KERN_DEBUG "%s: Unloaded.\n", THIS_MODULE->name);
 }
 
 module_param(debug, int, S_IRUGO | S_IWUSR);
-
 MODULE_DESCRIPTION("DAHDI Transcoder Support");
 MODULE_AUTHOR("Mark Spencer <markster at digium.com>");
-MODULE_LICENSE("GPL v2");
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
 
 module_init(dahdi_transcode_init);
 module_exit(dahdi_transcode_cleanup);

Modified: linux/trunk/drivers/dahdi/wctc4xxp/Kbuild
URL: http://svn.digium.com/view/dahdi/linux/trunk/drivers/dahdi/wctc4xxp/Kbuild?view=diff&rev=4717&r1=4716&r2=4717
==============================================================================
--- linux/trunk/drivers/dahdi/wctc4xxp/Kbuild (original)
+++ linux/trunk/drivers/dahdi/wctc4xxp/Kbuild Wed Aug  6 13:09:58 2008
@@ -8,7 +8,7 @@
   EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE
 endif
 
-wctc4xxp-objs := base.o 
+wctc4xxp-objs := base.o
 
 ifneq ($(HOTPLUG_FIRMWARE),yes)
 wctc4xxp-objs += $(FIRM_DIR)/dahdi-fw-tc400m.o

Modified: linux/trunk/drivers/dahdi/wctc4xxp/Makefile
URL: http://svn.digium.com/view/dahdi/linux/trunk/drivers/dahdi/wctc4xxp/Makefile?view=diff&rev=4717&r1=4716&r2=4717
==============================================================================
--- linux/trunk/drivers/dahdi/wctc4xxp/Makefile (original)
+++ linux/trunk/drivers/dahdi/wctc4xxp/Makefile Wed Aug  6 13:09:58 2008
@@ -3,14 +3,5 @@
 # For newer kernels, Kbuild will be included directly by the kernel
 # build system.
 include $(src)/Kbuild
-
 else
-
-tests: codec_test
-
-codec_test: codec_test.c ../../include/dahdi/kernel.h ../../include/dahdi/user.h
-	$(CC) -o $@ $< $(CFLAGS)
-
-clean:
-	rm -rf codec_test
 endif

Modified: linux/trunk/drivers/dahdi/wctc4xxp/base.c
URL: http://svn.digium.com/view/dahdi/linux/trunk/drivers/dahdi/wctc4xxp/base.c?view=diff&rev=4717&r1=4716&r2=4717
==============================================================================
--- linux/trunk/drivers/dahdi/wctc4xxp/base.c (original)
+++ linux/trunk/drivers/dahdi/wctc4xxp/base.c Wed Aug  6 13:09:58 2008
@@ -1,9 +1,7 @@
 /*
  * Wildcard TC400B Driver
  *
- * Written by John Sloan <jsloan at digium.com>
- *
- * Copyright (C) 2006, Digium, Inc.
+ * Copyright (C) 2006-2008, Digium, Inc.
  *
  * All rights reserved.
  *
@@ -23,90 +21,158 @@
  *
  */
 
-
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/kmod.h>
 #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>
-#include <asm/semaphore.h>
 #include <linux/jiffies.h>
-#include <linux/workqueue.h>
 #include <linux/moduleparam.h>
 #include <linux/firmware.h>
-
-#include <dahdi/kernel.h>
-
-
-/* #define USE_TEST_HW */
-#define USE_TDM_CONFIG
-#define QUIET_DSP
-
-#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 120
-
-#define DTE_FORMAT_ULAW   0x00
-#define DTE_FORMAT_G723_1 0x04
-#define DTE_FORMAT_ALAW   0x08
-#define DTE_FORMAT_G729A  0x12
-#define DTE_FORMAT_UNDEF  0xFF
-
-#define G729_LENGTH 20
-#define G723_LENGTH 30
-
-#define G729_SAMPLES 160	/* G.729 */
-#define G723_SAMPLES 240 	/* G.723.1 */
-
-#define G729_BYTES 20		/* G.729 */
-#define G723_6K_BYTES 24 	/* G.723.1 at 6.3kb/s */
-#define G723_5K_BYTES 20	/* G.723.1 at 5.3kb/s */
-#define G723_SID_BYTES 4	/* G.723.1 SID frame */
-
-#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 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 MDIO_SHIFT_CLK		0x10000
-#define MDIO_DATA_WRITE0 	0x00000
-#define MDIO_DATA_WRITE1 	0x20000
-#define MDIO_ENB		0x00000
-#define MDIO_ENB_IN		0x40000
-#define MDIO_DATA_READ		0x80000
-
-#define RCV_CSMENCAPS     1
-#define RCV_RTP           2
-#define RCV_CSMENCAPS_ACK 3
-#define RCV_OTHER         99
-
-
-/* TDM Commands */
+#include <linux/if_ether.h>
+#include <linux/ip.h>
+#include <linux/udp.h>
+#include <linux/etherdevice.h>
+#include <linux/timer.h>
+
+#include "dahdi/kernel.h"
+
+/* COMPILE TIME OPTIONS =================================================== */
+
+#define INTERRUPT 0
+#define WORKQUEUE 1
+#define TASKLET   2
+
+#ifndef DEFERRED_PROCESSING 
+#	define DEFERRED_PROCESSING WORKQUEUE
+#endif
+
+#if DEFERRED_PROCESSING == INTERRUPT
+#	define ALLOC_FLAGS GFP_ATOMIC
+#elif DEFERRED_PROCESSING == TASKLET
+#	define ALLOC_FLAGS GFP_ATOMIC
+#else
+#	define ALLOC_FLAGS GFP_KERNEL
+#endif
+
+#define WARN() WARN_ON(1)
+
+#define DTE_PRINTK(_lvl, _fmt, _args...) \
+	   printk(KERN_##_lvl "%s: %s: " _fmt, THIS_MODULE->name, \
+	          (wc)->board_name, ## _args)
+
+#define DTE_DEBUG(_dbgmask, _fmt, _args...)                                 \
+	if ((debug & _dbgmask) == (_dbgmask)) {                             \
+		printk(KERN_DEBUG "%s: %s: " _fmt, THIS_MODULE->name,       \
+		       (wc)->board_name, ## _args);                         \
+	}                                                                   \
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
+#define WARN_ON_ONCE(__condition) do {         \
+	static int __once = 1;                 \
+	if (unlikely(__condition)) {           \
+		if (__once) {                  \
+			__once = 0;            \
+			WARN_ON(0);            \
+		}                              \
+	}                                      \
+} while(0) 
+#endif
+
+#define INVALID 999 /* Used to mark invalid channels, commands, etc.. */
+#define MAX_CHANNEL_PACKETS  5 /* Never let more than 5 outstanding packets exist for any channel. */
+
+#define G729_LENGTH	20
+#define G723_LENGTH	30
+
+#define G729_SAMPLES	160	/* G.729 */
+#define G723_SAMPLES	240 	/* G.723.1 */
+
+#define G729_BYTES	20	/* G.729 */
+#define G723_6K_BYTES	24 	/* G.723.1 at 6.3kb/s */
+#define G723_5K_BYTES	20	/* G.723.1 at 5.3kb/s */
+#define G723_SID_BYTES	4	/* G.723.1 SID frame */
+
+#define MAX_CAPTURED_PACKETS 5000
+
+/* The following bit fields are used to set the various debug levels. */
+#define DTE_DEBUG_GENERAL          (1 << 0) /* 1  */
+#define DTE_DEBUG_CHANNEL_SETUP    (1 << 1) /* 2  */
+#define DTE_DEBUG_RTP_TX           (1 << 2) /* 4  */
+#define DTE_DEBUG_RTP_RX           (1 << 3) /* 8  */
+#define DTE_DEBUG_RX_TIMEOUT	   (1 << 4) /* 16 */
+#define DTE_DEBUG_NETWORK_IF       (1 << 5) /* 32 */
+#define DTE_DEBUG_NETWORK_EARLY    (1 << 6) /* 64 */
+
+int debug;
+char *mode;
+
+static spinlock_t wctc4xxp_list_lock;
+static struct list_head wctc4xxp_list;
+
+#define ETH_P_CSM_ENCAPS 0x889B
+
+struct rtphdr {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+	__u8    csrc_count:4;
+	__u8    extension:1;
+	__u8    padding:1;
+	__u8    ver:2;
+	__u8    type:7;
+	__u8 	marker:1;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+	__u8    ver:2;
+	__u8    padding:1;
+	__u8    extension:1;
+	__u8    csrc_count:4;
+	__u8 	marker:1;
+	__u8    type:7;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
+	__be16	seqno;
+	__be32  timestamp;
+	__be32  ssrc;
+} __attribute__((packed));
+
+struct rtp_packet {
+	struct ethhdr ethhdr;
+	struct iphdr  iphdr;
+	struct udphdr udphdr;
+	struct rtphdr rtphdr;
+	__u8   payload[0];
+}__attribute__((packed));
+
+/* Ethernet packet type for communication control information to the DTE. */
+struct csm_encaps_hdr {
+	struct ethhdr ethhdr;
+	/* CSM_ENCAPS HEADER */
+	__be16 op_code;
+	__u8   seq_num;
+	__u8   control;
+	__be16 channel;
+	/* COMMON PART OF PAYLOAD HEADER */
+	__u8   length;
+	__u8   index;
+	__u8   type;
+	__u8   class;
+	__le16 function;
+	__le16 reserved;
+	__le16 params[0];
+} __attribute__((packed));
+
+struct csm_create_channel_cmd {
+	struct csm_encaps_hdr hdr;
+	__le16 channel_type;
+	__le16 timeslot;
+} __attribute__((packed));
+
 #define CMD_MSG_TDM_SELECT_BUS_MODE_LEN 30
 #define CMD_MSG_TDM_SELECT_BUS_MODE(s) { \
 	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
@@ -182,17 +248,26 @@
 	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 CONTROL_PACKET_OPCODE  0x0001
+/* Control bits */
+#define LITTLE_ENDIAN   0x01
+#define SUPPRESS_ACK    0x40
+#define MESSAGE_PACKET  0x80
+
+#define SUPERVISOR_CHANNEL 0xffff
+
+/* Supervisor function codes */
+#define SUPVSR_CREATE_CHANNEL  0x0010
+
+#define CONFIG_CHANGE_TYPE        0x00 
+#define CONFIG_DEVICE_CLASS       0x06
+
 #define CMD_MSG_QUERY_CHANNEL_LEN 30
 #define CMD_MSG_QUERY_CHANNEL(s,t) { \
 	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
 	0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x01,0x06,0x10,0x00, 0x00,0x00, \
 	(t&0x00FF), ((t&0xFF00) >> 8) }
+
 #define CMD_MSG_TRANS_CONNECT_LEN 38
 #define CMD_MSG_TRANS_CONNECT(s,e,c1,c2,f1,f2) { \
 	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
@@ -243,303 +318,227 @@
 	0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x0A, 0x00, 0x00,0x02,0x5B,0x80, 0x00,0x00, \
 	0x00,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,s) { \
-	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,(s&0xFF)}
-
-#define CMD_MSG_DW_WRITE_LEN 38
-#define CMD_MSG_DW_WRITE(s,a,d) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01,s&0x0F,0x00,0x00,0x00,0x00,0x00,0x04,0x17,0x00,0x00, \
-	((a>>24)&0x00FF),((a>>16)&0x00FF), ((a>>8)&0x00FF),(a&0x00FF), \
-	((d>>24)&0x00FF),((d>>16)&0x00FF), ((d>>8)&0x00FF),(d&0x00FF) }
-
-#define CMD_MSG_FORCE_ALERT_LEN 32
-#define CMD_MSG_FORCE_ALERT(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,0x09,0x04, 0x00,0x00, \
-	0x24,0x00, 0x00,0x00 }
-
-#define dahdi_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(KERN_NOTICE "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->last_seqno = fifo[16]; \
-				wc->cmdq_wndx = (wc->cmdq_wndx + 1) % MAX_COMMANDS; \
-			} \
-			__transmit_demand(wc); \
-			up(&wc->cmdqsem); \
-			if (hex == 0x0000) \
-				ret = wcdte_waitfor_csmencaps(wc, RCV_CSMENCAPS_ACK, 2); \
-			else { \
-				ret = wcdte_waitfor_csmencaps(wc, RCV_CSMENCAPS, 0); \
-				if (wc->dsp_crashed) \
-					return 1; \
-			} \
-			if (ret == 1) \
-				return(1); \
-		} while (ret == 2); \
-	})
-
-
-struct cmdq {
-	unsigned int cmdlen;
-	unsigned char cmd[MAX_COMMAND_LEN];
+#define SFRAME_SIZE 320 
+
+/* Transcoder buffer (tcb) */
+struct tcb {
+	/* First field so that is aligned by default. */
+	u8 cmd[SFRAME_SIZE];
+	struct list_head node;
+	unsigned long timeout;
+	unsigned long retries;
+	/* NOTE:  these flags aren't bit fields because some of the flags are
+	 * combinations of the other ones. */
+#define DO_NOT_AUTO_FREE        (1 << 0)
+#define TX_COMPLETE             (1 << 1)
+#define DO_NOT_CAPTURE          (1 << 2)
+#define __WAIT_FOR_ACK          (1 << 3)
+#define __WAIT_FOR_RESPONSE     (1 << 4) 
+#define DTE_CMD_TIMEOUT         (1 << 5)
+#define WAIT_FOR_ACK (__WAIT_FOR_ACK | DO_NOT_AUTO_FREE)
+#define WAIT_FOR_RESPONSE (__WAIT_FOR_RESPONSE | DO_NOT_AUTO_FREE)
+	unsigned long flags;
+	struct tcb *response;
+	struct completion complete;
+	struct timer_list timer;
+	void *data;
+	/* The number of bytes available in data. */
+	int data_len; 
 };
 
+static inline void *hdr_from_cmd(struct tcb *cmd) {
+	return cmd->data;
+}
+
+static inline void 
+initialize_cmd(struct tcb *cmd, unsigned long cmd_flags) 
+{
+	memset(cmd, 0, sizeof(*cmd));
+	INIT_LIST_HEAD(&cmd->node);
+	init_completion(&cmd->complete);
+	cmd->flags = cmd_flags;
+	cmd->data = &cmd->cmd[0];
+	cmd->data_len = SFRAME_SIZE;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+/*! Used to allocate commands to submit to the dte. */
+kmem_cache_t *cmd_cache;
+#else
+/*! Used to allocate commands to submit to the dte. */
+struct kmem_cache *cmd_cache;
+#endif
+
+static inline struct tcb *
+__alloc_cmd(unsigned alloc_flags, unsigned long cmd_flags)
+{
+	struct tcb *cmd;
+
+	cmd = kmem_cache_alloc(cmd_cache, alloc_flags);
+	if (likely(cmd)) {
+		initialize_cmd(cmd, cmd_flags);
+	}
+	return cmd;
+}
+
+static struct tcb *
+alloc_cmd(void)
+{
+	return __alloc_cmd(GFP_KERNEL, 0);
+}
+
+static void 
+__free_cmd(struct tcb *cmd)
+{
+	if (cmd->data != &cmd->cmd[0]) {
+		kfree(cmd->data);
+	}
+	kmem_cache_free(cmd_cache, cmd);
+	return;
+}
+
+static void 
+free_cmd(struct tcb *cmd)
+{
+	if (cmd->response) {
+		__free_cmd(cmd->response);

[... 4605 lines stripped ...]



More information about the svn-commits mailing list