Index: build_tools/make_version
===================================================================
--- build_tools/make_version	(revision 7107)
+++ build_tools/make_version	(working copy)
@@ -4,7 +4,7 @@
 	cat ${1}.version
 elif [ -f ${1}/.svnrevision ]; then
 	echo SVN-`cat ${1}/.svnbranch`-r`cat ${1}/.svnrevision`
-elif [ -d .svn ]; then
+elif [ -d ${1}/.svn ]; then
     PARTS=`LANG=C svn info ${1} | grep URL | awk '{print $2;}' | sed -e s:^.*/svn/${2}/:: | sed -e 's:/: :g'`
     BRANCH=0
     TEAM=0
Index: include/dahdi/wctdm_user.h
===================================================================
--- include/dahdi/wctdm_user.h	(revision 7107)
+++ include/dahdi/wctdm_user.h	(working copy)
@@ -25,7 +25,11 @@
 #ifndef _WCTDM_H
 #define _WCTDM_H
 
+#if defined(__FreeBSD__)
+#include <sys/ioccom.h>
+#else
 #include <linux/ioctl.h>
+#endif
 
 #define NUM_REGS	  109
 #define NUM_INDIRECT_REGS 105
@@ -64,5 +68,4 @@
 #define WCTDM_SET_REG	_IOW (DAHDI_CODE, 62, struct wctdm_regop)
 #define WCTDM_SET_ECHOTUNE _IOW (DAHDI_CODE, 63, struct wctdm_echo_coefs)
 
-
 #endif /* _WCTDM_H */
Index: include/dahdi/compat/list.h
===================================================================
--- include/dahdi/compat/list.h	(revision 0)
+++ include/dahdi/compat/list.h	(revision 0)
@@ -0,0 +1,711 @@
+#ifndef _LINUX_LIST_H
+#define _LINUX_LIST_H
+
+#define prefetch(x) __builtin_prefetch(x)
+
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ * @ptr:        the pointer to the member.
+ * @type:       the type of the container struct this is embedded in.
+ * @member:     the name of the member within the struct.
+ *
+ */
+#define container_of(ptr, type, member) ({			\
+	__typeof( ((type *)0)->member ) *__mptr = (ptr);	\
+	(type *)( (char *)__mptr - offsetof(type,member) );})
+
+/*
+ * These are non-NULL pointers that will result in page faults
+ * under normal circumstances, used to verify that nobody uses
+ * non-initialized list entries.
+ */
+#define LIST_POISON1  ((void *) 0x00100100)
+#define LIST_POISON2  ((void *) 0x00200200)
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+	struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define _LIST_HEAD(name) \
+	struct list_head name = LIST_HEAD_INIT(name)
+
+static inline void INIT_LIST_HEAD(struct list_head *list)
+{
+	list->next = list;
+	list->prev = list;
+}
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+#ifndef CONFIG_DEBUG_LIST
+static inline void __list_add(struct list_head *new,
+			      struct list_head *prev,
+			      struct list_head *next)
+{
+	next->prev = new;
+	new->next = next;
+	new->prev = prev;
+	prev->next = new;
+}
+#else
+extern void __list_add(struct list_head *new,
+			      struct list_head *prev,
+			      struct list_head *next);
+#endif
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+	__list_add(new, head, head->next);
+}
+
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
+{
+	__list_add(new, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_del(struct list_head * prev, struct list_head * next)
+{
+	next->prev = prev;
+	prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty() on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+#ifndef CONFIG_DEBUG_LIST
+static inline void list_del(struct list_head *entry)
+{
+	__list_del(entry->prev, entry->next);
+	entry->next = LIST_POISON1;
+	entry->prev = LIST_POISON2;
+}
+#else
+extern void list_del(struct list_head *entry);
+#endif
+
+/**
+ * list_replace - replace old entry by new one
+ * @old : the element to be replaced
+ * @new : the new element to insert
+ *
+ * If @old was empty, it will be overwritten.
+ */
+static inline void list_replace(struct list_head *old,
+				struct list_head *new)
+{
+	new->next = old->next;
+	new->next->prev = new;
+	new->prev = old->prev;
+	new->prev->next = new;
+}
+
+static inline void list_replace_init(struct list_head *old,
+					struct list_head *new)
+{
+	list_replace(old, new);
+	INIT_LIST_HEAD(old);
+}
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static inline void list_del_init(struct list_head *entry)
+{
+	__list_del(entry->prev, entry->next);
+	INIT_LIST_HEAD(entry);
+}
+
+/**
+ * list_move - delete from one list and add as another's head
+ * @list: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void list_move(struct list_head *list, struct list_head *head)
+{
+	__list_del(list->prev, list->next);
+	list_add(list, head);
+}
+
+/**
+ * list_move_tail - delete from one list and add as another's tail
+ * @list: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void list_move_tail(struct list_head *list,
+				  struct list_head *head)
+{
+	__list_del(list->prev, list->next);
+	list_add_tail(list, head);
+}
+
+/**
+ * list_is_last - tests whether @list is the last entry in list @head
+ * @list: the entry to test
+ * @head: the head of the list
+ */
+static inline int list_is_last(const struct list_head *list,
+				const struct list_head *head)
+{
+	return list->next == head;
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(const struct list_head *head)
+{
+	return head->next == head;
+}
+
+/**
+ * list_empty_careful - tests whether a list is empty and not being modified
+ * @head: the list to test
+ *
+ * Description:
+ * tests whether a list is empty _and_ checks that no other CPU might be
+ * in the process of modifying either member (next or prev)
+ *
+ * NOTE: using list_empty_careful() without synchronization
+ * can only be safe if the only activity that can happen
+ * to the list entry is list_del_init(). Eg. it cannot be used
+ * if another CPU could re-list_add() it.
+ */
+static inline int list_empty_careful(const struct list_head *head)
+{
+	struct list_head *next = head->next;
+	return (next == head) && (next == head->prev);
+}
+
+/**
+ * list_is_singular - tests whether a list has just one entry.
+ * @head: the list to test.
+ */
+static inline int list_is_singular(const struct list_head *head)
+{
+	return !list_empty(head) && (head->next == head->prev);
+}
+
+static inline void __list_cut_position(struct list_head *list,
+		struct list_head *head, struct list_head *entry)
+{
+	struct list_head *new_first = entry->next;
+	list->next = head->next;
+	list->next->prev = list;
+	list->prev = entry;
+	entry->next = list;
+	head->next = new_first;
+	new_first->prev = head;
+}
+
+/**
+ * list_cut_position - cut a list into two
+ * @list: a new list to add all removed entries
+ * @head: a list with entries
+ * @entry: an entry within head, could be the head itself
+ *	and if so we won't cut the list
+ *
+ * This helper moves the initial part of @head, up to and
+ * including @entry, from @head to @list. You should
+ * pass on @entry an element you know is on @head. @list
+ * should be an empty list or a list you do not care about
+ * losing its data.
+ *
+ */
+static inline void list_cut_position(struct list_head *list,
+		struct list_head *head, struct list_head *entry)
+{
+	if (list_empty(head))
+		return;
+	if (list_is_singular(head) &&
+		(head->next != entry && head != entry))
+		return;
+	if (entry == head)
+		INIT_LIST_HEAD(list);
+	else
+		__list_cut_position(list, head, entry);
+}
+
+static inline void __list_splice(const struct list_head *list,
+				 struct list_head *prev,
+				 struct list_head *next)
+{
+	struct list_head *first = list->next;
+	struct list_head *last = list->prev;
+
+	first->prev = prev;
+	prev->next = first;
+
+	last->next = next;
+	next->prev = last;
+}
+
+/**
+ * list_splice - join two lists, this is designed for stacks
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice(const struct list_head *list,
+				struct list_head *head)
+{
+	if (!list_empty(list))
+		__list_splice(list, head, head->next);
+}
+
+/**
+ * list_splice_tail - join two lists, each list being a queue
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice_tail(struct list_head *list,
+				struct list_head *head)
+{
+	if (!list_empty(list))
+		__list_splice(list, head->prev, head);
+}
+
+/**
+ * list_splice_init - join two lists and reinitialise the emptied list.
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_init(struct list_head *list,
+				    struct list_head *head)
+{
+	if (!list_empty(list)) {
+		__list_splice(list, head, head->next);
+		INIT_LIST_HEAD(list);
+	}
+}
+
+/**
+ * list_splice_tail_init - join two lists and reinitialise the emptied list
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * Each of the lists is a queue.
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_tail_init(struct list_head *list,
+					 struct list_head *head)
+{
+	if (!list_empty(list)) {
+		__list_splice(list, head->prev, head);
+		INIT_LIST_HEAD(list);
+	}
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr:	the &struct list_head pointer.
+ * @type:	the type of the struct this is embedded in.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+	container_of(ptr, type, member)
+
+/**
+ * list_first_entry - get the first element from a list
+ * @ptr:	the list head to take the element from.
+ * @type:	the type of the struct this is embedded in.
+ * @member:	the name of the list_struct within the struct.
+ *
+ * Note, that list is expected to be not empty.
+ */
+#define list_first_entry(ptr, type, member) \
+	list_entry((ptr)->next, type, member)
+
+/**
+ * list_for_each	-	iterate over a list
+ * @pos:	the &struct list_head to use as a loop cursor.
+ * @head:	the head for your list.
+ */
+#define list_for_each(pos, head) \
+	for (pos = (head)->next; prefetch(pos->next), pos != (head); \
+        	pos = pos->next)
+
+/**
+ * __list_for_each	-	iterate over a list
+ * @pos:	the &struct list_head to use as a loop cursor.
+ * @head:	the head for your list.
+ *
+ * This variant differs from list_for_each() in that it's the
+ * simplest possible list iteration code, no prefetching is done.
+ * Use this for code that knows the list to be very short (empty
+ * or 1 entry) most of the time.
+ */
+#define __list_for_each(pos, head) \
+	for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * list_for_each_prev	-	iterate over a list backwards
+ * @pos:	the &struct list_head to use as a loop cursor.
+ * @head:	the head for your list.
+ */
+#define list_for_each_prev(pos, head) \
+	for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
+        	pos = pos->prev)
+
+/**
+ * list_for_each_safe - iterate over a list safe against removal of list entry
+ * @pos:	the &struct list_head to use as a loop cursor.
+ * @n:		another &struct list_head to use as temporary storage
+ * @head:	the head for your list.
+ */
+#define list_for_each_safe(pos, n, head) \
+	for (pos = (head)->next, n = pos->next; pos != (head); \
+		pos = n, n = pos->next)
+
+/**
+ * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
+ * @pos:	the &struct list_head to use as a loop cursor.
+ * @n:		another &struct list_head to use as temporary storage
+ * @head:	the head for your list.
+ */
+#define list_for_each_prev_safe(pos, n, head) \
+	for (pos = (head)->prev, n = pos->prev; \
+	     prefetch(pos->prev), pos != (head); \
+	     pos = n, n = pos->prev)
+
+/**
+ * list_for_each_entry	-	iterate over list of given type
+ * @pos:	the type * to use as a loop cursor.
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member)				\
+	for (pos = list_entry((head)->next, __typeof(*pos), member);	\
+	     prefetch(pos->member.next), &pos->member != (head); 	\
+	     pos = list_entry(pos->member.next, __typeof(*pos), member))
+
+/**
+ * list_for_each_entry_reverse - iterate backwards over list of given type.
+ * @pos:	the type * to use as a loop cursor.
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_reverse(pos, head, member)			\
+	for (pos = list_entry((head)->prev, __typeof(*pos), member);	\
+	     prefetch(pos->member.prev), &pos->member != (head);	\
+	     pos = list_entry(pos->member.prev, __typeof(*pos), member))
+
+/**
+ * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
+ * @pos:	the type * to use as a start point
+ * @head:	the head of the list
+ * @member:	the name of the list_struct within the struct.
+ *
+ * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
+ */
+#define list_prepare_entry(pos, head, member) \
+	((pos) ? : list_entry(head, __typeof(*pos), member))
+
+/**
+ * list_for_each_entry_continue - continue iteration over list of given type
+ * @pos:	the type * to use as a loop cursor.
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ *
+ * Continue to iterate over list of given type, continuing after
+ * the current position.
+ */
+#define list_for_each_entry_continue(pos, head, member)			\
+	for (pos = list_entry(pos->member.next, __typeof(*pos), member);\
+	     prefetch(pos->member.next), &pos->member != (head);	\
+	     pos = list_entry(pos->member.next, __typeof(*pos), member))
+
+/**
+ * list_for_each_entry_continue_reverse - iterate backwards from the given point
+ * @pos:	the type * to use as a loop cursor.
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ *
+ * Start to iterate over list of given type backwards, continuing after
+ * the current position.
+ */
+#define list_for_each_entry_continue_reverse(pos, head, member)		\
+	for (pos = list_entry(pos->member.prev, __typeof(*pos), member);\
+	     prefetch(pos->member.prev), &pos->member != (head);	\
+	     pos = list_entry(pos->member.prev, __typeof(*pos), member))
+
+/**
+ * list_for_each_entry_from - iterate over list of given type from the current point
+ * @pos:	the type * to use as a loop cursor.
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ *
+ * Iterate over list of given type, continuing from current position.
+ */
+#define list_for_each_entry_from(pos, head, member)			\
+	for (; prefetch(pos->member.next), &pos->member != (head);	\
+	     pos = list_entry(pos->member.next, __typeof(*pos), member))
+
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos:	the type * to use as a loop cursor.
+ * @n:		another type * to use as temporary storage
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_safe(pos, n, head, member)			\
+	for (pos = list_entry((head)->next, __typeof(*pos), member),	\
+		n = list_entry(pos->member.next, __typeof(*pos), member);\
+	     &pos->member != (head);					\
+	     pos = n, n = list_entry(n->member.next, __typeof(*n), member))
+
+/**
+ * list_for_each_entry_safe_continue
+ * @pos:	the type * to use as a loop cursor.
+ * @n:		another type * to use as temporary storage
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ *
+ * Iterate over list of given type, continuing after current point,
+ * safe against removal of list entry.
+ */
+#define list_for_each_entry_safe_continue(pos, n, head, member)			\
+	for (pos = list_entry(pos->member.next, __typeof(*pos), member)		\
+		n = list_entry(pos->member.next, __typeof(*pos), member);	\
+	     &pos->member != (head);						\
+	     pos = n, n = list_entry(n->member.next, __typeof(*n), member))
+
+/**
+ * list_for_each_entry_safe_from
+ * @pos:	the type * to use as a loop cursor.
+ * @n:		another type * to use as temporary storage
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ *
+ * Iterate over list of given type from current point, safe against
+ * removal of list entry.
+ */
+#define list_for_each_entry_safe_from(pos, n, head, member)			\
+	for (n = list_entry(pos->member.next, __typeof(*pos), member);		\
+	     &pos->member != (head);						\
+	     pos = n, n = list_entry(n->member.next, __typeof(*n), member))
+
+/**
+ * list_for_each_entry_safe_reverse
+ * @pos:	the type * to use as a loop cursor.
+ * @n:		another type * to use as temporary storage
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ *
+ * Iterate backwards over list of given type, safe against removal
+ * of list entry.
+ */
+#define list_for_each_entry_safe_reverse(pos, n, head, member)		\
+	for (pos = list_entry((head)->prev, __typeof(*pos), member),	\
+		n = list_entry(pos->member.prev, __typeof(*pos), member);\
+	     &pos->member != (head);					\
+	     pos = n, n = list_entry(n->member.prev, __typeof(*n), member))
+
+/*
+ * Double linked lists with a single pointer list head.
+ * Mostly useful for hash tables where the two pointer list head is
+ * too wasteful.
+ * You lose the ability to access the tail in O(1).
+ */
+
+struct hlist_head {
+	struct hlist_node *first;
+};
+
+struct hlist_node {
+	struct hlist_node *next, **pprev;
+};
+
+#define HLIST_HEAD_INIT { .first = 0 }
+#define HLIST_HEAD(name) struct hlist_head name = {  .first = 0 }
+#define INIT_HLIST_HEAD(ptr) ((ptr)->first = 0)
+static inline void INIT_HLIST_NODE(struct hlist_node *h)
+{
+	h->next = 0;
+	h->pprev = 0;
+}
+
+static inline int hlist_unhashed(const struct hlist_node *h)
+{
+	return !h->pprev;
+}
+
+static inline int hlist_empty(const struct hlist_head *h)
+{
+	return !h->first;
+}
+
+static inline void __hlist_del(struct hlist_node *n)
+{
+	struct hlist_node *next = n->next;
+	struct hlist_node **pprev = n->pprev;
+	*pprev = next;
+	if (next)
+		next->pprev = pprev;
+}
+
+static inline void hlist_del(struct hlist_node *n)
+{
+	__hlist_del(n);
+	n->next = LIST_POISON1;
+	n->pprev = LIST_POISON2;
+}
+
+static inline void hlist_del_init(struct hlist_node *n)
+{
+	if (!hlist_unhashed(n)) {
+		__hlist_del(n);
+		INIT_HLIST_NODE(n);
+	}
+}
+
+static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
+{
+	struct hlist_node *first = h->first;
+	n->next = first;
+	if (first)
+		first->pprev = &n->next;
+	h->first = n;
+	n->pprev = &h->first;
+}
+
+/* next must be != NULL */
+static inline void hlist_add_before(struct hlist_node *n,
+					struct hlist_node *next)
+{
+	n->pprev = next->pprev;
+	n->next = next;
+	next->pprev = &n->next;
+	*(n->pprev) = n;
+}
+
+static inline void hlist_add_after(struct hlist_node *n,
+					struct hlist_node *next)
+{
+	next->next = n->next;
+	n->next = next;
+	next->pprev = &n->next;
+
+	if(next->next)
+		next->next->pprev  = &next->next;
+}
+
+/*
+ * Move a list from one list head to another. Fixup the pprev
+ * reference of the first entry if it exists.
+ */
+static inline void hlist_move_list(struct hlist_head *old,
+				   struct hlist_head *new)
+{
+	new->first = old->first;
+	if (new->first)
+		new->first->pprev = &new->first;
+	old->first = 0;
+}
+
+#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
+
+#define hlist_for_each(pos, head) \
+	for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
+	     pos = pos->next)
+
+#define hlist_for_each_safe(pos, n, head) \
+	for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
+	     pos = n)
+
+/**
+ * hlist_for_each_entry	- iterate over list of given type
+ * @tpos:	the type * to use as a loop cursor.
+ * @pos:	the &struct hlist_node to use as a loop cursor.
+ * @head:	the head for your list.
+ * @member:	the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry(tpos, pos, head, member)			 \
+	for (pos = (head)->first;					 \
+	     pos && ({ prefetch(pos->next); 1;}) &&			 \
+		({ tpos = hlist_entry(pos, __typeof(*tpos), member); 1;}); \
+	     pos = pos->next)
+
+/**
+ * hlist_for_each_entry_continue - iterate over a hlist continuing after current point
+ * @tpos:	the type * to use as a loop cursor.
+ * @pos:	the &struct hlist_node to use as a loop cursor.
+ * @member:	the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_continue(tpos, pos, member)		 \
+	for (pos = (pos)->next;						 \
+	     pos && ({ prefetch(pos->next); 1;}) &&			 \
+		({ tpos = hlist_entry(pos, __typeof(*tpos), member); 1;}); \
+	     pos = pos->next)
+
+/**
+ * hlist_for_each_entry_from - iterate over a hlist continuing from current point
+ * @tpos:	the type * to use as a loop cursor.
+ * @pos:	the &struct hlist_node to use as a loop cursor.
+ * @member:	the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_from(tpos, pos, member)			 \
+	for (; pos && ({ prefetch(pos->next); 1;}) &&			 \
+		({ tpos = hlist_entry(pos, __typeof(*tpos), member); 1;}); \
+	     pos = pos->next)
+
+/**
+ * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @tpos:	the type * to use as a loop cursor.
+ * @pos:	the &struct hlist_node to use as a loop cursor.
+ * @n:		another &struct hlist_node to use as temporary storage
+ * @head:	the head for your list.
+ * @member:	the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_safe(tpos, pos, n, head, member) 		 \
+	for (pos = (head)->first;					 \
+	     pos && ({ n = pos->next; 1; }) && 				 \
+		({ tpos = hlist_entry(pos, __typeof(*tpos), member); 1;}); \
+	     pos = n)
+
+#endif
Index: include/dahdi/compat/types.h
===================================================================
--- include/dahdi/compat/types.h	(revision 0)
+++ include/dahdi/compat/types.h	(revision 0)
@@ -0,0 +1,11 @@
+#ifndef _DAHDI_COMPAT_TYPES_H_
+#define _DAHDI_COMPAT_TYPES_H_
+
+#include <sys/types.h>
+
+typedef uint8_t __u8;
+typedef int32_t __s32;
+typedef uint32_t __u32;
+typedef uint32_t u32;
+
+#endif /* _DAHDI_COMPAT_TYPES_H_ */
Index: include/dahdi/compat/bsd.h
===================================================================
--- include/dahdi/compat/bsd.h	(revision 0)
+++ include/dahdi/compat/bsd.h	(revision 0)
@@ -0,0 +1,175 @@
+#ifndef _DAHDI_COMPAT_BSD_H_
+#define _DAHDI_COMPAT_BSD_H_
+
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/sx.h>
+#include <machine/atomic.h>
+
+#define KERNEL_VERSION(x, y, z)	0
+
+#define copy_from_user(to, from, n)	(bcopy((from), (to), (n)), 0)
+#define copy_to_user(to, from, n)	(bcopy((from), (to), (n)), 0)
+
+#define get_user(v, p)	copy_from_user(&(v), (p), sizeof(v))
+#define put_user(v, p)	copy_to_user((p), &(v), sizeof(v))
+
+typedef void *wait_queue_head_t;
+#define init_waitqueue_head(q)
+#define wake_up_interruptible(q)	wakeup(q)
+
+#define test_bit(v, p)	((*(p)) & (1 << ((v) & 0x1f)))
+#define set_bit(v, p)	atomic_set_long((p), (1 << ((v) & 0x1f)))
+#define clear_bit(v, p)	atomic_clear_long((p), (1 << ((v) & 0x1f)))
+
+#define ADDR (*(volatile long *) addr)
+
+#ifdef SMP
+#define	LOCK_PREFIX "lock ; "
+#else
+#define	LOCK_PREFIX ""
+#endif /* SMP */
+
+static __inline int test_and_set_bit(int nr, volatile void * addr)
+{
+	int oldbit;
+
+	__asm__ __volatile__( LOCK_PREFIX
+		"btsl %2,%1\n\tsbbl %0,%0"
+		:"=r" (oldbit),"=m" (ADDR)
+		:"Ir" (nr) : "memory");
+	return oldbit;
+}
+
+static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
+{
+	int oldbit;
+
+	__asm__ __volatile__( LOCK_PREFIX
+		"btrl %2,%1\n\tsbbl %0,%0"
+		:"=r" (oldbit),"=m" (ADDR)
+		:"Ir" (nr) : "memory");
+	return oldbit;
+}
+
+typedef u_int atomic_t;
+#define atomic_set(p, v)	(*(p) = (v))
+#define atomic_read(p)		(*(p))
+#define atomic_inc(p)		atomic_add_int(p, 1)
+#define atomic_dec(p)		atomic_subtract_int(p, 1)
+#define atomic_add(v, p)	atomic_add_int(p, v)
+#define atomic_sub(v, p)	atomic_subtract_int(p, v)
+
+typedef struct mtx spinlock_t;
+
+#define DEFINE_SPINLOCK(name)				\
+	struct mtx name;				\
+	MTX_SYSINIT(name, &name, #name, MTX_SPIN)
+#define spin_lock_init(lock)	mtx_init(lock, "dahdi lock", NULL, MTX_SPIN)
+#define spin_lock_destroy(lock)	mtx_destroy(lock)
+#define spin_lock(lock)		mtx_lock_spin(lock)
+#define spin_unlock(lock)	mtx_unlock_spin(lock)
+#define spin_lock_irqsave(lock, flags)			\
+	do {						\
+		mtx_lock_spin(lock);			\
+		(void) &(flags);			\
+	} while (0)
+#define spin_unlock_irqrestore(lock, flags)		\
+	mtx_unlock_spin(lock)
+
+#define DEFINE_RWLOCK(name)				\
+	struct sx name;					\
+	SX_SYSINIT(name, &name, #name)
+#define read_lock(rwlock)	sx_slock(rwlock)
+#define read_unlock(rwlock)	sx_sunlock(rwlock)
+
+#define write_lock(rwlock)	sx_xlock(rwlock)
+#define write_unlock(rwlock)	sx_xunlock(rwlock)
+#define write_lock_irqsave(rwlock, flags)		\
+	do {						\
+		sx_xlock(rwlock);			\
+		(void) &(flags);			\
+	} while (0)
+#define write_unlock_irqrestore(rwlock, flags)		\
+	sx_xunlock(rwlock)
+
+#define WARN_ON(cond)					\
+	do {						\
+		if (cond)				\
+			printf("WARN_ON: " #cond "\n");	\
+	} while (0)
+
+#define KERN_EMERG	"<0>"	/* system is unusable			*/
+#define KERN_ALERT	"<1>"	/* action must be taken immediately	*/
+#define KERN_CRIT	"<2>"	/* critical conditions			*/
+#define KERN_ERR	"<3>"	/* error conditions			*/
+#define KERN_WARNING	"<4>"	/* warning conditions			*/
+#define KERN_NOTICE	"<5>"	/* normal but significant condition	*/
+#define KERN_INFO	"<6>"	/* informational			*/
+#define KERN_DEBUG	"<7>"	/* debug-level messages			*/
+
+#define dev_err(dev, fmt, args...)	device_printf(dev, fmt, ##args)
+#define dev_warn(dev, fmt, args...)	device_printf(dev, fmt, ##args)
+#define dev_notice(dev, fmt, args...)	device_printf(dev, fmt, ##args)
+#define dev_info(dev, fmt, args...)	device_printf(dev, fmt, ##args)
+#define dev_dbg(dev, fmt, args...)	device_printf(dev, fmt, ##args)
+
+#define pr_info(fmt, args...)		printf(fmt, ##args)
+
+#define printk(fmt, args...)		printf(fmt, ##args)
+
+#define GFP_KERNEL	0
+#define GFP_ATOMIC	0
+
+MALLOC_DECLARE(M_DAHDI);
+
+#define kmalloc(size, flags)	malloc((size), M_DAHDI, M_NOWAIT)
+#define kcalloc(n, size, flags)	malloc((n) * (size), M_DAHDI, M_NOWAIT | M_ZERO)
+#define kfree(p)		free(p, M_DAHDI)
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#define memmove(dst, src, size)	bcopy((src), (dst), (size))
+
+#define might_sleep()
+
+#define ENODATA EINVAL
+
+#define __init
+#define __exit
+#define __devinit
+#define __devexit
+#define __devinitdata
+
+#define likely(x)       __builtin_expect(!!(x), 1)
+#define unlikely(x)     __builtin_expect(!!(x), 0)
+
+/* emulate jiffies */
+static inline unsigned long _jiffies(void)
+{
+	struct timeval tv;
+
+	microuptime(&tv);
+	return tvtohz(&tv);
+}
+
+#define jiffies			_jiffies()
+#define HZ			hz
+#define udelay(usec)		DELAY(usec)
+#define mdelay(msec)		DELAY((msec) * 1000)
+#define time_after(a, b)	((a) > (b))
+#define time_after_eq(a, b)	((a) >= (b))
+
+#define DAHDI_IRQ_HANDLER(a)	static int a(void *dev_id)
+
+#define PCI_ANY_ID (~0)
+
+struct pci_device_id {
+	uint32_t vendor, device;	/* Vendor and device ID or PCI_ANY_ID*/
+	uint32_t subvendor, subdevice;	/* Subsystem ID's or PCI_ANY_ID */
+	uint32_t class, class_mask;	/* (class,subclass,prog-if) triplet */
+	unsigned long driver_data;	/* Data private to the driver */
+};
+
+#endif /* _DAHDI_COMPAT_BSD_H_ */
Index: include/dahdi/dahdi_config.h
===================================================================
--- include/dahdi/dahdi_config.h	(revision 7107)
+++ include/dahdi/dahdi_config.h	(working copy)
@@ -20,12 +20,14 @@
 #define _DAHDI_CONFIG_H
 
 #ifdef __KERNEL__
+#if !defined(__FreeBSD__)
 #include <linux/version.h>
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
 #include <linux/config.h>
 #else
 #include <linux/autoconf.h>
 #endif
+#endif /* !__FreeBSD__ */
 #endif
 
 /* DAHDI compile time options */
Index: include/dahdi/user.h
===================================================================
--- include/dahdi/user.h	(revision 7107)
+++ include/dahdi/user.h	(working copy)
@@ -35,10 +35,14 @@
 #ifndef _DAHDI_USER_H
 #define _DAHDI_USER_H
 
+#if defined(__FreeBSD__)
+#include <dahdi/compat/types.h>
+#else
 #include <linux/types.h>
 #include <linux/ioctl.h>
+#endif /* !__FreeBSD__ */
 
-#ifndef ELAST
+#if !defined(__FreeBSD__) && !defined(ELAST)
 #define ELAST 500
 #endif
 
Index: include/dahdi/kernel.h
===================================================================
--- include/dahdi/kernel.h	(revision 7107)
+++ include/dahdi/kernel.h	(working copy)
@@ -35,8 +35,22 @@
 
 #include <dahdi/user.h>
 #include <dahdi/fasthdlc.h>
+#include <dahdi/dahdi_config.h>
 
-#include <dahdi/dahdi_config.h>
+#if defined(__FreeBSD__)
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/selinfo.h>
+#include <sys/taskqueue.h>
+#include <sys/uio.h>
+
+#include <dahdi/compat/types.h>
+#include <dahdi/compat/list.h>
+#include <dahdi/compat/bsd.h>
+
+#define _RETVAL(errno)	(errno)
+
+#else /* !__FreeBSD */
 #include <linux/version.h>
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
 #include <linux/config.h>
@@ -85,6 +99,11 @@
 #endif
 #endif
 
+#define spin_lock_destroy(lock)
+#define _LIST_HEAD(n)	LIST_HEAD(n)
+#define _RETVAL(errno)	(-(errno))
+#endif /* !__FreeBSD__ */
+
 /*! Default chunk size for conferences and such -- static right now, might make
    variable sometime.  8 samples = 1 ms = most frequent service interval possible
    for a USB device */
@@ -257,10 +276,12 @@
 	/*! The name of the factory. */
 	const char *name;
 
+#if !defined(__FreeBSD__)
 	/*! Pointer to the module that owns this factory; the module's reference count will be
 	 * incremented/decremented by the DAHDI core as needed.
 	 */
 	struct module *owner;
+#endif
 
 	/*! \brief Function to create an instance of the echocan.
 	 * \param[in] ecp Structure defining parameters to be used for the instance creation.
@@ -369,7 +390,7 @@
 			/*! The echocan enabled its NLP automatically.
 			 */
 			u32 NLP_auto_enabled:1;
-		};
+		} e;
 	} events;
 };
 
@@ -427,9 +448,12 @@
 
 	/* Specified by driver, readable by DAHDI */
 	void *pvt;			/*!< Private channel data */
+#if defined(__FreeBSD__)
+	struct cdev *file;	/*!< Device structure */
+#else
 	struct file *file;	/*!< File structure */
+#endif
 	
-	
 	struct dahdi_span	*span;			/*!< Span we're a member of */
 	int		sig;			/*!< Signalling */
 	int		sigcap;			/*!< Capability for signalling */
@@ -491,7 +515,12 @@
 
 	/* I/O Mask */	
 	int		iomask;  /*! I/O Mux signal mask */
+#if defined(__FreeBSD__)
+	struct selinfo sel;	/*! thingy for select stuff */
+	struct task selwakeup_task;
+#else
 	wait_queue_head_t sel;	/*! thingy for select stuff */
+#endif
 	
 	/* HDLC state machines */
 	struct fasthdlc_state txhdlc;
@@ -519,7 +548,6 @@
 	short	conflast1[DAHDI_MAX_CHUNKSIZE];		/*!< Last conference sample  -- pseudo part of channel */
 	short	conflast2[DAHDI_MAX_CHUNKSIZE];		/*!< Previous last conference sample -- pseudo part of channel */
 	
-
 	/*! The echo canceler module that should be used to create an
 	   instance when this channel needs one */
 	const struct dahdi_echocan_factory *ec_factory;
@@ -644,6 +672,9 @@
 struct dahdi_chardev {
 	const char *name;
 	__u8 minor;
+#if defined(__FreeBSD__)
+	struct cdev *dev;
+#endif
 };
 
 int dahdi_register_chardev(struct dahdi_chardev *dev);
@@ -734,7 +765,11 @@
 
 struct dahdi_span {
 	spinlock_t lock;
+#if defined(__FreeBSD__)
+	int refcount;
+#else
 	struct module *owner;		/*!< Which module is exporting this span. */
+#endif
 	void *pvt;			/*!< Private stuff */
 	char name[40];			/*!< Span name */
 	char desc[80];			/*!< Span description */
@@ -916,7 +951,12 @@
 	int numchannels;
 	unsigned int srcfmts;
 	unsigned int dstfmts;
+#if defined(__FreeBSD__)
+	int (*write)(struct dahdi_transcoder_channel *channel, struct uio *uio, int ioflags);
+	int (*read)(struct dahdi_transcoder_channel *channel, struct uio *uio, int ioflags);
+#else
 	struct file_operations fops;
+#endif
 	int (*allocate)(struct dahdi_transcoder_channel *channel);
 	int (*release)(struct dahdi_transcoder_channel *channel);
 	/* Transcoder channels */
@@ -1042,7 +1082,9 @@
 void dahdi_ec_chunk(struct dahdi_chan *chan, unsigned char *rxchunk, const unsigned char *txchunk);
 void dahdi_ec_span(struct dahdi_span *span);
 
+#if !defined(__FreeBSD__)
 extern struct file_operations *dahdi_transcode_fops;
+#endif
 
 /* Don't use these directly -- they're not guaranteed to
    be there. */
@@ -1163,7 +1205,7 @@
 /*! Maximum audio mask */
 #define DAHDI_FORMAT_AUDIO_MASK	((1 << 16) - 1)
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
+#if defined(__FreeBSD__) || LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
 #define kzalloc(a, b) kcalloc(1, a, b)
 #endif
 
Index: freebsd/wcb4xxp/Makefile
===================================================================
--- freebsd/wcb4xxp/Makefile	(revision 0)
+++ freebsd/wcb4xxp/Makefile	(revision 0)
@@ -0,0 +1,10 @@
+# $Id$
+
+.PATH: ${.CURDIR}/../../drivers/dahdi/wcb4xxp
+
+KMOD=	wcb4xxp
+SRCS=	base.c
+SRCS+=	device_if.h bus_if.h pci_if.h
+CFLAGS=	--param inline-unit-growth=100
+
+.include <bsd.kmod.mk>
Index: freebsd/dahdi_echocan_sec/Makefile
===================================================================
--- freebsd/dahdi_echocan_sec/Makefile	(revision 0)
+++ freebsd/dahdi_echocan_sec/Makefile	(revision 0)
@@ -0,0 +1,8 @@
+# $Id$
+
+.PATH:	${.CURDIR}/../../drivers/dahdi
+
+KMOD=	dahdi_echocan_sec
+SRCS=	dahdi_echocan_sec.c
+
+.include <bsd.kmod.mk>
Index: freebsd/dahdi_dummy/dahdi_dummy.c
===================================================================
--- freebsd/dahdi_dummy/dahdi_dummy.c	(revision 0)
+++ freebsd/dahdi_dummy/dahdi_dummy.c	(revision 0)
@@ -0,0 +1,217 @@
+/*
+ * Dummy DAHDI Driver for DAHDI Telephony interface
+ *
+ * Required:  kernel compiled with "options HZ=1000" 
+ * Written by Chris Stenton <jacs@gnome.co.uk>
+ * 
+ * Copyright (C) 2004, Digium, Inc.
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Rewritten to use the time of day clock (which should be ntp synced
+ * for this to work perfectly) by David G. Lawrence <dg@dglawrence.com>.
+ * July 27th, 2007.
+ *
+ */
+
+#include <sys/cdefs.h>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/uio.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+
+#include <sys/conf.h>
+#include <sys/errno.h>
+
+#include <dahdi/kernel.h>
+
+struct dahdi_dummy {
+	struct dahdi_span span;
+	struct dahdi_chan _chan;
+	struct dahdi_chan *chan;
+};
+
+MALLOC_DEFINE(M_DAHDIDUMMY, "dahdy_dummy", "DAHDI dummy interface data structures");
+
+#ifndef timersub
+#define timersub(tvp, uvp, vvp)                                         \
+        do {                                                            \
+                (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec;          \
+                (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec;       \
+                if ((vvp)->tv_usec < 0) {                               \
+                        (vvp)->tv_sec--;                                \
+                        (vvp)->tv_usec += 1000000;                      \
+                }                                                       \
+        } while (0)
+#endif
+
+static struct callout_handle dahdi_dummy_timer_handle = CALLOUT_HANDLE_INITIALIZER(&dahdi_dummy_timer_handle);
+
+static struct dahdi_dummy *dahdi_d;
+
+static int debug = 0;
+static struct timeval basetime, curtime, sleeptime;
+
+static __inline void
+dahdi_dummy_timer(void *arg)
+{
+	int i, ticks;
+
+loop:
+	for (i = 0; i < hz / 100; i++) {
+		dahdi_receive(&dahdi_d->span);
+		dahdi_transmit(&dahdi_d->span);
+	}
+
+fixtime:
+	microtime(&curtime);
+
+	/*
+	 * Sleep until the next 10ms boundry.
+	 */
+	basetime.tv_usec += 10000;
+	if (basetime.tv_usec >= 1000000) {
+		basetime.tv_sec++;
+		basetime.tv_usec -= 1000000;
+	}
+	timersub(&basetime, &curtime, &sleeptime);
+
+	/*
+	 * Detect if we've gotten behind and need to start our processing
+	 * immediately.
+	 */
+	if (sleeptime.tv_sec < 0 || sleeptime.tv_usec == 0) {
+		/*
+		 * Limit how far we can get behind to something reasonable (1 sec)
+		 * so that we don't go nuts when something (ntp or admin) sets the
+		 * clock forward by a large amount.
+		 */
+		if (sleeptime.tv_sec < -1) {
+			basetime.tv_sec = curtime.tv_sec;
+			basetime.tv_usec = curtime.tv_usec;
+			goto fixtime;
+		}
+		goto loop;
+	}
+	/*
+	 * Detect if something is messing with the system clock by
+	 * checking that the sleep time is no more than 20ms and
+	 * resetting our base time if it is. This case will occur if
+	 * the system clock has been reset to an earlier time.
+	 */
+	if (sleeptime.tv_sec > 0 || sleeptime.tv_usec > 20000) {
+		basetime.tv_sec = curtime.tv_sec;
+		basetime.tv_usec = curtime.tv_usec;
+		goto fixtime;
+	}
+
+	ticks = sleeptime.tv_usec * hz / 1000000;
+	if (ticks == 0)
+		goto loop;
+
+	dahdi_dummy_timer_handle = timeout(dahdi_dummy_timer, NULL, ticks);
+}
+
+static int
+dahdi_dummy_initialize(struct dahdi_dummy *dahdi_d)
+{
+	/* DAHDI stuff */
+	dahdi_d->chan = &dahdi_d->_chan;
+	sprintf(dahdi_d->span.name, "DAHDI_DUMMY/1");
+	sprintf(dahdi_d->span.desc, "%s %d", dahdi_d->span.name, 1);
+	sprintf(dahdi_d->chan->name, "DAHDI_DUMMY/%d/%d", 1, 0);
+	dahdi_copy_string(dahdi_d->span.devicetype, "DAHDI Dummy Timing", sizeof(dahdi_d->span.devicetype));
+	dahdi_d->chan->chanpos = 1;
+	dahdi_d->span.chans = &dahdi_d->chan;
+	dahdi_d->span.channels = 0;		/* no channels on our span */
+	dahdi_d->span.deflaw = DAHDI_LAW_MULAW;
+	dahdi_d->span.pvt = dahdi_d;
+	dahdi_d->chan->pvt = dahdi_d;
+	if (dahdi_register(&dahdi_d->span, 0)) {
+		return -1;
+	}
+	return 0;
+}
+
+static int
+dahdi_dummy_attach(void)
+{
+	dahdi_d = malloc(sizeof(struct dahdi_dummy), M_DAHDIDUMMY, M_NOWAIT | M_ZERO);
+	if (dahdi_d == NULL) {
+		printf("dahdi_dummy: Unable to allocate memory\n");
+		return ENOMEM;
+	}
+
+	if (dahdi_dummy_initialize(dahdi_d)) {
+		printf("dahdi_dummy: Unable to intialize zaptel driver\n");
+		free(dahdi_d, M_DAHDIDUMMY);
+		return ENODEV;
+	}
+
+	microtime(&basetime);
+	dahdi_dummy_timer_handle = timeout(dahdi_dummy_timer, NULL, 1);
+
+	if (debug)
+		printf("dahdi_dummy: init() finished\n");
+	return 0;
+}
+
+static void
+cleanup_module(void)
+{
+	untimeout(dahdi_dummy_timer, NULL, dahdi_dummy_timer_handle);
+	dahdi_unregister(&dahdi_d->span);
+	free(dahdi_d, M_DAHDIDUMMY);
+
+	if (debug)
+		printf("dahdi_dummy: cleanup() finished\n");
+}
+
+static int
+dahdi_dummy_modevent(module_t mod,int  type, void*  data)
+{
+	int ret;
+
+	switch (type) {
+	case MOD_LOAD:
+		 ret = dahdi_dummy_attach();
+		 if (ret)
+			 return (ret);
+		 printf("dahdi_dummy: loaded\n");
+		 if (hz < 1000) {
+			 printf("dahdi_dummy: WARNING Ticker rate only %d. Timer will not work well!!\nRecompile kernel with \"options HZ=1000\"\n", hz);
+		 }
+		break;
+
+	case MOD_UNLOAD:
+		cleanup_module();
+		printf("dahdi_dummy: unloaded\n");
+		break;
+
+	default:
+		return EOPNOTSUPP;
+	}
+	return 0;
+}
+
+MODULE_VERSION(dahdi_dummy, 1);
+MODULE_DEPEND(dahdi_dummy, dahdi, 1, 1, 1);
+DEV_MODULE(dahdi_dummy, dahdi_dummy_modevent, NULL);
Index: freebsd/dahdi_dummy/Makefile
===================================================================
--- freebsd/dahdi_dummy/Makefile	(revision 0)
+++ freebsd/dahdi_dummy/Makefile	(revision 0)
@@ -0,0 +1,6 @@
+# $Id: Makefile 277 2008-12-22 15:25:03Z ys $
+
+SRCS=	dahdi_dummy.c
+KMOD=	dahdi_dummy
+
+.include <bsd.kmod.mk>
Index: freebsd/Makefile.inc
===================================================================
--- freebsd/Makefile.inc	(revision 0)
+++ freebsd/Makefile.inc	(revision 0)
@@ -0,0 +1,13 @@
+# $Id$
+
+PREFIX?=	/usr/local
+INCLUDEDIR=	${.CURDIR}/../../include
+KMODDIR?=	${PREFIX}/lib/dahdi
+
+CFLAGS+=	-I${INCLUDEDIR} -D__KERNEL__
+
+MKDIR?=		mkdir -p
+INSTALL_DATA?=	${INSTALL} -m ${SHAREMODE} -o ${SHAREOWN} -g ${SHAREGRP} -c
+
+beforeinstall:
+	${MKDIR} ${KMODDIR}
Index: freebsd/dahdi_echocan_sec2/Makefile
===================================================================
--- freebsd/dahdi_echocan_sec2/Makefile	(revision 0)
+++ freebsd/dahdi_echocan_sec2/Makefile	(revision 0)
@@ -0,0 +1,8 @@
+# $Id$
+
+.PATH:	${.CURDIR}/../../drivers/dahdi
+
+KMOD=	dahdi_echocan_sec2
+SRCS=	dahdi_echocan_sec2.c
+
+.include <bsd.kmod.mk>
Index: freebsd/dahdi_echocan_kb1/Makefile
===================================================================
--- freebsd/dahdi_echocan_kb1/Makefile	(revision 0)
+++ freebsd/dahdi_echocan_kb1/Makefile	(revision 0)
@@ -0,0 +1,8 @@
+# $Id$
+
+.PATH:	${.CURDIR}/../../drivers/dahdi
+
+KMOD=	dahdi_echocan_kb1
+SRCS=	dahdi_echocan_kb1.c
+
+.include <bsd.kmod.mk>
Index: freebsd/dahdi/Makefile
===================================================================
--- freebsd/dahdi/Makefile	(revision 0)
+++ freebsd/dahdi/Makefile	(revision 0)
@@ -0,0 +1,24 @@
+# $Id$
+
+.PATH: ${.CURDIR}/../../drivers/dahdi
+
+KMOD=		dahdi
+SRCS=		dahdi-base.c version.h
+SRCS+=		device_if.h bus_if.h
+CLEANFILES=	version.h
+INCS=		user.h wctdm_user.h compat/types.h
+
+DAHDIVERSION!=	${.CURDIR}/../../build_tools/make_version ../.. dahdi/linux
+version.h::
+	@DAHDIVERSION="${DAHDIVERSION}" ${.CURDIR}/../../build_tools/make_version_h >${.TARGET}.tmp
+	@if ! cmp -s ${.TARGET}.tmp ${.TARGET}; then mv ${.TARGET}.tmp ${.TARGET}; fi
+	@rm -f ${.TARGET}.tmp
+
+afterinstall:
+	${MKDIR} ${PREFIX}/include/dahdi/compat
+.for _h in ${INCS}
+	${INSTALL_DATA} ${INCLUDEDIR}/dahdi/${_h} ${PREFIX}/include/dahdi/${_h:H}
+.endfor
+
+.include <bsd.kmod.mk>
+.include <bsd.own.mk>
Index: freebsd/dahdi_echocan_jpah/Makefile
===================================================================
--- freebsd/dahdi_echocan_jpah/Makefile	(revision 0)
+++ freebsd/dahdi_echocan_jpah/Makefile	(revision 0)
@@ -0,0 +1,8 @@
+# $Id$
+
+.PATH:	${.CURDIR}/../../drivers/dahdi
+
+KMOD=	dahdi_echocan_jpah
+SRCS=	dahdi_echocan_jpah.c
+
+.include <bsd.kmod.mk>
Index: freebsd/Makefile
===================================================================
--- freebsd/Makefile	(revision 0)
+++ freebsd/Makefile	(revision 0)
@@ -0,0 +1,13 @@
+# $Id$
+
+SUBDIR=\
+	dahdi\
+	dahdi_dummy\
+	dahdi_echocan_jpah\
+	dahdi_echocan_kb1\
+	dahdi_echocan_mg2\
+	dahdi_echocan_sec\
+	dahdi_echocan_sec2\
+	wcb4xxp
+
+.include <bsd.subdir.mk>
Index: freebsd/dahdi_echocan_mg2/Makefile
===================================================================
--- freebsd/dahdi_echocan_mg2/Makefile	(revision 0)
+++ freebsd/dahdi_echocan_mg2/Makefile	(revision 0)
@@ -0,0 +1,8 @@
+# $Id$
+
+.PATH:	${.CURDIR}/../../drivers/dahdi
+
+KMOD=	dahdi_echocan_mg2
+SRCS=	dahdi_echocan_mg2.c
+
+.include <bsd.kmod.mk>
Index: drivers/dahdi/dahdi_echocan_mg2.c
===================================================================
--- drivers/dahdi/dahdi_echocan_mg2.c	(revision 7107)
+++ drivers/dahdi/dahdi_echocan_mg2.c	(working copy)
@@ -31,6 +31,18 @@
  * this program for more details.
  */
 
+#if defined(__FreeBSD__)
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/conf.h>
+#include <sys/ctype.h>
+#include <sys/libkern.h>
+#include <sys/module.h>
+
+#define module_printk(level, fmt, args...) printf(fmt, ## args)
+#define debug_printk(level, fmt, args...) if (debug >= level) printf("%s: " fmt, __FUNCTION__, ## args)
+
+#else /* !__FreeBSD__ */
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
@@ -39,14 +51,15 @@
 #include <linux/ctype.h>
 #include <linux/moduleparam.h>
 
+#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
+#define debug_printk(level, fmt, args...) if (debug >= level) printk("%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
+#endif /* !__FreeBSD__ */
+
 #include <dahdi/kernel.h>
 
 static int debug;
 static int aggressive;
 
-#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
-#define debug_printk(level, fmt, args...) if (debug >= level) printk("%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
-
 #define ABS(a) abs(a!=-32768?a:-32767)
 
 #define RESTORE_COEFFS {\
@@ -183,8 +196,10 @@
 
 static const struct dahdi_echocan_factory my_factory = {
 	.name = "MG2",
+	.echocan_create = echo_can_create,
+#if !defined(__FreeBSD__)
 	.owner = THIS_MODULE,
-	.echocan_create = echo_can_create,
+#endif
 };
 
 static const struct dahdi_echocan_features my_features = {
@@ -311,7 +326,7 @@
 	unsigned long tmp;
 
 	/* Double-word align past end of state */
-	ptr += sizeof(*pvt);
+	ptr = (char *) ptr + sizeof(*pvt);
 	tmp = (unsigned long)ptr;
 	tmp += 3;
 	tmp &= ~3L;
@@ -323,26 +338,26 @@
   
 	/* Allocate coefficient memory */
 	pvt->a_i = ptr;
-	ptr += (sizeof(int) * pvt->N_d);
+	ptr = (char *) ptr + (sizeof(int) * pvt->N_d);
 	pvt->a_s = ptr;
-	ptr += (sizeof(short) * pvt->N_d);
+	ptr = (char *) ptr + (sizeof(short) * pvt->N_d);
 
 	/* Allocate backup memory */
 	pvt->b_i = ptr;
-	ptr += (sizeof(int) * pvt->N_d);
+	ptr = (char *) ptr + (sizeof(int) * pvt->N_d);
 	pvt->c_i = ptr;
-	ptr += (sizeof(int) * pvt->N_d);
+	ptr = (char *) ptr + (sizeof(int) * pvt->N_d);
 
 	/* Reset Y circular buffer (short version) */
 	init_cb_s(&pvt->y_s, maxy, ptr);
-	ptr += (sizeof(short) * (maxy) * 2);
+	ptr = (char *) ptr + (sizeof(short) * (maxy) * 2);
   
 	/* Reset Sigma circular buffer (short version for FIR filter) */
 	init_cb_s(&pvt->s_s, (1 << DEFAULT_ALPHA_ST_I), ptr);
-	ptr += (sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) * 2);
+	ptr = (char *) ptr + (sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) * 2);
 
 	init_cb_s(&pvt->u_s, maxu, ptr);
-	ptr += (sizeof(short) * maxu * 2);
+	ptr = (char *) ptr + (sizeof(short) * maxu * 2);
 
 	/* Allocate a buffer for the reference signal power computation */
 	init_cb_s(&pvt->y_tilde_s, pvt->N_d, ptr);
@@ -387,7 +402,7 @@
 }
 
 #ifdef DC_NORMALIZE
-short inline dc_removal(int *dc_estimate, short samp)
+static short inline dc_removal(int *dc_estimate, short samp)
 {
 	*dc_estimate += ((((int)samp << 15) - *dc_estimate) >> 9);
 	return samp - (*dc_estimate >> 15);
@@ -799,7 +814,7 @@
 
 	pvt = kzalloc(size, GFP_KERNEL);
 	if (!pvt)
-		return -ENOMEM;
+		return _RETVAL(ENOMEM);
 
 	pvt->dahdi.ops = &my_ops;
 
@@ -815,7 +830,7 @@
 			printk(KERN_WARNING "Unknown parameter supplied to MG2 echo canceler: '%s'\n", p[x].name);
 			kfree(pvt);
 
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 		}
 	}
 
@@ -867,7 +882,7 @@
 	if (dahdi_register_echocan_factory(&my_factory)) {
 		module_printk(KERN_ERR, "could not register with DAHDI core\n");
 
-		return -EPERM;
+		return _RETVAL(EPERM);
 	}
 
 	module_printk(KERN_NOTICE, "Registered echo canceler '%s'\n", my_factory.name);
@@ -880,6 +895,26 @@
 	dahdi_unregister_echocan_factory(&my_factory);
 }
 
+#if defined(__FreeBSD__)
+static int
+echocan_mg2_modevent(module_t mod __unused, int type, void *data __unused)
+{
+	switch (type) {
+	case MOD_LOAD:
+		return mod_init();
+	case MOD_UNLOAD:
+		mod_exit();
+		return 0;
+	default:
+		return _RETVAL(EOPNOTSUPP);
+	}
+}
+
+DEV_MODULE(dahdi_echocan_mg2, echocan_mg2_modevent, NULL);
+MODULE_VERSION(dahdi_echocan_mg2, 1);
+MODULE_DEPEND(dahdi_echocan_mg2, dahdi, 1, 1, 1);
+
+#else /* !__FreeBSD__ */
 module_param(debug, int, S_IRUGO | S_IWUSR);
 module_param(aggressive, int, S_IRUGO | S_IWUSR);
 
@@ -889,3 +924,4 @@
 
 module_init(mod_init);
 module_exit(mod_exit);
+#endif /* !__FreeBSD__ */
Index: drivers/dahdi/dahdi-base.c
===================================================================
--- drivers/dahdi/dahdi-base.c	(revision 7107)
+++ drivers/dahdi/dahdi-base.c	(working copy)
@@ -34,7 +34,54 @@
  * this program for more details.
  */
 
+#if defined(__FreeBSD__)
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/ctype.h>
+#include <sys/kernel.h>
+#include <sys/fcntl.h>
+#include <sys/ioccom.h>
+#include <sys/libkern.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/poll.h>
+#include <net/ppp_defs.h>
+#include <sys/selinfo.h>
+#include <sys/syscallsubr.h>
 
+#include <machine/stdarg.h>
+
+#include "version.h"
+
+#define module_printk(level, fmt, args...) printf(fmt, ## args)
+
+#define FOP_ARGS_DECL		struct cdev *file
+#define FOP_ARGS		file
+
+#define FOP_OPEN_ARGS_DECL	FOP_ARGS_DECL, int oflags, int devtype, struct thread *td
+#define FOP_OPEN_ARGS		FOP_ARGS, oflags, devtype, td
+#define FOP_CLOSE_ARGS_DECL	FOP_ARGS_DECL, int fflag, int devtype, struct thread *td
+#define FOP_CLOSE_ARGS		FOP_ARGS, fflag, devtype, td
+#define FOP_IOCTL_ARGS_DECL	FOP_ARGS_DECL, u_long cmd, caddr_t data, int fflag, struct thread *td
+#define FOP_IOCTL_ARGS		FOP_ARGS, cmd, data, fflag, td
+
+#define FOP_READ_ARGS_DECL	FOP_ARGS_DECL, struct uio *uio, int ioflag
+#define FOP_READ_ARGS		FOP_ARGS, uio, ioflag
+#define FOP_WRITE_ARGS_DECL	FOP_ARGS_DECL, struct uio *uio, int ioflag
+#define FOP_WRITE_ARGS		FOP_ARGS, uio, ioflag
+#define FOP_POLL_ARGS_DECL	FOP_ARGS_DECL, int events, struct thread *td
+#define FOP_POLL_ARGS		FOP_ARGS, events, td
+#define FOP_MMAP_ARGS_DECL	FOP_ARGS_DECL, vm_offset_t offset, vm_paddr_t *paddr, int nprot
+#define FOP_MMAP_ARGS		FOP_ARGS, offset, paddr, nprot
+
+#define FOP_IO_SUCCESS(nbytes)	0
+
+typedef int read_retval_t;
+typedef int write_retval_t;
+typedef int poll_retval_t;
+
+#else /* !__FreeBSD__ */
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/module.h>
@@ -51,11 +98,44 @@
 
 #include <asm/atomic.h>
 
+#include <dahdi/version.h>
+
 #define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
 
+#define FOP_ARGS_DECL		struct inode *inode, struct file *file
+#define FOP_ARGS		inode, file
+
+#define FOP_OPEN_ARGS_DECL	FOP_ARGS_DECL
+#define FOP_OPEN_ARGS		FOP_ARGS
+#define FOP_CLOSE_ARGS_DECL	FOP_ARGS_DECL
+#define FOP_CLOSE_ARGS		FOP_ARGS
+#define FOP_IOCTL_ARGS_DECL	FOP_ARGS_DECL, unsigned int cmd, unsigned long data
+#define FOP_IOCTL_ARGS		FOP_ARGS, cmd, data
+
+#define FOP_READ_ARGS_DECL	struct file *file, char *usrbuf, size_t count, loff_t *ppos
+#define FOP_READ_ARGS		file, usrbuf, count, ppos
+#define FOP_WRITE_ARGS_DECL	struct file *file, const char *usrbuf, size_t count, loff_t *ppos
+#define FOP_WRITE_ARGS		file, usrbuf, count, ppos
+#define FOP_POLL_ARGS_DECL	struct file *file, struct poll_table_struct *wait_table
+#define FOP_POLL_ARGS		file, wait_table
+#define FOP_MMAP_ARGS_DECL	struct file *file, struct vm_area_struct *vm
+#define FOP_MMAP_ARGS		file, vm
+
+#define FOP_IO_SUCCESS(nbytes)	(nbytes)
+
+typedef ssize_t read_retval_t;
+typedef ssize_t write_retval_t;
+typedef unsigned int poll_retval_t;
+#endif /* !__FreeBSD__ */
+
+#define DAHDI_MINOR_CTL		0
+#define DAHDI_MINOR_TRANSCODE	250
+#define DAHDI_MINOR_TIMER	253
+#define DAHDI_MINOR_CHANNEL	254
+#define DAHDI_MINOR_PSEUDO	255
+
 /* #define BUF_MUNGE */
 
-#include <dahdi/version.h>
 /* Grab fasthdlc with tables */
 #define FAST_HDLC_NEED_TABLES
 #include <dahdi/kernel.h>
@@ -91,9 +171,6 @@
 #define dev_to_ztchan(h) (((struct dahdi_hdlc *)(dev_to_hdlc(h)->priv))->chan)
 #define ztchan_to_dev(h) ((h)->hdlcnetdev->netdev)
 
-/* macro-oni for determining a unit (channel) number */
-#define	UNIT(file) MINOR(file->f_dentry->d_inode->i_rdev)
-
 /* names of tx level settings */
 static char *dahdi_txlevelnames[] = {
 "0 db (CSU)/0-133 feet (DSX-1)",
@@ -106,6 +183,247 @@
 "-22.5db (CSU)"
 } ;
 
+#if defined(__FreeBSD__)
+
+#if 0
+static void rlprintf(int pps, const char *fmt, ...)
+{
+	va_list ap;
+	static struct timeval last_printf;
+	static int count;
+
+	if (ppsratecheck(&last_printf, &count, pps)) {
+		va_start(ap, fmt);
+		vprintf(fmt, ap);
+		va_end(ap);
+	}
+}
+
+#define DPRINTF(fmt, args...)	rlprintf(10, "%s: " fmt, __FUNCTION__, ##args)
+#endif
+
+MALLOC_DEFINE(M_DAHDI, "dahdi", "DAHDI interface data structures");
+
+/*
+ * FCS lookup table as calculated by genfcstab.
+ */
+static u_short fcstab[256] = {
+	0x0000,	0x1189,	0x2312,	0x329b,	0x4624,	0x57ad,	0x6536,	0x74bf,
+	0x8c48,	0x9dc1,	0xaf5a,	0xbed3,	0xca6c,	0xdbe5,	0xe97e,	0xf8f7,
+	0x1081,	0x0108,	0x3393,	0x221a,	0x56a5,	0x472c,	0x75b7,	0x643e,
+	0x9cc9,	0x8d40,	0xbfdb,	0xae52,	0xdaed,	0xcb64,	0xf9ff,	0xe876,
+	0x2102,	0x308b,	0x0210,	0x1399,	0x6726,	0x76af,	0x4434,	0x55bd,
+	0xad4a,	0xbcc3,	0x8e58,	0x9fd1,	0xeb6e,	0xfae7,	0xc87c,	0xd9f5,
+	0x3183,	0x200a,	0x1291,	0x0318,	0x77a7,	0x662e,	0x54b5,	0x453c,
+	0xbdcb,	0xac42,	0x9ed9,	0x8f50,	0xfbef,	0xea66,	0xd8fd,	0xc974,
+	0x4204,	0x538d,	0x6116,	0x709f,	0x0420,	0x15a9,	0x2732,	0x36bb,
+	0xce4c,	0xdfc5,	0xed5e,	0xfcd7,	0x8868,	0x99e1,	0xab7a,	0xbaf3,
+	0x5285,	0x430c,	0x7197,	0x601e,	0x14a1,	0x0528,	0x37b3,	0x263a,
+	0xdecd,	0xcf44,	0xfddf,	0xec56,	0x98e9,	0x8960,	0xbbfb,	0xaa72,
+	0x6306,	0x728f,	0x4014,	0x519d,	0x2522,	0x34ab,	0x0630,	0x17b9,
+	0xef4e,	0xfec7,	0xcc5c,	0xddd5,	0xa96a,	0xb8e3,	0x8a78,	0x9bf1,
+	0x7387,	0x620e,	0x5095,	0x411c,	0x35a3,	0x242a,	0x16b1,	0x0738,
+	0xffcf,	0xee46,	0xdcdd,	0xcd54,	0xb9eb,	0xa862,	0x9af9,	0x8b70,
+	0x8408,	0x9581,	0xa71a,	0xb693,	0xc22c,	0xd3a5,	0xe13e,	0xf0b7,
+	0x0840,	0x19c9,	0x2b52,	0x3adb,	0x4e64,	0x5fed,	0x6d76,	0x7cff,
+	0x9489,	0x8500,	0xb79b,	0xa612,	0xd2ad,	0xc324,	0xf1bf,	0xe036,
+	0x18c1,	0x0948,	0x3bd3,	0x2a5a,	0x5ee5,	0x4f6c,	0x7df7,	0x6c7e,
+	0xa50a,	0xb483,	0x8618,	0x9791,	0xe32e,	0xf2a7,	0xc03c,	0xd1b5,
+	0x2942,	0x38cb,	0x0a50,	0x1bd9,	0x6f66,	0x7eef,	0x4c74,	0x5dfd,
+	0xb58b,	0xa402,	0x9699,	0x8710,	0xf3af,	0xe226,	0xd0bd,	0xc134,
+	0x39c3,	0x284a,	0x1ad1,	0x0b58,	0x7fe7,	0x6e6e,	0x5cf5,	0x4d7c,
+	0xc60c,	0xd785,	0xe51e,	0xf497,	0x8028,	0x91a1,	0xa33a,	0xb2b3,
+	0x4a44,	0x5bcd,	0x6956,	0x78df,	0x0c60,	0x1de9,	0x2f72,	0x3efb,
+	0xd68d,	0xc704,	0xf59f,	0xe416,	0x90a9,	0x8120,	0xb3bb,	0xa232,
+	0x5ac5,	0x4b4c,	0x79d7,	0x685e,	0x1ce1,	0x0d68,	0x3ff3,	0x2e7a,
+	0xe70e,	0xf687,	0xc41c,	0xd595,	0xa12a,	0xb0a3,	0x8238,	0x93b1,
+	0x6b46,	0x7acf,	0x4854,	0x59dd,	0x2d62,	0x3ceb,	0x0e70,	0x1ff9,
+	0xf78f,	0xe606,	0xd49d,	0xc514,	0xb1ab,	0xa022,	0x92b9,	0x8330,
+	0x7bc7,	0x6a4e,	0x58d5,	0x495c,	0x3de3,	0x2c6a,	0x1ef1,	0x0f78
+};
+
+static int
+request_module(const char *fmt, ...)
+{
+	va_list ap;
+	char modname[128];
+	int fileid;
+
+	va_start(ap, fmt);
+	vsnprintf(modname, sizeof(modname), fmt, ap);
+	va_end(ap);
+
+	return kern_kldload(curthread, modname, &fileid);
+}
+
+static void
+handle_selwakeup(void *context, int pending)
+{
+	struct selinfo * sel = context;
+	selwakeup(sel);
+}
+
+/*
+ * Concatenate src on the end of dst.  At most strlen(dst)+n+1 bytes
+ * are written at dst (at most n+1 bytes being appended).  Return dst.
+ */
+static char *
+strncat(char * __restrict dst, const char * __restrict src, size_t n)
+{
+	if (n != 0) {
+		char *d = dst;
+		const char *s = src;
+
+		while (*d != 0)
+			d++;
+		do {
+			if ((*d = *s++) == 0)
+				break;
+			d++;
+		} while (--n != 0);
+		*d = 0;
+	}
+	return (dst);
+}
+
+#define UNIT(file)	minor(file)
+
+struct dahdi_fp {
+	int fflags;		/**< file flags */
+	void *private_data;	/**< private data */
+};
+
+static void
+dahdi_fp_free(void *fp)
+{
+	free(fp, M_DAHDI);
+}
+
+static int
+dahdi_get_fp(struct cdev *dev, struct dahdi_fp **pfp)
+{
+	int error = devfs_get_cdevpriv((void **) pfp);
+	if (error == ENOENT) {
+		*pfp = malloc(sizeof(struct dahdi_fp), M_DAHDI, M_NOWAIT | M_ZERO);
+		if (*pfp == NULL)
+			return _RETVAL(ENOMEM);
+
+		error = devfs_set_cdevpriv(*pfp, dahdi_fp_free);
+		if (error) {
+			dahdi_fp_free(*pfp);
+			return _RETVAL(ENXIO);
+		}
+	} else if (error) {
+		return (error);
+	}
+
+	return 0;
+}
+
+static int
+dahdi_get_flags(struct cdev *dev)
+{
+	int error;
+	struct dahdi_fp *fp;
+
+	error = devfs_get_cdevpriv((void **) &fp);
+	if (error || fp == NULL)
+		return 0;
+
+	return fp->fflags;
+}
+
+static void
+dahdi_set_flags(struct cdev *dev, int fflags)
+{
+	int error;
+	struct dahdi_fp *fp;
+
+	error = dahdi_get_fp(dev, &fp);
+	if (error)
+		return;
+
+	fp->fflags = fflags;
+}
+
+static void *
+dahdi_get_private_data(struct cdev *dev)
+{
+	int error;
+	struct dahdi_fp *fp;
+
+	error = devfs_get_cdevpriv((void **) &fp);
+	if (error || fp == NULL)
+		return NULL;
+
+	return fp->private_data;
+}
+
+static void
+dahdi_set_private_data(struct cdev *dev, void *private_data)
+{
+	int error;
+	struct dahdi_fp *fp;
+
+	error = dahdi_get_fp(dev, &fp);
+	if (error)
+		return;
+
+	fp->private_data = private_data;
+}
+
+static struct cdev *dev_ctl = NULL;
+
+static d_open_t         dahdi_open;
+static d_close_t        dahdi_release;
+static d_read_t         dahdi_read;
+static d_write_t        dahdi_write;
+static d_ioctl_t        dahdi_ioctl;
+static d_poll_t         dahdi_poll;
+static d_mmap_t         dahdi_mmap;
+
+static struct cdevsw dahdi_devsw = {
+	.d_version	= D_VERSION,
+	.d_open		= dahdi_open,
+	.d_close	= dahdi_release,
+	.d_read		= dahdi_read,
+	.d_write	= dahdi_write,
+	.d_ioctl	= dahdi_ioctl,
+	.d_poll		= dahdi_poll,
+	.d_mmap		= dahdi_mmap,
+	.d_name		= "dahdi",
+#if __FreeBSD_version >= 800039
+	.d_flags	= D_PSEUDO | D_TRACKCLOSE | D_NEEDMINOR
+#else
+	.d_flags	= D_PSEUDO | D_TRACKCLOSE
+#endif
+};
+
+#else /* !__FreeBSD__ */
+/* macro-oni for determining a unit (channel) number */
+#define	UNIT(file) MINOR(file->f_dentry->d_inode->i_rdev)
+
+static int
+dahdi_get_flags(struct file *file)
+{
+	if (!file)
+		return 0;
+
+	return file->f_flags;
+}
+
+static void *
+dahdi_get_private_data(struct file *file)
+{
+	return file->private_data;
+}
+
+static void
+dahdi_set_private_data(struct file *file, void *private_data)
+{
+	file->private_data = private_data;
+}
+
 EXPORT_SYMBOL(dahdi_transcode_fops);
 EXPORT_SYMBOL(dahdi_init_tone_state);
 EXPORT_SYMBOL(dahdi_mf_tone);
@@ -186,6 +504,7 @@
 #define class_create class_simple_create
 #define class_destroy class_simple_destroy
 #endif
+#endif /* !__FreeBSD__ */
 
 static int deftaps = 64;
 
@@ -227,8 +546,10 @@
 static sumtype *conf_sums_prev;
 
 static struct dahdi_span *master;
+#if !defined(__FreeBSD__)
 static struct file_operations dahdi_fops;
 struct file_operations *dahdi_transcode_fops = NULL;
+#endif
 
 static struct {
 	int	src;	/* source conf number */
@@ -303,7 +624,7 @@
 	.mfr2_tonelen = DEFAULT_MFR2_LENGTH,
 };
 
-static int dahdi_chan_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data, int unit);
+static int dahdi_chan_ioctl(FOP_IOCTL_ARGS_DECL, int unit);
 
 #if defined(CONFIG_DAHDI_MMX) || defined(ECHO_CAN_FP)
 #if (defined(CONFIG_X86) && !defined(CONFIG_X86_64)) || defined(CONFIG_I386)
@@ -364,10 +685,15 @@
 	int ping;		/* Whether we've been ping'd */
 	int tripped;	/* Whether we're tripped */
 	struct list_head list;
+#if defined(__FreeBSD__)
+	struct selinfo  sel;
+	struct task     selwakeup_task;
+#else
 	wait_queue_head_t sel;
+#endif
 };
 
-static LIST_HEAD(zaptimers);
+static _LIST_HEAD(zaptimers);
 
 #ifdef DEFINE_SPINLOCK
 static DEFINE_SPINLOCK(zaptimerlock);
@@ -416,10 +742,6 @@
 
 static u_char defgain[256];
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
-#define __RW_LOCK_UNLOCKED() RW_LOCK_UNLOCKED
-#endif
-
 #ifdef DEFINE_RWLOCK
 static DEFINE_RWLOCK(zone_lock);
 static DEFINE_RWLOCK(chan_lock);
@@ -435,10 +757,14 @@
 #ifdef DEFINE_RWLOCK
 static DEFINE_RWLOCK(ecfactory_list_lock);
 #else
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
+#define __RW_LOCK_UNLOCKED() RW_LOCK_UNLOCKED
+#endif
+
 static rwlock_t ecfactory_list_lock = __RW_LOCK_UNLOCKED();
 #endif
 
-static LIST_HEAD(ecfactory_list);
+static _LIST_HEAD(ecfactory_list);
 
 struct ecfactory {
 	const struct dahdi_echocan_factory *ec;
@@ -449,7 +775,9 @@
 {
 	struct ecfactory *cur;
 
+#if !defined(__FreeBSD__)
 	WARN_ON(!ec->owner);
+#endif
 
 	write_lock(&ecfactory_list_lock);
 
@@ -457,13 +785,13 @@
 	list_for_each_entry(cur, &ecfactory_list, list) {
 		if (cur->ec == ec) {
 			write_unlock(&ecfactory_list_lock);
-			return -EPERM;
+			return _RETVAL(EPERM);
 		}
 	}
 
 	if (!(cur = kzalloc(sizeof(*cur), GFP_KERNEL))) {
 		write_unlock(&ecfactory_list_lock);
-		return -ENOMEM;
+		return _RETVAL(ENOMEM);
 	}
 
 	cur->ec = ec;
@@ -887,7 +1215,11 @@
 
 	wake_up_interruptible(&chan->readbufq);
 	wake_up_interruptible(&chan->writebufq);
+#if defined(__FreeBSD__)
+	taskqueue_enqueue_fast(taskqueue_fast, &chan->selwakeup_task);
+#else
 	wake_up_interruptible(&chan->sel);
+#endif
 
 	return;
 }
@@ -908,6 +1240,15 @@
 /* sleep in user space until woken up. Equivilant of tsleep() in BSD */
 static int schluffen(wait_queue_head_t *q)
 {
+#if defined(__FreeBSD__)
+	int rc = tsleep(q, PZERO | PCATCH, "schluffen", 10);
+	switch (rc) {
+	case EINTR:
+	case ERESTART:
+		return rc;
+	}
+	return 0;
+#else /* !__FreeBSD__ */
 	DECLARE_WAITQUEUE(wait, current);
 
 	add_wait_queue(q, &wait);
@@ -920,9 +1261,10 @@
 	remove_wait_queue(q, &wait);
 
 	if (signal_pending(current))
-		return -ERESTARTSYS;
+		return _RETVAL(ERESTARTSYS);
 
 	return 0;
+#endif /* !__FreeBSD__ */
 }
 
 static inline void calc_fcs(struct dahdi_chan *ss, int inwritebuf)
@@ -961,7 +1303,7 @@
 	/* We need to allocate our buffers now */
 	if (j) {
 		if (!(newbuf = kcalloc(j * 2, numbufs, GFP_KERNEL)))
-			return -ENOMEM;
+			return _RETVAL(ENOMEM);
 	} else
 		newbuf = NULL;
 
@@ -1168,13 +1510,14 @@
 
 	list_for_each_entry(cur, &ecfactory_list, list) {
 		if (!strcmp(name_upper, cur->ec->name)) {
-			if (try_module_get(cur->ec->owner)) {
+#if !defined(__FreeBSD__)
+			if (!try_module_get(cur->ec->owner)) {
 				read_unlock(&ecfactory_list_lock);
-				return cur->ec;
-			} else {
-				read_unlock(&ecfactory_list_lock);
 				return NULL;
 			}
+#endif /* !__FreeBSD__ */
+			read_unlock(&ecfactory_list_lock);
+			return cur->ec;
 		}
 	}
 
@@ -1200,9 +1543,12 @@
 
 static void release_echocan(const struct dahdi_echocan_factory *ec)
 {
-	if (ec)
+	if (ec) {
+#if !defined(__FreeBSD__)
 		module_put(ec->owner);
+#endif
 }
+}
 
 /** 
  * close_channel - close the channel, resetting any channel variables
@@ -1323,7 +1669,7 @@
 	int res = 0;
 
 	if ((num >= DAHDI_TONE_ZONE_MAX) || (num < 0))
-		return -EINVAL;
+		return _RETVAL(EINVAL);
 
 	write_lock(&zone_lock);
 	if (tone_zones[num]) {
@@ -1331,7 +1677,7 @@
 			z = tone_zones[num];
 			tone_zones[num] = NULL;
 		} else {
-			res = -EBUSY;
+			res = _RETVAL(EBUSY);
 		}
 	}
 	write_unlock(&zone_lock);
@@ -1347,11 +1693,11 @@
 	int res = 0;
 
 	if ((num >= DAHDI_TONE_ZONE_MAX) || (num < 0))
-		return -EINVAL;
+		return _RETVAL(EINVAL);
 
 	write_lock(&zone_lock);
 	if (tone_zones[num]) {
-		res = -EINVAL;
+		res = _RETVAL(EINVAL);
 	} else {
 		res = 0;
 		tone_zones[num] = zone;
@@ -1370,7 +1716,7 @@
 	int base, max;
 
 	if (!chan->curzone)
-		return -ENODATA;
+		return _RETVAL(ENODATA);
 
 	switch (chan->digitmode) {
 	case DIGIT_MODE_DTMF:
@@ -1388,11 +1734,11 @@
 		max = DAHDI_TONE_MFR2_REV_MAX;
 		break;
 	default:
-		return -EINVAL;
+		return _RETVAL(EINVAL);
 	}
 
 	if ((tone < base) || (tone > max))
-		return -EINVAL;
+		return _RETVAL(EINVAL);
 
 	switch (chan->digitmode) {
 	case DIGIT_MODE_DTMF:
@@ -1407,7 +1753,7 @@
 	}
 
 	if (!playtone || !playtone->tonesamples)
-		return -ENOSYS;
+		return _RETVAL(ENOSYS);
 
 	chan->curtone = playtone;
 
@@ -1416,7 +1762,7 @@
 
 static int start_tone(struct dahdi_chan *chan, int tone)
 {
-	int res = -EINVAL;
+	int res = _RETVAL(EINVAL);
 
 	/* Stop the current tone, no matter what */
 	chan->tonep = 0;
@@ -1436,14 +1782,14 @@
 			module_printk(KERN_WARNING, "DAHDI: Cannot start tones until tone zone is loaded.\n");
 		}
 		/* Note that no tone zone exists at the moment */
-		res = -ENODATA;
+		res = _RETVAL(ENODATA);
 	} else if ((tone >= 0 && tone <= DAHDI_TONE_MAX)) {
 		/* Have a tone zone */
 		if (chan->curzone->tones[tone]) {
 			chan->curtone = chan->curzone->tones[tone];
 			res = 0;
 		} else { /* Indicate that zone is loaded but no such tone exists */
-			res = -ENOSYS;
+			res = _RETVAL(ENOSYS);
 		}
 	} else if (chan->digitmode == DIGIT_MODE_DTMF ||
 			chan->digitmode == DIGIT_MODE_MFR2_FWD ||
@@ -1451,7 +1797,7 @@
 		res = start_tone_digit(chan, tone);
 	} else {
 		chan->dialing = 0;
-		res = -EINVAL;
+		res = _RETVAL(EINVAL);
 	}
 
 	if (chan->curtone)
@@ -1471,7 +1817,7 @@
 		zone = default_zone;
 
 	if ((zone >= DAHDI_TONE_ZONE_MAX) || (zone < 0))
-		return -EINVAL;
+		return _RETVAL(EINVAL);
 
 	read_lock(&zone_lock);
 
@@ -1490,7 +1836,7 @@
 
 		spin_unlock_irqrestore(&chan->lock, flags);
 	} else {
-		res = -ENODATA;
+		res = _RETVAL(ENODATA);
 	}
 
 	read_unlock(&zone_lock);
@@ -1532,6 +1878,9 @@
 	might_sleep();
 
 	spin_lock_init(&chan->lock);
+#if defined(__FreeBSD__)
+	TASK_INIT(&chan->selwakeup_task, 0, handle_selwakeup, &chan->sel);
+#endif
 	if (!chan->master)
 		chan->master = chan;
 	if (!chan->readchunk)
@@ -1560,7 +1909,7 @@
 	if (DAHDI_MAX_CHANNELS == x) {
 		write_unlock_irqrestore(&chan_lock, flags);
 		module_printk(KERN_ERR, "No more channels available\n");
-		return -ENOMEM;
+		return _RETVAL(ENOMEM);
 	}
 
 	return 0;
@@ -1606,15 +1955,15 @@
 #endif
 	if (!ms) {
 		module_printk(KERN_NOTICE, "dahdi_net_open: nothing??\n");
-		return -EINVAL;
+		return _RETVAL(EINVAL);
 	}
 	if (test_bit(DAHDI_FLAGBIT_OPEN, &ms->flags)) {
 		module_printk(KERN_NOTICE, "%s is already open!\n", ms->name);
-		return -EBUSY;
+		return _RETVAL(EBUSY);
 	}
 	if (!(ms->flags & DAHDI_FLAG_NETDEV)) {
 		module_printk(KERN_NOTICE, "%s is not a net device!\n", ms->name);
-		return -EINVAL;
+		return _RETVAL(EINVAL);
 	}
 	ms->txbufpolicy = DAHDI_POLICY_IMMEDIATE;
 	ms->rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
@@ -1645,7 +1994,7 @@
 	}
 	result = register_netdev(dev);
 	if (result != 0)
-		return -EIO;
+		return _RETVAL(EIO);
 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,14)
 	if (netif_carrier_ok(dev))
 		netif_carrier_off(dev); /* no carrier until DCD goes up */
@@ -1708,14 +2057,14 @@
             encoding != ENCODING_FM_MARK &&
             encoding != ENCODING_FM_SPACE &&
             encoding != ENCODING_MANCHESTER)
-                return -EINVAL;
+                return _RETVAL(EINVAL);
 
         if (parity != PARITY_NONE &&
             parity != PARITY_CRC16_PR0_CCITT &&
             parity != PARITY_CRC16_PR1_CCITT &&
             parity != PARITY_CRC32_PR0_CCITT &&
             parity != PARITY_CRC32_PR1_CCITT)
-                return -EINVAL;
+                return _RETVAL(EINVAL);
 
         dpriv->encoding = encoding;
         dpriv->parity = parity;*/
@@ -1805,7 +2154,7 @@
 #else
 static int dahdi_net_ioctl(hdlc_device *hdlc, struct ifreq *ifr, int cmd)
 {
-	return -EIO;
+	return _RETVAL(EIO);
 }
 #endif
 
@@ -1899,7 +2248,7 @@
 
 static int dahdi_ppp_ioctl(struct ppp_channel *ppp, unsigned int cmd, unsigned long flags)
 {
-	return -EIO;
+	return _RETVAL(EIO);
 }
 
 static struct ppp_channel_ops ztppp_ops =
@@ -1967,10 +2316,14 @@
 			}
 		}
 	chan->channo = -1;
+	spin_lock_destroy(&chan->lock);
+#if defined(__FreeBSD__)
+	taskqueue_drain(taskqueue_fast, &chan->selwakeup_task);
+#endif
 	write_unlock_irqrestore(&chan_lock, flags);
 }
 
-static ssize_t dahdi_chan_read(struct file *file, char *usrbuf, size_t count, int unit)
+static ssize_t dahdi_chan_read(FOP_READ_ARGS_DECL, int unit)
 {
 	struct dahdi_chan *chan = chans[unit];
 	int amnt;
@@ -1979,19 +2332,26 @@
 	unsigned long flags;
 
 	/* Make sure count never exceeds 65k, and make sure it's unsigned */
+#if defined(__FreeBSD__)
+	int count = uio->uio_resid & 0xfffff;
+#else
+	int ioflag = file->f_flags;
 	count &= 0xffff;
+#endif
+	if (count < 0)
+		return _RETVAL(EINVAL);
 
 	if (!chan)
-		return -EINVAL;
+		return _RETVAL(EINVAL);
 
 	if (count < 1)
-		return -EINVAL;
+		return _RETVAL(EINVAL);
 
 	for (;;) {
 		spin_lock_irqsave(&chan->lock, flags);
 		if (chan->eventinidx != chan->eventoutidx) {
 			spin_unlock_irqrestore(&chan->lock, flags);
-			return -ELAST /* - chan->eventbuf[chan->eventoutidx]*/;
+			return _RETVAL(ELAST) /* - chan->eventbuf[chan->eventoutidx]*/;
 		}
 		res = chan->outreadbuf;
 		if (chan->rxdisable)
@@ -1999,8 +2359,8 @@
 		spin_unlock_irqrestore(&chan->lock, flags);
 		if (res >= 0)
 			break;
-		if (file->f_flags & O_NONBLOCK)
-			return -EAGAIN;
+		if (ioflag & O_NONBLOCK)
+			return _RETVAL(EAGAIN);
 		rv = schluffen(&chan->readbufq);
 		if (rv)
 			return rv;
@@ -2039,8 +2399,12 @@
 					pass = 128;
 				for (x = 0; x < pass; x++)
 					lindata[x] = DAHDI_XLAW(chan->readbuf[res][x + pos], chan);
+#if defined(__FreeBSD__)
+				if (uiomove(lindata, pass << 1, uio))
+#else
 				if (copy_to_user(usrbuf + (pos << 1), lindata, pass << 1))
-					return -EFAULT;
+#endif
+					return _RETVAL(EFAULT);
 				left -= pass;
 				pos += pass;
 			}
@@ -2049,8 +2413,12 @@
 		if (amnt > chan->readn[res])
 			amnt = chan->readn[res];
 		if (amnt) {
+#if defined(__FreeBSD__)
+			if (uiomove(chan->readbuf[res], amnt, uio))
+#else
 			if (copy_to_user(usrbuf, chan->readbuf[res], amnt))
-				return -EFAULT;
+#endif
+				return _RETVAL(EFAULT);
 		}
 	}
 	spin_lock_irqsave(&chan->lock, flags);
@@ -2070,7 +2438,7 @@
 	}
 	spin_unlock_irqrestore(&chan->lock, flags);
 
-	return amnt;
+	return FOP_IO_SUCCESS(amnt);
 }
 
 static int num_filled_bufs(struct dahdi_chan *chan)
@@ -2096,20 +2464,27 @@
 	return range1 + range2;
 }
 
-static ssize_t dahdi_chan_write(struct file *file, const char *usrbuf, size_t count, int unit)
+static ssize_t dahdi_chan_write(FOP_WRITE_ARGS_DECL, int unit)
 {
 	unsigned long flags;
 	struct dahdi_chan *chan = chans[unit];
 	int res, amnt, oldbuf, rv, x;
 
 	/* Make sure count never exceeds 65k, and make sure it's unsigned */
+#if defined(__FreeBSD__)
+	int count = uio->uio_resid & 0xfffff;
+#else
+	int ioflag = file->f_flags;
 	count &= 0xffff;
+#endif
+	if (count < 0)
+		return _RETVAL(EINVAL);
 
 	if (!chan)
-		return -EINVAL;
+		return _RETVAL(EINVAL);
 
 	if (count < 1) {
-		return -EINVAL;
+		return _RETVAL(EINVAL);
 	}
 
 	for (;;) {
@@ -2123,17 +2498,17 @@
 		}
 		if (chan->eventinidx != chan->eventoutidx) {
 			spin_unlock_irqrestore(&chan->lock, flags);
-			return -ELAST;
+			return _RETVAL(ELAST);
 		}
 		res = chan->inwritebuf;
 		spin_unlock_irqrestore(&chan->lock, flags);
 		if (res >= 0)
 			break;
-		if (file->f_flags & O_NONBLOCK) {
+		if (ioflag & O_NONBLOCK) {
 #ifdef BUFFER_DEBUG
 			printk("Error: Nonblock\n");
 #endif
-			return -EAGAIN;
+			return _RETVAL(EAGAIN);
 		}
 		/* Wait for something to be available */
 		rv = schluffen(&chan->writebufq);
@@ -2177,9 +2552,12 @@
 				pass = left;
 				if (pass > 128)
 					pass = 128;
-				if (copy_from_user(lindata, usrbuf + (pos << 1), pass << 1)) {
-					return -EFAULT;
-				}
+#if defined(__FreeBSD__)
+				if (uiomove(lindata, pass << 1, uio))
+#else
+				if (copy_from_user(lindata, usrbuf + (pos << 1), pass << 1))
+#endif
+					return _RETVAL(EFAULT);
 				left -= pass;
 				for (x = 0; x < pass; x++)
 					chan->writebuf[res][x + pos] = DAHDI_LIN2X(lindata[x], chan);
@@ -2187,9 +2565,12 @@
 			}
 			chan->writen[res] = amnt >> 1;
 		} else {
-			if (copy_from_user(chan->writebuf[res], usrbuf, amnt)) {
-				return -EFAULT;
-			}
+#if defined(__FreeBSD__)
+			if (uiomove(chan->writebuf[res], amnt, uio))
+#else
+			if (copy_from_user(chan->writebuf[res], usrbuf, amnt))
+#endif
+				return _RETVAL(EFAULT);
 			chan->writen[res] = amnt;
 		}
 		chan->writeidx[res] = 0;
@@ -2234,28 +2615,28 @@
 		if (chan->flags & DAHDI_FLAG_NOSTDTXRX && chan->span->hdlc_hard_xmit)
 			chan->span->hdlc_hard_xmit(chan);
 	}
-	return amnt;
+	return FOP_IO_SUCCESS(amnt);
 }
 
-static int dahdi_ctl_open(struct inode *inode, struct file *file)
+static int dahdi_ctl_open(FOP_ARGS_DECL)
 {
 	/* Nothing to do, really */
 	return 0;
 }
 
-static int dahdi_chan_open(struct inode *inode, struct file *file)
+static int dahdi_chan_open(FOP_ARGS_DECL)
 {
 	/* Nothing to do here for now either */
 	return 0;
 }
 
-static int dahdi_ctl_release(struct inode *inode, struct file *file)
+static int dahdi_ctl_release(FOP_ARGS_DECL)
 {
 	/* Nothing to do */
 	return 0;
 }
 
-static int dahdi_chan_release(struct inode *inode, struct file *file)
+static int dahdi_chan_release(FOP_ARGS_DECL)
 {
 	/* Nothing to do for now */
 	return 0;
@@ -2426,7 +2807,7 @@
 
 	/* Can't hang up a clear channel */
 	if (chan->flags & (DAHDI_FLAG_CLEAR | DAHDI_FLAG_NOSTDTXRX))
-		return -EINVAL;
+		return _RETVAL(EINVAL);
 
 	chan->kewlonhook = 0;
 
@@ -2615,17 +2996,20 @@
 	return 0;
 }
 
-static int dahdi_timing_open(struct inode *inode, struct file *file)
+static int dahdi_timing_open(FOP_ARGS_DECL)
 {
 	struct dahdi_timer *t;
 	unsigned long flags;
 
 	if (!(t = kzalloc(sizeof(*t), GFP_KERNEL)))
-		return -ENOMEM;
+		return _RETVAL(ENOMEM);
 
 	init_waitqueue_head(&t->sel);
 	INIT_LIST_HEAD(&t->list);
-	file->private_data = t;
+#if defined(__FreeBSD__)
+	TASK_INIT(&t->selwakeup_task, 0, handle_selwakeup, &t->sel);
+#endif
+	dahdi_set_private_data(file, t);
 
 	spin_lock_irqsave(&zaptimerlock, flags);
 	list_add(&t->list, &zaptimers);
@@ -2634,12 +3018,13 @@
 	return 0;
 }
 
-static int dahdi_timer_release(struct inode *inode, struct file *file)
+static int dahdi_timer_release(FOP_ARGS_DECL)
 {
-	struct dahdi_timer *t, *cur, *next;
+	struct dahdi_timer *t;
+	struct dahdi_timer *cur, *next;
 	unsigned long flags;
 
-	if (!(t = file->private_data))
+	if (!(t = dahdi_get_private_data(file)))
 		return 0;
 
 	spin_lock_irqsave(&zaptimerlock, flags);
@@ -2658,12 +3043,15 @@
 		return 0;
 	}
 
+#if defined(__FreeBSD__)
+	taskqueue_drain(taskqueue_fast, &t->selwakeup_task);
+#endif
 	kfree(cur);
 
 	return 0;
 }
 
-static int dahdi_specchan_open(struct inode *inode, struct file *file, int unit)
+static int dahdi_specchan_open(FOP_ARGS_DECL, int unit)
 {
 	int res = 0;
 	struct dahdi_chan *const chan = chans[unit];
@@ -2671,11 +3059,11 @@
 	if (chan && chan->sig) {
 		/* Make sure we're not already open, a net device, or a slave device */
 		if (chan->flags & DAHDI_FLAG_NETDEV)
-			res = -EBUSY;
+			res = _RETVAL(EBUSY);
 		else if (chan->master != chan)
-			res = -EBUSY;
+			res = _RETVAL(EBUSY);
 		else if ((chan->sig & __DAHDI_SIG_DACS) == __DAHDI_SIG_DACS)
-			res = -EBUSY;
+			res = _RETVAL(EBUSY);
 		else if (!test_and_set_bit(DAHDI_FLAGBIT_OPEN, &chan->flags)) {
 			unsigned long flags;
 			res = initialize_channel(chan);
@@ -2688,9 +3076,11 @@
 			if (chan->flags & DAHDI_FLAG_PSEUDO)
 				chan->flags |= DAHDI_FLAG_AUDIO;
 			if (chan->span) {
+#if !defined(__FreeBSD__)
 				if (!try_module_get(chan->span->owner))
-					res = -ENXIO;
-				else if (chan->span->open)
+					return _RETVAL(ENXIO);
+#endif
+				if (chan->span->open)
 					res = chan->span->open(chan);
 			}
 			if (!res) {
@@ -2702,14 +3092,14 @@
 				clear_bit(DAHDI_FLAGBIT_OPEN, &chan->flags);
 			}
 		} else {
-			res = -EBUSY;
+			res = _RETVAL(EBUSY);
 		}
 	} else
-		res = -ENXIO;
+		res = _RETVAL(ENXIO);
 	return res;
 }
 
-static int dahdi_specchan_release(struct inode *node, struct file *file, int unit)
+static int dahdi_specchan_release(FOP_ARGS_DECL, int unit)
 {
 	int res=0;
 	unsigned long flags;
@@ -2723,17 +3113,22 @@
 		spin_unlock_irqrestore(&chan->lock, flags);
 		close_channel(chan);
 		if (chan->span) {
+#if !defined(__FreeBSD__)
 			struct module *owner = chan->span->owner;
+#endif
 
 			if (chan->span->close)
 				res = chan->span->close(chan);
+#if !defined(__FreeBSD__)
 			module_put(owner);
+#endif
 		}
 		/* The channel might be destroyed by low-level driver span->close() */
 		if (chans[unit])
 			clear_bit(DAHDI_FLAGBIT_OPEN, &chans[unit]->flags);
 	} else
-		res = -ENXIO;
+		res = _RETVAL(ENXIO);
+
 	return res;
 }
 
@@ -2780,24 +3175,27 @@
 	}
 }
 
-static int dahdi_open(struct inode *inode, struct file *file)
+static int dahdi_open(FOP_OPEN_ARGS_DECL)
 {
 	int unit = UNIT(file);
+	int res;
 	struct dahdi_chan *chan;
+
 	/* Minor 0: Special "control" descriptor */
 	if (!unit)
-		return dahdi_ctl_open(inode, file);
-	if (unit == 250) {
+		return dahdi_ctl_open(FOP_ARGS);
+	if (unit == DAHDI_MINOR_TRANSCODE) {
+#if !defined(__FreeBSD__)
 		if (!dahdi_transcode_fops) {
 			if (request_module("dahdi_transcode")) {
-				return -ENXIO;
+				return _RETVAL(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;
+			return _RETVAL(ENXIO);
 		}
 #endif
 		if (dahdi_transcode_fops && dahdi_transcode_fops->open) {
@@ -2807,28 +3205,35 @@
 			 * file_operations table. */
 			 WARN_ON(1);
 		}
-		return -ENXIO;
+#endif /* !__FreeBSD__ */
+		return _RETVAL(ENXIO);
 	}
-	if (unit == 253) {
+	if (unit == DAHDI_MINOR_TIMER) {
 		if (can_open_timer()) {
-			return dahdi_timing_open(inode, file);
+			return dahdi_timing_open(FOP_ARGS);
 		} else {
-			return -ENXIO;
+			return _RETVAL(ENXIO);
 		}
 	}
-	if (unit == 254)
-		return dahdi_chan_open(inode, file);
-	if (unit == 255) {
+	if (unit == DAHDI_MINOR_CHANNEL)
+		return dahdi_chan_open(FOP_ARGS);
+	if (unit == DAHDI_MINOR_PSEUDO) {
 		chan = dahdi_alloc_pseudo();
-		if (chan) {
-			file->private_data = chan;
-			return dahdi_specchan_open(inode, file, chan->channo);
-		} else {
-			return -ENXIO;
+		if (!chan)
+			return _RETVAL(ENXIO);
+
+		res = dahdi_specchan_open(FOP_ARGS, chan->channo);
+		if (res != 0)
+			return res;
+		dahdi_set_private_data(file, chan);
+#if defined(__FreeBSD__)
+		dahdi_set_flags(file, oflags);
+#endif
+		return (res);
 		}
+
+	return dahdi_specchan_open(FOP_ARGS, unit);
 	}
-	return dahdi_specchan_open(inode, file, unit);
-}
 
 #if 0
 static int dahdi_open(struct inode *inode, struct file *file)
@@ -2842,77 +3247,72 @@
 }
 #endif
 
-static ssize_t dahdi_read(struct file *file, char *usrbuf, size_t count, loff_t *ppos)
+static read_retval_t dahdi_read(FOP_READ_ARGS_DECL)
 {
 	int unit = UNIT(file);
 	struct dahdi_chan *chan;
 
 	/* Can't read from control */
 	if (!unit) {
-		return -EINVAL;
+		return _RETVAL(EINVAL);
 	}
 
-	if (unit == 253)
-		return -EINVAL;
+	if (unit == DAHDI_MINOR_TIMER)
+		return _RETVAL(EINVAL);
 
-	if (unit == 254) {
-		chan = file->private_data;
+	if (unit == DAHDI_MINOR_CHANNEL) {
+		chan = dahdi_get_private_data(file);
 		if (!chan)
-			return -EINVAL;
-		return dahdi_chan_read(file, usrbuf, count, chan->channo);
+			return _RETVAL(EINVAL);
+		return dahdi_chan_read(FOP_READ_ARGS, chan->channo);
 	}
 
-	if (unit == 255) {
-		chan = file->private_data;
+	if (unit == DAHDI_MINOR_PSEUDO) {
+		chan = dahdi_get_private_data(file);
 		if (!chan) {
 			module_printk(KERN_NOTICE, "No pseudo channel structure to read?\n");
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 		}
-		return dahdi_chan_read(file, usrbuf, count, chan->channo);
+		return dahdi_chan_read(FOP_READ_ARGS, chan->channo);
 	}
-	if (count < 0)
-		return -EINVAL;
 
-	return dahdi_chan_read(file, usrbuf, count, unit);
+	return dahdi_chan_read(FOP_READ_ARGS, unit);
 }
 
-static ssize_t dahdi_write(struct file *file, const char *usrbuf, size_t count, loff_t *ppos)
+static write_retval_t dahdi_write(FOP_WRITE_ARGS_DECL)
 {
 	int unit = UNIT(file);
 	struct dahdi_chan *chan;
 	/* Can't read from control */
 	if (!unit)
-		return -EINVAL;
-	if (count < 0)
-		return -EINVAL;
-	if (unit == 253)
-		return -EINVAL;
-	if (unit == 254) {
-		chan = file->private_data;
+		return _RETVAL(EINVAL);
+	if (unit == DAHDI_MINOR_TIMER)
+		return _RETVAL(EINVAL);
+	if (unit == DAHDI_MINOR_CHANNEL) {
+		chan = dahdi_get_private_data(file);
 		if (!chan)
-			return -EINVAL;
-		return dahdi_chan_write(file, usrbuf, count, chan->channo);
+			return _RETVAL(EINVAL);
+		return dahdi_chan_write(FOP_WRITE_ARGS, chan->channo);
 	}
-	if (unit == 255) {
-		chan = file->private_data;
+	if (unit == DAHDI_MINOR_PSEUDO) {
+		chan = dahdi_get_private_data(file);
 		if (!chan) {
 			module_printk(KERN_NOTICE, "No pseudo channel structure to read?\n");
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 		}
-		return dahdi_chan_write(file, usrbuf, count, chan->channo);
+		return dahdi_chan_write(FOP_WRITE_ARGS, chan->channo);
 	}
-	return dahdi_chan_write(file, usrbuf, count, unit);
-
+	return dahdi_chan_write(FOP_WRITE_ARGS, unit);
 }
 
 static int dahdi_set_default_zone(int defzone)
 {
 	if ((defzone < 0) || (defzone >= DAHDI_TONE_ZONE_MAX))
-		return -EINVAL;
+		return _RETVAL(EINVAL);
 	write_lock(&zone_lock);
 	if (!tone_zones[defzone]) {
 		write_unlock(&zone_lock);
-		return -EINVAL;
+		return _RETVAL(EINVAL);
 	}
 	if ((default_zone != -1) && tone_zones[default_zone])
 		atomic_dec(&tone_zones[default_zone]->refcount);
@@ -2933,7 +3333,7 @@
    format is much simpler (an array structure field of the zone
    structure, rather an array of pointers).
 */
-static int ioctl_load_zone(unsigned long data)
+static int ioctl_load_zone(FOP_IOCTL_ARGS_DECL)
 {
 	struct load_zone_workarea {
 		struct dahdi_tone *samples[MAX_TONES];
@@ -2952,12 +3352,16 @@
 
 	work = kzalloc(sizeof(*work), GFP_KERNEL);
 	if (!work)
-		return -ENOMEM;
+		return _RETVAL(ENOMEM);
 
-	if (copy_from_user(&work->th, (struct dahdi_tone_def_header *)data,
-	    sizeof(work->th))) {
+#if defined(__FreeBSD__)
+	bcopy(data, &data, sizeof(void *));
+	if (copyin(data, &work->th, sizeof(work->th))) {
+#else
+	if (copy_from_user(&work->th, (struct dahdi_tone_def_header *)data, sizeof(work->th))) {
+#endif
 		kfree(work);
-		return -EFAULT;
+		return _RETVAL(EFAULT);
 	}
 
 	data += sizeof(work->th);
@@ -2965,23 +3369,23 @@
 	if ((work->th.count < 0) || (work->th.count > MAX_TONES)) {
 		module_printk(KERN_NOTICE, "Too many tones included\n");
 		kfree(work);
-		return -EINVAL;
+		return _RETVAL(EINVAL);
 	}
 
 	space = size = sizeof(*z) + work->th.count * sizeof(*t);
 
 	if (size > MAX_SIZE) {
 		kfree(work);
-		return -E2BIG;
+		return _RETVAL(E2BIG);
 	}
 
 	z = ptr = slab = kzalloc(size, GFP_KERNEL);
 	if (!z) {
 		kfree(work);
-		return -ENOMEM;
+		return _RETVAL(ENOMEM);
 	}
 
-	ptr += sizeof(*z);
+	ptr = (char *) ptr + sizeof(*z);
 	space -= sizeof(*z);
 
 	dahdi_copy_string(z->name, work->th.name, sizeof(z->name));
@@ -3004,15 +3408,18 @@
 			kfree(slab);
 			kfree(work);
 			module_printk(KERN_NOTICE, "Insufficient tone zone space\n");
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 		}
 
-		res = copy_from_user(&work->td, (struct dahdi_tone_def *)data,
-				     sizeof(work->td));
+#if defined(__FreeBSD__)
+		res = copyin(data, &work->td, sizeof(work->td));
+#else
+		res = copy_from_user(&work->td, (struct dahdi_tone_def *)data, sizeof(work->td));
+#endif
 		if (res) {
 			kfree(slab);
 			kfree(work);
-			return -EFAULT;
+			return _RETVAL(EFAULT);
 		}
 
 		data += sizeof(work->td);
@@ -3023,7 +3430,7 @@
 			t = work->samples[x] = ptr;
 
 			space -= sizeof(*t);
-			ptr += sizeof(*t);
+			ptr = (char *) ptr + sizeof(*t);
 
 			/* Remember which sample is work->next */
 			work->next[x] = work->td.next;
@@ -3036,7 +3443,7 @@
 					      work->next[x]);
 				kfree(slab);
 				kfree(work);
-				return -EINVAL;
+				return _RETVAL(EINVAL);
 			}
 		} else if ((work->td.tone >= DAHDI_TONE_DTMF_BASE) &&
 			   (work->td.tone <= DAHDI_TONE_DTMF_MAX)) {
@@ -3064,7 +3471,7 @@
 				      work->td.tone);
 			kfree(slab);
 			kfree(work);
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 		}
 
 		t->fac1 = work->td.fac1;
@@ -3340,6 +3747,7 @@
 				chan->tonep = 0;
 				if (chan->curtone) {
 					dahdi_init_tone_state(&chan->ts, chan->curtone);
+
 					return;
 				}
 			}
@@ -3351,47 +3759,50 @@
 	__qevent(chan, DAHDI_EVENT_DIALCOMPLETE);
 }
 
-static int dahdi_release(struct inode *inode, struct file *file)
+static int dahdi_release(FOP_CLOSE_ARGS_DECL)
 {
 	int unit = UNIT(file);
 	int res;
 	struct dahdi_chan *chan;
 
-	if (!unit)
-		return dahdi_ctl_release(inode, file);
-	if (unit == 253) {
-		return dahdi_timer_release(inode, file);
-	}
-	if (unit == 250) {
+	if (!unit) {
+		res = dahdi_ctl_release(FOP_ARGS);
+	} else if (unit == DAHDI_MINOR_TIMER) {
+		res = dahdi_timer_release(FOP_ARGS);
+	} else if (unit == DAHDI_MINOR_TRANSCODE) {
 		/* 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;
+		res = _RETVAL(EFAULT);
+	} else if (unit == DAHDI_MINOR_CHANNEL) {
+		chan = dahdi_get_private_data(file);
 		if (!chan)
-			return dahdi_chan_release(inode, file);
+			res = dahdi_chan_release(FOP_ARGS);
 		else
-			return dahdi_specchan_release(inode, file, chan->channo);
-	}
-	if (unit == 255) {
-		chan = file->private_data;
+			res = dahdi_specchan_release(FOP_ARGS, chan->channo);
+	} else if (unit == DAHDI_MINOR_PSEUDO) {
+		chan = dahdi_get_private_data(file);
 		if (chan) {
-			res = dahdi_specchan_release(inode, file, chan->channo);
+			res = dahdi_specchan_release(FOP_ARGS, chan->channo);
 			dahdi_free_pseudo(chan);
 		} else {
 			module_printk(KERN_NOTICE, "Pseudo release and no private data??\n");
 			res = 0;
 		}
-		return res;
+	} else {
+		res = dahdi_specchan_release(FOP_ARGS, unit);
 	}
-	return dahdi_specchan_release(inode, file, unit);
+
+#if defined(__FreeBSD__)
+	if (res == 0)
+		devfs_clear_cdevpriv();
+#endif
+	return (res);
 }
 
 #if 0
-static int dahdi_release(struct inode *inode, struct file *file)
+static int dahdi_release(FOP_CLOSE_ARGS)
 {
 	/* Lock the big zap lock when handling a release */
 	unsigned long flags;
@@ -3446,26 +3857,26 @@
 
 #define VALID_SPAN(j) do { \
 	if ((j >= DAHDI_MAX_SPANS) || (j < 1)) \
-		return -EINVAL; \
+		return _RETVAL(EINVAL); \
 	if (!spans[j]) \
-		return -ENXIO; \
+		return _RETVAL(ENXIO); \
 } while(0)
 
 #define CHECK_VALID_SPAN(j) do { \
 	/* Start a given span */ \
 	if (get_user(j, (int *)data)) \
-		return -EFAULT; \
+		return _RETVAL(EFAULT); \
 	VALID_SPAN(j); \
 } while(0)
 
 #define VALID_CHANNEL(j) do { \
 	if ((j >= DAHDI_MAX_CHANNELS) || (j < 1)) \
-		return -EINVAL; \
+		return _RETVAL(EINVAL); \
 	if (!chans[j]) \
-		return -ENXIO; \
+		return _RETVAL(ENXIO); \
 } while(0)
 
-static int dahdi_timer_ioctl(struct inode *node, struct file *file, unsigned int cmd, unsigned long data, struct dahdi_timer *timer)
+static int dahdi_timer_ioctl(FOP_IOCTL_ARGS_DECL, struct dahdi_timer * timer)
 {
 	int j;
 	unsigned long flags;
@@ -3500,7 +3911,11 @@
 	case DAHDI_TIMERPING:
 		spin_lock_irqsave(&zaptimerlock, flags);
 		timer->ping = 1;
+#if defined(__FreeBSD__)
+		taskqueue_enqueue_fast(taskqueue_fast, &timer->selwakeup_task);
+#else
 		wake_up_interruptible(&timer->sel);
+#endif
 		spin_unlock_irqrestore(&zaptimerlock, flags);
 		break;
 	case DAHDI_TIMERPONG:
@@ -3509,13 +3924,12 @@
 		spin_unlock_irqrestore(&zaptimerlock, flags);
 		break;
 	default:
-		return -ENOTTY;
+		return _RETVAL(ENOTTY);
 	}
 	return 0;
 }
 
-static int dahdi_ioctl_getgains(struct inode *node, struct file *file,
-				unsigned int cmd, unsigned long data, int unit)
+static int dahdi_ioctl_getgains(FOP_IOCTL_ARGS_DECL, int unit)
 {
 	int res = 0;
 	struct dahdi_gains *gain;
@@ -3559,8 +3973,7 @@
 	return 0;
 }
 
-static int dahdi_ioctl_setgains(struct inode *node, struct file *file,
-				unsigned int cmd, unsigned long data, int unit)
+static int dahdi_ioctl_setgains(FOP_IOCTL_ARGS_DECL, int unit)
 {
 	int res = 0;
 	struct dahdi_gains *gain;
@@ -3636,7 +4049,7 @@
 	return 0;
 }
 
-static int dahdi_common_ioctl(struct inode *node, struct file *file, unsigned int cmd, unsigned long data, int unit)
+static int dahdi_common_ioctl(FOP_IOCTL_ARGS_DECL, int unit)
 {
 	union {
 		struct dahdi_spaninfo spaninfo;
@@ -3654,7 +4067,7 @@
 	case DAHDI_GET_PARAMS:
 		size_to_copy = sizeof(struct dahdi_params);
 		if (copy_from_user(&stack.param, (struct dahdi_params *) data, size_to_copy))
-			return -EFAULT;
+			return _RETVAL(EFAULT);
 
 		/* check to see if the caller wants to receive our master channel number */
 		if (stack.param.channo & DAHDI_GET_PARAMS_RETURN_MASTER) {
@@ -3732,13 +4145,13 @@
 			stack.param.curlaw = DAHDI_LAW_MULAW;
 
 		if (copy_to_user((struct dahdi_params *) data, &stack.param, size_to_copy))
-			return -EFAULT;
+			return _RETVAL(EFAULT);
 
 		break;
 		/* set channel parameters */
 	case DAHDI_SET_PARAMS:
 		if (copy_from_user(&stack.param, (struct dahdi_params *) data, sizeof(struct dahdi_params)))
-			return -EFAULT;
+			return _RETVAL(EFAULT);
 
 		stack.param.chan_alarms = 0; /* be explicit about the above */
 
@@ -3769,23 +4182,23 @@
 		break;
 	case DAHDI_GETGAINS_V1: /* Intentional drop through. */
 	case DAHDI_GETGAINS:  /* get gain stuff */
-		return dahdi_ioctl_getgains(node, file, cmd, data, unit);
+		return dahdi_ioctl_getgains(FOP_IOCTL_ARGS, unit);
 	case DAHDI_SETGAINS:  /* set gain stuff */
-		return dahdi_ioctl_setgains(node, file, cmd, data, unit);
+		return dahdi_ioctl_setgains(FOP_IOCTL_ARGS, unit);
 	case DAHDI_SPANSTAT:
 		size_to_copy = sizeof(struct dahdi_spaninfo);
 		if (copy_from_user(&stack.spaninfo, (struct dahdi_spaninfo *) data, size_to_copy))
-			return -EFAULT;
+			return _RETVAL(EFAULT);
 		i = stack.spaninfo.spanno; /* get specified span number */
-		if ((i < 0) || (i >= maxspans)) return(-EINVAL);  /* if bad span no */
+		if ((i < 0) || (i >= maxspans)) return(_RETVAL(EINVAL));  /* if bad span no */
 		if (i == 0) {
 			/* if to figure it out for this chan */
 			if (!chans[unit])
-				return -EINVAL;
+				return _RETVAL(EINVAL);
 			i = chans[unit]->span->spanno;
 		}
 		if (!spans[i])
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 		stack.spaninfo.spanno = i; /* put the span # in here */
 		stack.spaninfo.totalspans = 0;
 		if (maxspans) stack.spaninfo.totalspans = maxspans - 1; /* put total number of spans here */
@@ -3821,7 +4234,7 @@
 			dahdi_copy_string(stack.spaninfo.spantype, spans[i]->spantype, sizeof(stack.spaninfo.spantype));
 
 		if (copy_to_user((struct dahdi_spaninfo *) data, &stack.spaninfo, size_to_copy))
-			return -EFAULT;
+			return _RETVAL(EFAULT);
 		break;
 	case DAHDI_CHANDIAG_V1: /* Intentional drop through. */
 	case DAHDI_CHANDIAG:
@@ -3835,14 +4248,14 @@
 		get_user(j, (int *) data); /* get channel number from user */
 		/* make sure its a valid channel number */
 		if ((j < 1) || (j >= maxchans))
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 		/* if channel not mapped, not there */
 		if (!chans[j])
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 
 		chan = kmalloc(sizeof(*chan), GFP_KERNEL);
 		if (!chan)
-			return -ENOMEM;
+			return _RETVAL(ENOMEM);
 
 		/* lock channel */
 		spin_lock_irqsave(&chans[j]->lock, flags);
@@ -3887,7 +4300,7 @@
 		break;
 	}
 	default:
-		return -ENOTTY;
+		return _RETVAL(ENOTTY);
 	}
 	return 0;
 }
@@ -3936,7 +4349,7 @@
 #endif
 }
 
-static int dahdi_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data)
+static int dahdi_ctl_ioctl(FOP_IOCTL_ARGS_DECL)
 {
 	/* I/O CTL's for control interface */
 	int i,j;
@@ -3952,19 +4365,19 @@
 		struct dahdi_indirect_data ind;
 
 		if (copy_from_user(&ind, (struct dahdi_indirect_data *)data, sizeof(ind)))
-			return -EFAULT;
+			return _RETVAL(EFAULT);
 		VALID_CHANNEL(ind.chan);
-		return dahdi_chan_ioctl(inode, file, ind.op, (unsigned long) ind.data, ind.chan);
+		return dahdi_chan_ioctl(FOP_IOCTL_ARGS, ind.chan);
 	}
 	case DAHDI_SPANCONFIG:
 	{
 		struct dahdi_lineconfig lc;
 
 		if (copy_from_user(&lc, (struct dahdi_lineconfig *)data, sizeof(lc)))
-			return -EFAULT;
+			return _RETVAL(EFAULT);
 		VALID_SPAN(lc.span);
 		if ((lc.lineconfig & 0x07f0 & spans[lc.span]->linecompat) != (lc.lineconfig & 0x07f0))
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 		if (spans[lc.span]->spanconfig) {
 			spans[lc.span]->lineconfig = lc.lineconfig;
 			spans[lc.span]->lbo = lc.lbo;
@@ -4015,7 +4428,7 @@
 		const struct dahdi_echocan_factory *new = NULL, *old;
 
 		if (copy_from_user(&ae, (struct dahdi_attach_echocan *) data, sizeof(ae))) {
-			return -EFAULT;
+			return _RETVAL(EFAULT);
 		}
 
 		VALID_CHANNEL(ae.chan);
@@ -4023,7 +4436,7 @@
 		ae.echocan[sizeof(ae.echocan) - 1] = 0;
 		if (ae.echocan[0]) {
 			if (!(new = find_echocan(ae.echocan))) {
-				return -EINVAL;
+				return _RETVAL(EINVAL);
 			}
 		}
 
@@ -4043,22 +4456,22 @@
 		struct dahdi_chanconfig ch;
 
 		if (copy_from_user(&ch, (struct dahdi_chanconfig *)data, sizeof(ch)))
-			return -EFAULT;
+			return _RETVAL(EFAULT);
 		VALID_CHANNEL(ch.chan);
 		if (ch.sigtype == DAHDI_SIG_SLAVE) {
 			/* We have to use the master's sigtype */
 			if ((ch.master < 1) || (ch.master >= DAHDI_MAX_CHANNELS))
-				return -EINVAL;
+				return _RETVAL(EINVAL);
 			if (!chans[ch.master])
-				return -EINVAL;
+				return _RETVAL(EINVAL);
 			ch.sigtype = chans[ch.master]->sig;
 			newmaster = chans[ch.master];
 		} else if ((ch.sigtype & __DAHDI_SIG_DACS) == __DAHDI_SIG_DACS) {
 			newmaster = chans[ch.chan];
 			if ((ch.idlebits < 1) || (ch.idlebits >= DAHDI_MAX_CHANNELS))
-				return -EINVAL;
+				return _RETVAL(EINVAL);
 			if (!chans[ch.idlebits])
-				return -EINVAL;
+				return _RETVAL(EINVAL);
 		} else {
 			newmaster = chans[ch.chan];
 		}
@@ -4068,7 +4481,7 @@
 			if (ztchan_to_dev(chans[ch.chan])->flags & IFF_UP) {
 				spin_unlock_irqrestore(&chans[ch.chan]->lock, flags);
 				module_printk(KERN_WARNING, "Can't switch HDLC net mode on channel %s, since current interface is up\n", chans[ch.chan]->name);
-				return -EBUSY;
+				return _RETVAL(EBUSY);
 			}
 			spin_unlock_irqrestore(&chans[ch.chan]->lock, flags);
 			unregister_hdlc_device(chans[ch.chan]->hdlcnetdev->netdev);
@@ -4082,7 +4495,7 @@
 		if (ch.sigtype == DAHDI_SIG_HDLCNET) {
 			spin_unlock_irqrestore(&chans[ch.chan]->lock, flags);
 			module_printk(KERN_WARNING, "DAHDI networking not supported by this build.\n");
-			return -ENOSYS;
+			return _RETVAL(ENOSYS);
 		}
 #endif
 		sigcap = chans[ch.chan]->sigcap;
@@ -4092,7 +4505,7 @@
 			sigcap |= (DAHDI_SIG_HDLCRAW | DAHDI_SIG_HDLCFCS | DAHDI_SIG_HDLCNET | DAHDI_SIG_DACS);
 
 		if ((sigcap & ch.sigtype) != ch.sigtype)
-			res = -EINVAL;
+			res = _RETVAL(EINVAL);
 
 		if (!res && chans[ch.chan]->span->chanconfig)
 			res = chans[ch.chan]->span->chanconfig(chans[ch.chan], ch.sigtype);
@@ -4215,7 +4628,7 @@
 			/* Copy back any modified settings */
 			spin_unlock_irqrestore(&chans[ch.chan]->lock, flags);
 			if (copy_to_user((struct dahdi_chanconfig *)data, &ch, sizeof(ch)))
-				return -EFAULT;
+				return _RETVAL(EFAULT);
 			spin_lock_irqsave(&chans[ch.chan]->lock, flags);
 			/* And hangup */
 			dahdi_hangup(chans[ch.chan]);
@@ -4236,9 +4649,9 @@
 		struct dahdi_sfconfig sf;
 
 		if (copy_from_user(&sf, (struct dahdi_chanconfig *)data, sizeof(sf)))
-			return -EFAULT;
+			return _RETVAL(EFAULT);
 		VALID_CHANNEL(sf.chan);
-		if (chans[sf.chan]->sig != DAHDI_SIG_SF) return -EINVAL;
+		if (chans[sf.chan]->sig != DAHDI_SIG_SF) return _RETVAL(EINVAL);
 		spin_lock_irqsave(&chans[sf.chan]->lock, flags);
 		chans[sf.chan]->rxp1 = sf.rxp1;
 		chans[sf.chan]->rxp2 = sf.rxp2;
@@ -4264,10 +4677,10 @@
 	}
 	case DAHDI_DEFAULTZONE:
 		if (get_user(j,(int *)data))
-			return -EFAULT;
+			return _RETVAL(EFAULT);
 		return dahdi_set_default_zone(j);
 	case DAHDI_LOADZONE:
-		return ioctl_load_zone(data);
+		return ioctl_load_zone(FOP_IOCTL_ARGS);
 	case DAHDI_FREEZONE:
 		get_user(j, (int *) data);
 		return free_tone_zone(j);
@@ -4276,7 +4689,7 @@
 		struct dahdi_dialparams tdp;
 
 		if (copy_from_user(&tdp, (struct dahdi_dialparams *) data, sizeof(tdp)))
-			return -EFAULT;
+			return _RETVAL(EFAULT);
 
 		if ((tdp.dtmf_tonelen >= 10) && (tdp.dtmf_tonelen <= 4000)) {
 			global_dialparams.dtmf_tonelen = tdp.dtmf_tonelen;
@@ -4327,7 +4740,7 @@
 
 		tdp = global_dialparams;
 		if (copy_to_user((struct dahdi_dialparams *) data, &tdp, sizeof(tdp)))
-			return -EFAULT;
+			return _RETVAL(EFAULT);
 		break;
 	}
 	case DAHDI_GETVERSION:
@@ -4355,7 +4768,7 @@
 		}
 		read_unlock(&ecfactory_list_lock);
 		if (copy_to_user((struct dahdi_versioninfo *) data, &vi, sizeof(vi)))
-			return -EFAULT;
+			return _RETVAL(EFAULT);
 		break;
 	}
 	case DAHDI_MAINT:  /* do maintenance stuff */
@@ -4363,12 +4776,12 @@
 		struct dahdi_maintinfo maint;
 		  /* get struct from user */
 		if (copy_from_user(&maint,(struct dahdi_maintinfo *) data, sizeof(maint)))
-			return -EFAULT;
+			return _RETVAL(EFAULT);
 		/* must be valid span number */
 		if ((maint.spanno < 1) || (maint.spanno > DAHDI_MAX_SPANS) || (!spans[maint.spanno]))
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 		if (!spans[maint.spanno]->maint)
-			return -ENOSYS;
+			return _RETVAL(ENOSYS);
 		spin_lock_irqsave(&spans[maint.spanno]->lock, flags);
 		  /* save current maint state */
 		i = spans[maint.spanno]->maintstat;
@@ -4409,30 +4822,30 @@
 	case DAHDI_DYNAMIC_CREATE:
 	case DAHDI_DYNAMIC_DESTROY:
 		if (dahdi_dynamic_ioctl) {
-			return dahdi_dynamic_ioctl(cmd, data);
+			return dahdi_dynamic_ioctl(cmd, (u_long) data);
 		} else {
 			request_module("dahdi_dynamic");
 			if (dahdi_dynamic_ioctl)
-				return dahdi_dynamic_ioctl(cmd, data);
+				return dahdi_dynamic_ioctl(cmd, (u_long) data);
 		}
-		return -ENOSYS;
+		return _RETVAL(ENOSYS);
 	case DAHDI_EC_LICENSE_CHALLENGE:
 	case DAHDI_EC_LICENSE_RESPONSE:
 		if (dahdi_hpec_ioctl) {
-			return dahdi_hpec_ioctl(cmd, data);
+			return dahdi_hpec_ioctl(cmd, (u_long) data);
 		} else {
 			request_module("dahdi_echocan_hpec");
 			if (dahdi_hpec_ioctl)
-				return dahdi_hpec_ioctl(cmd, data);
+				return dahdi_hpec_ioctl(cmd, (u_long) data);
 		}
-		return -ENOSYS;
+		return _RETVAL(ENOSYS);
 	default:
-		return dahdi_common_ioctl(inode, file, cmd, data, 0);
+		return dahdi_common_ioctl(FOP_IOCTL_ARGS, 0);
 	}
 	return 0;
 }
 
-static int ioctl_dahdi_dial(struct dahdi_chan *chan, unsigned long data)
+static int ioctl_dahdi_dial(FOP_IOCTL_ARGS_DECL, struct dahdi_chan *chan)
 {
 	struct dahdi_dialoperation *tdo;
 	unsigned long flags;
@@ -4440,12 +4853,11 @@
 	int rv;
 
 	tdo = kmalloc(sizeof(*tdo), GFP_KERNEL);
-
 	if (!tdo)
-		return -ENOMEM;
+		return _RETVAL(ENOMEM);
 
 	if (copy_from_user(tdo, (struct dahdi_dialoperation *)data, sizeof(*tdo)))
-		return -EFAULT;
+		return _RETVAL(EFAULT);
 	rv = 0;
 	/* Force proper NULL termination and uppercase entry */
 	tdo->dialstr[DAHDI_MAX_DTMF_BUF - 1] = '\0';
@@ -4456,7 +4868,7 @@
 		spin_unlock_irqrestore(&chan->lock, flags);
 		/* The tone zones are loaded by dahdi_cfg from /etc/dahdi/system.conf */
 		module_printk(KERN_WARNING, "Cannot dial until a tone zone is loaded.\n");
-		return -ENODATA;
+		return _RETVAL(ENODATA);
 	}
 	switch (tdo->op) {
 	case DAHDI_DIAL_OP_CANCEL:
@@ -4473,7 +4885,7 @@
 		break;
 	case DAHDI_DIAL_OP_APPEND:
 		if (strlen(tdo->dialstr) + strlen(chan->txdialbuf) >= (DAHDI_MAX_DTMF_BUF - 1)) {
-			rv = -EBUSY;
+			rv = _RETVAL(EBUSY);
 			break;
 		}
 		dahdi_copy_string(chan->txdialbuf + strlen(chan->txdialbuf), tdo->dialstr, DAHDI_MAX_DTMF_BUF - strlen(chan->txdialbuf));
@@ -4483,13 +4895,13 @@
 		}
 		break;
 	default:
-		rv = -EINVAL;
+		rv = _RETVAL(EINVAL);
 	}
 	spin_unlock_irqrestore(&chan->lock, flags);
 	return rv;
 }
 
-static int dahdi_chanandpseudo_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data, int unit)
+static int dahdi_chanandpseudo_ioctl(FOP_IOCTL_ARGS_DECL, int unit)
 {
 	struct dahdi_chan *chan = chans[unit];
 	union {
@@ -4502,17 +4914,17 @@
 	int ret, c;
 
 	if (!chan)
-		return -EINVAL;
+		return _RETVAL(EINVAL);
 	switch(cmd) {
 	case DAHDI_DIALING:
 		spin_lock_irqsave(&chan->lock, flags);
 		j = chan->dialing;
 		spin_unlock_irqrestore(&chan->lock, flags);
 		if (copy_to_user((int *)data,&j,sizeof(int)))
-			return -EFAULT;
+			return _RETVAL(EFAULT);
 		return 0;
 	case DAHDI_DIAL:
-		return ioctl_dahdi_dial(chan, data);
+		return ioctl_dahdi_dial(FOP_IOCTL_ARGS, chan);
 	case DAHDI_GET_BUFINFO:
 		memset(&stack.bi, 0, sizeof(stack.bi));
 		stack.bi.rxbufpolicy = chan->rxbufpolicy;
@@ -4523,17 +4935,17 @@
 		stack.bi.readbufs = -1;
 		stack.bi.writebufs = -1;
 		if (copy_to_user((struct dahdi_bufferinfo *)data, &stack.bi, sizeof(stack.bi)))
-			return -EFAULT;
+			return _RETVAL(EFAULT);
 		break;
 	case DAHDI_SET_BUFINFO:
 		if (copy_from_user(&stack.bi, (struct dahdi_bufferinfo *)data, sizeof(stack.bi)))
-			return -EFAULT;
+			return _RETVAL(EFAULT);
 		if (stack.bi.bufsize > DAHDI_MAX_BLOCKSIZE)
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 		if (stack.bi.bufsize < 16)
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 		if (stack.bi.bufsize * stack.bi.numbufs > DAHDI_MAX_BUF_SPACE)
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 		/* It does not make sense to allow user mode to change the
 		 * receive buffering policy.  DAHDI always provides received
 		 * buffers to upper layers immediately.  Transmission is
@@ -4550,9 +4962,9 @@
 	case DAHDI_SET_BLOCKSIZE:  /* set blocksize */
 		get_user(j,(int *)data);
 		  /* cannot be larger than max amount */
-		if (j > DAHDI_MAX_BLOCKSIZE) return(-EINVAL);
+		if (j > DAHDI_MAX_BLOCKSIZE) return(_RETVAL(EINVAL));
 		  /* cannot be less then 16 */
-		if (j < 16) return(-EINVAL);
+		if (j < 16) return(_RETVAL(EINVAL));
 		  /* allocate a single kernel buffer which we then
 		     sub divide into four pieces */
 		if ((rv = dahdi_reallocbufs(chan, j, chan->numbufs)))
@@ -4572,7 +4984,11 @@
 				chan->readidx[j] = 0;
 			}
 			wake_up_interruptible(&chan->readbufq);  /* wake_up_interruptible waiting on read */
+#if defined(__FreeBSD__)
+			taskqueue_enqueue_fast(taskqueue_fast, &chan->selwakeup_task);
+#else
 			wake_up_interruptible(&chan->sel); /* wake_up_interruptible waiting on select */
+#endif
 		   }
 		if (i & DAHDI_FLUSH_WRITE) /* if for write (output) */
 		   {
@@ -4585,7 +5001,11 @@
 				chan->writeidx[j] = 0;
 			}
 			wake_up_interruptible(&chan->writebufq); /* wake_up_interruptible waiting on write */
+#if defined(__FreeBSD__)
+			taskqueue_enqueue_fast(taskqueue_fast, &chan->selwakeup_task);
+#else
 			wake_up_interruptible(&chan->sel);  /* wake_up_interruptible waiting on select */
+#endif
 			   /* if IO MUX wait on write empty, well, this
 				certainly *did* empty the write */
 			if (chan->iomask & DAHDI_IOMUX_WRITEEMPTY)
@@ -4612,7 +5032,7 @@
 		break;
 	case DAHDI_IOMUX: /* wait for something to happen */
 		get_user(chan->iomask,(int*)data);  /* save mask */
-		if (!chan->iomask) return(-EINVAL);  /* cant wait for nothing */
+		if (!chan->iomask) return(_RETVAL(EINVAL));  /* cant wait for nothing */
 		for(;;)  /* loop forever */
 		   {
 			  /* has to have SOME mask */
@@ -4678,13 +5098,13 @@
 		break;
 	case DAHDI_CONFMUTE:  /* set confmute flag */
 		get_user(j,(int *)data);  /* get conf # */
-		if (!(chan->flags & DAHDI_FLAG_AUDIO)) return (-EINVAL);
+		if (!(chan->flags & DAHDI_FLAG_AUDIO)) return (_RETVAL(EINVAL));
 		spin_lock_irqsave(&bigzaplock, flags);
 		chan->confmute = j;
 		spin_unlock_irqrestore(&bigzaplock, flags);
 		break;
 	case DAHDI_GETCONFMUTE:  /* get confmute flag */
-		if (!(chan->flags & DAHDI_FLAG_AUDIO)) return (-EINVAL);
+		if (!(chan->flags & DAHDI_FLAG_AUDIO)) return (_RETVAL(EINVAL));
 		j = chan->confmute;
 		put_user(j,(int *)data);  /* get conf # */
 		rv = 0;
@@ -4709,29 +5129,29 @@
 	case DAHDI_GETCONF_V1: /* intentional drop through */
 	case DAHDI_GETCONF:  /* get conf stuff */
 		if (copy_from_user(&stack.conf,(struct dahdi_confinfo *) data,sizeof(stack.conf)))
-			return -EFAULT;
+			return _RETVAL(EFAULT);
 		i = stack.conf.chan;  /* get channel no */
 		   /* if zero, use current channel no */
 		if (!i) i = chan->channo;
 		  /* make sure channel number makes sense */
-		if ((i < 0) || (i > DAHDI_MAX_CONF) || (!chans[i])) return(-EINVAL);
-		if (!(chans[i]->flags & DAHDI_FLAG_AUDIO)) return (-EINVAL);
+		if ((i < 0) || (i > DAHDI_MAX_CONF) || (!chans[i])) return(_RETVAL(EINVAL));
+		if (!(chans[i]->flags & DAHDI_FLAG_AUDIO)) return (_RETVAL(EINVAL));
 		stack.conf.chan = i;  /* get channel number */
 		stack.conf.confno = chans[i]->confna;  /* get conference number */
 		stack.conf.confmode = chans[i]->confmode; /* get conference mode */
 		if (copy_to_user((struct dahdi_confinfo *) data,&stack.conf,sizeof(stack.conf)))
-			return -EFAULT;
+			return _RETVAL(EFAULT);
 		break;
 	case DAHDI_SETCONF_V1: /* Intentional fall through. */
 	case DAHDI_SETCONF:  /* set conf stuff */
 		if (copy_from_user(&stack.conf,(struct dahdi_confinfo *) data,sizeof(stack.conf)))
-			return -EFAULT;
+			return _RETVAL(EFAULT);
 		i = stack.conf.chan;  /* get channel no */
 		   /* if zero, use current channel no */
 		if (!i) i = chan->channo;
 		  /* make sure channel number makes sense */
-		if ((i < 1) || (i > DAHDI_MAX_CHANNELS) || (!chans[i])) return(-EINVAL);
-		if (!(chans[i]->flags & DAHDI_FLAG_AUDIO)) return (-EINVAL);
+		if ((i < 1) || (i > DAHDI_MAX_CHANNELS) || (!chans[i])) return(_RETVAL(EINVAL));
+		if (!(chans[i]->flags & DAHDI_FLAG_AUDIO)) return (_RETVAL(EINVAL));
 		if ((stack.conf.confmode & DAHDI_CONF_MODE_MASK) == DAHDI_CONF_MONITOR ||
 			(stack.conf.confmode & DAHDI_CONF_MODE_MASK) == DAHDI_CONF_MONITORTX ||
 			(stack.conf.confmode & DAHDI_CONF_MODE_MASK) == DAHDI_CONF_MONITORBOTH ||
@@ -4739,16 +5159,16 @@
 			(stack.conf.confmode & DAHDI_CONF_MODE_MASK) == DAHDI_CONF_MONITOR_TX_PREECHO ||
 			(stack.conf.confmode & DAHDI_CONF_MODE_MASK) == DAHDI_CONF_MONITORBOTH_PREECHO) {
 			/* Monitor mode -- it's a channel */
-			if ((stack.conf.confno < 0) || (stack.conf.confno >= DAHDI_MAX_CHANNELS) || !chans[stack.conf.confno]) return(-EINVAL);
+			if ((stack.conf.confno < 0) || (stack.conf.confno >= DAHDI_MAX_CHANNELS) || !chans[stack.conf.confno]) return(_RETVAL(EINVAL));
 		} else {
 			  /* make sure conf number makes sense, too */
-			if ((stack.conf.confno < -1) || (stack.conf.confno > DAHDI_MAX_CONF)) return(-EINVAL);
+			if ((stack.conf.confno < -1) || (stack.conf.confno > DAHDI_MAX_CONF)) return(_RETVAL(EINVAL));
 		}
 
 		  /* if taking off of any conf, must have 0 mode */
-		if ((!stack.conf.confno) && stack.conf.confmode) return(-EINVAL);
+		if ((!stack.conf.confno) && stack.conf.confmode) return(_RETVAL(EINVAL));
 		  /* likewise if 0 mode must have no conf */
-		if ((!stack.conf.confmode) && stack.conf.confno) return (-EINVAL);
+		if ((!stack.conf.confmode) && stack.conf.confno) return (_RETVAL(EINVAL));
 		stack.conf.chan = i;  /* return with real channel # */
 		spin_lock_irqsave(&bigzaplock, flags);
 		spin_lock(&chan->lock);
@@ -4758,7 +5178,7 @@
 			/* No more empty conferences */
 			spin_unlock(&chan->lock);
 			spin_unlock_irqrestore(&bigzaplock, flags);
-			return -EBUSY;
+			return _RETVAL(EBUSY);
 		}
 		  /* if changing confs, clear last added info */
 		if (stack.conf.confno != chans[i]->confna) {
@@ -4812,17 +5232,17 @@
 		spin_unlock(&chan->lock);
 		spin_unlock_irqrestore(&bigzaplock, flags);
 		if (copy_to_user((struct dahdi_confinfo *) data,&stack.conf,sizeof(stack.conf)))
-			return -EFAULT;
+			return _RETVAL(EFAULT);
 		break;
 	case DAHDI_CONFLINK:  /* do conf link stuff */
-		if (!(chan->flags & DAHDI_FLAG_AUDIO)) return (-EINVAL);
+		if (!(chan->flags & DAHDI_FLAG_AUDIO)) return (_RETVAL(EINVAL));
 		if (copy_from_user(&stack.conf,(struct dahdi_confinfo *) data,sizeof(stack.conf)))
-			return -EFAULT;
+			return _RETVAL(EFAULT);
 		  /* check sanity of arguments */
-		if ((stack.conf.chan < 0) || (stack.conf.chan > DAHDI_MAX_CONF)) return(-EINVAL);
-		if ((stack.conf.confno < 0) || (stack.conf.confno > DAHDI_MAX_CONF)) return(-EINVAL);
+		if ((stack.conf.chan < 0) || (stack.conf.chan > DAHDI_MAX_CONF)) return(_RETVAL(EINVAL));
+		if ((stack.conf.confno < 0) || (stack.conf.confno > DAHDI_MAX_CONF)) return(_RETVAL(EINVAL));
 		  /* cant listen to self!! */
-		if (stack.conf.chan && (stack.conf.chan == stack.conf.confno)) return(-EINVAL);
+		if (stack.conf.chan && (stack.conf.chan == stack.conf.confno)) return(_RETVAL(EINVAL));
 		spin_lock_irqsave(&bigzaplock, flags);
 		spin_lock(&chan->lock);
 		  /* if to clear all links */
@@ -4851,7 +5271,7 @@
 			   }
 			else /* if to add and already there, error */
 			   {
-				rv = -EEXIST;
+				rv = _RETVAL(EEXIST);
 			   }
 		   }
 		else  /* if not found */
@@ -4873,12 +5293,12 @@
 				   }
 				else /* if no empties -- error */
 				   {
-					rv = -ENOSPC;
+					rv = _RETVAL(ENOSPC);
 				   }
 			   }
 			else /* if to remove, and not found -- error */
 			   {
-				rv = -ENOENT;
+				rv = _RETVAL(ENOENT);
 			   }
 		   }
 		recalc_maxlinks();
@@ -4887,7 +5307,7 @@
 		return(rv);
 	case DAHDI_CONFDIAG_V1: /* Intention fall-through */
 	case DAHDI_CONFDIAG:  /* output diagnostic info to console */
-		if (!(chan->flags & DAHDI_FLAG_AUDIO)) return (-EINVAL);
+		if (!(chan->flags & DAHDI_FLAG_AUDIO)) return (_RETVAL(EINVAL));
 		get_user(j,(int *)data);  /* get conf # */
  		  /* loop thru the interesting ones */
 		for(i = ((j) ? j : 1); i <= ((j) ? j : DAHDI_MAX_CONF); i++)
@@ -4924,14 +5344,14 @@
 	case DAHDI_SETLAW:
 		get_user(j, (int *)data);
 		if ((j < 0) || (j > DAHDI_LAW_ALAW))
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 		dahdi_set_law(chan, j);
 		break;
 	case DAHDI_SETLINEAR:
 		get_user(j, (int *)data);
 		/* Makes no sense on non-audio channels */
 		if (!(chan->flags & DAHDI_FLAG_AUDIO))
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 
 		if (j)
 			chan->flags |= DAHDI_FLAG_LINEAR;
@@ -4942,7 +5362,7 @@
 		if (data) {
 			/* Use specific ring cadence */
 			if (copy_from_user(&stack.cad, (struct dahdi_ring_cadence *)data, sizeof(stack.cad)))
-				return -EFAULT;
+				return _RETVAL(EFAULT);
 			memcpy(chan->ringcadence, &stack.cad, sizeof(chan->ringcadence));
 			chan->firstcadencepos = 0;
 			/* Looking for negative ringing time indicating where to loop back into ringcadence */
@@ -4975,11 +5395,11 @@
 		break;
 	default:
 		/* Check for common ioctl's and private ones */
-		rv = dahdi_common_ioctl(inode, file, cmd, data, unit);
+		rv = dahdi_common_ioctl(FOP_IOCTL_ARGS, unit);
 		/* if no span, just return with value */
 		if (!chan->span) return rv;
-		if ((rv == -ENOTTY) && chan->span->ioctl)
-			rv = chan->span->ioctl(chan, cmd, data);
+		if ((rv == _RETVAL(ENOTTY)) && chan->span->ioctl)
+			rv = chan->span->ioctl(chan, cmd, (u_long) data);
 		return rv;
 
 	}
@@ -5022,7 +5442,7 @@
 	unsigned long flags;
 
 	if (ecp->param_count > DAHDI_MAX_ECHOCANPARAMS)
-		return -E2BIG;
+		return _RETVAL(E2BIG);
 
 	if (ecp->tap_length == 0) {
 		/* disable mode, don't need to inspect params */
@@ -5036,21 +5456,26 @@
 			ec_state->ops->echocan_free(chan, ec_state);
 			release_echocan(ec_current);
 		}
-
 		return 0;
 	}
 
 	params = kmalloc(sizeof(params[0]) * DAHDI_MAX_ECHOCANPARAMS, GFP_KERNEL);
-
 	if (!params)
-		return -ENOMEM;
+		return _RETVAL(ENOMEM);
 
 	/* enable mode, need the params */
-
-	if (copy_from_user(params, (struct dahdi_echocanparam *) data, sizeof(params[0]) * ecp->param_count)) {
-		ret = -EFAULT;
+	if (ecp->param_count != 0) {
+#if defined(__FreeBSD__)
+		bcopy(data, &data, sizeof(void *));
+		if (copyin(data, params, sizeof(params[0]) * ecp->param_count)) {
+#else
+		if (copy_from_user(params, (struct dahdi_echocanparam *) data,
+			   sizeof(params[0]) * ecp->param_count)) {
+#endif
+			ret = _RETVAL(EFAULT);
 		goto exit_with_free;
 	}
+	}
 
 	/* free any echocan that may be on the channel already */
 	spin_lock_irqsave(&chan->lock, flags);
@@ -5076,7 +5501,7 @@
 		ecp->tap_length = deftaps;
 	}
 
-	ret = -ENODEV;
+	ret = _RETVAL(ENODEV);
 	ec_current = NULL;
 
 	/* attempt to use the span's echo canceler; fall back to built-in
@@ -5084,13 +5509,15 @@
 	if (chan->span && chan->span->echocan_create)
 		ret = chan->span->echocan_create(chan, ecp, params, &ec);
 
-	if ((ret == -ENODEV) && chan->ec_factory) {
+	if ((ret == _RETVAL(ENODEV)) && chan->ec_factory) {
 		/* try to get another reference to the module providing
 		   this channel's echo canceler */
+#if !defined(__FreeBSD__)
 		if (!try_module_get(chan->ec_factory->owner)) {
 			module_printk(KERN_ERR, "Cannot get a reference to the '%s' echo canceler\n", chan->ec_factory->name);
 			goto exit_with_free;
 		}
+#endif
 
 		/* got the reference, copy the pointer and use it for making
 		   an echo canceler instance if possible */
@@ -5099,14 +5526,13 @@
 		ret = ec_current->echocan_create(chan, ecp, params, &ec);
 		if (ret) {
 			release_echocan(ec_current);
-
 			goto exit_with_free;
 		}
 		if (!ec) {
 			module_printk(KERN_ERR, "%s failed to allocate an " \
 				      "dahdi_echocan_state instance.\n",
 				      ec_current->name);
-			ret = -EFAULT;
+			ret = _RETVAL(EFAULT);
 			goto exit_with_free;
 		}
 	}
@@ -5181,7 +5607,7 @@
 	}
 }
 
-static int dahdi_chan_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data, int unit)
+static int dahdi_chan_ioctl(FOP_IOCTL_ARGS_DECL, int unit)
 {
 	struct dahdi_chan *chan = chans[unit];
 	unsigned long flags;
@@ -5189,12 +5615,34 @@
 	int ret;
 	int oldconf;
 	void *rxgain=NULL;
+#if !defined(__FreeBSD__)
+	int fflag = file->f_flags;
+#endif
 
 	WARN_ON(!chan->master);
 	if (!chan)
-		return -ENOSYS;
+		return _RETVAL(ENOSYS);
 
 	switch(cmd) {
+#if defined(__FreeBSD__)
+	case F_SETFL: {
+		int fflags = dahdi_get_flags(file);
+
+		get_user(j, data);
+		printf("F_SETFL: 0x%x\n", j);
+
+		/*
+		 * XXX: On the moment we're interested only in O_NONBLOCK
+		 * Need any other flags?
+		 */
+		if ((j & O_NONBLOCK) != 0) {
+			dahdi_set_flags(file, fflags | O_NONBLOCK);
+		} else {
+			dahdi_set_flags(file, fflags & ~O_NONBLOCK);
+		}
+		break;
+	}
+#endif
 	case DAHDI_SETSIGFREEZE:
 		get_user(j, (int *)data);
 		spin_lock_irqsave(&chan->lock, flags);
@@ -5216,7 +5664,7 @@
 		break;
 	case DAHDI_AUDIOMODE:
 		/* Only literal clear channels can be put in  */
-		if (chan->sig != DAHDI_SIG_CLEAR) return (-EINVAL);
+		if (chan->sig != DAHDI_SIG_CLEAR) return (_RETVAL(EINVAL));
 		get_user(j, (int *)data);
 		if (j) {
 			spin_lock_irqsave(&chan->lock, flags);
@@ -5272,7 +5720,7 @@
 		break;
 	case DAHDI_HDLCPPP:
 #ifdef CONFIG_DAHDI_PPP
-		if (chan->sig != DAHDI_SIG_CLEAR) return (-EINVAL);
+		if (chan->sig != DAHDI_SIG_CLEAR) return (_RETVAL(EINVAL));
 		get_user(j, (int *)data);
 		if (j) {
 			if (!chan->ppp) {
@@ -5318,7 +5766,7 @@
 						release_echocan(ec_current);
 					}
 				} else
-					return -ENOMEM;
+					return _RETVAL(ENOMEM);
 			}
 		} else {
 			chan->flags &= ~(DAHDI_FLAG_PPP | DAHDI_FLAG_HDLC | DAHDI_FLAG_FCS);
@@ -5333,11 +5781,11 @@
 		}
 #else
 		module_printk(KERN_NOTICE, "PPP support not compiled in\n");
-		return -ENOSYS;
+		return _RETVAL(ENOSYS);
 #endif
 		break;
 	case DAHDI_HDLCRAWMODE:
-		if (chan->sig != DAHDI_SIG_CLEAR)	return (-EINVAL);
+		if (chan->sig != DAHDI_SIG_CLEAR)	return (_RETVAL(EINVAL));
 		get_user(j, (int *)data);
 		chan->flags &= ~(DAHDI_FLAG_AUDIO | DAHDI_FLAG_HDLC | DAHDI_FLAG_FCS);
 		if (j) {
@@ -5347,7 +5795,7 @@
 		}
 		break;
 	case DAHDI_HDLCFCSMODE:
-		if (chan->sig != DAHDI_SIG_CLEAR)	return (-EINVAL);
+		if (chan->sig != DAHDI_SIG_CLEAR)	return (_RETVAL(EINVAL));
 		get_user(j, (int *)data);
 		chan->flags &= ~(DAHDI_FLAG_AUDIO | DAHDI_FLAG_HDLC | DAHDI_FLAG_FCS);
 		if (j) {
@@ -5372,9 +5820,9 @@
 		struct dahdi_echocanparams ecp;
 
 		if (!(chan->flags & DAHDI_FLAG_AUDIO))
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 		if (copy_from_user(&ecp, (struct dahdi_echocanparams *) data, sizeof(ecp)))
-			return -EFAULT;
+			return _RETVAL(EFAULT);
 		data += sizeof(ecp);
 		if ((ret = ioctl_echocancel(chan, &ecp, (void *) data)))
 			return ret;
@@ -5385,7 +5833,7 @@
 		struct dahdi_echocanparams ecp;
 
 		if (!(chan->flags & DAHDI_FLAG_AUDIO))
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 		get_user(j, (int *) data);
 		ecp.tap_length = j;
 		ecp.param_count = 0;
@@ -5396,7 +5844,7 @@
 	case DAHDI_ECHOTRAIN:
 		get_user(j, (int *)data); /* get pre-training time from user */
 		if ((j < 0) || (j >= DAHDI_MAX_PRETRAINING))
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 		j <<= 3;
 		spin_lock_irqsave(&chan->lock, flags);
 		if (chan->ec_state) {
@@ -5408,12 +5856,12 @@
 			spin_unlock_irqrestore(&chan->lock, flags);
 		} else {
 			spin_unlock_irqrestore(&chan->lock, flags);
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 		}
 		break;
 	case DAHDI_ECHOCANCEL_FAX_MODE:
 		if (!chan->ec_state) {
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 		} else {
 			get_user(j, (int *) data);
 			spin_lock_irqsave(&chan->lock, flags);
@@ -5423,7 +5871,7 @@
 		break;
 	case DAHDI_SETTXBITS:
 		if (chan->sig != DAHDI_SIG_CAS)
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 		get_user(j,(int *)data);
 		dahdi_cas_setbits(chan, j);
 		break;
@@ -5442,9 +5890,9 @@
 	case DAHDI_HOOK:
 		get_user(j,(int *)data);
 		if (chan->flags & DAHDI_FLAG_CLEAR)
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 		if (chan->sig == DAHDI_SIG_CAS)
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 		/* if no span, just do nothing */
 		if (!chan->span) return(0);
 		spin_lock_irqsave(&chan->lock, flags);
@@ -5467,7 +5915,7 @@
 				if ((chan->txstate == DAHDI_TXSTATE_KEWL) ||
 				  (chan->txstate == DAHDI_TXSTATE_AFTERKEWL)) {
 					spin_unlock_irqrestore(&chan->lock, flags);
-					return -EBUSY;
+					return _RETVAL(EBUSY);
 				}
 				dahdi_rbs_sethook(chan, DAHDI_TXSIG_OFFHOOK, DAHDI_TXSTATE_DEBOUNCE, chan->debouncetime);
 				spin_unlock_irqrestore(&chan->lock, flags);
@@ -5478,11 +5926,11 @@
 				if (!chan->curzone) {
 					spin_unlock_irqrestore(&chan->lock, flags);
 					module_printk(KERN_WARNING, "Cannot start tone until a tone zone is loaded.\n");
-					return -ENODATA;
+					return _RETVAL(ENODATA);
 				}
 				if (chan->txstate != DAHDI_TXSTATE_ONHOOK) {
 					spin_unlock_irqrestore(&chan->lock, flags);
-					return -EBUSY;
+					return _RETVAL(EBUSY);
 				}
 				if (chan->sig & __DAHDI_SIG_FXO) {
 					ret = 0;
@@ -5492,23 +5940,25 @@
 				} else
 					dahdi_rbs_sethook(chan, DAHDI_TXSIG_START, DAHDI_TXSTATE_START, chan->starttime);
 				spin_unlock_irqrestore(&chan->lock, flags);
-				if (file->f_flags & O_NONBLOCK)
-					return -EINPROGRESS;
+				if (fflag & O_NONBLOCK)
+					return _RETVAL(EINPROGRESS);
 #if 0
 				rv = schluffen(&chan->txstateq);
 				if (rv) return rv;
+#else
+				rv = 0;
 #endif
 				break;
 			case DAHDI_WINK:
 				spin_lock_irqsave(&chan->lock, flags);
 				if (chan->txstate != DAHDI_TXSTATE_ONHOOK) {
 					spin_unlock_irqrestore(&chan->lock, flags);
-					return -EBUSY;
+					return _RETVAL(EBUSY);
 				}
 				dahdi_rbs_sethook(chan, DAHDI_TXSIG_ONHOOK, DAHDI_TXSTATE_PREWINK, chan->prewinktime);
 				spin_unlock_irqrestore(&chan->lock, flags);
-				if (file->f_flags & O_NONBLOCK)
-					return -EINPROGRESS;
+				if (fflag & O_NONBLOCK)
+					return _RETVAL(EINPROGRESS);
 				rv = schluffen(&chan->txstateq);
 				if (rv) return rv;
 				break;
@@ -5516,12 +5966,12 @@
 				spin_lock_irqsave(&chan->lock, flags);
 				if (chan->txstate != DAHDI_TXSTATE_OFFHOOK) {
 					spin_unlock_irqrestore(&chan->lock, flags);
-					return -EBUSY;
+					return _RETVAL(EBUSY);
 				}
 				dahdi_rbs_sethook(chan, DAHDI_TXSIG_OFFHOOK, DAHDI_TXSTATE_PREFLASH, chan->preflashtime);
 				spin_unlock_irqrestore(&chan->lock, flags);
-				if (file->f_flags & O_NONBLOCK)
-					return -EINPROGRESS;
+				if (fflag & O_NONBLOCK)
+					return _RETVAL(EINPROGRESS);
 				rv = schluffen(&chan->txstateq);
 				if (rv) return rv;
 				break;
@@ -5531,7 +5981,7 @@
 				spin_unlock_irqrestore(&chan->lock, flags);
 				break;
 			default:
-				return -EINVAL;
+				return _RETVAL(EINVAL);
 			}
 		} else if (chan->span->sethook) {
 			if (chan->txhooksig != j) {
@@ -5539,31 +5989,31 @@
 				chan->span->sethook(chan, j);
 			}
 		} else
-			return -ENOSYS;
+			return _RETVAL(ENOSYS);
 		break;
 #ifdef CONFIG_DAHDI_PPP
 	case PPPIOCGCHAN:
 		if (chan->flags & DAHDI_FLAG_PPP)
-			return put_user(ppp_channel_index(chan->ppp), (int *)data) ? -EFAULT : 0;
+			return put_user(ppp_channel_index(chan->ppp), (int *)data) ? _RETVAL(EFAULT) : 0;
 		else
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 		break;
 	case PPPIOCGUNIT:
 		if (chan->flags & DAHDI_FLAG_PPP)
-			return put_user(ppp_unit_number(chan->ppp), (int *)data) ? -EFAULT : 0;
+			return put_user(ppp_unit_number(chan->ppp), (int *)data) ? _RETVAL(EFAULT) : 0;
 		else
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 		break;
 #endif
 	default:
-		return dahdi_chanandpseudo_ioctl(inode, file, cmd, data, unit);
+		return dahdi_chanandpseudo_ioctl(FOP_IOCTL_ARGS, unit);
 	}
 	return 0;
 }
 
-static int dahdi_prechan_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data, int unit)
+static int dahdi_prechan_ioctl(FOP_IOCTL_ARGS_DECL, int unit)
 {
-	struct dahdi_chan *chan = file->private_data;
+	struct dahdi_chan *chan = dahdi_get_private_data(file);
 	int channo;
 	int res;
 
@@ -5574,63 +6024,63 @@
 	case DAHDI_SPECIFY:
 		get_user(channo,(int *)data);
 		if (channo < 1)
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 		if (channo > DAHDI_MAX_CHANNELS)
-			return -EINVAL;
-		res = dahdi_specchan_open(inode, file, channo);
+			return _RETVAL(EINVAL);
+		res = dahdi_specchan_open(FOP_ARGS, channo);
 		if (!res) {
 			/* Setup the pointer for future stuff */
 			chan = chans[channo];
-			file->private_data = chan;
+			dahdi_set_private_data(file, chan);
 			/* Return success */
 			return 0;
 		}
 		return res;
 	default:
-		return -ENOSYS;
+		return _RETVAL(ENOSYS);
 	}
 	return 0;
 }
 
-static int dahdi_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data)
+static int dahdi_ioctl(FOP_IOCTL_ARGS_DECL)
 {
 	int unit = UNIT(file);
 	struct dahdi_chan *chan;
 	struct dahdi_timer *timer;
 
 	if (!unit)
-		return dahdi_ctl_ioctl(inode, file, cmd, data);
+		return dahdi_ctl_ioctl(FOP_IOCTL_ARGS);
 
-	if (unit == 250) {
+	if (unit == DAHDI_MINOR_TRANSCODE) {
 		/* 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;
+		return _RETVAL(EFAULT);
 	}
 
-	if (unit == 253) {
-		timer = file->private_data;
+	if (unit == DAHDI_MINOR_TIMER) {
+		timer = dahdi_get_private_data(file);
 		if (timer)
-			return dahdi_timer_ioctl(inode, file, cmd, data, timer);
+			return dahdi_timer_ioctl(FOP_IOCTL_ARGS, timer);
 		else
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 	}
-	if (unit == 254) {
-		chan = file->private_data;
+	if (unit == DAHDI_MINOR_CHANNEL) {
+		chan = dahdi_get_private_data(file);
 		if (chan)
-			return dahdi_chan_ioctl(inode, file, cmd, data, chan->channo);
+			return dahdi_chan_ioctl(FOP_IOCTL_ARGS, chan->channo);
 		else
-			return dahdi_prechan_ioctl(inode, file, cmd, data, unit);
+			return dahdi_prechan_ioctl(FOP_IOCTL_ARGS, unit);
 	}
-	if (unit == 255) {
-		chan = file->private_data;
+	if (unit == DAHDI_MINOR_PSEUDO) {
+		chan = dahdi_get_private_data(file);
 		if (!chan) {
 			module_printk(KERN_NOTICE, "No pseudo channel structure to read?\n");
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 		}
-		return dahdi_chanandpseudo_ioctl(inode, file, cmd, data, chan->channo);
+		return dahdi_chanandpseudo_ioctl(FOP_IOCTL_ARGS, chan->channo);
 	}
-	return dahdi_chan_ioctl(inode, file, cmd, data, unit);
+	return dahdi_chan_ioctl(FOP_IOCTL_ARGS, unit);
 }
 
 int dahdi_register(struct dahdi_span *span, int prefmaster)
@@ -5638,19 +6088,21 @@
 	int x;
 
 	if (!span)
-		return -EINVAL;
+		return _RETVAL(EINVAL);
 
+#if !defined(__FreeBSD__)
 	WARN_ON(!span->owner);
+#endif
 
 	if (test_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags)) {
 		module_printk(KERN_ERR, "Span %s already appears to be registered\n", span->name);
-		return -EBUSY;
+		return _RETVAL(EBUSY);
 	}
 
 	for (x = 1; x < maxspans; x++) {
 		if (spans[x] == span) {
 			module_printk(KERN_ERR, "Span %s already in list\n", span->name);
-			return -EBUSY;
+			return _RETVAL(EBUSY);
 		}
 	}
 
@@ -5665,7 +6117,7 @@
 			maxspans = x + 1;
 	} else {
 		module_printk(KERN_ERR, "Too many DAHDI spans registered\n");
-		return -EBUSY;
+		return _RETVAL(EBUSY);
 	}
 
 	set_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags);
@@ -5695,11 +6147,19 @@
 
 	for (x = 0; x < span->channels; x++) {
 		if (span->chans[x]->channo < 250) {
+#if defined(__FreeBSD__)
+			span->chans[x]->file = make_dev(
+			    &dahdi_devsw, span->chans[x]->channo,
+			    UID_ROOT, GID_WHEEL, 0644,
+			    "dahdi/%d", span->chans[x]->channo);
+			dev_depends(dev_ctl, span->chans[x]->file);
+#else
 			char chan_name[32];
 			snprintf(chan_name, sizeof(chan_name), "dahdi!%d", 
 					span->chans[x]->channo);
 			CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, 
 					span->chans[x]->channo), NULL, chan_name);
+#endif
 		}
 	}
 
@@ -5750,9 +6210,17 @@
 #endif /* CONFIG_PROC_FS */
 
 	for (x = 0; x < span->channels; x++) {
-		if (span->chans[x]->channo < 250)
+		if (span->chans[x]->channo < 250) {
+#if defined(__FreeBSD__)
+			if (span->chans[x]->file != NULL) {
+				destroy_dev(span->chans[x]->file);
+				span->chans[x]->file = NULL;
+			}
+#else
 			CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, span->chans[x]->channo));
+#endif
 	}
+	}
 
 	spans[span->spanno] = NULL;
 	span->spanno = 0;
@@ -5777,6 +6245,7 @@
 				      (new_master)? new_master->name: "no master");
 	master = new_master;
 
+	spin_lock_destroy(&span->lock);
 	return 0;
 }
 
@@ -6261,7 +6730,11 @@
 out in the later versions, and is put back now. */
 				if (!(ms->flags & (DAHDI_FLAG_NETDEV | DAHDI_FLAG_PPP))) {
 					wake_up_interruptible(&ms->writebufq);
+#if defined(__FreeBSD__)
+					taskqueue_enqueue_fast(taskqueue_fast, &ms->selwakeup_task);
+#else
 					wake_up_interruptible(&ms->sel);
+#endif
 					if (ms->iomask & DAHDI_IOMUX_WRITE)
 						wake_up_interruptible(&ms->eventbufq);
 				}
@@ -6426,7 +6899,7 @@
 	case DAHDI_TXSTATE_WINK:
 		/* Wink complete, go on hook and stabalize */
 		dahdi_rbs_sethook(chan, DAHDI_TXSIG_ONHOOK, DAHDI_TXSTATE_ONHOOK, 0);
-		if (chan->file && (chan->file->f_flags & O_NONBLOCK))
+		if (dahdi_get_flags(chan->file) & O_NONBLOCK)
 			__qevent(chan, DAHDI_EVENT_HOOKCOMPLETE);
 		wake_up_interruptible(&chan->txstateq);
 		break;
@@ -6438,7 +6911,7 @@
 
 	case DAHDI_TXSTATE_FLASH:
 		dahdi_rbs_sethook(chan, DAHDI_TXSIG_OFFHOOK, DAHDI_TXSTATE_OFFHOOK, 0);
-		if (chan->file && (chan->file->f_flags & O_NONBLOCK))
+		if (dahdi_get_flags(chan->file) & O_NONBLOCK)
 			__qevent(chan, DAHDI_EVENT_HOOKCOMPLETE);
 		wake_up_interruptible(&chan->txstateq);
 		break;
@@ -6453,14 +6926,14 @@
 
 	case DAHDI_TXSTATE_AFTERSTART:
 		dahdi_rbs_sethook(chan, DAHDI_TXSIG_OFFHOOK, DAHDI_TXSTATE_OFFHOOK, 0);
-		if (chan->file && (chan->file->f_flags & O_NONBLOCK))
+		if (dahdi_get_flags(chan->file) & O_NONBLOCK)
 			__qevent(chan, DAHDI_EVENT_HOOKCOMPLETE);
 		wake_up_interruptible(&chan->txstateq);
 		break;
 
 	case DAHDI_TXSTATE_KEWL:
 		dahdi_rbs_sethook(chan, DAHDI_TXSIG_ONHOOK, DAHDI_TXSTATE_AFTERKEWL, DAHDI_AFTERKEWLTIME);
-		if (chan->file && (chan->file->f_flags & O_NONBLOCK))
+		if (dahdi_get_flags(chan->file) & O_NONBLOCK)
 			__qevent(chan, DAHDI_EVENT_HOOKCOMPLETE);
 		wake_up_interruptible(&chan->txstateq);
 		break;
@@ -6746,7 +7219,7 @@
 {
 	union dahdi_echocan_events events = chan->ec_state->events;
 
-	if (events.CED_tx_detected) {
+	if (events.e.CED_tx_detected) {
 		dahdi_qevent_nolock(chan, DAHDI_EVENT_TX_CED_DETECTED);
 		if (chan->ec_state) {
 			if (chan->ec_state->status.mode == ECHO_MODE_ACTIVE)
@@ -6756,7 +7229,7 @@
 		}
 	}
 
-	if (events.CED_rx_detected) {
+	if (events.e.CED_rx_detected) {
 		dahdi_qevent_nolock(chan, DAHDI_EVENT_RX_CED_DETECTED);
 		if (chan->ec_state) {
 			if (chan->ec_state->status.mode == ECHO_MODE_ACTIVE)
@@ -6766,18 +7239,18 @@
 		}
 	}
 
-	if (events.CNG_tx_detected)
+	if (events.e.CNG_tx_detected)
 		dahdi_qevent_nolock(chan, DAHDI_EVENT_TX_CNG_DETECTED);
 
-	if (events.CNG_rx_detected)
+	if (events.e.CNG_rx_detected)
 		dahdi_qevent_nolock(chan, DAHDI_EVENT_RX_CNG_DETECTED);
 
-	if (events.NLP_auto_disabled) {
+	if (events.e.NLP_auto_disabled) {
 		dahdi_qevent_nolock(chan, DAHDI_EVENT_EC_NLP_DISABLED);
 		chan->ec_state->status.mode = ECHO_MODE_FAX;
 	}
 
-	if (events.NLP_auto_enabled) {
+	if (events.e.NLP_auto_enabled) {
 		dahdi_qevent_nolock(chan, DAHDI_EVENT_EC_NLP_ENABLED);
 		chan->ec_state->status.mode = ECHO_MODE_ACTIVE;
 	}
@@ -7356,7 +7829,11 @@
 							/* if there are processes waiting in poll() on this channel,
 							   wake them up */
 							if (!ms->rxdisable) {
+#if defined(__FreeBSD__)
+								taskqueue_enqueue_fast(taskqueue_fast, &ms->selwakeup_task);
+#else
 								wake_up_interruptible(&ms->sel);
+#endif
 							}
 						}
 /* In the very orignal driver, it was quite well known to me (Jim) that there
@@ -7554,7 +8031,11 @@
 
 	if (!ss->rxdisable) {
 		wake_up_interruptible(&ss->readbufq);
+#if defined(__FreeBSD__)
+		taskqueue_enqueue_fast(taskqueue_fast, &ss->selwakeup_task);
+#else
 		wake_up_interruptible(&ss->sel);
+#endif
 		if (ss->iomask & DAHDI_IOMUX_READ)
 			wake_up_interruptible(&ss->eventbufq);
 	}
@@ -7606,7 +8087,11 @@
 
 			if (!(ss->flags & (DAHDI_FLAG_NETDEV | DAHDI_FLAG_PPP))) {
 				wake_up_interruptible(&ss->writebufq);
+#if defined(__FreeBSD__)
+				taskqueue_enqueue_fast(taskqueue_fast, &ss->selwakeup_task);
+#else
 				wake_up_interruptible(&ss->sel);
+#endif
 				if ((ss->iomask & DAHDI_IOMUX_WRITE) && (res >= 0))
 					wake_up_interruptible(&ss->eventbufq);
 			}
@@ -7634,7 +8119,11 @@
 			if (cur->pos <= 0) {
 				cur->tripped++;
 				cur->pos = cur->ms;
+#if defined(__FreeBSD__)
+				taskqueue_enqueue_fast(taskqueue_fast, &cur->selwakeup_task);
+#else
 				wake_up_interruptible(&cur->sel);
+#endif
 			}
 		}
 	}
@@ -7642,34 +8131,56 @@
 	spin_unlock_irqrestore(&zaptimerlock, flags);
 }
 
-static unsigned int dahdi_timer_poll(struct file *file, struct poll_table_struct *wait_table)
+static int dahdi_timer_poll(FOP_POLL_ARGS_DECL)
 {
-	struct dahdi_timer *timer = file->private_data;
+	struct dahdi_timer *timer = dahdi_get_private_data(file);
 	unsigned long flags;
 	int ret = 0;
-	if (timer) {
+
+	if (!timer) {
+#if defined(__FreeBSD__)
+		return (0);
+#else
+		return _RETVAL(EINVAL);
+#endif
+	}
+
+#if !defined(__FreeBSD__)
 		poll_wait(file, &timer->sel, wait_table);
+#endif
 		spin_lock_irqsave(&zaptimerlock, flags);
 		if (timer->tripped || timer->ping)
 			ret |= POLLPRI;
 		spin_unlock_irqrestore(&zaptimerlock, flags);
-	} else
-		ret = -EINVAL;
-	return ret;
+#if defined(__FreeBSD__)
+	if ((ret & events) == 0)
+		selrecord(td, &timer->sel);
+	return (ret & events);
+#else
+	return (ret);
+#endif
 }
 
 /* device poll routine */
-static unsigned int
-dahdi_chan_poll(struct file *file, struct poll_table_struct *wait_table, int unit)
+static int
+dahdi_chan_poll(FOP_POLL_ARGS_DECL, int unit)
 {
-
 	struct dahdi_chan *chan = chans[unit];
 	int	ret;
 	unsigned long flags;
 
 	  /* do the poll wait */
-	if (chan) {
+	if (!chan) {
+#if defined(__FreeBSD__)
+		return (0);
+#else
+		ret = _RETVAL(EINVAL);
+#endif
+	}
+
+#if !defined(__FreeBSD__)
 		poll_wait(file, &chan->sel, wait_table);
+#endif
 		ret = 0; /* start with nothing to return */
 		spin_lock_irqsave(&chan->lock, flags);
 		   /* if at least 1 write buffer avail */
@@ -7679,54 +8190,65 @@
 		if ((chan->outreadbuf > -1) && !chan->rxdisable) {
 			ret |= POLLIN | POLLRDNORM;
 		}
-		if (chan->eventoutidx != chan->eventinidx)
-		   {
+	if (chan->eventoutidx != chan->eventinidx) {
 			/* Indicate an exception */
 			ret |= POLLPRI;
 		   }
 		spin_unlock_irqrestore(&chan->lock, flags);
-	} else
-		ret = -EINVAL;
+
+#if defined(__FreeBSD__)
+	if ((ret & events) == 0)
+		selrecord(td, &chan->sel);
+	return (ret & events);
+#else
 	return(ret);  /* return what we found */
+#endif
 }
 
-static int dahdi_mmap(struct file *file, struct vm_area_struct *vm)
+static int dahdi_mmap(FOP_MMAP_ARGS_DECL)
 {
+#if !defined(__FreeBSD__)
 	int unit = UNIT(file);
-	if (unit == 250)
+	if (unit == DAHDI_MINOR_TRANSCODE)
 		return dahdi_transcode_fops->mmap(file, vm);
-	return -ENOSYS;
+#endif
+	return _RETVAL(ENOSYS);
 }
 
-static unsigned int dahdi_poll(struct file *file, struct poll_table_struct *wait_table)
+static poll_retval_t dahdi_poll(FOP_POLL_ARGS_DECL)
 {
 	int unit = UNIT(file);
 	struct dahdi_chan *chan;
 
 	if (!unit)
-		return -EINVAL;
+		return _RETVAL(EINVAL);
 
-	if (unit == 250)
-		return dahdi_transcode_fops->poll(file, wait_table);
+	if (unit == DAHDI_MINOR_TRANSCODE) {
+#if defined(__FreeBSD__)
+		return _RETVAL(ENXIO);
+#else
+		return dahdi_transcode_fops->poll(FOP_POLL_ARGS);
+#endif
+	}
 
-	if (unit == 253)
-		return dahdi_timer_poll(file, wait_table);
+	if (unit == DAHDI_MINOR_TIMER)
+		return dahdi_timer_poll(FOP_POLL_ARGS);
 
-	if (unit == 254) {
-		chan = file->private_data;
+	if (unit == DAHDI_MINOR_CHANNEL) {
+		chan = dahdi_get_private_data(file);
 		if (!chan)
-			return -EINVAL;
-		return dahdi_chan_poll(file, wait_table,chan->channo);
+			return _RETVAL(EINVAL);
+		return dahdi_chan_poll(FOP_POLL_ARGS, chan->channo);
 	}
-	if (unit == 255) {
-		chan = file->private_data;
+	if (unit == DAHDI_MINOR_PSEUDO) {
+		chan = dahdi_get_private_data(file);
 		if (!chan) {
 			module_printk(KERN_NOTICE, "No pseudo channel structure to read?\n");
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 		}
-		return dahdi_chan_poll(file, wait_table, chan->channo);
+		return dahdi_chan_poll(FOP_POLL_ARGS, chan->channo);
 	}
-	return dahdi_chan_poll(file, wait_table, unit);
+	return dahdi_chan_poll(FOP_POLL_ARGS, unit);
 }
 
 static void __dahdi_transmit_chunk(struct dahdi_chan *chan, unsigned char *buf)
@@ -8141,8 +8663,9 @@
 					do {
 						data[pos++] = span->chans[z]->readchunk[y];
 						if (pos == DAHDI_CHUNKSIZE) {
-							if(!(span->chans[x]->flags & DAHDI_FLAG_NOSTDTXRX))
+							if(!(span->chans[x]->flags & DAHDI_FLAG_NOSTDTXRX)) {
 								__dahdi_receive_chunk(span->chans[x], data);
+							}
 							pos = 0;
 						}
 						z=span->chans[z]->nextslave;
@@ -8150,9 +8673,10 @@
 				}
 			} else {
 				/* Process a normal channel */
-				if (!(span->chans[x]->flags & DAHDI_FLAG_NOSTDTXRX))
+				if (!(span->chans[x]->flags & DAHDI_FLAG_NOSTDTXRX)) {
 					__dahdi_real_receive(span->chans[x]);
 			}
+			}
 			if (span->chans[x]->itimer) {
 				span->chans[x]->itimer -= DAHDI_CHUNKSIZE;
 				if (span->chans[x]->itimer <= 0) {
@@ -8210,6 +8734,7 @@
 	return 0;
 }
 
+#if !defined(__FreeBSD__)
 MODULE_AUTHOR("Mark Spencer <markster@digium.com>");
 MODULE_DESCRIPTION("DAHDI Telephony Interface");
 MODULE_LICENSE("GPL v2");
@@ -8232,6 +8757,7 @@
 	.fsync   = NULL,
 	.fasync  = NULL,
 };
+#endif /* !__FreeBSD__ */
 
 #ifdef CONFIG_DAHDI_WATCHDOG
 static struct timer_list watchdogtimer;
@@ -8295,18 +8821,30 @@
 
 int dahdi_register_chardev(struct dahdi_chardev *dev)
 {
+#if defined(__FreeBSD__)
+	dev->dev = make_dev(&dahdi_devsw, dev->minor,
+	    UID_ROOT, GID_WHEEL, 0644,
+	    "dahdi/%s", dev->name);
+#else
 	char udevname[strlen(dev->name) + sizeof("dahdi!")];
 
 	strcpy(udevname, "dahdi!");
 	strcat(udevname, dev->name);
 	CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, dev->minor), NULL, udevname);
-
+#endif /* !__FreeBSD__ */
 	return 0;
 }
 
 int dahdi_unregister_chardev(struct dahdi_chardev *dev)
 {
+#if defined(__FreeBSD__)
+	if (dev->dev) {
+		destroy_dev(dev->dev);
+		dev->dev = NULL;
+	}
+#else
 	CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, dev->minor));
+#endif /* !__FreeBSD__ */
 
 	return 0;
 }
@@ -8314,21 +8852,38 @@
 static int __init dahdi_init(void)
 {
 	int res = 0;
+#if defined(__FreeBSD__)
+	struct cdev *dev;
+#endif
 
 #ifdef CONFIG_PROC_FS
 	proc_entries[0] = proc_mkdir("dahdi", NULL);
 #endif
 
+#if defined(__FreeBSD__)
+	dev_ctl = make_dev(&dahdi_devsw, DAHDI_MINOR_CTL,
+	    UID_ROOT, GID_WHEEL, 0644, "dahdi/ctl");
+	dev = make_dev(&dahdi_devsw, DAHDI_MINOR_TIMER,
+	    UID_ROOT, GID_WHEEL, 0644, "dahdi/timer");
+	dev_depends(dev_ctl, dev);
+	dev = make_dev(&dahdi_devsw, DAHDI_MINOR_CHANNEL,
+	    UID_ROOT, GID_WHEEL, 0644, "dahdi/channel");
+	dev_depends(dev_ctl, dev);
+	dev = make_dev(&dahdi_devsw, DAHDI_MINOR_PSEUDO,
+	    UID_ROOT, GID_WHEEL, 0644, "dahdi/pseudo");
+	dev_depends(dev_ctl, dev);
+#else /* !__FreeBSD__ */
 	if ((res = register_chrdev(DAHDI_MAJOR, "dahdi", &dahdi_fops))) {
 		module_printk(KERN_ERR, "Unable to register DAHDI character device handler on %d\n", DAHDI_MAJOR);
 		return res;
 	}
 
 	dahdi_class = class_create(THIS_MODULE, "dahdi");
-	CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, 253), NULL, "dahdi!timer");
-	CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, 254), NULL, "dahdi!channel");
-	CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, 255), NULL, "dahdi!pseudo");
-	CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, 0), NULL, "dahdi!ctl");
+	CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, DAHDI_MINOR_TIMER), NULL, "dahdi!timer");
+	CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, DAHDI_MINOR_CHANNEL), NULL, "dahdi!channel");
+	CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, DAHDI_MINOR_PSEUDO), NULL, "dahdi!pseudo");
+	CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, DAHDI_MINOR_CTL), NULL, "dahdi!ctl");
+#endif
 
 	module_printk(KERN_INFO, "Telephony Interface Registered on major %d\n", DAHDI_MAJOR);
 	module_printk(KERN_INFO, "Version: %s\n", DAHDI_VERSION);
@@ -8348,13 +8903,20 @@
 
 	coretimer_cleanup();
 
-	CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, 253)); /* timer */
-	CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, 254)); /* channel */
-	CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, 255)); /* pseudo */
-	CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, 0)); /* ctl */
+#if defined(__FreeBSD__)
+	if (dev_ctl != NULL) {
+		destroy_dev(dev_ctl);
+		dev_ctl = NULL;
+	}
+#else
+	CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, DAHDI_MINOR_TIMER)); /* timer */
+	CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, DAHDI_MINOR_CHANNEL)); /* channel */
+	CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, DAHDI_MINOR_PSEUDO)); /* pseudo */
+	CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, DAHDI_MINOR_CTL)); /* ctl */
 	class_destroy(dahdi_class);
 
 	unregister_chrdev(DAHDI_MAJOR, "dahdi");
+#endif
 
 #ifdef CONFIG_PROC_FS
 	remove_proc_entry("dahdi", NULL);
@@ -8371,5 +8933,28 @@
 #endif
 }
 
+#if defined(__FreeBSD__)
+static int
+dahdi_modevent(module_t mod, int cmd, void *arg)
+{
+	switch (cmd) {
+	case MOD_LOAD:
+		return dahdi_init();
+
+	case MOD_UNLOAD:
+		dahdi_cleanup();
+		return 0;
+
+	default:
+		/* we only understand load/unload*/
+		return _RETVAL(EINVAL);
+	}
+}
+
+/* Now declare the module to the system */
+MODULE_VERSION(dahdi, 1);
+DEV_MODULE(dahdi, dahdi_modevent, NULL);
+#else /* !__FreeBSD__ */
 module_init(dahdi_init);
 module_exit(dahdi_cleanup);
+#endif /* !__FreeBSD__ */
Index: drivers/dahdi/dahdi_echocan_kb1.c
===================================================================
--- drivers/dahdi/dahdi_echocan_kb1.c	(revision 7107)
+++ drivers/dahdi/dahdi_echocan_kb1.c	(working copy)
@@ -31,6 +31,18 @@
  * this program for more details.
  */
 
+#if defined(__FreeBSD__)
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/conf.h>
+#include <sys/ctype.h>
+#include <sys/libkern.h>
+#include <sys/module.h>
+
+#define module_printk(level, fmt, args...) printf(fmt, ## args)
+#define debug_printk(level, fmt, args...) if (debug >= level) printf("%s: " fmt, __FUNCTION__, ## args)
+
+#else /* !__FreeBSD__ */
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
@@ -39,14 +51,15 @@
 #include <linux/ctype.h>
 #include <linux/moduleparam.h>
 
+#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
+#define debug_printk(level, fmt, args...) if (debug >= level) printk(KERN_DEBUG "%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
+#endif /* !__FreeBSD__ */
+
 #include <dahdi/kernel.h>
 
 static int debug;
 static int aggressive;
 
-#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
-#define debug_printk(level, fmt, args...) if (debug >= level) printk(KERN_DEBUG "%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
-
 /* Uncomment to provide summary statistics for overall echo can performance every 4000 samples */ 
 /* #define MEC2_STATS 4000 */
 
@@ -151,8 +164,10 @@
 
 static const struct dahdi_echocan_factory my_factory = {
 	.name = "KB1",
+	.echocan_create = echo_can_create,
+#if !defined(__FreeBSD__)
 	.owner = THIS_MODULE,
-	.echocan_create = echo_can_create,
+#endif
 };
 
 static const struct dahdi_echocan_features my_features = {
@@ -270,7 +285,7 @@
 	unsigned long tmp;
 
 	/* Double-word align past end of state */
-	ptr += sizeof(*pvt);
+	ptr = (char *) ptr + sizeof(*pvt);
 	tmp = (unsigned long)ptr;
 	tmp += 3;
 	tmp &= ~3L;
@@ -282,20 +297,20 @@
   
 	/* Allocate coefficient memory */
 	pvt->a_i = ptr;
-	ptr += (sizeof(int) * pvt->N_d);
+	ptr = (char *) ptr + (sizeof(int) * pvt->N_d);
 	pvt->a_s = ptr;
-	ptr += (sizeof(short) * pvt->N_d);
+	ptr = (char *) ptr + (sizeof(short) * pvt->N_d);
 
 	/* Reset Y circular buffer (short version) */
 	init_cb_s(&pvt->y_s, maxy, ptr);
-	ptr += (sizeof(short) * (maxy) * 2);
+	ptr = (char *) ptr + (sizeof(short) * (maxy) * 2);
   
 	/* Reset Sigma circular buffer (short version for FIR filter) */
 	init_cb_s(&pvt->s_s, (1 << DEFAULT_ALPHA_ST_I), ptr);
-	ptr += (sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) * 2);
+	ptr = (char *) ptr + (sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) * 2);
 
 	init_cb_s(&pvt->u_s, maxu, ptr);
-	ptr += (sizeof(short) * maxu * 2);
+	ptr = (char *) ptr + (sizeof(short) * maxu * 2);
 
 	/* Allocate a buffer for the reference signal power computation */
 	init_cb_s(&pvt->y_tilde_s, pvt->N_d, ptr);
@@ -658,7 +673,7 @@
 
 	pvt = kzalloc(size, GFP_KERNEL);
 	if (!pvt)
-		return -ENOMEM;
+		return _RETVAL(ENOMEM);
 
 	pvt->dahdi.ops = &my_ops;
 
@@ -674,7 +689,7 @@
 			printk(KERN_WARNING "Unknown parameter supplied to KB1 echo canceler: '%s'\n", p[x].name);
 			kfree(pvt);
 
-			return -EINVAL;
+			return _RETVAL(EINVAL);
 		}
 	}
 
@@ -719,12 +734,10 @@
 {
 	if (dahdi_register_echocan_factory(&my_factory)) {
 		module_printk(KERN_ERR, "could not register with DAHDI core\n");
-
-		return -EPERM;
+		return _RETVAL(EPERM);
 	}
 
 	module_printk(KERN_NOTICE, "Registered echo canceler '%s'\n", my_factory.name);
-
 	return 0;
 }
 
@@ -733,6 +746,26 @@
 	dahdi_unregister_echocan_factory(&my_factory);
 }
 
+#if defined(__FreeBSD__)
+static int
+echocan_kb1_modevent(module_t mod __unused, int type, void *data __unused)
+{
+	switch (type) {
+	case MOD_LOAD:
+		return mod_init();
+	case MOD_UNLOAD:
+		mod_exit();
+		return 0;
+	default:
+		return _RETVAL(EOPNOTSUPP);
+	}
+}
+
+DEV_MODULE(dahdi_echocan_kb1, echocan_kb1_modevent, NULL);
+MODULE_VERSION(dahdi_echocan_kb1, 1);
+MODULE_DEPEND(dahdi_echocan_kb1, dahdi, 1, 1, 1);
+
+#else /* !__FreeBSD__ */
 module_param(debug, int, S_IRUGO | S_IWUSR);
 module_param(aggressive, int, S_IRUGO | S_IWUSR);
 
@@ -742,3 +775,4 @@
 
 module_init(mod_init);
 module_exit(mod_exit);
+#endif /* !__FreeBSD__ */
Index: drivers/dahdi/ecdis.h
===================================================================
--- drivers/dahdi/ecdis.h	(revision 7107)
+++ drivers/dahdi/ecdis.h	(working copy)
@@ -29,7 +29,9 @@
 #include "biquad.h"
 
 #define FALSE 0
+#ifndef TRUE
 #define TRUE (!FALSE)
+#endif
 
 static inline void echo_can_disable_detector_init (echo_can_disable_detector_state_t *det)
 {
Index: drivers/dahdi/dahdi_echocan_sec2.c
===================================================================
--- drivers/dahdi/dahdi_echocan_sec2.c	(revision 7107)
+++ drivers/dahdi/dahdi_echocan_sec2.c	(working copy)
@@ -35,6 +35,18 @@
    Improve double talk detector (iterative!)
 */
 
+#if defined(__FreeBSD__)
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/conf.h>
+#include <sys/ctype.h>
+#include <sys/libkern.h>
+#include <sys/module.h>
+
+#define module_printk(level, fmt, args...) printf(fmt, ## args)
+#define debug_printk(level, fmt, args...) if (debug >= level) printf("%s: " fmt, __FUNCTION__, ## args)
+
+#else /* !__FreeBSD__ */
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
@@ -43,13 +55,14 @@
 #include <linux/ctype.h>
 #include <linux/moduleparam.h>
 
+#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
+#define debug_printk(level, fmt, args...) if (debug >= level) printk(KERN_DEBUG "%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
+#endif /* !__FreeBSD__ */
+
 #include <dahdi/kernel.h>
 
 static int debug;
 
-#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
-#define debug_printk(level, fmt, args...) if (debug >= level) printk(KERN_DEBUG "%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
-
 #include "fir.h"
 
 #ifndef NULL
@@ -84,8 +97,10 @@
 
 static const struct dahdi_echocan_factory my_factory = {
 	.name = "SEC2",
+	.echocan_create = echo_can_create,
+#if !defined(__FreeBSD__)
 	.owner = THIS_MODULE,
-	.echocan_create = echo_can_create,
+#endif
 };
 
 static const struct dahdi_echocan_ops my_ops = {
@@ -135,20 +150,19 @@
 
 	if (ecp->param_count > 0) {
 		printk(KERN_WARNING "SEC2 does not support parameters; failing request\n");
-		return -EINVAL;
+		return _RETVAL(EINVAL);
 	}
 
 	size = sizeof(*pvt) + ecp->tap_length * sizeof(int32_t) + ecp->tap_length * 3 * sizeof(int16_t);
-	
 	pvt = kzalloc(size, GFP_KERNEL);
 	if (!pvt)
-		return -ENOMEM;
+		return _RETVAL(ENOMEM);
 
 	pvt->dahdi.ops = &my_ops;
 
 	if (ecp->param_count > 0) {
 		printk(KERN_WARNING "SEC-2 echo canceler does not support parameters; failing request\n");
-		return -EINVAL;
+		return _RETVAL(EINVAL);
 	}
 
 	pvt->taps = ecp->tap_length;
@@ -328,7 +342,7 @@
 	if (dahdi_register_echocan_factory(&my_factory)) {
 		module_printk(KERN_ERR, "could not register with DAHDI core\n");
 
-		return -EPERM;
+		return _RETVAL(EPERM);
 	}
 
 	module_printk(KERN_NOTICE, "Registered echo canceler '%s'\n", my_factory.name);
@@ -341,6 +355,26 @@
 	dahdi_unregister_echocan_factory(&my_factory);
 }
 
+#if defined(__FreeBSD__)
+static int
+echocan_sec2_modevent(module_t mod __unused, int type, void *data __unused)
+{
+	switch (type) {
+	case MOD_LOAD:
+		return mod_init();
+	case MOD_UNLOAD:
+		mod_exit();
+		return 0;
+	default:
+		return _RETVAL(EOPNOTSUPP);
+	}
+}
+
+DEV_MODULE(dahdi_echocan_sec2, echocan_sec2_modevent, NULL);
+MODULE_VERSION(dahdi_echocan_sec2, 1);
+MODULE_DEPEND(dahdi_echocan_sec2, dahdi, 1, 1, 1);
+
+#else /* !__FreeBSD__ */
 module_param(debug, int, S_IRUGO | S_IWUSR);
 
 MODULE_DESCRIPTION("DAHDI 'SEC2' Echo Canceler");
@@ -349,3 +383,4 @@
 
 module_init(mod_init);
 module_exit(mod_exit);
+#endif /* !__FreeBSD__ */
Index: drivers/dahdi/wcb4xxp/wcb4xxp.h
===================================================================
--- drivers/dahdi/wcb4xxp/wcb4xxp.h	(revision 7107)
+++ drivers/dahdi/wcb4xxp/wcb4xxp.h	(working copy)
@@ -6,7 +6,9 @@
 #ifndef _B4XX_H_
 #define _B4XX_H_
 
+#if !defined(__FreeBSD__)
 #include <linux/ioctl.h>
+#endif
 
 #define HFC_NR_FIFOS	32
 #define HFC_ZMIN	0x80			/* from datasheet */
@@ -432,11 +434,25 @@
 	char *variety;
 	int chiprev;				/* revision of HFC-4S */
 
+#if defined(__FreeBSD__)
+	device_t dev;				/* device */
+
+	struct resource *io_res;		/* resource for I/O range */
+	int io_rid;
+
+	struct resource *mem_res;		/* resource for memory range */
+	int mem_rid;
+
+	struct resource *irq_res;		/* resource for irq */
+	int irq_rid;
+	void *irq_handle;
+#else
 	struct pci_dev *pdev;			/* Pointer to PCI device */
 	struct device *dev;			/* kernel dev struct (from pdev->dev) */
 	void __iomem *addr;			/* I/O address (memory mapped) */
 	void __iomem *ioaddr;			/* I/O address (index based) */
 	int irq;				/* IRQ used by device */
+#endif
 
 	spinlock_t reglock;			/* lock for all register accesses */
 	spinlock_t seqlock;			/* lock for "sequence" accesses that must be ordered */
@@ -473,7 +489,9 @@
 
 	/* Flags for our bottom half */
 	unsigned int shutdown;			/* 1=bottom half doesn't process anything, just returns */
+#if !defined(__FreeBSD__)
 	struct tasklet_struct b4xxp_tlet;
+#endif
 };
 
 /* CPLD access bits */
@@ -501,7 +519,7 @@
 #define LED_RED		(1)
 #define LED_GREEN	(2)
 
-#define get_F(f1, f2, flen) {				\
+#define get_F(b4, f1, f2, flen) {			\
 	f1 = hfc_readcounter8(b4, A_F1);		\
 	f2 = hfc_readcounter8(b4, A_F2);		\
 	flen = f1 - f2;					\
@@ -510,7 +528,7 @@
 		flen += (HFC_FMAX - HFC_FMIN) + 1;	\
 	}
 
-#define get_Z(z1, z2, zlen) {				\
+#define get_Z(b4, z1, z2, zlen) {			\
 	z1 = hfc_readcounter16(b4, A_Z1);		\
 	z2 = hfc_readcounter16(b4, A_Z2);		\
 	zlen = z1 - z2;					\
@@ -519,7 +537,14 @@
 		zlen += (HFC_ZMAX - HFC_ZMIN) + 1;	\
 	}
 
+#if defined(__FreeBSD__)
+#define flush_pci()	(void) bus_space_read_1(	\
+	rman_get_bustag(b4->mem_res),			\
+	rman_get_bushandle(b4->mem_res),		\
+	R_STATUS)
+#else
 #define flush_pci()	(void)ioread8(b4->addr + R_STATUS)
+#endif
 
 #endif	/* __KERNEL__ */
 #endif	/* _B4XX_H_ */
Index: drivers/dahdi/wcb4xxp/base.c
===================================================================
--- drivers/dahdi/wcb4xxp/base.c	(revision 7107)
+++ drivers/dahdi/wcb4xxp/base.c	(working copy)
@@ -20,6 +20,26 @@
  * this program for more details.
  */
 
+#if defined(__FreeBSD__)
+#include <sys/types.h>
+#include <sys/bus.h>
+#include <sys/module.h>
+#include <sys/queue.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
+
+#include <machine/bus.h>
+#include <machine/stdarg.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#define mb()
+#define wmb()
+#define mmiowb()
+
+#define printk_ratelimit()	1
+
+#else /* !__FreeBSD__ */
 #include <linux/autoconf.h>
 #include <linux/init.h>
 
@@ -42,6 +62,7 @@
 #include <linux/timer.h>	/* timer_struct */
 #include <linux/moduleparam.h>
 #include <linux/proc_fs.h>
+#endif /* !__FreeBSD__ */
 
 #include <dahdi/kernel.h>
 
@@ -55,7 +76,6 @@
 #define IS_SET(x, i)     (((x) & BIT(i)) != 0)
 #define BITMASK(i)      (((u64)1 << (i)) - 1)
 
-
 #if (DAHDI_CHUNKSIZE != 8)
 #error Sorry, wcb4xxp does not support chunksize != 8
 #endif
@@ -88,8 +108,10 @@
 #ifdef LOOPBACK_SUPPORTED
 static int loopback = 0;
 #endif
+#if !defined(__FreeBSD__)
 static int milliwatt = 0;
 static int pedanticpci = 0;
+#endif
 static int teignorered = 0;
 static int alarmdebounce = 500;
 static int vpmsupport = 1;
@@ -170,8 +192,82 @@
  * has the effect of flushing any pending PCI writes.
  */
 
+#if defined(__FreeBSD__)
+static void device_rlprintf(int pps, device_t dev, const char *fmt, ...)
+{
+	va_list ap;
+	static struct timeval last_printf;
+	static int count;
+
+	if (ppsratecheck(&last_printf, &count, pps)) {
+		va_start(ap, fmt);
+		device_print_prettyname(dev);
+		vprintf(fmt, ap);
+		va_end(ap);
+	}
+}
+
+#define DPRINTF(dev, fmt, args...)	device_rlprintf(10, dev, fmt, ##args)
+
 static inline unsigned char __pci_in8(struct b4xxp *b4, const unsigned int reg)
 {
+        return bus_space_read_1(
+	    rman_get_bustag(b4->mem_res), rman_get_bushandle(b4->mem_res),
+	    reg);
+}
+
+static inline unsigned short __pci_in16(struct b4xxp *b4, const unsigned int reg)
+{
+        return bus_space_read_2(
+	    rman_get_bustag(b4->mem_res), rman_get_bushandle(b4->mem_res),
+	    reg);
+}
+
+static inline unsigned int __pci_in32(struct b4xxp *b4, const unsigned int reg)
+{
+        return bus_space_read_4(
+	    rman_get_bustag(b4->mem_res), rman_get_bushandle(b4->mem_res),
+	    reg);
+}
+
+static inline unsigned char __reg_in8(struct b4xxp *b4, const unsigned int reg)
+{
+        return bus_space_read_1(
+	    rman_get_bustag(b4->io_res), rman_get_bushandle(b4->io_res),
+	    reg);
+}
+
+static inline void __pci_out8(struct b4xxp *b4, const unsigned int reg, const unsigned char val)
+{
+        bus_space_write_1(
+	    rman_get_bustag(b4->mem_res), rman_get_bushandle(b4->mem_res),
+	    reg, val);
+}
+
+static inline void __pci_out32(struct b4xxp *b4, const unsigned int reg, const unsigned int val)
+{
+        bus_space_write_4(
+	    rman_get_bustag(b4->mem_res), rman_get_bushandle(b4->mem_res),
+	    reg, val);
+}
+
+static inline void __reg_out16(struct b4xxp *b4, const unsigned int reg, const unsigned short val)
+{
+        bus_space_write_2(
+	    rman_get_bustag(b4->io_res), rman_get_bushandle(b4->io_res),
+	    reg, val);
+}
+
+static inline void __reg_out32(struct b4xxp *b4, const unsigned int reg, const unsigned int val)
+{
+        bus_space_write_4(
+	    rman_get_bustag(b4->io_res), rman_get_bushandle(b4->io_res),
+	    reg, val);
+}
+
+#else /* !__FreeBSD__ */
+static inline unsigned char __pci_in8(struct b4xxp *b4, const unsigned int reg)
+{
 	unsigned char ret = ioread8(b4->addr + reg);
 
 #ifdef DEBUG_LOWLEVEL_REGS
@@ -215,6 +311,11 @@
 	return ret;
 }
 
+static inline unsigned char __reg_in8(struct b4xxp *b4, const unsigned int reg)
+{
+	return ioread8(b4->ioaddr + reg);
+}
+
 static inline void __pci_out32(struct b4xxp *b4, const unsigned int reg, const unsigned int val)
 {
 #ifdef DEBUG_LOWLEVEL_REGS
@@ -243,7 +344,17 @@
 	}
 }
 
+static inline void __reg_out16(struct b4xxp *b4, const unsigned int reg, const unsigned short val)
+{
+	iowrite16(val, b4->ioaddr + reg);
+}
 
+static inline void __reg_out32(struct b4xxp *b4, const unsigned int reg, const unsigned int val)
+{
+	iowrite32(val, b4->ioaddr + reg);
+}
+#endif /* !__FreeBSD__ */
+
 /*
  * Standard I/O access functions
  * uses spinlocks to protect against multiple I/O accesses
@@ -291,7 +402,7 @@
 
 #ifndef DEBUG_LOWLEVEL_REGS
 	if (unlikely(DBG_REGS)) {
-		dev_dbg(b4->dev, "read 0x%02x from 0x%p\n", ret, b4->addr + reg);
+		dev_dbg(b4->dev, "read 0x%02x from 0x%x\n", ret, reg);
 	}
 #endif
 	return ret;
@@ -308,7 +419,7 @@
 
 #ifndef DEBUG_LOWLEVEL_REGS
 	if (unlikely(DBG_REGS)) {
-		dev_dbg(b4->dev, "read 0x%04x from 0x%p\n", ret, b4->addr + reg);
+		dev_dbg(b4->dev, "read 0x%04x from 0x%x\n", ret, reg);
 	}
 #endif
 	return ret;
@@ -325,7 +436,7 @@
 
 #ifndef DEBUG_LOWLEVEL_REGS
 	if (unlikely(DBG_REGS)) {
-		dev_dbg(b4->dev, "read 0x%04x from 0x%p\n", ret, b4->addr + reg);
+		dev_dbg(b4->dev, "read 0x%04x from 0x%x\n", ret, reg);
 	}
 #endif
 	return ret;
@@ -337,7 +448,7 @@
 
 #ifndef DEBUG_LOWLEVEL_REGS
 	if (unlikely(DBG_REGS)) {
-		dev_dbg(b4->dev, "writing 0x%02x to 0x%p\n", val, b4->addr + reg);
+		dev_dbg(b4->dev, "writing 0x%02x to 0x%x\n", val, reg);
 	}
 #endif
 	spin_lock_irqsave(&b4->reglock, irq_flags);
@@ -351,7 +462,7 @@
 
 #ifndef DEBUG_LOWLEVEL_REGS
 	if (unlikely(DBG_REGS)) {
-		dev_dbg(b4->dev, "writing 0x%02x to 0x%p\n", val, b4->addr + reg);
+		dev_dbg(b4->dev, "writing 0x%02x to 0x%x\n", val, reg);
 	}
 #endif
 	spin_lock_irqsave(&b4->reglock, irq_flags);
@@ -479,9 +590,9 @@
 		cipv=0x5800;
 
 /* select local bridge port address by writing to CIP port */
-	iowrite16(cipv, b4->ioaddr + 4);
+	__reg_out16(b4, 4, cipv);
 	wmb();
-	data = ioread8(b4->ioaddr);
+	data = __reg_in8(b4, 0);
 
 /* restore R_CTRL for normal PCI read cycle speed */
 	b4xxp_setreg8(b4, R_CTRL, 0x0);
@@ -503,7 +614,7 @@
 		cipv=0x5800;
 
 /* select local bridge port address by writing to CIP port */
-	iowrite16(cipv, b4->ioaddr + 4);
+	__reg_out16(b4, 4, cipv);
 	wmb();
 
 /* define a 32 bit dword with 4 identical bytes for write sequence */
@@ -516,7 +627,7 @@
  * the number of write accesses is undefined but >=1 and depends on the next PCI transaction
  * during write sequence on the local bus
  */
-	iowrite32(datav, b4->ioaddr);
+	__reg_out32(b4, 0, datav);
 	wmb();
 	flush_pci();
 }
@@ -1506,7 +1617,7 @@
 /* select RX FIFO */
 	hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT) | V_FIFO_DIR | V_REV);
 
-	get_Z(z1, z2, zlen);
+	get_Z(b4, z1, z2, zlen);
 
 /* TODO: error checking, full FIFO mostly */
 
@@ -1574,8 +1685,8 @@
 {
 	int f1, f2, flen, z1, z2, zlen;
 
-	get_F(f1, f2, flen);
-	get_Z(z1, z2, zlen);
+	get_F(b4, f1, f2, flen);
+	get_Z(b4, z1, z2, zlen);
 
 	sprintf(buf, "%s: (fifo %d): f1/f2/flen=%d/%d/%d, z1/z2/zlen=%d/%d/%d\n", prefix, fifo, f1, f2, flen, z1, z2, zlen);
 }
@@ -1620,8 +1731,8 @@
 
 	spin_lock_irqsave(&b4->fifolock, irq_flags);
 	hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT) | V_FIFO_DIR);
-	get_F(f1, f2, flen);
-	get_Z(z1, z2, zlen);
+	get_F(b4, f1, f2, flen);
+	get_Z(b4, z1, z2, zlen);
 	debug_fz(b4, fifo, "hdlc_rx_frame", debugbuf);
 	spin_unlock_irqrestore(&b4->fifolock, irq_flags);
 
@@ -1668,7 +1779,7 @@
 /* Frame received, increment F2 and get an updated count of frames left */
 	spin_lock_irqsave(&b4->fifolock, irq_flags);
 	hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_INC_F);
-	get_F(f1, f2, flen);
+	get_F(b4, f1, f2, flen);
 	spin_unlock_irqrestore(&b4->fifolock, irq_flags);
 
 	/* If this channel is not configured with a signalling span we don't
@@ -1736,7 +1847,7 @@
 	spin_lock_irqsave(&b4->fifolock, irq_flags);
 	hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT));
 
-	get_Z(z1, z2, zlen);
+	get_Z(b4, z1, z2, zlen);
 	debug_fz(b4, fifo, "hdlc_tx_frame", debugbuf);
 
 /* TODO: check zlen, etc. */
@@ -1964,8 +2075,8 @@
 	/* Write Leds...*/
 	leddw = lled << 24 | lled << 16 | lled << 8 | lled;
 	b4xxp_setreg8(b4, R_BRG_PCM_CFG, 0x21);
-	iowrite16(0x4000, b4->ioaddr + 4);
-	iowrite32(leddw, b4->ioaddr);
+	__reg_out16(b4, 4, 0x4000);
+	__reg_out32(b4, 0, leddw);
 	b4xxp_setreg8(b4, R_BRG_PCM_CFG, 0x20);
 
 	if (b4->blinktimer == 0xff)
@@ -2306,7 +2417,11 @@
 		bspan = &b4->spans[i];
 		bspan->parent = b4;
 
+#if defined(__FreeBSD__)
+		bspan->span.irq = bus_get_resource_start(b4->dev, SYS_RES_IRQ, b4->irq_rid);
+#else
 		bspan->span.irq = b4->pdev->irq;
+#endif
 		bspan->span.pvt = bspan;
 		bspan->span.spantype = (bspan->te_mode) ? "TE" : "NT";
 		bspan->span.offset = i;
@@ -2325,10 +2440,14 @@
 		sprintf(bspan->span.desc, "B4XXP (PCI) Card %d Span %d", b4->cardno, i+1);
 		bspan->span.manufacturer = "Digium";
 		dahdi_copy_string(bspan->span.devicetype, b4->variety, sizeof(bspan->span.devicetype));
+#if !defined(__FreeBSD__)
 		sprintf(bspan->span.location, "PCI Bus %02d Slot %02d",
 			b4->pdev->bus->number, PCI_SLOT(b4->pdev->devfn) + 1);
+#endif
 
+#if !defined(__FreeBSD__)
 		bspan->span.owner = THIS_MODULE;
+#endif
 		bspan->span.spanconfig = b4xxp_spanconfig;
 		bspan->span.chanconfig = b4xxp_chanconfig;
 		bspan->span.startup = b4xxp_startup;
@@ -2379,8 +2498,13 @@
 
 	/* Make sure it's really for us */
 	status = __pci_in8(b4, R_STATUS);
-	if (!(status & HFC_INTS))
+	if (!(status & HFC_INTS)) {
+#if defined(__FreeBSD__)
+		return (FILTER_STRAY);
+#else
 		return IRQ_NONE;
+#endif
+	}
 
 /*
  * since the interrupt is for us, read in the FIFO and misc IRQ status registers.
@@ -2420,10 +2544,20 @@
 	}
 
 /* kick off bottom-half handler */
-	/* tasklet_hi_schedule(&b4->b4xxp_tlet); */
+#if 0
+#if defined(__FreeBSD__)
+	return (FILTER_HANDLED | FILTER_SCHEDULE_THREAD);
+#else
+	tasklet_hi_schedule(&b4->b4xxp_tlet);
+#endif
+#endif
 	b4xxp_bottom_half((unsigned long)b4);
 
+#if defined(__FreeBSD__)
+	return (FILTER_HANDLED);
+#else
 	return IRQ_RETVAL(1);
+#endif
 }
 
 
@@ -2664,54 +2798,25 @@
 	return b4xxp_spanconfig(&b4->spans[0].span, &lc);
 }
 
-static int __devinit b4xx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int b4xxp_setup_intr(struct b4xxp *b4);
+static void b4xxp_release_intr(struct b4xxp *b4);
+
+static int b4xxp_register(struct b4xxp *b4, struct devtype *dt)
 {
 	int x, ret;
-	struct b4xxp *b4;
-	struct devtype *dt;
 
-	dt = (struct devtype *)(ent->driver_data);
-	dev_info(&pdev->dev, "probe called for b4xx...\n");
-
-	if ((ret = pci_enable_device(pdev)))
-		goto err_out_disable_pdev;
-
-	if ((ret = pci_request_regions(pdev, dt->desc))) {
-		dev_err(&pdev->dev, "Unable to request regions!\n");
-		goto err_out_disable_pdev;
-	}
-
-	if (!pdev->irq) {			/* we better have an IRQ */
-		dev_err(&pdev->dev, "Device has no associated IRQ?\n");
-		ret = -EIO;
-		goto err_out_release_regions;
-	}
-
-	if (!(b4 = kzalloc(sizeof(struct b4xxp), GFP_KERNEL))) {
-		dev_err(&pdev->dev, "Couldn't allocate memory for b4xxp structure!\n");
-		ret = -ENOMEM;
-		goto err_out_release_regions;
-	}
-
 /* card found, enabled and main struct allocated.  Fill it out. */
 	b4->variety = dt->desc;
 	b4->card_type = dt->card_type;
-	b4->pdev = pdev;
-	b4->dev = &pdev->dev;
-	pci_set_drvdata(pdev, b4);
 
-	b4->ioaddr = pci_iomap(pdev, 0, 0);
-	b4->addr = pci_iomap(pdev, 1, 0);
-	b4->irq = pdev->irq;
-
 	spin_lock_init(&b4->reglock);
 	spin_lock_init(&b4->seqlock);
 	spin_lock_init(&b4->fifolock);
 
 	x = b4xxp_getreg8(b4, R_CHIP_ID);
 	if ((x != 0xc0) && (x != 0x80)) {		/* wrong chip? */
-		dev_err(&pdev->dev, "Unknown/unsupported controller detected (R_CHIP_ID = 0x%02x)\n", x);
-		goto err_out_free_mem;
+		dev_err(b4->dev, "Unknown/unsupported controller detected (R_CHIP_ID = 0x%02x)\n", x);
+		return _RETVAL(ENXIO);
 	}
 
 /* future proofing */
@@ -2728,11 +2833,13 @@
 	b4->syncspan = -1;		/* sync span is unknown */
 	if (b4->numspans > MAX_SPANS_PER_CARD) {
 		dev_err(b4->dev, "Driver does not know how to handle a %d span card!\n", b4->numspans);
-		goto err_out_free_mem;
+		return _RETVAL(ENXIO);
 	}
 
+#if !defined(__FreeBSD__)
 	dev_info(b4->dev, "Identified %s (controller rev %d) at %p, IRQ %i\n",
 		b4->variety, b4->chiprev, b4->ioaddr, b4->irq);
+#endif
 
 /* look for the next free card structure */
 	for (x=0; x < MAX_B4_CARDS; x++) {
@@ -2741,8 +2848,8 @@
 	}
 
 	if (x >= MAX_B4_CARDS) {
-		dev_err(&pdev->dev, "Attempt to register more than %i cards, aborting!\n", MAX_B4_CARDS);
-		goto err_out_free_mem;
+		dev_err(b4->dev, "Attempt to register more than %i cards, aborting!\n", MAX_B4_CARDS);
+		return _RETVAL(ENXIO);
 	}
 
 /* update the cards array, make sure the b4xxp struct knows where in the array it is */
@@ -2751,16 +2858,9 @@
 
 	b4xxp_init_stage1(b4);
 
-	if (request_irq(pdev->irq, b4xxp_interrupt, DAHDI_IRQ_SHARED_DISABLED, "b4xxp", b4)) {
-		dev_err(b4->dev, "Unable to request IRQ %d\n", pdev->irq);
-		ret = -EIO;
+	if ((ret = b4xxp_setup_intr(b4)))
 		goto err_out_del_from_card_array;
-	}
 
-/* initialize the tasklet structure */
-/* TODO: perhaps only one tasklet for any number of cards in the system... don't need one per card I don't think. */
-	tasklet_init(&b4->b4xxp_tlet, b4xxp_bottom_half, (unsigned long)b4);
-
 /* interrupt allocated and tasklet initialized, it's now safe to finish initializing the hardware */
 	b4xxp_init_stage2(b4);
 	hfc_init_all_st(b4);
@@ -2774,8 +2874,6 @@
 		}
 	}
 
-
-
 #if 0
 	/* Launch cards as appropriate */
 	for (;;) {
@@ -2813,7 +2911,7 @@
 	};
 
 	b4xxp_init_stage1(b4);			/* full reset, re-init to "no-irq" state */
-	free_irq(pdev->irq, b4);
+	b4xxp_release_intr(b4);
 
 err_out_del_from_card_array:
 	for (x=0; x < MAX_B4_CARDS; x++) {
@@ -2825,8 +2923,296 @@
 	}
 
 	if (x >= MAX_B4_CARDS)
-		dev_err(&pdev->dev, "b4 struct @ %p should be in cards array but isn't?!\n", b4);
+		dev_err(b4->dev, "b4 struct @ %p should be in cards array but isn't?!\n", b4);
 
+	return ret;
+}
+
+static void b4xxp_unregister(struct b4xxp *b4)
+{
+	int i;
+
+	b4->shutdown = 1;
+
+	for (i = b4->numspans - 1; i >= 0; i--) {
+		dahdi_unregister(&b4->spans[i].span);
+	}
+
+	b4xxp_init_stage1(b4);
+
+	spin_lock_destroy(&b4->reglock);
+	spin_lock_destroy(&b4->seqlock);
+	spin_lock_destroy(&b4->fifolock);
+}
+
+static struct pci_device_id b4xxp_ids[] __devinitdata =
+{
+	{ 0xd161, 0xb410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wcb4xxp },
+	{ 0x1397, 0x16b8, 0x1397, 0xe552, 0, 0, (unsigned long)&hfc8s },
+	{ 0x1397, 0x08b4, 0x1397, 0xb520, 0, 0, (unsigned long)&hfc4s },
+	{ 0x1397, 0x08b4, 0x1397, 0xb556, 0, 0, (unsigned long)&hfc2s },
+	{ 0x1397, 0x08b4, 0x1397, 0xe884, 0, 0, (unsigned long)&hfc2s_OV },
+	{ 0x1397, 0x08b4, 0x1397, 0xe888, 0, 0, (unsigned long)&hfc4s_OV },
+	{ 0x1397, 0x16b8, 0x1397, 0xe998, 0, 0, (unsigned long)&hfc8s_OV },
+	{ 0x1397, 0x08b4, 0x1397, 0xb566, 0, 0, (unsigned long)&hfc2s_BN },
+	{ 0x1397, 0x08b4, 0x1397, 0xb560, 0, 0, (unsigned long)&hfc4s_BN },
+	{ 0x1397, 0x16b8, 0x1397, 0xb562, 0, 0, (unsigned long)&hfc8s_BN },
+	{ 0, }
+};
+
+#if defined(__FreeBSD__)
+static void b4xxp_release_intr(struct b4xxp *b4)
+{
+	if (b4->irq_handle != NULL) {
+		bus_teardown_intr(b4->dev, b4->irq_res, b4->irq_handle);
+		b4->irq_handle = NULL;
+	}
+
+	if (b4->irq_res != NULL) {
+		bus_release_resource(b4->dev, SYS_RES_IRQ, b4->irq_rid, b4->irq_res);
+		b4->irq_res = NULL;
+	}
+}
+
+static void b4xxp_release_resources(struct b4xxp *b4)
+{
+        /* disconnect the interrupt handler */
+	b4xxp_release_intr(b4);
+
+	/* release I/O range */
+	if (b4->io_res != NULL) {
+		bus_deactivate_resource(b4->dev, SYS_RES_IOPORT, b4->io_rid, b4->mem_res);
+		bus_release_resource(b4->dev, SYS_RES_IOPORT, b4->io_rid, b4->io_res);
+		b4->io_res = NULL;
+	}
+
+	/* release memory window */
+	if (b4->mem_res != NULL) {
+		bus_deactivate_resource(b4->dev, SYS_RES_MEMORY, b4->mem_rid, b4->mem_res);
+		bus_release_resource(b4->dev, SYS_RES_MEMORY, b4->mem_rid, b4->mem_res);
+		b4->mem_res = NULL;
+	}
+}
+
+static int b4xxp_setup_intr(struct b4xxp *b4)
+{
+	int error;
+
+	b4->irq_res = bus_alloc_resource_any(
+	     b4->dev, SYS_RES_IRQ, &b4->irq_rid, RF_SHAREABLE | RF_ACTIVE);
+	if (b4->irq_res == NULL) {
+		device_printf(b4->dev, "Can't allocate irq resource\n");
+		return _RETVAL(ENXIO);
+	}
+
+	error = bus_setup_intr(
+	    b4->dev, b4->irq_res, INTR_TYPE_CLK, b4xxp_interrupt, NULL,
+	    b4, &b4->irq_handle);
+	if (error) {
+		device_printf(b4->dev, "Can't setup interrupt handler (error %d)\n", error);
+		b4xxp_release_resources(b4);
+		return _RETVAL(ENXIO);
+	}
+
+	return (0);
+}
+
+static struct pci_device_id *
+b4xxp_pci_device_id_lookup(device_t dev)
+{
+	struct pci_device_id *id;
+	uint16_t vendor = pci_get_vendor(dev);
+	uint16_t device = pci_get_device(dev);
+	uint16_t subdevice = pci_get_subdevice(dev);
+
+	for (id = b4xxp_ids; id->vendor != 0; id++) {
+		if (id->vendor != vendor || id->device != device || id->subdevice != subdevice)
+			continue;
+
+		return id;
+	}
+
+	return NULL;
+}
+
+static int
+b4xxp_device_probe(device_t dev)
+{
+        struct pci_device_id *id;
+
+	id = b4xxp_pci_device_id_lookup(dev);
+	if (id == NULL)
+		return _RETVAL(ENXIO);
+
+	/* found device */
+	device_printf(dev, "vendor=%x device=%x subvendor=%x\n",
+	    id->vendor, id->device, id->subdevice);
+	return (0);
+}
+
+static int
+b4xxp_device_attach(device_t dev)
+{
+	int res;
+        struct pci_device_id *id;
+	struct devtype *dt;
+	struct b4xxp *b4;
+
+	id = b4xxp_pci_device_id_lookup(dev);
+	if (id == NULL)
+		return _RETVAL(ENXIO);
+
+	dt = (struct devtype *) id->driver_data;
+	device_set_desc(dev, dt->desc);
+	b4 = device_get_softc(dev);
+	b4->dev = dev;
+
+        /* allocate I/O resource */
+	b4->io_rid = PCIR_BAR(0);
+	b4->io_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &b4->io_rid, RF_ACTIVE);
+	if (b4->io_res == NULL) {
+		device_printf(dev, "Can't allocate I/O resource\n");
+		b4xxp_release_resources(b4);
+		return _RETVAL(ENXIO);
+	}
+
+        /* allocate memory resource */
+	b4->mem_rid = PCIR_BAR(1);
+	b4->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &b4->mem_rid, RF_ACTIVE);
+	if (b4->mem_res == NULL) {
+		device_printf(dev, "Can't allocate memory resource\n");
+		b4xxp_release_resources(b4);
+		return _RETVAL(ENXIO);
+	}
+
+	/* register */
+	res = b4xxp_register(b4, dt);
+	if (res) {
+		b4xxp_release_resources(b4);
+		return res;
+	}
+
+	return 0;
+}
+
+static int
+b4xxp_device_detach(device_t dev)
+{
+	struct b4xxp *b4 = device_get_softc(dev);
+
+	/* unregister */
+	b4xxp_unregister(b4);
+
+	/* release resources */
+	b4xxp_release_resources(b4);
+
+	return (0);
+}
+
+static int
+b4xxp_device_shutdown(device_t dev)
+{
+	DPRINTF(dev, "wcb4xxp shutdown\n");
+	return (0);
+}
+
+static int
+b4xxp_device_suspend(device_t dev)
+{
+	DPRINTF(dev, "wcb4xxp suspend\n");
+	return (0);
+}
+
+static int
+b4xxp_device_resume(device_t dev)
+{
+	DPRINTF(dev, "wcb4xxp resume\n");
+	return (0);
+}
+
+static device_method_t b4xxp_methods[] = {
+	DEVMETHOD(device_probe,     b4xxp_device_probe),
+	DEVMETHOD(device_attach,    b4xxp_device_attach),
+	DEVMETHOD(device_detach,    b4xxp_device_detach),
+	DEVMETHOD(device_shutdown,  b4xxp_device_shutdown),
+	DEVMETHOD(device_suspend,   b4xxp_device_suspend),
+	DEVMETHOD(device_resume,    b4xxp_device_resume),
+	{ 0, 0 }
+};
+
+static driver_t b4xxp_pci_driver = {
+	"wcb4xxp",
+	b4xxp_methods,
+	sizeof(struct b4xxp)
+};
+
+static devclass_t b4xxp_devclass;
+
+DRIVER_MODULE(wcb4xxp, pci, b4xxp_pci_driver, b4xxp_devclass, 0, 0);
+MODULE_DEPEND(wcb4xxp, pci, 1, 1, 1);
+MODULE_DEPEND(wcb4xxp, dahdi, 1, 1, 1);
+
+#else /* !__FreeBSD__ */
+static int b4xxp_setup_intr(struct b4xxp *b4)
+{
+	if (request_irq(b4->pdev->irq, b4xxp_interrupt, DAHDI_IRQ_SHARED_DISABLED, "b4xxp", b4)) {
+		dev_err(b4->dev, "Unable to request IRQ %d\n", b4->pdev->irq);
+		return _RETVAL(EIO);
+	}
+
+/* initialize the tasklet structure */
+/* TODO: perhaps only one tasklet for any number of cards in the system... don't need one per card I don't think. */
+	tasklet_init(&b4->b4xxp_tlet, b4xxp_bottom_half, (unsigned long)b4);
+	return 0;
+}
+
+static void b4xxp_release_intr(struct b4xxp *b4)
+{
+	free_irq(b4->pdev->irq, b4);
+	tasklet_kill(&b4->b4xxp_tlet);
+}
+
+static int __devinit b4xxp_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	int ret;
+	struct b4xxp *b4;
+	struct devtype *dt;
+
+	dt = (struct devtype *)(ent->driver_data);
+	dev_info(&pdev->dev, "probe called for b4xx...\n");
+
+	if ((ret = pci_enable_device(pdev)))
+		goto err_out_disable_pdev;
+
+	if ((ret = pci_request_regions(pdev, dt->desc))) {
+		dev_err(&pdev->dev, "Unable to request regions!\n");
+		goto err_out_disable_pdev;
+	}
+
+	if (!pdev->irq) {			/* we better have an IRQ */
+		dev_err(&pdev->dev, "Device has no associated IRQ?\n");
+		ret = _RETVAL(EIO);
+		goto err_out_release_regions;
+	}
+
+	if (!(b4 = kzalloc(sizeof(struct b4xxp), GFP_KERNEL))) {
+		dev_err(&pdev->dev, "Couldn't allocate memory for b4xxp structure!\n");
+		ret = _RETVAL(ENOMEM);
+		goto err_out_release_regions;
+	}
+
+	b4->pdev = pdev;
+	b4->dev = &pdev->dev;
+	pci_set_drvdata(pdev, b4);
+	b4->ioaddr = pci_iomap(pdev, 0, 0);
+	b4->addr = pci_iomap(pdev, 1, 0);
+	b4->irq = pdev->irq;
+
+	ret = b4xxp_register(b4, dt);
+	if (ret)
+		goto err_out_free_mem;
+	return 0;
+
 err_out_free_mem:
 	pci_set_drvdata(pdev, NULL);
 	pci_iounmap(pdev, b4->ioaddr);
@@ -2838,24 +3224,17 @@
 
 err_out_disable_pdev:
 	pci_disable_device(pdev);
-
 	return ret;
 }
 
 static void __devexit b4xxp_remove(struct pci_dev *pdev)
 {
 	struct b4xxp *b4 = pci_get_drvdata(pdev);
-	int i;
 
 	if (b4) {
-		b4->shutdown = 1;
+		b4xxp_unregister(b4);
 
-		for (i=b4->numspans - 1; i >= 0; i--) {
-			dahdi_unregister(&b4->spans[i].span);
-		}
-
-		b4xxp_init_stage1(b4);
-		free_irq(pdev->irq, b4);
+		b4xxp_release_intr(b4);
 		pci_set_drvdata(pdev, NULL);
 		pci_iounmap(pdev, b4->ioaddr);
 		pci_iounmap(pdev, b4->addr);
@@ -2864,8 +3243,6 @@
 
 		b4->ioaddr = b4->addr = NULL;
 
-		tasklet_kill(&b4->b4xxp_tlet);
-
 		kfree(b4);
 	}
 
@@ -2873,30 +3250,14 @@
 	return;
 }
 
-static struct pci_device_id b4xx_ids[] __devinitdata =
-{
-	{ 0xd161, 0xb410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wcb4xxp },
-	{ 0x1397, 0x16b8, 0x1397, 0xe552, 0, 0, (unsigned long)&hfc8s },
-	{ 0x1397, 0x08b4, 0x1397, 0xb520, 0, 0, (unsigned long)&hfc4s },
-	{ 0x1397, 0x08b4, 0x1397, 0xb556, 0, 0, (unsigned long)&hfc2s },
-	{ 0x1397, 0x08b4, 0x1397, 0xe884, 0, 0, (unsigned long)&hfc2s_OV },
-	{ 0x1397, 0x08b4, 0x1397, 0xe888, 0, 0, (unsigned long)&hfc4s_OV },
-	{ 0x1397, 0x16b8, 0x1397, 0xe998, 0, 0, (unsigned long)&hfc8s_OV },
-	{ 0x1397, 0x08b4, 0x1397, 0xb566, 0, 0, (unsigned long)&hfc2s_BN },
-	{ 0x1397, 0x08b4, 0x1397, 0xb560, 0, 0, (unsigned long)&hfc4s_BN },
-	{ 0x1397, 0x16b8, 0x1397, 0xb562, 0, 0, (unsigned long)&hfc8s_BN },
-	{0, }
-
-};
-
-static struct pci_driver b4xx_driver = {
+static struct pci_driver b4xxp_driver = {
 	.name = "wcb4xxp",
-	.probe = b4xx_probe,
+	.probe = b4xxp_probe,
 	.remove = __devexit_p(b4xxp_remove),
-	.id_table = b4xx_ids,
+	.id_table = b4xxp_ids,
 };
 
-static int __init b4xx_init(void)
+static int __init b4xxp_init(void)
 {
 
 #ifdef CREATE_WCB4XXP_PROCFS_ENTRY
@@ -2905,18 +3266,18 @@
 		printk(KERN_ERR "%s: ERROR: Could not initialize /proc/%s\n",THIS_MODULE->name, PROCFS_NAME);
 	}
 #endif
-	if (dahdi_pci_module(&b4xx_driver))
+	if (dahdi_pci_module(&b4xxp_driver))
 		return -ENODEV;
 
 	return 0;
 }
 
-static void __exit b4xx_exit(void)
+static void __exit b4xxp_exit(void)
 {
 #ifdef CREATE_WCB4XXP_PROCFS_ENTRY
 	remove_proc_entry(PROCFS_NAME, NULL);
 #endif
-	pci_unregister_driver(&b4xx_driver);
+	pci_unregister_driver(&b4xxp_driver);
 }
 
 module_param(debug, int, S_IRUGO | S_IWUSR);
@@ -2949,7 +3310,8 @@
 MODULE_DESCRIPTION("B410P & Similars multi-port BRI module driver.");
 MODULE_LICENSE("GPL");
 
-MODULE_DEVICE_TABLE(pci, b4xx_ids);
+MODULE_DEVICE_TABLE(pci, b4xxp_ids);
 
-module_init(b4xx_init);
-module_exit(b4xx_exit);
+module_init(b4xxp_init);
+module_exit(b4xxp_exit);
+#endif /* !__FreeBSD__ */
Index: drivers/dahdi/dahdi_echocan_sec.c
===================================================================
--- drivers/dahdi/dahdi_echocan_sec.c	(revision 7107)
+++ drivers/dahdi/dahdi_echocan_sec.c	(working copy)
@@ -36,6 +36,18 @@
    Improve double talk detector (iterative!)
 */
 
+#if defined(__FreeBSD__)
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/conf.h>
+#include <sys/ctype.h>
+#include <sys/libkern.h>
+#include <sys/module.h>
+
+#define module_printk(level, fmt, args...) printf(fmt, ## args)
+#define debug_printk(level, fmt, args...) if (debug >= level) printf("%s: " fmt, __FUNCTION__, ## args)
+
+#else /* !__FreeBSD__ */
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
@@ -44,13 +56,14 @@
 #include <linux/ctype.h>
 #include <linux/moduleparam.h>
 
+#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
+#define debug_printk(level, fmt, args...) if (debug >= level) printk(KERN_DEBUG "%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
+#endif /* !__FreeBSD__ */
+
 #include <dahdi/kernel.h>
 
 static int debug;
 
-#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
-#define debug_printk(level, fmt, args...) if (debug >= level) printk(KERN_DEBUG "%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
-
 #include "arith.h"
 
 #ifndef NULL
@@ -89,8 +102,10 @@
 
 static const struct dahdi_echocan_factory my_factory = {
 	.name = "SEC",
+	.echocan_create = echo_can_create,
+#if !defined(__FreeBSD__)
 	.owner = THIS_MODULE,
-	.echocan_create = echo_can_create,
+#endif
 };
 
 static const struct dahdi_echocan_features my_features = {
@@ -145,14 +160,13 @@
 
 	if (ecp->param_count > 0) {
 		printk(KERN_WARNING "SEC does not support parameters; failing request\n");
-		return -EINVAL;
+		return _RETVAL(EINVAL);
 	}
 
 	size = sizeof(*pvt) + ecp->tap_length * sizeof(int32_t) + ecp->tap_length * 3 * sizeof(int16_t);
-	
 	pvt = kzalloc(size, GFP_KERNEL);
 	if (!pvt)
-		return -ENOMEM;
+		return _RETVAL(ENOMEM);
 
 	pvt->dahdi.ops = &my_ops;
 	pvt->dahdi.features = my_features;
@@ -333,7 +347,7 @@
 	if (dahdi_register_echocan_factory(&my_factory)) {
 		module_printk(KERN_ERR, "could not register with DAHDI core\n");
 
-		return -EPERM;
+		return _RETVAL(EPERM);
 	}
 
 	module_printk(KERN_NOTICE, "Registered echo canceler '%s'\n", my_factory.name);
@@ -346,6 +360,26 @@
 	dahdi_unregister_echocan_factory(&my_factory);
 }
 
+#if defined(__FreeBSD__)
+static int
+echocan_sec_modevent(module_t mod __unused, int type, void *data __unused)
+{
+	switch (type) {
+	case MOD_LOAD:
+		return mod_init();
+	case MOD_UNLOAD:
+		mod_exit();
+		return 0;
+	default:
+		return _RETVAL(EOPNOTSUPP);
+	}
+}
+
+DEV_MODULE(dahdi_echocan_sec, echocan_sec_modevent, NULL);
+MODULE_VERSION(dahdi_echocan_sec, 1);
+MODULE_DEPEND(dahdi_echocan_sec, dahdi, 1, 1, 1);
+
+#else /* !__FreeBSD__ */
 module_param(debug, int, S_IRUGO | S_IWUSR);
 
 MODULE_DESCRIPTION("DAHDI 'SEC' Echo Canceler");
@@ -354,3 +388,4 @@
 
 module_init(mod_init);
 module_exit(mod_exit);
+#endif /* !__FreeBSD__ */
Index: drivers/dahdi/dahdi_echocan_jpah.c
===================================================================
--- drivers/dahdi/dahdi_echocan_jpah.c	(revision 7107)
+++ drivers/dahdi/dahdi_echocan_jpah.c	(working copy)
@@ -26,6 +26,18 @@
  * this program for more details.
  */
 
+#if defined(__FreeBSD__)
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/conf.h>
+#include <sys/ctype.h>
+#include <sys/libkern.h>
+#include <sys/module.h>
+
+#define module_printk(level, fmt, args...) printf(fmt, ## args)
+#define debug_printk(level, fmt, args...) if (debug >= level) printf("%s: " fmt, __FUNCTION__, ## args)
+
+#else /* !__FreeBSD__ */
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/module.h>
@@ -33,13 +45,14 @@
 #include <linux/ctype.h>
 #include <linux/moduleparam.h>
 
+#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
+#define debug_printk(level, fmt, args...) if (debug >= level) printk("%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
+#endif /* !__FreeBSD__ */
+
 #include <dahdi/kernel.h>
 
 static int debug;
 
-#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
-#define debug_printk(level, fmt, args...) if (debug >= level) printk("%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
-
 static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
 			   struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec);
 static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec);
@@ -48,8 +61,10 @@
 
 static const struct dahdi_echocan_factory my_factory = {
 	.name = "JPAH",
+	.echocan_create = echo_can_create,
+#if !defined(__FreeBSD__)
 	.owner = THIS_MODULE,
-	.echocan_create = echo_can_create,
+#endif
 };
 
 static const struct dahdi_echocan_ops my_ops = {
@@ -73,12 +88,12 @@
 
 	if (ecp->param_count > 0) {
 		printk(KERN_WARNING "JPAH does not support parameters; failing request\n");
-		return -EINVAL;
+		return _RETVAL(EINVAL);
 	}
 
 	pvt = kzalloc(sizeof(*pvt), GFP_KERNEL);
 	if (!pvt)
-		return -ENOMEM;
+		return _RETVAL(ENOMEM);
 
 	pvt->dahdi.ops = &my_ops;
 
@@ -121,7 +136,7 @@
 	if (dahdi_register_echocan_factory(&my_factory)) {
 		module_printk(KERN_ERR, "could not register with DAHDI core\n");
 
-		return -EPERM;
+		return _RETVAL(EPERM);
 	}
 
 	module_printk(KERN_NOTICE, "Registered echo canceler '%s'\n", my_factory.name);
@@ -134,6 +149,26 @@
 	dahdi_unregister_echocan_factory(&my_factory);
 }
 
+#if defined(__FreeBSD__)
+static int
+echocan_jpah_modevent(module_t mod __unused, int type, void *data __unused)
+{
+	switch (type) {
+	case MOD_LOAD:
+		return mod_init();
+	case MOD_UNLOAD:
+		mod_exit();
+		return 0;
+	default:
+		return _RETVAL(EOPNOTSUPP);
+	}
+}
+
+DEV_MODULE(dahdi_echocan_jpah, echocan_jpah_modevent, NULL);
+MODULE_VERSION(dahdi_echocan_jpah, 1);
+MODULE_DEPEND(dahdi_echocan_jpah, dahdi, 1, 1, 1);
+
+#else /* !__FreeBSD__ */
 module_param(debug, int, S_IRUGO | S_IWUSR);
 
 MODULE_DESCRIPTION("DAHDI Jason Parker Audio Hoser");
@@ -142,3 +177,4 @@
 
 module_init(mod_init);
 module_exit(mod_exit);
+#endif /* !__FreeBSD__ */
