[dahdi-commits] sruffell: branch linux/sruffell/dahdi-transcoder r4607 - in /linux/team/sruff...

SVN commits to the DAHDI project dahdi-commits at lists.digium.com
Mon Jul 14 09:45:56 CDT 2008


Author: sruffell
Date: Mon Jul 14 09:45:55 2008
New Revision: 4607

URL: http://svn.digium.com/view/dahdi?view=rev&rev=4607
Log:
Work in progress on moving the zaptel-1.4-transcoder branch to under the DAHDI
tree.  Also includes changes for non-blocking open.

(Issue DAHDI-42)

Added:
    linux/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/wcdte_commands.h   (with props)
    linux/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/wcdte_net.c   (with props)
    linux/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/wctc4xxp.h   (with props)
Modified:
    linux/team/sruffell/dahdi-transcoder/drivers/dahdi/dahdi_transcode.c
    linux/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/Kbuild
    linux/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/base.c
    linux/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/codec_test.c
    linux/team/sruffell/dahdi-transcoder/include/dahdi/kernel.h

Modified: linux/team/sruffell/dahdi-transcoder/drivers/dahdi/dahdi_transcode.c
URL: http://svn.digium.com/view/dahdi/linux/team/sruffell/dahdi-transcoder/drivers/dahdi/dahdi_transcode.c?view=diff&rev=4607&r1=4606&r2=4607
==============================================================================
--- linux/team/sruffell/dahdi-transcoder/drivers/dahdi/dahdi_transcode.c (original)
+++ linux/team/sruffell/dahdi-transcoder/drivers/dahdi/dahdi_transcode.c Mon Jul 14 09:45:55 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,14 +36,21 @@
 #include <linux/vmalloc.h>
 #include <linux/mm.h>
 #include <linux/page-flags.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>
+#endif
+#ifdef LINUX26
 #include <linux/moduleparam.h>
-#include <asm/io.h>
-
-#include <dahdi/kernel.h>
-#include <dahdi/user.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);
@@ -65,89 +73,72 @@
 	ztc->numchannels = numchans;
 	for (x=0;x<ztc->numchannels;x++) {
 		init_waitqueue_head(&ztc->channels[x].ready);
+		INIT_LIST_HEAD(&ztc->node);
 		ztc->channels[x].parent = ztc;
-		ztc->channels[x].offset = x;
-		ztc->channels[x].chan_built = 0;
-		ztc->channels[x].built_fmts = 0;
-	}
-
+	}
+
+	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(&ztc->fops, dahdi_transcode_fops, sizeof(*dahdi_transcode_fops));
 	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);
+}
+
+/* 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("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("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;
 }
@@ -155,285 +146,283 @@
 /* Alert a transcoder */
 int dahdi_transcoder_alert(struct dahdi_transcoder_channel *ztc)
 {
-	if (debug)
-		printk("DAHDI Transcoder Alert!\n");
-	if (ztc->tch)
-		ztc->tch->status &= ~DAHDI_TC_FLAG_BUSY;
 	wake_up_interruptible(&ztc->ready);
-
 	return 0;
 }
 
 static int dahdi_tc_open(struct inode *inode, struct file *file)
 {
+	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 zaptel
+	 * 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 ztc_release(struct dahdi_transcoder_channel *ztc)
+{
+	BUG_ON(!ztc);
+	if (ztc->parent && ztc->parent->operation) {
+		ztc->parent->operation(ztc, DAHDI_TCOP_RELEASE);
+	}
+	dahdi_tc_clear_busy(ztc);
+}
+
+static int dahdi_tc_release(struct inode *inode, struct file *file)
+{
+	struct dahdi_transcoder_channel *ztc = file->private_data;
+	/* There will not be a transcoder channel associated with this file if
+	 * the ALLOCATE ioctl never succeeded. 
+	 */
+	if (ztc) {
+		ztc_release(ztc);
+	}
+
+	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 *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("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("Released Transcoder!\n");
-}
-
-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;
+	int i;
+	/* Should be called with the translock held. */
+	WARN_ON(!spin_is_locked(&translock));
+
+	for (i = 0; i < tc->numchannels; i++) {
+		ztc = &tc->channels[i];
+		if (!dahdi_tc_is_busy(ztc)) {
+			dahdi_tc_set_busy(ztc);
+			return ztc;
+		}
+	}
+	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 *ztc = 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 ((ztc = 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 ztc;
 			}
 		}
-		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 *ztc = NULL;
+	struct dahdi_transcoder_formats fmts;
+	
+	if (copy_from_user(&fmts, 
+		(struct dahdi_transcoder_formats*) data, sizeof(fmts))) {
+		return -EFAULT;
+	}
+
+	spin_lock(&translock);
+	ztc = __find_free_channel(&trans, &fmts);
+	spin_unlock(&translock);
+
+	if (IS_ERR(ztc)) {
+		return PTR_ERR(ztc);
+	}
+
+	/* Every transcoder channel must be associated with a parent
+	 * transcoder. */
+	BUG_ON(!ztc->parent);
+
+	ztc->srcfmt = fmts.srcfmt;
+	ztc->dstfmt = fmts.dstfmt;
+
+	if (file->private_data) {
+		/* This open file is moving to a new channel. Cleanup and
+		 * close the old channel here.  */
+		ztc_release(file->private_data);
+	}
+
+	file->private_data = ztc;
+	if (ztc->parent->fops.owner != file->f_op->owner) {
+		if (!try_module_get(ztc->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 = &ztc->parent->fops;
+	}
+
+	(file->f_flags & O_NONBLOCK) ? dahdi_tc_set_nonblock(ztc) : dahdi_tc_clear_nonblock(ztc);
 
 	/* Actually reset the transcoder channel */
-	if ((*ztc)->parent && ((*ztc)->parent->operation))
-		return (*ztc)->parent->operation((*ztc), DAHDI_TCOP_ALLOCATE);
+	if (ztc->parent->operation)
+		return ztc->parent->operation(ztc, DAHDI_TCOP_ALLOCATE);
 
 	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
+		 * zaptel-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.
+		 */
+		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("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;
-	}
-
+	if (!ztc) {
+		/* This is because the DAHDI_TC_ALLOCATE ioctl was not called
+		 * before calling poll, which is invalid. */
+		return -EINVAL;
+	}
+
+	poll_wait(file, &ztc->ready, wait_table);
+
+	ret =  dahdi_tc_is_busy(ztc)         ? 0       : POLLPRI;
+	ret |= dahdi_tc_is_built(ztc)        ? POLLOUT : 0;
+	ret |= dahdi_tc_is_data_waiting(ztc) ? 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("zttranscode: Attempted to mmap with offset!\n");
-		return -EINVAL;
-	}
-
-	if ((vma->vm_end - vma->vm_start) != sizeof(struct dahdi_transcode_header)) {
-		if (debug)
-			printk("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("zttranscode: remap failed!\n");
-		return -EAGAIN;
-	}
-
-	if (debug)
-		printk("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 = {
@@ -446,7 +435,7 @@
 	int res;
 
 	if (dahdi_transcode_fops) {
-		printk("Whoa, dahdi_transcode_fops already set?!\n");
+		printk(KERN_WARNING "Whoa, dahdi_transcode_fops already set?!\n");
 		return -EBUSY;
 	}
 
@@ -455,7 +444,7 @@
 	if ((res = dahdi_register_chardev(&transcode_chardev)))
 		return res;
 
-	printk("DAHDI Transcoder support loaded\n");
+	printk(KERN_INFO "%s: Loaded.\n", THIS_MODULE->name);
 
 	return 0;
 }
@@ -466,14 +455,15 @@
 
 	dahdi_transcode_fops = NULL;
 
-	printk("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/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/Kbuild
URL: http://svn.digium.com/view/dahdi/linux/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/Kbuild?view=diff&rev=4607&r1=4606&r2=4607
==============================================================================
--- linux/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/Kbuild (original)
+++ linux/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/Kbuild Mon Jul 14 09:45:55 2008
@@ -8,7 +8,9 @@
   EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE
 endif
 
-wctc4xxp-objs := base.o 
+wctc4xxp-objs := base.o
+wctc4xxp-objs += wcdte_net.o
+wctc4xxp-objs += wcdte_commands.o
 
 ifneq ($(HOTPLUG_FIRMWARE),yes)
 wctc4xxp-objs += $(FIRM_DIR)/dahdi-fw-tc400m.o

Modified: linux/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/base.c
URL: http://svn.digium.com/view/dahdi/linux/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/base.c?view=diff&rev=4607&r1=4606&r2=4607
==============================================================================
--- linux/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/base.c (original)
+++ linux/team/sruffell/dahdi-transcoder/drivers/dahdi/wctc4xxp/base.c Mon Jul 14 09:45:55 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,48 +21,53 @@
  *
  */
 
-
 #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>
-#include <dahdi/user.h>
-
-
-/* #define USE_TEST_HW */
+#include <linux/if_ether.h>
+#include <linux/timer.h>
+#ifdef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+#endif
+
+#include "dahdi/kernel.h"
+#include "wctc4xxp.h"
+#include "wcdte_commands.h"
+#include "wcdte_net.h"
+
+/* \todo Need to check these functions with more linux versions... */
+#undef CONFIG_DEBUG_FS
+
+#define INVALID 999 /* Used to mark invalid channels, commands, etc.. */
+#define MAX_CHANNEL_PACKETS  5 /* Never let more than 5 outstanding packets exist for any channel. */
+
 #define USE_TDM_CONFIG
 #define QUIET_DSP
 
 #define WC_MAX_IFACES 128
 
-#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
+#if 0
+#define HERE() printk(KERN_DEBUG "HERE: %s:%d\n", __FILE__, __LINE__);
+#define ENTERING() printk(KERN_DEBUG "Entering %s \n", __FUNCTION__);
+#define LEAVING() printk(KERN_DEBUG "Leaving %s (%d)\n", __FUNCTION__, __LINE__);
+#else
+#define HERE() printk(KERN_DEBUG "HERE: %s:%d\n", __FILE__, __LINE__);
+// #define HERE() do {;} while (0)
+#define ENTERING() do {;} while (0)
+#define LEAVING() do {;} while (0)
+#endif
+
 
 #define G729_LENGTH 20
 #define G723_LENGTH 30
@@ -72,30 +75,12 @@
 #define G729_SAMPLES 160	/* G.729 */
 #define G723_SAMPLES 240 	/* G.723.1 */
 
-#define G729_BYTES 20		/* G.729 */
+#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
@@ -107,1144 +92,1173 @@
 #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_QUERY_CHANNEL_LEN 30
-#define CMD_MSG_QUERY_CHANNEL(s,t) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x01,0x06,0x10,0x00, 0x00,0x00, \
-	(t&0x00FF), ((t&0xFF00) >> 8) }
-#define CMD_MSG_TRANS_CONNECT_LEN 38
-#define CMD_MSG_TRANS_CONNECT(s,e,c1,c2,f1,f2) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x12, 0x00, 0x00,0x06,0x22,0x93, 0x00,0x00, \
-	e,0x00, (c1&0x00FF),((c1&0xFF00)>>8), f1,0x00, (c2&0x00FF),((c2&0xFF00)>>8), f2,0x00 }
-#define CMD_MSG_DESTROY_CHANNEL_LEN 32
-#define CMD_MSG_DESTROY_CHANNEL(s,t) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x11,0x00, 0x00,0x00, \
-	(t&0x00FF),((t&0xFF00)>>8), 0x00, 0x00 }
-
-/* Individual channel config commands */
-#define CMD_MSG_SET_IP_HDR_CHANNEL_LEN 58
-#define CMD_MSG_SET_IP_HDR_CHANNEL(s,c,t2,t1) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, ((c&0xFF00) >> 8),(c&0x00FF), 0x26, 0x00, 0x00,0x02,0x00,0x90, 0x00,0x00, \
-	0x00,0x00, 0x45,0x00, 0x00,0x00, 0x00,0x00, 0x40,0x00, 0x80,0x11, 0x00,0x00, \
-	0xC0,0xA8,0x09,0x03, 0xC0,0xA8,0x09,0x03, \
-	((t2&0xFF00)>>8)+0x50,(t2&0x00FF), ((t1&0xFF00)>>8)+0x50,(t1&0x00FF), 0x00,0x00, 0x00,0x00 }
-#define CMD_MSG_VOIP_VCEOPT_LEN 40
-#define CMD_MSG_VOIP_VCEOPT(s,c,l,w) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x12, 0x00, 0x00,0x02,0x01,0x80, 0x00,0x00, \
-	0x21,l, 0x00,0x1C, 0x04,0x00, 0x00,0x00, w,0x00, 0x80,0x11 }
-#define CMD_MSG_VOIP_VOPENA_LEN 44
-#define CMD_MSG_VOIP_VOPENA(s,c,f) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x16, 0x00, 0x00,0x02,0x00,0x80, 0x00,0x00, \
-	0x01,0x00, 0x80,f, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x12,0x34, 0x56,0x78, 0x00,0x00 }
-#define CMD_MSG_VOIP_VOPENA_CLOSE_LEN 32
-#define CMD_MSG_VOIP_VOPENA_CLOSE(s,c) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x0A, 0x00, 0x00,0x02,0x00,0x80, 0x00,0x00, \
-	0x00,0x00, 0x00,0x00 }
-#define CMD_MSG_VOIP_INDCTRL_LEN 32
-#define CMD_MSG_VOIP_INDCTRL(s,c) {0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x0A, 0x00, 0x00,0x02,0x84,0x80, 0x00,0x00, \
-	0x07,0x00, 0x00,0x00 }
-#define CMD_MSG_VOIP_DTMFOPT_LEN 32
-#define CMD_MSG_VOIP_DTMFOPT(s,c) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x0A, 0x00, 0x00,0x02,0x02,0x80, 0x00,0x00, \
-	0x08,0x00, 0x00,0x00 }
-
-#define CMD_MSG_VOIP_TONECTL_LEN 32
-#define CMD_MSG_VOIP_TONECTL(s,c) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x0A, 0x00, 0x00,0x02,0x5B,0x80, 0x00,0x00, \
-	0x00,0x00, 0x00,0x00 }
-
-/* 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("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];
+int debug;
+static int debug_des;     /* Set the number of descriptor packet bytes to output on errors, 0 disables output */
+static int debug_des_cnt; /* Set the number of times descriptor packets are displayed before the output is disabled */
+static char *mode;
+static int debug_packets;
+
+
+/*! In-memory structure shared by the host and the adapter. */
+struct dte_descriptor {
+	__le32 des0;
+	__le32 des1;
+	__le32 buffer1;
+	__le32 container; /* Unused */
+} __attribute__((packed));
+
+#define DRING_SIZE (1 << 3) /* Must be a power of two */
+#define DRING_MASK (DRING_SIZE-1)
+#define MIN_PACKET_LEN  64
+
+struct dte_descriptor_ring {
+	/* Pointer to an array of descriptors to give to hardware. */
+	struct dte_descriptor* desc;
+	/* Read completed buffers from the head. */
+	unsigned int 	head;
+	/* Write ready buffers to the tail. */
+	unsigned int 	tail;
+	/* Array to save the kernel virtual address of pending commands. */
+	struct dte_cmd *pending[DRING_SIZE];
+	/* PCI Bus address of the descriptor list. */
+	dma_addr_t	desc_dma;
+	/*! either DMA_FROM_DEVICE or DMA_TO_DEVICE */
+	unsigned int 	direction;
+	/*! The number of buffers currently submitted to the hardware. */
+	unsigned int    count;
+	/*! The number of bytes to pad each descriptor for cache alignment. */
+	unsigned int	padding;
+	/*! Protects this structure from concurrent access. */
+	spinlock_t      lock;
+	/*! PCI device for the card associated with this ring. */
+	struct pci_dev  *pdev;
 };
 
-struct wcdte {
-	struct pci_dev *dev;
-	char *variety;
-	unsigned int intcount;
-	unsigned int rxints;
-	unsigned int txints;
-	unsigned int intmask;
-	int pos;
-	int freeregion;
-	int rdbl;
-	int tdbl;
-	int cards;
-	spinlock_t reglock;
-	wait_queue_head_t regq;
-	int rcvflags;
+/* Returns the desriptor at index.
+ * 
+ * We need this function because we do not know what the padding on the
+ * descriptors will be.
+ */
+static inline struct dte_descriptor *
+dte_descriptor(struct dte_descriptor_ring *dr, int index)
+{
+	struct dte_descriptor *d;
+	d = (struct dte_descriptor *)((u8*)dr->desc + 
+		((sizeof(*d) + dr->padding) * index));
+	return d;
+}
+
+static int
+dte_initialize_descriptor_ring(struct pci_dev *pdev, struct dte_descriptor_ring *dr, 
+	u32 des1, unsigned int direction)
+{
+	int i; 
+	const u32 END_OF_RING = 0x02000000;
+	u8 cache_line_size = 0;
+	struct dte_descriptor *d;
+
+	BUG_ON(!pdev);
+	BUG_ON(!dr);
+
+	if (pci_read_config_byte(pdev, 0x0c, &cache_line_size)) {
+		/* \todo Print an error message... */
+		return -EIO;
+	}
+
+	memset(dr, 0, sizeof(*dr));
+
+	/*
+	 * Add some padding to each descriptor to ensure that they are
+	 * aligned on host system cache-line boundaries, but only for the 
+	 * cache-line sizes that we support.
+	 *
+	 */
+	if ((0x08 == cache_line_size) || (0x10 == cache_line_size) ||
+	    (0x20 == cache_line_size)) 
+	{
+		dr->padding = (cache_line_size*sizeof(u32)) - sizeof(*d);
+	} 
+
+	dr->desc = pci_alloc_consistent(pdev, 
+			(sizeof(*d)+dr->padding)*DRING_SIZE, &dr->desc_dma);
+
+	if (!dr->desc) {
+		return -ENOMEM;
+	}
+
+	memset(dr->desc, 0, (sizeof(*d) + dr->padding) * DRING_SIZE);
+	for (i = 0; i < DRING_SIZE; ++i) {
+		d = dte_descriptor(dr, i);
+		d->des1 = cpu_to_le32(des1);
+	}
+
+	d->des1 |= cpu_to_le32(END_OF_RING);
+	dr->direction = direction;
+	spin_lock_init(&dr->lock);
+	return 0;
+}
+
+#define OWN_BIT cpu_to_le32(0x80000000)
+#define OWNED(_d_) (((_d_)->des0)&OWN_BIT)
+#define SET_OWNED(_d_) do { wmb(); (_d_)->des0 |= OWN_BIT; wmb();} while (0)
+
+const unsigned int BUFFER1_SIZE_MASK = 0x7ff;
+
+/*! Submit a command to the descriptor list for processing by the DTE. */
+static int 
+dte_submit(struct dte_descriptor_ring* dr, struct dte_cmd *c)
+{
+	volatile struct dte_descriptor *d;
+	unsigned int tail = dr->tail;
+	unsigned int len;
+
+	WARN_ON(!c);
+	len = (c->cmdlen < MIN_PACKET_LEN) ? MIN_PACKET_LEN : c->cmdlen;
+	if (c->cmdlen > 1518) {
+		printk(KERN_ERR "Invalid frame size: %d.\n", c->cmdlen);
+		return -EBUSY;
+	}
+
+	spin_lock_bh(&dr->lock);
+
+	d = dte_descriptor(dr, tail); 
+	WARN_ON(!d);
+	if (d->buffer1) {
+		spin_unlock_bh(&dr->lock);
+		/* Do not overwrite a buffer that is still in progress. */
+		return -EBUSY;
+	}
+	d->des1 &= cpu_to_le32(~(BUFFER1_SIZE_MASK));
+	d->des1 |= cpu_to_le32(len & BUFFER1_SIZE_MASK);
+	d->buffer1 = pci_map_single(dr->pdev, c->data, 

[... 4984 lines stripped ...]



More information about the dahdi-commits mailing list