[dahdi-commits] fjoe: freebsd/trunk r9171 - in /freebsd/trunk: drivers/dahdi/wctc4xxp/ freebs...

SVN commits to the DAHDI project dahdi-commits at lists.digium.com
Fri Aug 20 04:39:13 CDT 2010


Author: fjoe
Date: Fri Aug 20 04:39:10 2010
New Revision: 9171

URL: http://svnview.digium.com/svn/dahdi?view=rev&rev=9171
Log:
Initial wctc4xxp driver port.

Added:
    freebsd/trunk/freebsd/wctc4xxp/
    freebsd/trunk/freebsd/wctc4xxp/Makefile   (with props)
Modified:
    freebsd/trunk/drivers/dahdi/wctc4xxp/base.c
    freebsd/trunk/freebsd/Makefile

Modified: freebsd/trunk/drivers/dahdi/wctc4xxp/base.c
URL: http://svnview.digium.com/svn/dahdi/freebsd/trunk/drivers/dahdi/wctc4xxp/base.c?view=diff&rev=9171&r1=9170&r2=9171
==============================================================================
--- freebsd/trunk/drivers/dahdi/wctc4xxp/base.c (original)
+++ freebsd/trunk/drivers/dahdi/wctc4xxp/base.c Fri Aug 20 04:39:10 2010
@@ -20,6 +20,20 @@
  * this program for more details.
  */
 
+#if defined(__FreeBSD__)
+#include <sys/types.h>
+#include <sys/bus.h>
+#include <sys/fcntl.h>
+#include <sys/firmware.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <machine/resource.h>
+#include <net/ethernet.h>
+#include <vm/uma.h>
+#else /* !__FreeBSD__ */
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/module.h>
@@ -38,14 +52,137 @@
 #include <linux/udp.h>
 #include <linux/etherdevice.h>
 #include <linux/timer.h>
+#endif /* !__FreeBSD__ */
 
 #include "dahdi/kernel.h"
 
+#if defined(__FreeBSD__)
+#define DMA_FROM_DEVICE	0
+#define DMA_TO_DEVICE	1
+
+#define ETH_P_IP ETHERTYPE_IP
+typedef __u16 __sum16;
+typedef unsigned gfp_t;
+
+struct ethhdr {
+	unsigned char	h_dest[ETH_ALEN];       /* destination eth addr */
+	unsigned char	h_source[ETH_ALEN];     /* source ether addr    */
+	__be16		h_proto;                /* packet type ID field */
+} __attribute__((packed));
+
+struct iphdr {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+	__u8	ihl:4,
+		version:4;
+#elif defined (__BIG_ENDIAN_BITFIELD)
+	__u8	version:4,
+		ihl:4;
+#else
+#error  "Please fix <asm/byteorder.h>"
+#endif
+	__u8	tos;
+	__be16	tot_len;
+	__be16	id;
+	__be16	frag_off;
+	__u8	ttl;
+	__u8	protocol;
+	__sum16	check;
+	__be32	saddr;
+	__be32	daddr;
+	/*The options start here. */
+};
+
+struct udphdr {
+	__be16	source;
+	__be16	dest;
+	__be16	len;
+	__sum16	check;
+};
+
+static inline unsigned short
+from32to16(unsigned int x)
+{
+	/* add up 16-bit and 16-bit for 16+c bit */
+	x = (x & 0xffff) + (x >> 16);
+	/* add up carry.. */
+	x = (x & 0xffff) + (x >> 16);
+	return x;
+}
+
+static unsigned int
+do_csum(const unsigned char *buff, int len)
+{
+	int odd, count;
+	unsigned int result = 0;
+
+	if (len <= 0)
+		goto out;
+	odd = 1 & (unsigned long) buff;
+	if (odd) {
+#ifdef __LITTLE_ENDIAN
+		result += (*buff << 8);
+#else
+		result = *buff;
+#endif
+		len--;
+		buff++;
+	}
+	count = len >> 1;		/* nr of 16-bit words.. */
+	if (count) {
+		if (2 & (unsigned long) buff) {
+			result += *(const unsigned short *) buff;
+			count--;
+			len -= 2;
+			buff += 2;
+		}
+		count >>= 1;		/* nr of 32-bit words.. */
+		if (count) {
+			unsigned int carry = 0;
+			do {
+				unsigned int w = *(const unsigned int *) buff;
+				count--;
+				buff += 4;
+				result += carry;
+				result += w;
+				carry = (w > result);
+			} while (count);
+			result += carry;
+			result = (result & 0xffff) + (result >> 16);
+		}
+		if (len & 2) {
+			result += *(const unsigned short *) buff;
+			buff += 2;
+		}
+	}
+	if (len & 1)
+#ifdef __LITTLE_ENDIAN
+		result += *buff;
+#else
+		result += (*buff << 8);
+#endif
+	result = from32to16(result);
+	if (odd)
+		result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
+out:
+	return result;
+}
+
+/*
+ *	This is a version of ip_compute_csum() optimized for IP headers,
+ *	which always checksum on 4 octet boundaries.
+ */
+static __sum16
+ip_fast_csum(const void *iph, unsigned int ihl)
+{
+	return (__sum16)~do_csum(iph, ihl*4);
+}
+#else /* !__FreeBSD__ */
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
 #include <asm/io.h>
 #else
 #include <linux/io.h>
 #endif
+#endif /* !__FreeBSD__ */
 
 /* COMPILE TIME OPTIONS =================================================== */
 
@@ -128,10 +265,20 @@
 #define DTE_DEBUG_NETWORK_EARLY	(1 << 6) /* 64 */
 
 static int debug;
+#if defined(__FreeBSD__)
+static char mode[8];
+#else
 static char *mode;
-
-static spinlock_t wctc4xxp_list_lock;
-static struct list_head wctc4xxp_list;
+#endif
+
+#if !defined(__FreeBSD__)
+#ifdef DEFINE_SPINLOCK
+DEFINE_SPINLOCK(wctc4xxp_list_lock);
+#else
+static spinlock_t wctc4xxp_list_lock = SPIN_LOCK_UNLOCKED;
+#endif
+static _LIST_HEAD(wctc4xxp_list);
+#endif
 
 #define ETH_P_CSM_ENCAPS 0x889B
 
@@ -186,9 +333,9 @@
 
 #define CONTROL_PACKET_OPCODE  0x0001
 /* Control bits */
-#define LITTLE_ENDIAN	0x01
-#define SUPPRESS_ACK	0x40
-#define MESSAGE_PACKET	0x80
+#define CONTROL_LITTLE_ENDIAN	0x01
+#define CONTROL_SUPPRESS_ACK	0x40
+#define CONTROL_MESSAGE_PACKET	0x80
 
 #define SUPERVISOR_CHANNEL 0xffff
 
@@ -241,14 +388,34 @@
 }
 
 static inline void
-initialize_cmd(struct tcb *cmd, unsigned long cmd_flags)
+initialize_cmd(struct tcb *cmd)
 {
 	INIT_LIST_HEAD(&cmd->node);
 	init_completion(&cmd->complete);
-	cmd->flags = cmd_flags;
 	spin_lock_init(&cmd->lock);
 }
 
+#if defined(__FreeBSD__)
+static uma_zone_t cmd_cache;
+
+static int
+cmd_cache_ctor(void *mem, int size, void *arg, int flags)
+{
+	struct tcb *cmd = (struct tcb *) mem;
+
+	initialize_cmd(cmd);
+	return (0);
+}
+
+static void
+cmd_cache_dtor(void *mem, int size, void *arg)
+{
+	struct tcb *cmd = (struct tcb *) mem;
+
+	destroy_completion(&cmd->complete);
+	spin_lock_destroy(&cmd->lock);
+}
+#else /* !__FreeBSD__ */
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
 /*! Used to allocate commands to submit to the dte. */
 kmem_cache_t *cmd_cache;
@@ -256,6 +423,7 @@
 /*! Used to allocate commands to submit to the dte. */
 static struct kmem_cache *cmd_cache;
 #endif
+#endif /* !__FreeBSD__ */
 
 static inline struct tcb *
 __alloc_cmd(size_t size, gfp_t alloc_flags, unsigned long cmd_flags)
@@ -266,16 +434,29 @@
 		return NULL;
 	if (size < MIN_PACKET_LEN)
 		size = MIN_PACKET_LEN;
+#if defined(__FreeBSD__)
+	cmd = uma_zalloc(cmd_cache, M_WAITOK | M_ZERO);
+#else
 	cmd = kmem_cache_alloc(cmd_cache, alloc_flags);
+#endif
 	if (likely(cmd)) {
+#if !defined(__FreeBSD__)
 		memset(cmd, 0, sizeof(*cmd));
+#endif
 		cmd->data = kzalloc(size, alloc_flags);
 		if (unlikely(!cmd->data)) {
+#if defined(__FreeBSD__)
+			uma_zfree(cmd_cache, cmd);
+#else
 			kmem_cache_free(cmd_cache, cmd);
+#endif
 			return NULL;
 		}
 		cmd->data_len = size;
-		initialize_cmd(cmd, cmd_flags);
+		cmd->flags = cmd_flags;
+#if !defined(__FreeBSD__)
+		initialize_cmd(cmd);
+#endif
 	}
 	return cmd;
 }
@@ -291,7 +472,11 @@
 {
 	if (cmd)
 		kfree(cmd->data);
+#if defined(__FreeBSD__)
+	uma_zfree(cmd_cache, cmd);
+#else
 	kmem_cache_free(cmd_cache, cmd);
+#endif
 	return;
 }
 
@@ -321,7 +506,7 @@
 	u32 timestamp;
 	struct {
 		u8 encoder:1;	/* If we're an encoder */
-	};
+	} e;
 	struct channel_stats stats;
 	struct list_head rx_queue; /* Transcoded packets for this channel. */
 };
@@ -329,8 +514,12 @@
 struct wcdte {
 	char board_name[40];
 	const char *variety;
+#if defined(__FreeBSD__)
+	struct pci_dev _dev;
+#else
 	int pos;
 	struct list_head node;
+#endif
 	spinlock_t reglock;
 	wait_queue_head_t waitq;
 	struct semaphore chansem;
@@ -358,7 +547,16 @@
 	 * physical interface to the transcoding engine.  */
 	struct pci_dev *pdev;
 	unsigned int   intmask;
+#if defined(__FreeBSD__)
+	struct resource *io_res;
+	int io_rid;
+
+	struct resource *irq_res;		/* resource for irq */
+	int irq_rid;
+	void *irq_handle;
+#else
 	unsigned long  iobase;
+#endif
 	struct wctc4xxp_descriptor_ring *txd;
 	struct wctc4xxp_descriptor_ring *rxd;
 
@@ -371,6 +569,7 @@
 	struct work_struct deferred_work;
 #endif
 
+#ifndef WITHOUT_NETDEV
 	/*
 	 * This section contains the members necessary for exporting the
 	 * network interface to the host system.  This is only used for
@@ -383,14 +582,16 @@
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
 	struct napi_struct napi;
 #endif
+#endif /* !WITHOUT_NETDEV */
 	struct timer_list watchdog;
 	atomic_t open_channels;
 	struct timer_list polling;
-#if HZ > 100
+#if defined(__FreeBSD__) || HZ > 100
 	unsigned long jiffies_at_last_poll;
 #endif
 };
 
+#ifndef WITHOUT_NETDEV
 #ifdef HAVE_NETDEV_PRIV
 struct wcdte_netdev_priv {
 	struct wcdte *wc;
@@ -408,7 +609,7 @@
 	return netdev->priv;
 #endif
 }
-
+#endif /* !WITHOUT_NETDEV */
 
 static inline void wctc4xxp_set_ready(struct wcdte *wc)
 {
@@ -451,6 +652,7 @@
 	return pt;
 }
 
+#ifndef WITHOUT_NETDEV
 static struct sk_buff *
 tcb_to_skb(struct net_device *netdev, const struct tcb *cmd)
 {
@@ -802,7 +1004,7 @@
 #	endif
 	return;
 }
-
+#endif /* !WITHOUT_NETDEV */
 
 /*! In-memory structure shared by the host and the adapter. */
 struct wctc4xxp_descriptor {
@@ -811,6 +1013,8 @@
 	__le32 buffer1;
 	__le32 container; /* Unused */
 } __attribute__((packed));
+
+#define _countof(a)	(sizeof(a)/sizeof((a)[0]))
 
 struct wctc4xxp_descriptor_ring {
 	/* Pointer to an array of descriptors to give to hardware. */
@@ -821,8 +1025,17 @@
 	unsigned int 	tail;
 	/* Array to save the kernel virtual address of pending commands. */
 	struct tcb *pending[DRING_SIZE];
+#if defined(__FreeBSD__)
+	bus_dma_tag_t   dma_tag;
+	bus_dmamap_t    dma_map;
+	uint32_t        desc_dma;
+
+	bus_dma_tag_t	tcb_dma_tag;
+	bus_dmamap_t	tcb_dma_map[DRING_SIZE];
+#else /* !__FreeBSD__ */
 	/* PCI Bus address of the descriptor list. */
 	dma_addr_t	desc_dma;
+#endif /* !__FreeBSD__ */
 	/*! either DMA_FROM_DEVICE or DMA_TO_DEVICE */
 	unsigned int 	direction;
 	/*! The number of buffers currently submitted to the hardware. */
@@ -854,7 +1067,7 @@
 wctc4xxp_initialize_descriptor_ring(struct pci_dev *pdev,
 	struct wctc4xxp_descriptor_ring *dr, u32 des1, unsigned int direction)
 {
-	int i;
+	int i, res;
 	const u32 END_OF_RING = 0x02000000;
 	u8 cache_line_size = 0;
 	struct wctc4xxp_descriptor *d;
@@ -863,8 +1076,13 @@
 	BUG_ON(!pdev);
 	BUG_ON(!dr);
 
+#if defined(__FreeBSD__)
+	if ((cache_line_size = pci_read_config(pdev->dev, 0x0c, 1)) == 0)
+		return -EIO;
+#else
 	if (pci_read_config_byte(pdev, 0x0c, &cache_line_size))
 		return -EIO;
+#endif
 
 	memset(dr, 0, sizeof(*dr));
 
@@ -880,19 +1098,51 @@
 	if (add_padding)
 		dr->padding = (cache_line_size*sizeof(u32)) - sizeof(*d);
 
+#if defined(__FreeBSD__)
+	res = dahdi_dma_allocate(pdev->dev, (sizeof(*d) + dr->padding) * DRING_SIZE,
+	    &dr->dma_tag, &dr->dma_map, (void **) &dr->desc, &dr->desc_dma);
+	if (res)
+		return -res;
+
+        res = bus_dma_tag_create(bus_get_dma_tag(pdev->dev), 8, 0,
+	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+	    SFRAME_SIZE, 1, SFRAME_SIZE, 0, NULL, NULL, &dr->tcb_dma_tag);
+	if (res) {
+		dahdi_dma_free(&dr->dma_tag, &dr->dma_map, (void **) &dr->desc, &dr->desc_dma);
+		return -res;
+	}
+
+	for (i = 0; i < _countof(dr->tcb_dma_map); i++) {
+		res = bus_dmamap_create(dr->tcb_dma_tag, 0, dr->tcb_dma_map + i);
+		if (res) {
+			int j;
+
+			for (j = 0; j < i; j++) {
+				bus_dmamap_destroy(dr->tcb_dma_tag, dr->tcb_dma_map[j]);
+			}
+			bus_dma_tag_destroy(dr->tcb_dma_tag);
+
+			dahdi_dma_free(&dr->dma_tag, &dr->dma_map, (void **) &dr->desc, &dr->desc_dma);
+			return -res;
+		}
+	}
+#else
 	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);
+#endif
+
 	for (i = 0; i < DRING_SIZE; ++i) {
 		d = wctc4xxp_descriptor(dr, i);
 		d->des1 = cpu_to_le32(des1);
 	}
 
 	d->des1 |= cpu_to_le32(END_OF_RING);
+#if defined(__FreeBSD__)
+	bus_dmamap_sync(dr->dma_tag, dr->dma_map, BUS_DMASYNC_PREWRITE);
+#endif
 	dr->direction = direction;
 	spin_lock_init(&dr->lock);
 	dr->pdev = pdev;
@@ -908,6 +1158,7 @@
 static int
 wctc4xxp_submit(struct wctc4xxp_descriptor_ring *dr, struct tcb *c)
 {
+	int res;
 	volatile struct wctc4xxp_descriptor *d;
 	unsigned int len;
 	unsigned long flags;
@@ -929,8 +1180,17 @@
 	}
 	d->des1 &= cpu_to_le32(~(BUFFER1_SIZE_MASK));
 	d->des1 |= cpu_to_le32(len & BUFFER1_SIZE_MASK);
+#if defined(__FreeBSD__)
+	res = bus_dmamap_load(dr->tcb_dma_tag, dr->tcb_dma_map[dr->tail], c->data, c->data_len,
+	    dahdi_dma_map_addr, __DEVOLATILE(void *, &d->buffer1), 0);
+	if (res)
+		return -res;
+	bus_dmamap_sync(dr->dma_tag, dr->dma_map, BUS_DMASYNC_PREWRITE);
+	bus_dmamap_sync(dr->tcb_dma_tag, dr->tcb_dma_map[dr->tail], BUS_DMASYNC_PREWRITE);
+#else
 	d->buffer1 = pci_map_single(dr->pdev, c->data,
 			SFRAME_SIZE, dr->direction);
+#endif
 
 	SET_OWNED(d); /* That's it until the hardware is done with it. */
 	dr->pending[dr->tail] = c;
@@ -949,13 +1209,24 @@
 	unsigned long flags;
 	spin_lock_irqsave(&dr->lock, flags);
 	d = wctc4xxp_descriptor(dr, head);
+#if defined(__FreeBSD__)
+	bus_dmamap_sync(dr->dma_tag, dr->dma_map, BUS_DMASYNC_POSTREAD);
+#endif
 	if (d->buffer1 && !OWNED(d)) {
+#if defined(__FreeBSD__)
+		bus_dmamap_sync(dr->tcb_dma_tag, dr->tcb_dma_map[head], BUS_DMASYNC_POSTREAD);
+		bus_dmamap_unload(dr->tcb_dma_tag, dr->tcb_dma_map[head]);
+#else
 		pci_unmap_single(dr->pdev, d->buffer1,
 			SFRAME_SIZE, dr->direction);
+#endif
 		c = dr->pending[head];
 		WARN_ON(!c);
 		dr->head = (++head) & DRING_MASK;
 		d->buffer1 = 0;
+#if defined(__FreeBSD__)
+		bus_dmamap_sync(dr->dma_tag, dr->dma_map, BUS_DMASYNC_PREWRITE);
+#endif
 		--dr->count;
 		WARN_ON(!c);
 		c->data_len = (d->des0 >> 16) & BUFFER1_SIZE_MASK;
@@ -980,13 +1251,23 @@
 static inline void
 __wctc4xxp_setctl(struct wcdte *wc, unsigned int addr, unsigned int val)
 {
+#if defined(__FreeBSD__)
+	bus_space_write_4(rman_get_bustag(wc->io_res),
+	    rman_get_bushandle(wc->io_res), addr, val);
+#else
 	outl(val, wc->iobase + addr);
+#endif
 }
 
 static inline unsigned int
 __wctc4xxp_getctl(struct wcdte *wc, unsigned int addr)
 {
+#if defined(__FreeBSD__)
+	return bus_space_read_4(rman_get_bustag(wc->io_res),
+	    rman_get_bushandle(wc->io_res), addr);
+#else
 	return inl(wc->iobase + addr);
+#endif
 }
 
 static inline void
@@ -1049,7 +1330,7 @@
 	setup_common_header(wc, hdr);
 
 	hdr->op_code = cpu_to_be16(CONTROL_PACKET_OPCODE);
-	hdr->control = LITTLE_ENDIAN;
+	hdr->control = CONTROL_LITTLE_ENDIAN;
 	hdr->seq_num = (wc->seq_num++)&0xf;
 	hdr->channel = cpu_to_be16(SUPERVISOR_CHANNEL);
 }
@@ -1184,14 +1465,14 @@
 	const u8 *host_mac, const u8 *assigned_mac)
 {
 	u16 parameters[8];
-	u16 *part;
+	const u16 *part;
 
 	parameters[0] = 0x0001;
-	part = (u16 *)host_mac;
+	part = (const u16 *)host_mac;
 	parameters[1] = part[0];
 	parameters[2] = part[1];
 	parameters[3] = part[2];
-	part = (u16 *)assigned_mac;
+	part = (const u16 *)assigned_mac;
 	parameters[4] = part[0];
 	parameters[5] = part[1];
 	parameters[6] = part[2];
@@ -1530,11 +1811,18 @@
 	if (!dr || !dr->desc)
 		return;
 
+#if defined(__FreeBSD__)
+	bus_dmamap_sync(dr->dma_tag, dr->dma_map, BUS_DMASYNC_POSTREAD);
+#endif
 	for (i = 0; i < DRING_SIZE; ++i) {
 		d = wctc4xxp_descriptor(dr, i);
 		if (d->buffer1) {
+#if defined(__FreeBSD__)
+			bus_dmamap_unload(dr->tcb_dma_tag, dr->tcb_dma_map[i]);
+#else
 			pci_unmap_single(dr->pdev, d->buffer1,
 				SFRAME_SIZE, dr->direction);
+#endif
 			d->buffer1 = 0;
 			/* Commands will also be sitting on the waiting for
 			 * response list, so we want to make sure to delete
@@ -1543,19 +1831,30 @@
 			free_cmd(dr->pending[i]);
 			dr->pending[i] = NULL;
 		}
+#if defined(__FreeBSD__)
+		bus_dmamap_destroy(dr->tcb_dma_tag, dr->tcb_dma_map[i]);
+#endif
 	}
 	dr->head = 0;
 	dr->tail = 0;
 	dr->count = 0;
+#if defined(__FreeBSD__)
+	bus_dmamap_sync(dr->dma_tag, dr->dma_map, BUS_DMASYNC_PREWRITE);
+	bus_dma_tag_destroy(dr->tcb_dma_tag);
+
+	dahdi_dma_free(&dr->dma_tag, &dr->dma_map, (void **) &dr->desc, &dr->desc_dma);
+#else
 	pci_free_consistent(dr->pdev, (sizeof(*d)+dr->padding) * DRING_SIZE,
 		dr->desc, dr->desc_dma);
+#endif
+	spin_lock_destroy(&dr->lock);
 }
 
 static void wctc4xxp_cleanup_command_list(struct wcdte *wc)
 {
 	struct tcb *cmd;
 	unsigned long flags;
-	LIST_HEAD(local_list);
+	_LIST_HEAD(local_list);
 
 	spin_lock_irqsave(&wc->cmd_list_lock, flags);
 	list_splice_init(&wc->cmd_list, &local_list);
@@ -1621,14 +1920,16 @@
 			 * retry if we do not get the response within the
 			 * timeout period. */
 			struct csm_encaps_hdr *hdr = cmd->data;
-			hdr->control |= SUPPRESS_ACK;
+			hdr->control |= CONTROL_SUPPRESS_ACK;
 		}
 		WARN_ON(!list_empty(&cmd->node));
 		wctc4xxp_add_to_response_list(wc, cmd);
 		mod_timer(&wc->watchdog, jiffies + HZ/2);
 	}
+#ifndef WITHOUT_NETDEV
 	if (!(cmd->flags & DO_NOT_CAPTURE))
 		wctc4xxp_net_capture_cmd(wc, cmd);
+#endif
 	res = wctc4xxp_submit(wc->txd, cmd);
 	if (-EBUSY == res) {
 		/* Looks like we're out of room in the descriptor
@@ -1670,7 +1971,7 @@
 	unsigned int channel, struct wcdte *wc)
 {
 	memset(cpvt, 0, sizeof(*cpvt));
-	cpvt->encoder = encoder;
+	cpvt->e.encoder = encoder;
 	cpvt->wc = wc;
 	cpvt->chan_in_num = INVALID;
 	cpvt->chan_out_num = INVALID;
@@ -1703,7 +2004,7 @@
 	struct tcb *cmd, *temp;
 	struct channel_pvt *cpvt = dtc->pvt;
 	unsigned long flags;
-	LIST_HEAD(local_list);
+	_LIST_HEAD(local_list);
 
 	spin_lock_irqsave(&cpvt->lock, flags);
 	list_splice_init(&cpvt->rx_queue, &local_list);
@@ -1729,7 +2030,7 @@
 	BUG_ON(!cpvt);
 	index = cpvt->timeslot_in_num/2;
 	BUG_ON(index >= wc->numchannels);
-	if (cpvt->encoder)
+	if (cpvt->e.encoder)
 		compl_dtc = &(wc->udecode->channels[index]);
 	else
 		compl_dtc = &(wc->uencode->channels[index]);
@@ -1904,7 +2205,7 @@
 		
 	if ((packets_sent - packets_received) > 5) {
 		DTE_DEBUG(DTE_DEBUG_GENERAL, "%s channel %d sent %d packets " 
-			"and received %d packets.\n", (cpvt->encoder) ? 
+			"and received %d packets.\n", (cpvt->e.encoder) ? 
 			"encoder" : "decoder", cpvt->chan_out_num,
 			packets_sent, packets_received);
 	}
@@ -1913,7 +2214,7 @@
 	wctc4xxp_cleanup_channel_private(wc, dtc);
 	index = cpvt->timeslot_in_num/2;
 	BUG_ON(index >= wc->numchannels);
-	if (cpvt->encoder)
+	if (cpvt->e.encoder)
 		compl_dtc = &(wc->udecode->channels[index]);
 	else
 		compl_dtc = &(wc->uencode->channels[index]);
@@ -1981,6 +2282,9 @@
 	/* If we can't grab this lock, another thread must already be checking
 	 * the receive ring...so we should just finish up, and we'll try again
 	 * later. */
+#if defined(__FreeBSD__)
+	spin_lock_irqsave(&wc->rx_lock, flags);
+#else /* !__FreeBSD__ */
 #if defined(spin_trylock_irqsave)
 	if (!spin_trylock_irqsave(&wc->rx_lock, flags))
 		return 0;
@@ -1989,6 +2293,7 @@
 		return 0;
 	spin_lock_irqsave(&wc->rx_lock, flags);
 #endif
+#endif /* !__FreeBSD__ */
 
 	while ((cmd = wctc4xxp_retrieve(wc->rxd))) {
 		++count;
@@ -2029,10 +2334,10 @@
 
 /* Called with a buffer in which to copy a transcoded frame. */
 static ssize_t
-wctc4xxp_read(struct file *file, char __user *frame, size_t count, loff_t *ppos)
+wctc4xxp_read(FOP_READ_ARGS_DECL)
 {
 	ssize_t ret;
-	struct dahdi_transcoder_channel *dtc = file->private_data;
+	struct dahdi_transcoder_channel *dtc = dahdi_get_private_data(file);
 	struct channel_pvt *cpvt = dtc->pvt;
 	struct wcdte *wc = cpvt->wc;
 	struct tcb *cmd;
@@ -2055,13 +2360,14 @@
 		} else {
 			ret = wait_event_interruptible(dtc->ready,
 				dahdi_tc_is_data_waiting(dtc));
+#if !defined(__FreeBSD__)
 			if (-ERESTARTSYS == ret) {
 				/* Signal interrupted the wait */
 				return -EINTR;
-			} else {
-				/* List went not empty. */
-				cmd = get_ready_cmd(dtc);
 			}
+#endif
+			/* List went not empty. */
+			cmd = get_ready_cmd(dtc);
 		}
 	}
 
@@ -2083,7 +2389,11 @@
 
 	atomic_inc(&cpvt->stats.packets_received);
 
+#if defined(__FreeBSD__)
+	if (unlikely(uiomove(packet->payload, payload_bytes, uio))) {
+#else
 	if (unlikely(copy_to_user(frame, &packet->payload[0], payload_bytes))) {
+#endif
 		DTE_PRINTK(ERR, "Failed to copy data in %s\n", __func__);
 		free_cmd(cmd);
 		return -EFAULT;
@@ -2096,10 +2406,9 @@
 
 /* Called with a frame in the srcfmt to be transcoded into the dstfmt. */
 static ssize_t
-wctc4xxp_write(struct file *file, const char __user *frame,
-	size_t count, loff_t *ppos)
-{
-	struct dahdi_transcoder_channel *dtc = file->private_data;
+wctc4xxp_write(FOP_WRITE_ARGS_DECL)
+{
+	struct dahdi_transcoder_channel *dtc = dahdi_get_private_data(file);
 	struct channel_pvt *cpvt = dtc->pvt;
 	struct wcdte *wc = cpvt->wc;
 	struct tcb *cmd;
@@ -2149,8 +2458,12 @@
 	if (!cmd)
 		return -ENOMEM;
 	/* Copy the data directly from user space into the command buffer. */
+#if defined(__FreeBSD__)
+	if (uiomove(((struct rtp_packet *) cmd->data)->payload, count, uio)) {
+#else
 	if (copy_from_user(&((struct rtp_packet *)(cmd->data))->payload[0],
 		frame, count)) {
+#endif
 		DTE_PRINTK(ERR, "Failed to copy packet from userspace.\n");
 		free_cmd(cmd);
 		return -EFAULT;
@@ -2164,7 +2477,7 @@
 	wctc4xxp_transmit_cmd(wc, cmd);
 
 	if (test_bit(DTE_POLLING, &wc->flags)) {
-#if HZ == 100
+#if !defined(__FreeBSD__) && HZ == 100
 		__wctc4xxp_polling(wc);
 #else
 		if (jiffies != wc->jiffies_at_last_poll) {
@@ -2337,8 +2650,8 @@
 {
 	const struct csm_encaps_hdr *hdr = cmd->data;
 
-	if (!(hdr->control & MESSAGE_PACKET)) {
-		if (!(hdr->control & SUPPRESS_ACK))
+	if (!(hdr->control & CONTROL_MESSAGE_PACKET)) {
+		if (!(hdr->control & CONTROL_SUPPRESS_ACK))
 			wctc4xxp_send_ack(wc, hdr->seq_num, hdr->channel);
 
 		if (is_response(hdr)) {
@@ -2493,7 +2806,7 @@
 {
 	struct tcb *cmd;
 	unsigned long flags;
-	LIST_HEAD(local_list);
+	_LIST_HEAD(local_list);
 	spin_lock_irqsave(&wc->rx_list_lock, flags);
 	list_splice_init(&wc->rx_list, &local_list);
 	spin_unlock_irqrestore(&wc->rx_list_lock, flags);
@@ -2505,7 +2818,9 @@
 		cmd = container_of(local_list.next, struct tcb, node);
 		list_del_init(&cmd->node);
 
+#ifndef WITHOUT_NETDEV
 		wctc4xxp_net_capture_cmd(wc, cmd);
+#endif
 		wctc4xxp_receiveprep(wc, cmd);
 	}
 	wctc4xxp_receive_demand_poll(wc);
@@ -2517,7 +2832,7 @@
 	service_rx_ring(wc);
 }
 
-
+#if DEFERRED_PROCESSING == WORKQUEUE
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
 static void deferred_work_func(void *param)
 {
@@ -2529,6 +2844,7 @@
 #endif
 	service_dte(wc);
 }
+#endif
 
 DAHDI_IRQ_HANDLER(wctc4xxp_interrupt)
 {
@@ -2607,11 +2923,21 @@
 	const u32 DEFAULT_PCI_ACCESS = 0xfff80000;
 
 	/* Enable I/O Access */
+#if defined(__FreeBSD__)
+	pci_enable_busmaster(wc->pdev->dev);
+	pci_enable_io(wc->pdev->dev, SYS_RES_IOPORT);
+	pci_enable_io(wc->pdev->dev, SYS_RES_MEMORY);
+#else
 	pci_read_config_dword(wc->pdev, 0x0004, &reg);
 	reg |= 0x00000007;
 	pci_write_config_dword(wc->pdev, 0x0004, reg);
-
+#endif
+
+#if defined(__FreeBSD__)
+	if ((cache_line_size = pci_read_config(wc->pdev->dev, 0x0c, 1)) == 0)
+#else
 	if (pci_read_config_byte(wc->pdev, 0x0c, &cache_line_size))
+#endif
 		return -EIO;
 
 	switch (cache_line_size) {
@@ -2819,6 +3145,12 @@
 	unsigned int last_byteloc;
 	unsigned int length;
 	struct tcb *cmd;
+	const char *firmware_data = (const char *) firmware->data;
+#if defined(__FreeBSD__)
+	size_t firmware_size = firmware->datasize;
+#else
+	size_t firmware_size = firmware->size;
+#endif
 
 	byteloc = 17;
 
@@ -2826,14 +3158,14 @@
 	if (!cmd)
 		return -ENOMEM;
 
-	while (byteloc < (firmware->size-20)) {
+	while (byteloc < (firmware_size-20)) {
 		last_byteloc = byteloc;
-		length = (firmware->data[byteloc] << 8) |
-				firmware->data[byteloc+1];
+		length = (firmware_data[byteloc] << 8) |
+				firmware_data[byteloc+1];
 		byteloc += 2;
 		cmd->data_len = length;
 		BUG_ON(length > cmd->data_len);
-		memcpy(cmd->data, &firmware->data[byteloc], length);
+		memcpy(cmd->data, &firmware_data[byteloc], length);
 		byteloc += length;
 		cmd->flags = WAIT_FOR_ACK;
 		wctc4xxp_transmit_cmd(wc, cmd);
@@ -2940,7 +3272,7 @@
 		return -ENOMEM;
 
 	BUG_ON(!wc || !cpvt);
-	if (cpvt->encoder) {
+	if (cpvt->e.encoder) {
 		encoder_timeslot = cpvt->timeslot_in_num;
 		decoder_timeslot = cpvt->timeslot_out_num;
 	} else {
@@ -3021,7 +3353,7 @@
 	if (!cmd)
 		return -ENOMEM;
 
-	if (cpvt->encoder) {
+	if (cpvt->e.encoder) {
 		chan1 = cpvt->chan_in_num;
 		timeslot1 = cpvt->timeslot_in_num;
 		chan2 = cpvt->chan_out_num;
@@ -3157,6 +3489,24 @@
 	for (chan = 0; chan < wc->numchannels; ++chan)
 		wctc4xxp_init_state((*cpvt) + chan, encoder, chan, wc);
 	return 0;
+}
+
+static void
+destroy_channel_pvt(struct wcdte *wc, struct channel_pvt **cpvt)
+{
+	int chan;
+
+	if (*cpvt == NULL)
+		return;
+
+	for (chan = 0; chan < wc->numchannels; ++chan) {
+		struct channel_pvt *cp = *cpvt + chan;
+
+		spin_lock_destroy(&cp->lock);
+	}
+
+	kfree(*cpvt);
+	*cpvt = NULL;
 }
 
 static int
@@ -3227,7 +3577,7 @@
 {
 	struct wcdte *wc = (struct wcdte *)data;
 	struct tcb *cmd, *temp;
-	LIST_HEAD(cmds_to_retry);
+	_LIST_HEAD(cmds_to_retry);
 	const int MAX_RETRIES = 5;
 	int reschedule_timer = 0;
 
@@ -3284,6 +3634,7 @@
 		wctc4xxp_send_commands(wc, &cmds_to_retry);
 }
 
+#if !defined(__FreeBSD__)
 /**
  * Insert an struct wcdte on the global list in sorted order
  *
@@ -3310,6 +3661,7 @@
 	spin_unlock(&wctc4xxp_list_lock);
 	return pos;
 }
+#endif /* !__FreeBSD__ */
 
 struct wctc4xxp_desc {
 	const char *short_name;
@@ -3326,10 +3678,18 @@
 	.long_name = "Wildcard TCE400+TC400M",
 };
 
+#if defined(__FreeBSD__)
+static int
+wctc4xxp_init_one(device_t dev, const struct pci_device_id *ent)
+#else
 static int __devinit
 wctc4xxp_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	int res, reg, position_on_list;
+#endif
+{
+	int res, reg;
+#if !defined(__FreeBSD__)
+	int position_on_list;
+#endif
 	struct wcdte *wc = NULL;
 	struct wctc4xxp_desc *d = (struct wctc4xxp_desc *)ent->driver_data;
 	unsigned char g729_numchannels, g723_numchannels, min_numchannels;
@@ -3337,6 +3697,7 @@
 	unsigned int complexfmts;
 	struct firmware embedded_firmware;
 	const struct firmware *firmware = &embedded_firmware;
+	const char *firmware_data;
 #if !defined(HOTPLUG_FIRMWARE)
 	extern void _binary_dahdi_fw_tc400m_bin_size;
 	extern u8 _binary_dahdi_fw_tc400m_bin_start[];
@@ -3347,7 +3708,19 @@
 	/* ------------------------------------------------------------------
 	 * Setup the pure software constructs internal to this driver.
 	 * --------------------------------------------------------------- */
-
+#if defined(__FreeBSD__)
+	wc = device_get_softc(dev);
+	wc->pdev = &wc->_dev;
+	wc->pdev->dev = dev;
+
+        /* allocate memory resource */
+	wc->io_rid = PCIR_BAR(0);
+	wc->io_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &wc->io_rid, RF_ACTIVE);
+	if (wc->io_res == NULL) {
+		device_printf(wc->pdev->dev, "Can't allocate memory resource\n");
+		return (-ENXIO);
+	}
+#else
 	wc = kzalloc(sizeof(*wc), GFP_KERNEL);
 	if (!wc)
 		return -ENOMEM;
@@ -3358,6 +3731,7 @@
 	wc->iobase           = pci_resource_start(pdev, 0);
 	wc->pdev             = pdev;
 	wc->pos              = position_on_list;
+#endif
 	wc->variety          = d->long_name;
 	wc->last_rx_seq_num  = -1;
 
@@ -3374,6 +3748,9 @@
 #else
 	INIT_WORK(&wc->deferred_work, deferred_work_func);
 #endif
+	init_waitqueue_head(&wc->waitq);
+
+#if !defined(__FreeBSD__)
 	DTE_PRINTK(INFO, "Attached to device at %s.\n", pci_name(wc->pdev));
 
 	/* Keep track of whether we need to free the region */
@@ -3384,13 +3761,12 @@
 		return -EIO;
 	}
 
-	init_waitqueue_head(&wc->waitq);
-
 	if (pci_set_dma_mask(wc->pdev, DMA_BIT_MASK(32))) {
 		release_region(wc->iobase, 0xff);
 		DTE_PRINTK(WARNING, "No suitable DMA available.\n");
 		return -EIO;
 	}
+#endif
 
 	wc->txd = kmalloc(sizeof(*wc->txd), GFP_KERNEL);
 	if (!wc->txd) {
@@ -3427,14 +3803,15 @@
 	embedded_firmware.size = (size_t) &_binary_dahdi_fw_tc400m_bin_size;
 #endif
 
-	wctc4xxp_firmware_ver = firmware->data[0];
-	wctc4xxp_firmware_ver_minor = firmware->data[16];
-	g729_numchannels = firmware->data[1];
-	g723_numchannels = firmware->data[2];
+	firmware_data = (const char *) firmware->data;
+	wctc4xxp_firmware_ver = firmware_data[0];
+	wctc4xxp_firmware_ver_minor = firmware_data[16];
+	g729_numchannels = firmware_data[1];
+	g723_numchannels = firmware_data[2];
 
 	min_numchannels = min(g723_numchannels, g729_numchannels);
 
-	if (!mode || strlen(mode) < 4) {
+	if (strlen(mode) < 4) {
 		sprintf(wc->complexname, "G.729a / G.723.1");
 		complexfmts = DAHDI_FORMAT_G729A | DAHDI_FORMAT_G723_1;
 		wc->numchannels = min_numchannels;
@@ -3459,11 +3836,13 @@
 	if (res)
 		goto error_exit_swinit;
 
+#ifndef WITHOUT_NETDEV
 	if (DTE_DEBUG_NETWORK_IF & debug) {
 		res = wctc4xxp_net_register(wc);
 		if (res)
 			goto error_exit_swinit;
 	}
+#endif /* !WITHOUT_NETDEV */
 
 #	if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
 	wc->watchdog.function = wctc4xxp_watchdog;
@@ -3484,7 +3863,22 @@
 	/* ------------------------------------------------------------------
 	 * Load the firmware and start the DTE.
 	 * --------------------------------------------------------------- */
-
+#if defined(__FreeBSD__)
+	wc->irq_res = bus_alloc_resource_any(
+	    wc->pdev->dev, SYS_RES_IRQ, &wc->irq_rid, RF_SHAREABLE | RF_ACTIVE);
+	if (wc->irq_res == NULL) {
+		device_printf(wc->pdev->dev, "Can't allocate irq resource\n");
+		res = -ENXIO;
+	}
+
+	res = bus_setup_intr(
+		wc->pdev->dev, wc->irq_res, INTR_TYPE_CLK | INTR_MPSAFE,
+		wctc4xxp_interrupt, NULL, wc, &wc->irq_handle);
+	if (res) {
+		device_printf(wc->pdev->dev, "Can't setup interrupt handler (error %d)\n", res);
+		return (-ENXIO);
+	}
+#else
 	res = pci_enable_device(pdev);
 	if (res) {
 		DTE_PRINTK(ERR, "Failed to enable device.\n");
@@ -3500,6 +3894,7 @@
 			release_firmware(firmware);
 		goto error_exit_hwinit;
 	}
+#endif
 	res = wctc4xxp_hardware_init(wc);
 	if (res) {
 		if (firmware != &embedded_firmware)
@@ -3538,23 +3933,46 @@
 error_exit_hwinit:
 	wctc4xxp_stop_dma(wc);
 	wctc4xxp_cleanup_command_list(wc);
+#if defined(__FreeBSD__)
+	/* disconnect the interrupt handler */
+	if (wc->irq_handle != NULL) {
+		bus_teardown_intr(wc->pdev->dev, wc->irq_res, wc->irq_handle);
+		wc->irq_handle = NULL;
+	}
+
+	if (wc->irq_res != NULL) {
+		bus_release_resource(wc->pdev->dev, SYS_RES_IRQ, wc->irq_rid, wc->irq_res);
+		wc->irq_res = NULL;
+	}
+#else
 	free_irq(pdev->irq, wc);
 	pci_set_drvdata(pdev, NULL);
+#endif
 error_exit_swinit:
+#ifndef WITHOUT_NETDEV
 	wctc4xxp_net_unregister(wc);
-	kfree(wc->encoders);
-	kfree(wc->decoders);
+#endif
+	destroy_channel_pvt(wc, &wc->encoders);
+	destroy_channel_pvt(wc, &wc->decoders);
 	dahdi_transcoder_free(wc->uencode);
 	dahdi_transcoder_free(wc->udecode);
 	wctc4xxp_cleanup_descriptor_ring(wc->txd);
 	kfree(wc->txd);
 	wctc4xxp_cleanup_descriptor_ring(wc->rxd);
 	kfree(wc->rxd);
+#if defined(__FreeBSD__)
+	/* release I/O region */
+	if (wc->io_res != NULL) {
+		bus_release_resource(wc->pdev->dev, SYS_RES_IOPORT, wc->io_rid, wc->io_res);
+		wc->io_res = NULL;
+	}
+#else
 	release_region(wc->iobase, 0xff);
 	spin_lock(&wctc4xxp_list_lock);
 	list_del(&wc->node);
 	spin_unlock(&wctc4xxp_list_lock);
 	kfree(wc);
+#endif
 	return res;
 }
 
@@ -3572,27 +3990,43 @@
 	}
 }
 
+#if defined(__FreeBSD__)
+static void __devexit wctc4xxp_remove_one(device_t dev)
+#else
 static void __devexit wctc4xxp_remove_one(struct pci_dev *pdev)
-{
+#endif
+{
+#if defined(__FreeBSD__)
+	struct wcdte *wc = device_get_softc(dev);
+#else
 	struct wcdte *wc = pci_get_drvdata(pdev);
+#endif
 
 	if (!wc)
 		return;
 
+#if !defined(__FreeBSD__)
 	spin_lock(&wctc4xxp_list_lock);
 	list_del(&wc->node);
 	spin_unlock(&wctc4xxp_list_lock);
+#endif
 
 	set_bit(DTE_SHUTDOWN, &wc->flags);
+#if !defined(__FreeBSD__)
 	if (del_timer_sync(&wc->watchdog))
+#endif
 		del_timer_sync(&wc->watchdog);
 
 	/* This should already be stopped, but it doesn't hurt to make sure. */
 	clear_bit(DTE_POLLING, &wc->flags);
+#if !defined(__FreeBSD__)
 	if (del_timer_sync(&wc->polling))
+#endif
 		del_timer_sync(&wc->polling);
 
+#ifndef WITHOUT_NETDEV
 	wctc4xxp_net_unregister(wc);
+#endif
 
 	/* Stop any DMA */
 	wctc4xxp_stop_dma(wc);
@@ -3600,7 +4034,20 @@
 	/* In case hardware is still there */
 	wctc4xxp_disable_interrupts(wc);
 
+#if defined(__FreeBSD__)
+        /* disconnect the interrupt handler */
+	if (wc->irq_handle != NULL) {
+		bus_teardown_intr(wc->pdev->dev, wc->irq_res, wc->irq_handle);
+		wc->irq_handle = NULL;
+	}
+
+	if (wc->irq_res != NULL) {
+		bus_release_resource(wc->pdev->dev, SYS_RES_IRQ, wc->irq_rid, wc->irq_res);
+		wc->irq_res = NULL;
+	}
+#else
 	free_irq(pdev->irq, wc);
+#endif
 
 	/* There isn't anything that would run in the workqueue that will wait
 	 * on an interrupt. */
@@ -3609,7 +4056,15 @@
 	dahdi_transcoder_unregister(wc->uencode);
 
 	/* Free Resources */
+#if defined(__FreeBSD__)
+	/* release I/O region */
+	if (wc->io_res != NULL) {
+		bus_release_resource(wc->pdev->dev, SYS_RES_IOPORT, wc->io_rid, wc->io_res);
+		wc->io_res = NULL;
+	}
+#else
 	release_region(wc->iobase, 0xff);
+#endif
 	wctc4xxp_cleanup_descriptor_ring(wc->txd);
 	kfree(wc->txd);
 	wctc4xxp_cleanup_descriptor_ring(wc->rxd);
@@ -3618,13 +4073,21 @@
 	wctc4xxp_cleanup_command_list(wc);
 	wctc4xxp_cleanup_channels(wc);
 
+#if !defined(__FreeBSD__)
 	pci_set_drvdata(pdev, NULL);
+#endif
 
 	dahdi_transcoder_free(wc->uencode);
 	dahdi_transcoder_free(wc->udecode);
-	kfree(wc->encoders);
-	kfree(wc->decoders);
+	destroy_channel_pvt(wc, &wc->encoders);
+	destroy_channel_pvt(wc, &wc->decoders);
+	spin_lock_destroy(&wc->reglock);
+	spin_lock_destroy(&wc->cmd_list_lock);
+	spin_lock_destroy(&wc->rx_list_lock);
+	spin_lock_destroy(&wc->rx_lock);
+#if !defined(__FreeBSD__)
 	kfree(wc);
+#endif
 }
 
 static struct pci_device_id wctc4xxp_pci_tbl[] = {
@@ -3635,6 +4098,64 @@
 	{ 0 }
 };
 
+#if defined(__FreeBSD__)
+SYSCTL_NODE(_dahdi, OID_AUTO, wctc4xxp, CTLFLAG_RW, 0, "DAHDI wctc4xxp");
+#define MODULE_PARAM_PREFIX "dahdi.wctc4xxp"
+#define MODULE_PARAM_PARENT _dahdi_wctc4xxp
+
+static int
+wctc4xxp_device_probe(device_t dev)
+{
+	struct pci_device_id *id;
+	struct wctc4xxp_desc *d;
+
+	id = dahdi_pci_device_id_lookup(dev, wctc4xxp_pci_tbl);
+	if (id == NULL)
+		return (ENXIO);
+
+	/* found device */
+	device_printf(dev, "vendor=%x device=%x subvendor=%x\n",
+	    id->vendor, id->device, id->subvendor);
+	d = (struct wctc4xxp_desc *) id->driver_data;
+	device_set_desc(dev, d->long_name);
+	return (0);
+}
+
+static int
+wctc4xxp_device_attach(device_t dev)
+{
+	int res;
+	struct pci_device_id *id;
+
+	id = dahdi_pci_device_id_lookup(dev, wctc4xxp_pci_tbl);
+	if (id == NULL)
+		return (ENXIO);
+
+	res = wctc4xxp_init_one(dev, id);
+	return (-res);
+}
+
+static int
+wctc4xxp_device_detach(device_t dev)
+{
+	wctc4xxp_remove_one(dev);
+	return (0);
+}
+
+static device_method_t wctc4xxp_methods[] = {
+	DEVMETHOD(device_probe,     wctc4xxp_device_probe),
+	DEVMETHOD(device_attach,    wctc4xxp_device_attach),
+	DEVMETHOD(device_detach,    wctc4xxp_device_detach),
+	{ 0, 0 }
+};
+
+static driver_t wctc4xxp_pci_driver = {
+	"wctc4xxp",
+	wctc4xxp_methods,
+	sizeof(struct wcdte)
+};
+
+#else /* !__FreeBSD__ */
 MODULE_DEVICE_TABLE(pci, wctc4xxp_pci_tbl);
 
 static struct pci_driver wctc4xxp_driver = {
@@ -3643,9 +4164,20 @@
 	.remove = __devexit_p(wctc4xxp_remove_one),
 	.id_table = wctc4xxp_pci_tbl,
 };
+#endif /* !__FreeBSD__ */
 
 static int __init wctc4xxp_init(void)
 {
+#if defined(__FreeBSD__)
+	cmd_cache = uma_zcreate("wctc4xxp", sizeof(struct tcb),
+	    cmd_cache_ctor, cmd_cache_dtor, NULL, NULL, 0, 0);
+	if (cmd_cache == NULL) {
+		printf("%s: can not allocate UMA zone\n", THIS_MODULE->name);
+		return (-ENXIO);
+	}
+
+	return (0);
+#else /* !__FreeBSD__ */
 	int res;
 	unsigned long cache_flags;
 
@@ -3665,24 +4197,52 @@
 
 	if (!cmd_cache)
 		return -ENOMEM;
-	spin_lock_init(&wctc4xxp_list_lock);
-	INIT_LIST_HEAD(&wctc4xxp_list);
 	res = dahdi_pci_module(&wctc4xxp_driver);
 	if (res) {
 		kmem_cache_destroy(cmd_cache);
 		return -ENODEV;
 	}
 	return 0;
+#endif
 }
 
 static void __exit wctc4xxp_cleanup(void)
 {
+#if defined(__FreeBSD__)
+	uma_zdestroy(cmd_cache);
+#else /* !__FreeBSD__ */
 	pci_unregister_driver(&wctc4xxp_driver);
 	kmem_cache_destroy(cmd_cache);
+#endif /* !__FreeBSD__ */
 }
 
 module_param(debug, int, S_IRUGO | S_IWUSR);
 module_param(mode, charp, S_IRUGO | S_IWUSR);
+
+#if defined(__FreeBSD__)
+static devclass_t wctc4xxp_devclass;
+
+static int
+wctc4xxp_modevent(module_t mod __unused, int type, void *data __unused)
+{
+	int res;
+
+	switch (type) {
+	case MOD_LOAD:
+		res = wctc4xxp_init();
+		return (-res);
+	case MOD_UNLOAD:
+		wctc4xxp_cleanup();
+		return (0);
+	default:
+		return (EOPNOTSUPP);
+	}
+}
+
+DAHDI_DRIVER_MODULE(wctc4xxp, pci, wctc4xxp_pci_driver, wctc4xxp_devclass, wctc4xxp_modevent, 0);
+MODULE_DEPEND(wctc4xxp, dahdi, 1, 1, 1);
+MODULE_DEPEND(wctc4xxp, dahdi_transcode, 1, 1, 1);
+#else /* !__FreeBSD__ */
 MODULE_PARM_DESC(mode, "'g729', 'g723.1', or 'any'.  Default 'any'.");
 MODULE_DESCRIPTION("Wildcard TC400P+TC400M Driver");
 MODULE_AUTHOR("Digium Incorporated <support at digium.com>");
@@ -3690,3 +4250,4 @@
 
 module_init(wctc4xxp_init);
 module_exit(wctc4xxp_cleanup);
+#endif /* !__FreeBSD__ */

Modified: freebsd/trunk/freebsd/Makefile
URL: http://svnview.digium.com/svn/dahdi/freebsd/trunk/freebsd/Makefile?view=diff&rev=9171&r1=9170&r2=9171
==============================================================================
--- freebsd/trunk/freebsd/Makefile (original)
+++ freebsd/trunk/freebsd/Makefile Fri Aug 20 04:39:10 2010
@@ -39,8 +39,8 @@
 	wcb4xxp
 
 # Transcoding cards
-#SUBDIR+=\
-#	wctc4xxp
+SUBDIR+=\
+	wctc4xxp
 
 # firmware drivers
 SUBDIR+=\

Added: freebsd/trunk/freebsd/wctc4xxp/Makefile
URL: http://svnview.digium.com/svn/dahdi/freebsd/trunk/freebsd/wctc4xxp/Makefile?view=auto&rev=9171
==============================================================================
--- freebsd/trunk/freebsd/wctc4xxp/Makefile (added)
+++ freebsd/trunk/freebsd/wctc4xxp/Makefile Fri Aug 20 04:39:10 2010
@@ -1,0 +1,10 @@
+# $Id$
+
+.PATH: ${.CURDIR}/../../drivers/dahdi/wctc4xxp
+
+KMOD=	wctc4xxp
+SRCS=	base.c
+SRCS+=	device_if.h bus_if.h pci_if.h
+CFLAGS=	-DHOTPLUG_FIRMWARE -DWITHOUT_NETDEV
+
+.include <bsd.kmod.mk>

Propchange: freebsd/trunk/freebsd/wctc4xxp/Makefile
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: freebsd/trunk/freebsd/wctc4xxp/Makefile
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: freebsd/trunk/freebsd/wctc4xxp/Makefile
------------------------------------------------------------------------------
    svn:mime-type = text/plain




More information about the dahdi-commits mailing list