diff -ruN linux-2.4.20-WRTup/drivers/Makefile linux-2.4.20-WRTstp/drivers/Makefile
--- linux-2.4.20-WRTup/drivers/Makefile	2006-06-12 18:04:59.000000000 -0700
+++ linux-2.4.20-WRTstp/drivers/Makefile	2005-11-08 06:24:37.000000000 -0800
@@ -8,7 +8,7 @@
 
 mod-subdirs :=	dio hil mtd sbus video macintosh usb input telephony sgi ide \
 		message/i2o message/fusion scsi md ieee1394 pnp isdn atm \
-		fc4 net/hamradio i2c acpi bluetooth usb/gadget
+		fc4 net/hamradio i2c acpi bluetooth
 
 subdir-y :=	parport char block net sound misc media cdrom hotplug
 subdir-m :=	$(subdir-y)
@@ -28,7 +28,6 @@
 subdir-$(CONFIG_MAC)		+= macintosh
 subdir-$(CONFIG_PPC32)		+= macintosh
 subdir-$(CONFIG_USB)		+= usb
-subdir-$(CONFIG_USB_GADGET)	+= usb/gadget
 subdir-$(CONFIG_INPUT)		+= input
 subdir-$(CONFIG_PHONE)		+= telephony
 subdir-$(CONFIG_SGI)		+= sgi
diff -ruN linux-2.4.20-WRTup/drivers/usb/auerbuf.c linux-2.4.20-WRTstp/drivers/usb/auerbuf.c
--- linux-2.4.20-WRTup/drivers/usb/auerbuf.c	2006-06-12 18:04:59.000000000 -0700
+++ linux-2.4.20-WRTstp/drivers/usb/auerbuf.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,150 +0,0 @@
-/*****************************************************************************/
-/*
- *      auerbuf.c  --  Auerswald PBX/System Telephone urb list storage.
- *
- *      Copyright (C) 2002  Wolfgang Mües (wolfgang@iksw-muees.de)
- *
- *      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.
- */
- /*****************************************************************************/
-
-#undef DEBUG			/* include debug macros until it's done */
-#include <linux/usb.h>
-#include "auerbuf.h"
-#include <linux/slab.h>
-
-/* free a single auerbuf */
-void auerbuf_free(struct auerbuf *bp)
-{
-	if (!bp) return;
-	kfree(bp->bufp);
-	kfree(bp->dr);
-	if (bp->urbp) {
-		usb_free_urb(bp->urbp);
-	}
-	kfree(bp);
-}
-
-/* free the buffers from an auerbuf list */
-void auerbuf_free_list(struct list_head *q)
-{
-	struct list_head *tmp;
-	struct list_head *p;
-	struct auerbuf *bp;
-
-	dbg("auerbuf_free_list");
-	for (p = q->next; p != q;) {
-		bp = list_entry(p, struct auerbuf, buff_list);
-		tmp = p->next;
-		list_del(p);
-		p = tmp;
-		auerbuf_free(bp);
-	}
-}
-
-/* free all buffers from an auerbuf chain */
-void auerbuf_free_buffers(struct auerbufctl *bcp)
-{
-	unsigned long flags;
-	dbg("auerbuf_free_buffers");
-
-	spin_lock_irqsave(&bcp->lock, flags);
-
-	auerbuf_free_list(&bcp->free_buff_list);
-	auerbuf_free_list(&bcp->rec_buff_list);
-
-	spin_unlock_irqrestore(&bcp->lock, flags);
-}
-
-/* init the members of a list control block */
-void auerbuf_init(struct auerbufctl *bcp)
-{
-	dbg("auerbuf_init");
-	spin_lock_init(&bcp->lock);
-	INIT_LIST_HEAD(&bcp->free_buff_list);
-	INIT_LIST_HEAD(&bcp->rec_buff_list);
-}
-
-/* setup a list of buffers */
-/* requirement: auerbuf_init() */
-int auerbuf_setup(struct auerbufctl *bcp, unsigned int numElements,
-		  unsigned int bufsize)
-{
-	struct auerbuf *bep = NULL;
-
-	dbg("auerbuf_setup called with %d elements of %d bytes",
-	    numElements, bufsize);
-
-	/* fill the list of free elements */
-	for (; numElements; numElements--) {
-		bep =
-		    (struct auerbuf *) kmalloc(sizeof(struct auerbuf),
-					       GFP_KERNEL);
-		if (!bep)
-			goto bl_fail;
-		memset(bep, 0, sizeof(struct auerbuf));
-		bep->list = bcp;
-		INIT_LIST_HEAD(&bep->buff_list);
-		bep->bufp = (char *) kmalloc(bufsize, GFP_KERNEL);
-		if (!bep->bufp)
-			goto bl_fail;
-		bep->dr =
-		    (struct usb_ctrlrequest *)
-		    kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
-		if (!bep->dr)
-			goto bl_fail;
-		bep->urbp = usb_alloc_urb(0);
-		if (!bep->urbp)
-			goto bl_fail;
-		list_add_tail(&bep->buff_list, &bcp->free_buff_list);
-	}
-	return 0;
-
-      bl_fail:			/* not enought memory. Free allocated elements */
-	dbg("auerbuf_setup: no more memory");
-	auerbuf_free (bep);
-	auerbuf_free_buffers(bcp);
-	return -ENOMEM;
-}
-
-/* alloc a free buffer from the list. Returns NULL if no buffer available */
-struct auerbuf *auerbuf_getbuf(struct auerbufctl *bcp)
-{
-	unsigned long flags;
-	struct auerbuf *bp = NULL;
-
-	spin_lock_irqsave(&bcp->lock, flags);
-	if (!list_empty(&bcp->free_buff_list)) {
-		/* yes: get the entry */
-		struct list_head *tmp = bcp->free_buff_list.next;
-		list_del(tmp);
-		bp = list_entry(tmp, struct auerbuf, buff_list);
-	}
-	spin_unlock_irqrestore(&bcp->lock, flags);
-	return bp;
-}
-
-/* insert a used buffer into the free list */
-void auerbuf_releasebuf(struct auerbuf *bp)
-{
-	unsigned long flags;
-	struct auerbufctl *bcp = bp->list;
-	bp->retries = 0;
-
-	dbg("auerbuf_releasebuf called");
-	spin_lock_irqsave(&bcp->lock, flags);
-	list_add_tail(&bp->buff_list, &bcp->free_buff_list);
-	spin_unlock_irqrestore(&bcp->lock, flags);
-}
diff -ruN linux-2.4.20-WRTup/drivers/usb/auerbuf.h linux-2.4.20-WRTstp/drivers/usb/auerbuf.h
--- linux-2.4.20-WRTup/drivers/usb/auerbuf.h	2006-06-12 18:04:59.000000000 -0700
+++ linux-2.4.20-WRTstp/drivers/usb/auerbuf.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,69 +0,0 @@
-/*****************************************************************************/
-/*
- *      auerbuf.h  --  Auerswald PBX/System Telephone urb list storage.
- *
- *      Copyright (C) 2002  Wolfgang Mües (wolfgang@iksw-muees.de)
- *
- *      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.
- */
- /*****************************************************************************/
-
-/* This module assembles together an URB, an usb_ctrlrequest struct for sending of
- * control messages, and a data buffer.
- * These items (auerbuf) are collected in a list (auerbufctl) and are used
- * for serialized usb data transfer.
- */
-
-#ifndef AUERBUF_H
-#define AUERBUF_H
-
-#include <linux/usb.h>
-
-/* buffer element */
-struct auerbufctl;			/* forward */
-struct auerbuf {
-	unsigned char *bufp;		/* reference to allocated data buffer */
-	unsigned int len;		/* number of characters in data buffer */
-	unsigned int retries;		/* for urb retries */
-	struct usb_ctrlrequest *dr;	/* for setup data in control messages */
-	struct urb *urbp;		/* USB urb */
-	struct auerbufctl *list;	/* pointer to list */
-	struct list_head buff_list;	/* reference to next buffer in list */
-};
-
-/* buffer list control block */
-struct auerbufctl {
-	spinlock_t lock;		/* protection in interrupt */
-	struct list_head free_buff_list;/* free buffers */
-	struct list_head rec_buff_list;	/* buffers with received data */
-};
-
-/* Function prototypes */
-void auerbuf_free(struct auerbuf *bp);
-
-void auerbuf_free_list(struct list_head *q);
-
-void auerbuf_init(struct auerbufctl *bcp);
-
-void auerbuf_free_buffers(struct auerbufctl *bcp);
-
-int auerbuf_setup(struct auerbufctl *bcp, unsigned int numElements,
-		  unsigned int bufsize);
-
-struct auerbuf *auerbuf_getbuf(struct auerbufctl *bcp);
-
-void auerbuf_releasebuf(struct auerbuf *bp);
-
-#endif	/* AUERBUF_H */
diff -ruN linux-2.4.20-WRTup/drivers/usb/auerchain.c linux-2.4.20-WRTstp/drivers/usb/auerchain.c
--- linux-2.4.20-WRTup/drivers/usb/auerchain.c	2006-06-12 18:04:59.000000000 -0700
+++ linux-2.4.20-WRTstp/drivers/usb/auerchain.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,468 +0,0 @@
-/*****************************************************************************/
-/*
- *      auerchain.c  --  Auerswald PBX/System Telephone chained urb support.
- *
- *      Copyright (C) 2002  Wolfgang Mües (wolfgang@iksw-muees.de)
- *
- *      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.
- */
- /*****************************************************************************/
-
-#undef DEBUG			/* include debug macros until it's done */
-#include <linux/usb.h>
-#include "auerchain.h"
-#include <linux/slab.h>
-
-/* completion function for chained urbs */
-static void auerchain_complete(struct urb *urb)
-{
-	unsigned long flags;
-	int result;
-
-	/* get pointer to element and to chain */
-	struct auerchainelement *acep =
-	    (struct auerchainelement *) urb->context;
-	struct auerchain *acp = acep->chain;
-
-	/* restore original entries in urb */
-	urb->context = acep->context;
-	urb->complete = acep->complete;
-
-	dbg("auerchain_complete called");
-
-	/* call original completion function
-	   NOTE: this function may lead to more urbs submitted into the chain.
-	   (no chain lock at calling complete()!)
-	   acp->active != NULL is protecting us against recursion. */
-	urb->complete(urb);
-
-	/* detach element from chain data structure */
-	spin_lock_irqsave(&acp->lock, flags);
-	if (acp->active != acep)	/* paranoia debug check */
-		dbg("auerchain_complete: completion on non-active element called!");
-	else
-		acp->active = NULL;
-
-	/* add the used chain element to the list of free elements */
-	list_add_tail(&acep->list, &acp->free_list);
-	acep = NULL;
-
-	/* is there a new element waiting in the chain? */
-	if (!acp->active && !list_empty(&acp->waiting_list)) {
-		/* yes: get the entry */
-		struct list_head *tmp = acp->waiting_list.next;
-		list_del(tmp);
-		acep = list_entry(tmp, struct auerchainelement, list);
-		acp->active = acep;
-	}
-	spin_unlock_irqrestore(&acp->lock, flags);
-
-	/* submit the new urb */
-	if (acep) {
-		urb = acep->urbp;
-		dbg("auerchain_complete: submitting next urb from chain");
-		urb->status = 0;	/* needed! */
-		result = usb_submit_urb(urb);
-
-		/* check for submit errors */
-		if (result) {
-			urb->status = result;
-			dbg("auerchain_complete: usb_submit_urb with error code %d", result);
-			/* and do error handling via *this* completion function (recursive) */
-			auerchain_complete(urb);
-		}
-	} else {
-		/* simple return without submitting a new urb.
-		   The empty chain is detected with acp->active == NULL. */
-	};
-}
-
-/* submit function for chained urbs
-   this function may be called from completion context or from user space!
-   early = 1 -> submit in front of chain
-*/
-int auerchain_submit_urb_list(struct auerchain *acp, struct urb *urb,
-			      int early)
-{
-	int result;
-	unsigned long flags;
-	struct auerchainelement *acep = NULL;
-
-	dbg("auerchain_submit_urb called");
-
-	/* try to get a chain element */
-	spin_lock_irqsave(&acp->lock, flags);
-	if (!list_empty(&acp->free_list)) {
-		/* yes: get the entry */
-		struct list_head *tmp = acp->free_list.next;
-		list_del(tmp);
-		acep = list_entry(tmp, struct auerchainelement, list);
-	}
-	spin_unlock_irqrestore(&acp->lock, flags);
-
-	/* if no chain element available: return with error */
-	if (!acep) {
-		return -ENOMEM;
-	}
-
-	/* fill in the new chain element values */
-	acep->chain = acp;
-	acep->context = urb->context;
-	acep->complete = urb->complete;
-	acep->urbp = urb;
-	INIT_LIST_HEAD(&acep->list);
-
-	/* modify urb */
-	urb->context = acep;
-	urb->complete = auerchain_complete;
-	urb->status = -EINPROGRESS;	/* usb_submit_urb does this, too */
-
-	/* add element to chain - or start it immediately */
-	spin_lock_irqsave(&acp->lock, flags);
-	if (acp->active) {
-		/* there is traffic in the chain, simple add element to chain */
-		if (early) {
-			dbg("adding new urb to head of chain");
-			list_add(&acep->list, &acp->waiting_list);
-		} else {
-			dbg("adding new urb to end of chain");
-			list_add_tail(&acep->list, &acp->waiting_list);
-		}
-		acep = NULL;
-	} else {
-		/* the chain is empty. Prepare restart */
-		acp->active = acep;
-	}
-	/* Spin has to be removed before usb_submit_urb! */
-	spin_unlock_irqrestore(&acp->lock, flags);
-
-	/* Submit urb if immediate restart */
-	if (acep) {
-		dbg("submitting urb immediate");
-		urb->status = 0;	/* needed! */
-		result = usb_submit_urb(urb);
-		/* check for submit errors */
-		if (result) {
-			urb->status = result;
-			dbg("auerchain_submit_urb: usb_submit_urb with error code %d", result);
-			/* and do error handling via completion function */
-			auerchain_complete(urb);
-		}
-	}
-
-	return 0;
-}
-
-/* submit function for chained urbs
-   this function may be called from completion context or from user space!
-*/
-int auerchain_submit_urb(struct auerchain *acp, struct urb *urb)
-{
-	return auerchain_submit_urb_list(acp, urb, 0);
-}
-
-/* cancel an urb which is submitted to the chain
-   the result is 0 if the urb is cancelled, or -EINPROGRESS if
-   USB_ASYNC_UNLINK is set and the function is successfully started.
-*/
-int auerchain_unlink_urb(struct auerchain *acp, struct urb *urb)
-{
-	unsigned long flags;
-	struct urb *urbp;
-	struct auerchainelement *acep;
-	struct list_head *tmp;
-
-	dbg("auerchain_unlink_urb called");
-
-	/* search the chain of waiting elements */
-	spin_lock_irqsave(&acp->lock, flags);
-	list_for_each(tmp, &acp->waiting_list) {
-		acep = list_entry(tmp, struct auerchainelement, list);
-		if (acep->urbp == urb) {
-			list_del(tmp);
-			urb->context = acep->context;
-			urb->complete = acep->complete;
-			list_add_tail(&acep->list, &acp->free_list);
-			spin_unlock_irqrestore(&acp->lock, flags);
-			dbg("unlink waiting urb");
-			urb->status = -ENOENT;
-			urb->complete(urb);
-			return 0;
-		}
-	}
-	/* not found. */
-	spin_unlock_irqrestore(&acp->lock, flags);
-
-	/* get the active urb */
-	acep = acp->active;
-	if (acep) {
-		urbp = acep->urbp;
-
-		/* check if we have to cancel the active urb */
-		if (urbp == urb) {
-			/* note that there is a race condition between the check above
-			   and the unlink() call because of no lock. This race is harmless,
-			   because the usb module will detect the unlink() after completion.
-			   We can't use the acp->lock here because the completion function
-			   wants to grab it.
-			 */
-			dbg("unlink active urb");
-			return usb_unlink_urb(urbp);
-		}
-	}
-
-	/* not found anyway
-	   ... is some kind of success
-	 */
-	dbg("urb to unlink not found in chain");
-	return 0;
-}
-
-/* cancel all urbs which are in the chain.
-   this function must not be called from interrupt or completion handler.
-*/
-void auerchain_unlink_all(struct auerchain *acp)
-{
-	unsigned long flags;
-	struct urb *urbp;
-	struct auerchainelement *acep;
-
-	dbg("auerchain_unlink_all called");
-
-	/* clear the chain of waiting elements */
-	spin_lock_irqsave(&acp->lock, flags);
-	while (!list_empty(&acp->waiting_list)) {
-		/* get the next entry */
-		struct list_head *tmp = acp->waiting_list.next;
-		list_del(tmp);
-		acep = list_entry(tmp, struct auerchainelement, list);
-		urbp = acep->urbp;
-		urbp->context = acep->context;
-		urbp->complete = acep->complete;
-		list_add_tail(&acep->list, &acp->free_list);
-		spin_unlock_irqrestore(&acp->lock, flags);
-		dbg("unlink waiting urb");
-		urbp->status = -ENOENT;
-		urbp->complete(urbp);
-		spin_lock_irqsave(&acp->lock, flags);
-	}
-	spin_unlock_irqrestore(&acp->lock, flags);
-
-	/* clear the active urb */
-	acep = acp->active;
-	if (acep) {
-		urbp = acep->urbp;
-		urbp->transfer_flags &= ~USB_ASYNC_UNLINK;
-		dbg("unlink active urb");
-		usb_unlink_urb(urbp);
-	}
-}
-
-
-/* free the chain.
-   this function must not be called from interrupt or completion handler.
-*/
-void auerchain_free(struct auerchain *acp)
-{
-	unsigned long flags;
-	struct auerchainelement *acep;
-
-	dbg("auerchain_free called");
-
-	/* first, cancel all pending urbs */
-	auerchain_unlink_all(acp);
-
-	/* free the elements */
-	spin_lock_irqsave(&acp->lock, flags);
-	while (!list_empty(&acp->free_list)) {
-		/* get the next entry */
-		struct list_head *tmp = acp->free_list.next;
-		list_del(tmp);
-		spin_unlock_irqrestore(&acp->lock, flags);
-		acep = list_entry(tmp, struct auerchainelement, list);
-		kfree(acep);
-		spin_lock_irqsave(&acp->lock, flags);
-	}
-	spin_unlock_irqrestore(&acp->lock, flags);
-}
-
-
-/* Init the chain control structure */
-void auerchain_init(struct auerchain *acp)
-{
-	/* init the chain data structure */
-	acp->active = NULL;
-	spin_lock_init(&acp->lock);
-	INIT_LIST_HEAD(&acp->waiting_list);
-	INIT_LIST_HEAD(&acp->free_list);
-}
-
-/* setup a chain.
-   It is assumed that there is no concurrency while setting up the chain
-   requirement: auerchain_init()
-*/
-int auerchain_setup(struct auerchain *acp, unsigned int numElements)
-{
-	struct auerchainelement *acep;
-
-	dbg("auerchain_setup called with %d elements", numElements);
-
-	/* fill the list of free elements */
-	for (; numElements; numElements--) {
-		acep =
-		    (struct auerchainelement *)
-		    kmalloc(sizeof(struct auerchainelement), GFP_KERNEL);
-		if (!acep)
-			goto ac_fail;
-		memset(acep, 0, sizeof(struct auerchainelement));
-		INIT_LIST_HEAD(&acep->list);
-		list_add_tail(&acep->list, &acp->free_list);
-	}
-	return 0;
-
-      ac_fail:	/* free the elements */
-	while (!list_empty(&acp->free_list)) {
-		/* get the next entry */
-		struct list_head *tmp = acp->free_list.next;
-		list_del(tmp);
-		acep = list_entry(tmp, struct auerchainelement, list);
-		kfree(acep);
-	}
-	return -ENOMEM;
-}
-
-
-/* completion handler for synchronous chained URBs */
-static void auerchain_blocking_completion(struct urb *urb)
-{
-	struct auerchain_chs *pchs = (struct auerchain_chs *) urb->context;
-	pchs->done = 1;
-	wmb();
-	wake_up(&pchs->wqh);
-}
-
-
-/* Starts chained urb and waits for completion or timeout */
-static int auerchain_start_wait_urb(struct auerchain *acp, struct urb *urb,
-				    int timeout, int *actual_length)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	struct auerchain_chs chs;
-	int status;
-
-	dbg("auerchain_start_wait_urb called");
-	init_waitqueue_head(&chs.wqh);
-	chs.done = 0;
-
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	add_wait_queue(&chs.wqh, &wait);
-	urb->context = &chs;
-	status = auerchain_submit_urb(acp, urb);
-	if (status) {
-		/* something went wrong */
-		set_current_state(TASK_RUNNING);
-		remove_wait_queue(&chs.wqh, &wait);
-		return status;
-	}
-
-	while (timeout && !chs.done) {
-		timeout = schedule_timeout(timeout);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		rmb();
-	}
-
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&chs.wqh, &wait);
-
-	if (!timeout && !chs.done) {
-		if (urb->status != -EINPROGRESS) {	/* No callback?!! */
-			dbg("auerchain_start_wait_urb: raced timeout");
-			status = urb->status;
-		} else {
-			dbg("auerchain_start_wait_urb: timeout");
-			auerchain_unlink_urb(acp, urb);	/* remove urb safely */
-			status = -ETIMEDOUT;
-		}
-	} else
-		status = urb->status;
-
-	if (actual_length)
-		*actual_length = urb->actual_length;
-
-	return status;
-}
-
-
-/* auerchain_control_msg - Builds a control urb, sends it off and waits for completion
-   acp: pointer to the auerchain
-   dev: pointer to the usb device to send the message to
-   pipe: endpoint "pipe" to send the message to
-   request: USB message request value
-   requesttype: USB message request type value
-   value: USB message value
-   index: USB message index value
-   data: pointer to the data to send
-   size: length in bytes of the data to send
-   timeout: time to wait for the message to complete before timing out (if 0 the wait is forever)
-
-   This function sends a simple control message to a specified endpoint
-   and waits for the message to complete, or timeout.
-
-   If successful, it returns the transfered length, othwise a negative error number.
-
-   Don't use this function from within an interrupt context, like a
-   bottom half handler.  If you need a asyncronous message, or need to send
-   a message from within interrupt context, use auerchain_submit_urb()
-*/
-int auerchain_control_msg(struct auerchain *acp, struct usb_device *dev,
-			  unsigned int pipe, __u8 request,
-			  __u8 requesttype, __u16 value, __u16 index,
-			  void *data, __u16 size, int timeout)
-{
-	int ret;
-	struct usb_ctrlrequest *dr;
-	struct urb *urb;
-	int length;
-
-	dbg("auerchain_control_msg");
-	dr = (struct usb_ctrlrequest *)
-	    kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
-	if (!dr)
-		return -ENOMEM;
-	urb = usb_alloc_urb(0);
-	if (!urb) {
-		kfree(dr);
-		return -ENOMEM;
-	}
-
-	dr->bRequestType = requesttype;
-	dr->bRequest = request;
-	dr->wValue = cpu_to_le16(value);
-	dr->wIndex = cpu_to_le16(index);
-	dr->wLength = cpu_to_le16(size);
-
-	FILL_CONTROL_URB(urb, dev, pipe, (unsigned char *) dr, data, size,	/* build urb */
-			 (usb_complete_t) auerchain_blocking_completion,
-			 0);
-	ret = auerchain_start_wait_urb(acp, urb, timeout, &length);
-
-	usb_free_urb(urb);
-	kfree(dr);
-
-	if (ret < 0)
-		return ret;
-	else
-		return length;
-}
diff -ruN linux-2.4.20-WRTup/drivers/usb/auerchain.h linux-2.4.20-WRTstp/drivers/usb/auerchain.h
--- linux-2.4.20-WRTup/drivers/usb/auerchain.h	2006-06-12 18:04:59.000000000 -0700
+++ linux-2.4.20-WRTstp/drivers/usb/auerchain.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,79 +0,0 @@
-/*****************************************************************************/
-/*
- *      auerchain.h  --  Auerswald PBX/System Telephone chained urb support.
- *
- *      Copyright (C) 2002  Wolfgang Mües (wolfgang@iksw-muees.de)
- *
- *      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.
- */
- /*****************************************************************************/
-
-/* This module is used to make a FIFO of URBs, to serialize the submit.
- * This may be used to serialize control messages, which is not supported
- * by the Linux USB subsystem.
- */
-
-#ifndef AUERCHAIN_H
-#define AUERCHAIN_H
-
-#include <linux/usb.h>
-
-/* urb chain element */
-struct auerchain;			/* forward for circular reference */
-struct auerchainelement {
-	struct auerchain *chain;	/* pointer to the chain to which this element belongs */
-	struct urb *urbp;		/* pointer to attached urb */
-	void *context;			/* saved URB context */
-	usb_complete_t complete;	/* saved URB completion function */
-	struct list_head list;		/* to include element into a list */
-};
-
-/* urb chain */
-struct auerchain {
-	struct auerchainelement *active;/* element which is submitted to urb */
-	spinlock_t lock;		/* protection agains interrupts */
-	struct list_head waiting_list;	/* list of waiting elements */
-	struct list_head free_list;	/* list of available elements */
-};
-
-/* urb blocking completion helper struct */
-struct auerchain_chs {
-	wait_queue_head_t wqh;		/* wait for completion */
-	unsigned int done;		/* completion flag */
-};
-
-
-/* Function prototypes */
-int auerchain_submit_urb_list(struct auerchain *acp, struct urb *urb,
-			      int early);
-
-int auerchain_submit_urb(struct auerchain *acp, struct urb *urb);
-
-int auerchain_unlink_urb(struct auerchain *acp, struct urb *urb);
-
-void auerchain_unlink_all(struct auerchain *acp);
-
-void auerchain_free(struct auerchain *acp);
-
-void auerchain_init(struct auerchain *acp);
-
-int auerchain_setup(struct auerchain *acp, unsigned int numElements);
-
-int auerchain_control_msg(struct auerchain *acp, struct usb_device *dev,
-			  unsigned int pipe, __u8 request,
-			  __u8 requesttype, __u16 value, __u16 index,
-			  void *data, __u16 size, int timeout);
-
-#endif	/* AUERCHAIN_H */
diff -ruN linux-2.4.20-WRTup/drivers/usb/auerchar.c linux-2.4.20-WRTstp/drivers/usb/auerchar.c
--- linux-2.4.20-WRTup/drivers/usb/auerchar.c	2006-06-12 18:04:59.000000000 -0700
+++ linux-2.4.20-WRTstp/drivers/usb/auerchar.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,615 +0,0 @@
-/*****************************************************************************/
-/*
- *      auerchar.c  --  Auerswald PBX/System Telephone character interface.
- *
- *      Copyright (C) 2002  Wolfgang Mües (wolfgang@iksw-muees.de)
- *
- *      Very much code of this driver is borrowed from dabusb.c (Deti Fliegl)
- *      and from the USB Skeleton driver (Greg Kroah-Hartman). Thank you.
- *
- *      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.
- */
- /*****************************************************************************/
-
-#undef DEBUG			/* include debug macros until it's done */
-#include <linux/usb.h>
-#include "auerchar.h"
-#include "auermain.h"
-#include <linux/slab.h>
-#include <asm/uaccess.h>	/* user area access functions */
-
-/*-------------------------------------------------------------------*/
-
-/* wake up waiting readers */
-static void auerchar_disconnect(struct auerscon *scp)
-{
-	struct auerchar *ccp =((struct auerchar *) ((char *) (scp) - (unsigned long) (&((struct auerchar *) 0)->scontext)));
-	dbg("auerchar_disconnect called");
-	ccp->removed = 1;
-	wake_up(&ccp->readwait);
-}
-
-
-/* dispatch a read paket to a waiting character device */
-static void auerchar_ctrlread_dispatch(struct auerscon *scp,
-				       struct auerbuf *bp)
-{
-	unsigned long flags;
-	struct auerchar *ccp;
-	struct auerbuf *newbp = NULL;
-	char *charp;
-	dbg("auerchar_ctrlread_dispatch called");
-	ccp =((struct auerchar *) ((char *) (scp) - (unsigned long)(&((struct auerchar *) 0)->scontext)));
-
-	/* get a read buffer from character device context */
-	newbp = auerbuf_getbuf(&ccp->bufctl);
-	if (!newbp) {
-		dbg("No read buffer available, discard paket!");
-		return;		/* no buffer, no dispatch */
-	}
-
-	/* copy information to new buffer element
-	   (all buffers have the same length) */
-	charp = newbp->bufp;
-	newbp->bufp = bp->bufp;
-	bp->bufp = charp;
-	newbp->len = bp->len;
-
-	/* insert new buffer in read list */
-	spin_lock_irqsave(&ccp->bufctl.lock, flags);
-	list_add_tail(&newbp->buff_list, &ccp->bufctl.rec_buff_list);
-	spin_unlock_irqrestore(&ccp->bufctl.lock, flags);
-	dbg("read buffer appended to rec_list");
-
-	/* wake up pending synchronous reads */
-	wake_up(&ccp->readwait);
-}
-
-
-/* Delete an auerswald character context */
-void auerchar_delete(struct auerchar *ccp)
-{
-	dbg("auerchar_delete");
-	if (ccp == NULL)
-		return;
-
-	/* wake up pending synchronous reads */
-	ccp->removed = 1;
-	wake_up(&ccp->readwait);
-
-	/* remove the read buffer */
-	if (ccp->readbuf) {
-		auerbuf_releasebuf(ccp->readbuf);
-		ccp->readbuf = NULL;
-	}
-
-	/* remove the character buffers */
-	auerbuf_free_buffers(&ccp->bufctl);
-
-	/* release the memory */
-	kfree(ccp);
-}
-
-
-/* --------------------------------------------------------------------- */
-/* Char device functions                                                 */
-
-/* Open a new character device */
-int auerchar_open(struct inode *inode, struct file *file)
-{
-	int dtindex = MINOR(inode->i_rdev) - AUER_MINOR_BASE;
-	struct auerswald *cp = NULL;
-	struct auerchar *ccp = NULL;
-	int ret;
-
-	/* minor number in range? */
-	if ((dtindex < 0) || (dtindex >= AUER_MAX_DEVICES)) {
-		return -ENODEV;
-	}
-	/* usb device available? */
-	if (down_interruptible(&auerdev_table_mutex)) {
-		return -ERESTARTSYS;
-	}
-	cp = auerdev_table[dtindex];
-	if (cp == NULL) {
-		up(&auerdev_table_mutex);
-		return -ENODEV;
-	}
-	if (down_interruptible(&cp->mutex)) {
-		up(&auerdev_table_mutex);
-		return -ERESTARTSYS;
-	}
-	up(&auerdev_table_mutex);
-
-	/* we have access to the device. Now lets allocate memory */
-	ccp = (struct auerchar *) kmalloc(sizeof(struct auerchar), GFP_KERNEL);
-	if (ccp == NULL) {
-		err("out of memory");
-		ret = -ENOMEM;
-		goto ofail;
-	}
-
-	/* Initialize device descriptor */
-	memset(ccp, 0, sizeof(struct auerchar));
-	init_MUTEX(&ccp->mutex);
-	init_MUTEX(&ccp->readmutex);
-	auerbuf_init(&ccp->bufctl);
-	ccp->scontext.id = AUH_UNASSIGNED;
-	ccp->scontext.dispatch = auerchar_ctrlread_dispatch;
-	ccp->scontext.disconnect = auerchar_disconnect;
-	init_waitqueue_head(&ccp->readwait);
-
-	ret =
-	    auerbuf_setup(&ccp->bufctl, AU_RBUFFERS,
-			  cp->maxControlLength + AUH_SIZE);
-	if (ret) {
-		goto ofail;
-	}
-
-	cp->open_count++;
-	ccp->auerdev = cp;
-	dbg("open %s as /dev/usb/%s", cp->dev_desc, cp->name);
-	up(&cp->mutex);
-
-	/* file IO stuff */
-	file->f_pos = 0;
-	file->private_data = ccp;
-	return 0;
-
-	/* Error exit */
-      ofail:up(&cp->mutex);
-	auerchar_delete(ccp);
-	return ret;
-}
-
-
-/* IOCTL functions */
-int auerchar_ioctl(struct inode *inode, struct file *file,
-		   unsigned int cmd, unsigned long arg)
-{
-	struct auerchar *ccp = (struct auerchar *) file->private_data;
-	int ret = 0;
-	struct audevinfo devinfo;
-	struct auerswald *cp = NULL;
-	unsigned int u;
-	dbg("ioctl");
-
-	/* get the mutexes */
-	if (down_interruptible(&ccp->mutex)) {
-		return -ERESTARTSYS;
-	}
-	cp = ccp->auerdev;
-	if (!cp) {
-		up(&ccp->mutex);
-		return -ENODEV;
-	}
-	if (down_interruptible(&cp->mutex)) {
-		up(&ccp->mutex);
-		return -ERESTARTSYS;
-	}
-
-	/* Check for removal */
-	if (!cp->usbdev) {
-		up(&cp->mutex);
-		up(&ccp->mutex);
-		return -ENODEV;
-	}
-
-	switch (cmd) {
-
-		/* return != 0 if Transmitt channel ready to send */
-	case IOCTL_AU_TXREADY:
-		dbg("IOCTL_AU_TXREADY");
-		u = ccp->auerdev && (ccp->scontext.id != AUH_UNASSIGNED)
-		    && !list_empty(&cp->bufctl.free_buff_list);
-		ret = put_user(u, (unsigned int *) arg);
-		break;
-
-		/* return != 0 if connected to a service channel */
-	case IOCTL_AU_CONNECT:
-		dbg("IOCTL_AU_CONNECT");
-		u = (ccp->scontext.id != AUH_UNASSIGNED);
-		ret = put_user(u, (unsigned int *) arg);
-		break;
-
-		/* return != 0 if Receive Data available */
-	case IOCTL_AU_RXAVAIL:
-		dbg("IOCTL_AU_RXAVAIL");
-		if (ccp->scontext.id == AUH_UNASSIGNED) {
-			ret = -EIO;
-			break;
-		}
-		u = 0;		/* no data */
-		if (ccp->readbuf) {
-			int restlen = ccp->readbuf->len - ccp->readoffset;
-			if (restlen > 0)
-				u = 1;
-		}
-		if (!u) {
-			if (!list_empty(&ccp->bufctl.rec_buff_list)) {
-				u = 1;
-			}
-		}
-		ret = put_user(u, (unsigned int *) arg);
-		break;
-
-		/* return the max. buffer length for the device */
-	case IOCTL_AU_BUFLEN:
-		dbg("IOCTL_AU_BUFLEN");
-		u = cp->maxControlLength;
-		ret = put_user(u, (unsigned int *) arg);
-		break;
-
-		/* requesting a service channel */
-	case IOCTL_AU_SERVREQ:
-		dbg("IOCTL_AU_SERVREQ");
-		/* requesting a service means: release the previous one first */
-		auerswald_removeservice(cp, &ccp->scontext);
-		/* get the channel number */
-		ret = get_user(u, (unsigned int *) arg);
-		if (ret) {
-			break;
-		}
-		if ((u < AUH_FIRSTUSERCH) || (u >= AUH_TYPESIZE)) {
-			ret = -EIO;
-			break;
-		}
-		dbg("auerchar service request parameters are ok");
-		ccp->scontext.id = u;
-
-		/* request the service now */
-		ret = auerswald_addservice(cp, &ccp->scontext);
-		if (ret) {
-			/* no: revert service entry */
-			ccp->scontext.id = AUH_UNASSIGNED;
-		}
-		break;
-
-		/* get a string descriptor for the device */
-	case IOCTL_AU_DEVINFO:
-		dbg("IOCTL_AU_DEVINFO");
-		if (copy_from_user
-		    (&devinfo, (void *) arg, sizeof(struct audevinfo))) {
-			ret = -EFAULT;
-			break;
-		}
-		u = strlen(cp->dev_desc) + 1;
-		if (u > devinfo.bsize) {
-			u = devinfo.bsize;
-		}
-		ret = copy_to_user(devinfo.buf, cp->dev_desc, u);
-		break;
-
-		/* get the max. string descriptor length */
-	case IOCTL_AU_SLEN:
-		dbg("IOCTL_AU_SLEN");
-		u = AUSI_DLEN;
-		ret = put_user(u, (unsigned int *) arg);
-		break;
-
-	default:
-		dbg("IOCTL_AU_UNKNOWN");
-		ret = -ENOIOCTLCMD;
-		break;
-	}
-	/* release the mutexes */
-	up(&cp->mutex);
-	up(&ccp->mutex);
-	return ret;
-}
-
-
-/* Seek is not supported */
-loff_t auerchar_llseek(struct file * file, loff_t offset, int origin)
-{
-	dbg("auerchar_seek");
-	return -ESPIPE;
-}
-
-
-/* Read data from the device */
-ssize_t auerchar_read(struct file * file, char *buf, size_t count,
-		      loff_t * ppos)
-{
-	unsigned long flags;
-	struct auerchar *ccp = (struct auerchar *) file->private_data;
-	struct auerbuf *bp = NULL;
-	wait_queue_t wait;
-
-	dbg("auerchar_read");
-
-	/* Error checking */
-	if (!ccp)
-		return -EIO;
-	if (*ppos)
-		return -ESPIPE;
-	if (count == 0)
-		return 0;
-
-	/* get the mutex */
-	if (down_interruptible(&ccp->mutex))
-		return -ERESTARTSYS;
-
-	/* Can we expect to read something? */
-	if (ccp->scontext.id == AUH_UNASSIGNED) {
-		up(&ccp->mutex);
-		return -EIO;
-	}
-
-	/* only one reader per device allowed */
-	if (down_interruptible(&ccp->readmutex)) {
-		up(&ccp->mutex);
-		return -ERESTARTSYS;
-	}
-
-	/* read data from readbuf, if available */
-      doreadbuf:
-	bp = ccp->readbuf;
-	if (bp) {
-		/* read the maximum bytes */
-		int restlen = bp->len - ccp->readoffset;
-		if (restlen < 0)
-			restlen = 0;
-		if (count > restlen)
-			count = restlen;
-		if (count) {
-			if (copy_to_user
-			    (buf, bp->bufp + ccp->readoffset, count)) {
-				dbg("auerswald_read: copy_to_user failed");
-				up(&ccp->readmutex);
-				up(&ccp->mutex);
-				return -EFAULT;
-			}
-		}
-		/* advance the read offset */
-		ccp->readoffset += count;
-		restlen -= count;
-		// reuse the read buffer
-		if (restlen <= 0) {
-			auerbuf_releasebuf(bp);
-			ccp->readbuf = NULL;
-		}
-		/* return with number of bytes read */
-		if (count) {
-			up(&ccp->readmutex);
-			up(&ccp->mutex);
-			return count;
-		}
-	}
-
-	/* a read buffer is not available. Try to get the next data block. */
-      doreadlist:
-	/* Preparing for sleep */
-	init_waitqueue_entry(&wait, current);
-	set_current_state(TASK_INTERRUPTIBLE);
-	add_wait_queue(&ccp->readwait, &wait);
-
-	bp = NULL;
-	spin_lock_irqsave(&ccp->bufctl.lock, flags);
-	if (!list_empty(&ccp->bufctl.rec_buff_list)) {
-		/* yes: get the entry */
-		struct list_head *tmp = ccp->bufctl.rec_buff_list.next;
-		list_del(tmp);
-		bp = list_entry(tmp, struct auerbuf, buff_list);
-	}
-	spin_unlock_irqrestore(&ccp->bufctl.lock, flags);
-
-	/* have we got data? */
-	if (bp) {
-		ccp->readbuf = bp;
-		ccp->readoffset = AUH_SIZE;	/* for headerbyte */
-		set_current_state(TASK_RUNNING);
-		remove_wait_queue(&ccp->readwait, &wait);
-		goto doreadbuf;	/* now we can read! */
-	}
-
-	/* no data available. Should we wait? */
-	if (file->f_flags & O_NONBLOCK) {
-		dbg("No read buffer available, returning -EAGAIN");
-		set_current_state(TASK_RUNNING);
-		remove_wait_queue(&ccp->readwait, &wait);
-		up(&ccp->readmutex);
-		up(&ccp->mutex);
-		return -EAGAIN;	/* nonblocking, no data available */
-	}
-
-	/* yes, we should wait! */
-	up(&ccp->mutex);	/* allow other operations while we wait */
-	schedule();
-	remove_wait_queue(&ccp->readwait, &wait);
-	if (signal_pending(current)) {
-		/* waked up by a signal */
-		up(&ccp->readmutex);
-		return -ERESTARTSYS;
-	}
-
-	/* Anything left to read? */
-	if ((ccp->scontext.id == AUH_UNASSIGNED) || ccp->removed) {
-		up(&ccp->readmutex);
-		return -EIO;
-	}
-
-	if (down_interruptible(&ccp->mutex)) {
-		up(&ccp->readmutex);
-		return -ERESTARTSYS;
-	}
-
-	/* try to read the incomming data again */
-	goto doreadlist;
-}
-
-
-/* Write a data block into the right service channel of the device */
-ssize_t auerchar_write(struct file *file, const char *buf, size_t len,
-		       loff_t * ppos)
-{
-	struct auerchar *ccp = (struct auerchar *) file->private_data;
-	struct auerswald *cp = NULL;
-	struct auerbuf *bp;
-	int ret;
-	wait_queue_t wait;
-
-	dbg("auerchar_write %d bytes", len);
-
-	/* Error checking */
-	if (!ccp)
-		return -EIO;
-	if (*ppos)
-		return -ESPIPE;
-	if (len == 0)
-		return 0;
-
-      write_again:
-	/* get the mutex */
-	if (down_interruptible(&ccp->mutex))
-		return -ERESTARTSYS;
-
-	/* Can we expect to write something? */
-	if (ccp->scontext.id == AUH_UNASSIGNED) {
-		up(&ccp->mutex);
-		return -EIO;
-	}
-
-	cp = ccp->auerdev;
-	if (!cp) {
-		up(&ccp->mutex);
-		return -ERESTARTSYS;
-	}
-	if (down_interruptible(&cp->mutex)) {
-		up(&ccp->mutex);
-		return -ERESTARTSYS;
-	}
-	if (!cp->usbdev) {
-		up(&cp->mutex);
-		up(&ccp->mutex);
-		return -EIO;
-	}
-	/* Prepare for sleep */
-	init_waitqueue_entry(&wait, current);
-	set_current_state(TASK_INTERRUPTIBLE);
-	add_wait_queue(&cp->bufferwait, &wait);
-
-	/* Try to get a buffer from the device pool.
-	   We can't use a buffer from ccp->bufctl because the write
-	   command will last beond a release() */
-	bp = auerbuf_getbuf(&cp->bufctl);
-	/* are there any buffers left? */
-	if (!bp) {
-		up(&cp->mutex);
-		up(&ccp->mutex);
-
-		/* NONBLOCK: don't wait */
-		if (file->f_flags & O_NONBLOCK) {
-			set_current_state(TASK_RUNNING);
-			remove_wait_queue(&cp->bufferwait, &wait);
-			return -EAGAIN;
-		}
-
-		/* BLOCKING: wait */
-		schedule();
-		remove_wait_queue(&cp->bufferwait, &wait);
-		if (signal_pending(current)) {
-			/* waked up by a signal */
-			return -ERESTARTSYS;
-		}
-		goto write_again;
-	} else {
-		set_current_state(TASK_RUNNING);
-		remove_wait_queue(&cp->bufferwait, &wait);
-	}
-
-	/* protect against too big write requests */
-	if (len > cp->maxControlLength)
-		len = cp->maxControlLength;
-
-	/* Fill the buffer */
-	if (copy_from_user(bp->bufp + AUH_SIZE, buf, len)) {
-		dbg("copy_from_user failed");
-		auerbuf_releasebuf(bp);
-		/* Wake up all processes waiting for a buffer */
-		wake_up(&cp->bufferwait);
-		up(&cp->mutex);
-		up(&ccp->mutex);
-		return -EIO;
-	}
-
-	/* set the header byte */
-	*(bp->bufp) = ccp->scontext.id | AUH_DIRECT | AUH_UNSPLIT;
-
-	/* Set the transfer Parameters */
-	bp->len = len + AUH_SIZE;
-	bp->dr->bRequestType = AUT_WREQ;
-	bp->dr->bRequest = AUV_WBLOCK;
-	bp->dr->wValue = cpu_to_le16(0);
-	bp->dr->wIndex =
-	    cpu_to_le16(ccp->scontext.id | AUH_DIRECT | AUH_UNSPLIT);
-	bp->dr->wLength = cpu_to_le16(len + AUH_SIZE);
-	FILL_CONTROL_URB(bp->urbp, cp->usbdev,
-			 usb_sndctrlpipe(cp->usbdev, 0),
-			 (unsigned char *) bp->dr, bp->bufp,
-			 len + AUH_SIZE, auerchar_ctrlwrite_complete, bp);
-	/* up we go */
-	ret = auerchain_submit_urb(&cp->controlchain, bp->urbp);
-	up(&cp->mutex);
-	if (ret) {
-		dbg("auerchar_write: nonzero result of auerchain_submit_urb %d", ret);
-		auerbuf_releasebuf(bp);
-		/* Wake up all processes waiting for a buffer */
-		wake_up(&cp->bufferwait);
-		up(&ccp->mutex);
-		return -EIO;
-	} else {
-		dbg("auerchar_write: Write OK");
-		up(&ccp->mutex);
-		return len;
-	}
-}
-
-
-/* Close a character device */
-int auerchar_release(struct inode *inode, struct file *file)
-{
-	struct auerchar *ccp = (struct auerchar *) file->private_data;
-	struct auerswald *cp;
-	dbg("release");
-
-	/* get the mutexes */
-	if (down_interruptible(&ccp->mutex)) {
-		return -ERESTARTSYS;
-	}
-	cp = ccp->auerdev;
-	if (cp) {
-		if (down_interruptible(&cp->mutex)) {
-			up(&ccp->mutex);
-			return -ERESTARTSYS;
-		}
-		/* remove an open service */
-		auerswald_removeservice(cp, &ccp->scontext);
-		/* detach from device */
-		if ((--cp->open_count <= 0) && (cp->usbdev == NULL)) {
-			/* usb device waits for removal */
-			up(&cp->mutex);
-			auerswald_delete(cp);
-		} else {
-			up(&cp->mutex);
-		}
-		cp = NULL;
-		ccp->auerdev = NULL;
-	}
-	up(&ccp->mutex);
-	auerchar_delete(ccp);
-
-	return 0;
-}
diff -ruN linux-2.4.20-WRTup/drivers/usb/auerchar.h linux-2.4.20-WRTstp/drivers/usb/auerchar.h
--- linux-2.4.20-WRTup/drivers/usb/auerchar.h	2006-06-12 18:04:59.000000000 -0700
+++ linux-2.4.20-WRTstp/drivers/usb/auerchar.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,79 +0,0 @@
-/*****************************************************************************/
-/*
- *      auerchar.h  --  Auerswald PBX/System Telephone character interface.
- *
- *      Copyright (C) 2002  Wolfgang Mües (wolfgang@iksw-muees.de)
- *
- *      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.
- */
- /*****************************************************************************/
-
-#ifndef AUERCHAR_H
-#define AUERCHAR_H
-
-#include "auerchain.h"
-#include "auerbuf.h"
-#include "auerserv.h"
-
-/* External data structures / Interface                              */
-struct audevinfo {
-	char *buf;		/* return buffer for string contents */
-	unsigned int bsize;	/* size of return buffer */
-};
-
-/* IO controls */
-#define IOCTL_AU_SLEN	  _IOR( 'U', 0xF0, int)	/* return the max. string descriptor length */
-#define IOCTL_AU_DEVINFO  _IOWR('U', 0xF1, struct audevinfo)	/* get name of a specific device */
-#define IOCTL_AU_SERVREQ  _IOW( 'U', 0xF2, int)	/* request a service channel */
-#define IOCTL_AU_BUFLEN	  _IOR( 'U', 0xF3, int)	/* return the max. buffer length for the device */
-#define IOCTL_AU_RXAVAIL  _IOR( 'U', 0xF4, int)	/* return != 0 if Receive Data available */
-#define IOCTL_AU_CONNECT  _IOR( 'U', 0xF5, int)	/* return != 0 if connected to a service channel */
-#define IOCTL_AU_TXREADY  _IOR( 'U', 0xF6, int)	/* return != 0 if Transmitt channel ready to send */
-/*                              'U'  0xF7..0xFF reserved */
-
-/* character device context */
-struct auerswald;
-struct auerchar {
-	struct semaphore mutex;		/* protection in user context */
-	struct auerswald *auerdev;	/* context pointer of assigned device */
-	struct auerbufctl bufctl;	/* controls the buffer chain */
-	struct auerscon scontext;	/* service context */
-	wait_queue_head_t readwait;	/* for synchronous reading */
-	struct semaphore readmutex;	/* protection against multiple reads */
-	struct auerbuf *readbuf;	/* buffer held for partial reading */
-	unsigned int readoffset;	/* current offset in readbuf */
-	unsigned int removed;		/* is != 0 if device is removed */
-};
-
-/* Function prototypes */
-void auerchar_delete(struct auerchar *ccp);
-
-int auerchar_open(struct inode *inode, struct file *file);
-
-int auerchar_ioctl(struct inode *inode, struct file *file,
-		   unsigned int cmd, unsigned long arg);
-
-loff_t auerchar_llseek(struct file *file, loff_t offset, int origin);
-
-ssize_t auerchar_read(struct file *file, char *buf, size_t count,
-		      loff_t * ppos);
-
-ssize_t auerchar_write(struct file *file, const char *buf, size_t len,
-		       loff_t * ppos);
-
-int auerchar_release(struct inode *inode, struct file *file);
-
-
-#endif	/* AUERCHAR_H */
diff -ruN linux-2.4.20-WRTup/drivers/usb/auerisdn_b.c linux-2.4.20-WRTstp/drivers/usb/auerisdn_b.c
--- linux-2.4.20-WRTup/drivers/usb/auerisdn_b.c	2006-06-12 18:04:59.000000000 -0700
+++ linux-2.4.20-WRTstp/drivers/usb/auerisdn_b.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,689 +0,0 @@
-/*****************************************************************************/
-/*
- *      auerisdn_b.c  --  Auerswald PBX/System Telephone ISDN B-channel interface.
- *
- *      Copyright (C) 2002  Wolfgang Mües (wolfgang@iksw-muees.de)
- *
- *      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.
- */
- /*****************************************************************************/
-
-#include <linux/isdnif.h>	/* ISDN constants */
-#include <linux/netdevice.h>	/* skb functions */
-
-#undef DEBUG			/* include debug macros until it's done */
-#include <linux/usb.h>		/* standard usb header */
-
-#include "auerisdn.h"
-#include "auermain.h"
-
-/*-------------------------------------------------------------------*/
-/* ISDN B channel support defines                                    */
-#define AUISDN_BC_1MS		8	/* Bytes per channel and ms */
-#define AUISDN_BC_INC		4	/* change INT OUT size increment */
-#define AUISDN_BCDATATHRESHOLD	48	/* for unsymmetric 2-B-channels */
-#define AUISDN_TOGGLETIME	6	/* Timeout for unsymmetric serve */
-
-/*-------------------------------------------------------------------*/
-/* Debug support 						     */
-#ifdef DEBUG
-#define dump( desc, adr, len) \
-do {			\
-	unsigned int u;	\
-	printk (KERN_DEBUG); \
-	printk (desc); \
-	for (u = 0; u < len; u++) \
-		printk (" %02X", adr[u] & 0xFF); \
-	printk ("\n"); \
-} while (0)
-#else
-#define dump( desc, adr, len)
-#endif
-
-/*-------------------------------------------------------------------*/
-
-/* Callback to L2 for HISAX */
-/* This callback can be called from 3 sources:
-   a) from hisax context (answer from a l2l1 function)
-   b) from interrupt context (a B channel paket arrived, a B channel paket was sent)
-   c) from kernel daemon context (probe/disconnecting)
-*/
-void auerisdn_b_l1l2(struct auerisdnbc *bc, int pr, void *arg)
-{
-	struct auerhisax *ahp;
-	struct sk_buff *skb;
-
-	/* do the callback */
-	ahp = bc->cp->isdn.ahp;
-	if (ahp) {
-		ahp->hisax_b_if[bc->channel].ifc.l1l2(&ahp->
-						      hisax_b_if[bc->
-								 channel].
-						      ifc, pr, arg);
-	} else {
-		dbg("auerisdn_b_l1l2 called without ahp");
-		if (pr == (PH_DATA | INDICATION)) {
-			skb = (struct sk_buff *) arg;
-			if (skb) {
-				skb_pull(skb, skb->len);
-				dev_kfree_skb_any(skb);
-			}
-		}
-	}
-}
-
-/* fill the INT OUT data buffer with new data */
-/* Transfer buffer size to fill is in urbp->transfer_buffer_length */
-static void auerisdn_bintbo_newdata(struct auerisdn *ip)
-{
-	unsigned long flags;
-	struct urb *urbp = ip->intbo_urbp;
-	struct auerisdnbc *bc = &ip->bc[0];	/* start with B-channel 0 */
-	struct sk_buff *skb;
-	unsigned char *ucp;
-	int buf_size;
-	int len;
-	int bytes_sent;
-	int i;
-
-	/* FIXME: this algorithm is fixed to 2 B-channels */
-	/* Which B channel should we serve? */
-	if (ip->bc[1].mode != L1_MODE_NULL) {
-		/* B channel 1 is used */
-		if (bc->mode != L1_MODE_NULL) {
-			/* both B-channels are used */
-			if (ip->intbo_toggletimer) {
-				/* simply toggling */
-				ip->intbo_toggletimer--;
-				i = ip->intbo_index ^ 1;	/* serve both channels equal */
-			} else {
-				/* search the B channel with the most demand of data */
-				i = bc->txfree - ip->bc[1].txfree;
-				if (i < -AUISDN_BCDATATHRESHOLD)
-					i = 1;	/* B channel 1 needs more data */
-				else if (i > AUISDN_BCDATATHRESHOLD)
-					i = 0;	/* B channel 0 needs more data */
-				else
-					i = ip->intbo_index ^ 1;	/* serve both channels equal */
-				if (i == ip->intbo_index)
-					ip->intbo_toggletimer =
-					    AUISDN_TOGGLETIME;
-			}
-			bc = &ip->bc[i];
-			ip->intbo_index = i;
-		} else {
-			bc = &ip->bc[1];
-		}
-	}
-	dbg("INTBO: Fill B%d with %d Bytes, %d Bytes free",
-	    bc->channel + 1, urbp->transfer_buffer_length - AUH_SIZE,
-	    bc->txfree);
-
-	/* Fill the buffer with data */
-	ucp = ip->intbo_bufp;
-	*ucp++ = AUH_B1CHANNEL + bc->channel;	/* First byte is channel nr. */
-	buf_size = urbp->transfer_buffer_length - AUH_SIZE;
-	len = 0;
-	while (len < buf_size) {
-		spin_lock_irqsave(&bc->txskb_lock, flags);
-		if ((skb = bc->txskb)) {
-			/* dump ("raw tx data:", skb->data, skb->len); */
-			if (bc->mode == L1_MODE_TRANS) {
-				bytes_sent = buf_size - len;
-				if (skb->len < bytes_sent)
-					bytes_sent = skb->len;
-				{	/* swap tx bytes */
-					register unsigned char *src =
-					    skb->data;
-					unsigned int count;
-					for (count = 0; count < bytes_sent;
-					     count++)
-						*ucp++ =
-						    isdnhdlc_bit_rev_tab
-						    [*src++];
-				}
-				len += bytes_sent;
-				bc->lastbyte = skb->data[bytes_sent - 1];
-			} else {
-				int bs =
-				    isdnhdlc_encode(&bc->outp_hdlc_state,
-						    skb->data, skb->len,
-						    &bytes_sent,
-						    ucp, buf_size - len);
-				/* dump ("hdlc data:", ucp, bs); */
-				len += bs;
-				ucp += bs;
-			}
-			skb_pull(skb, bytes_sent);
-
-			if (!skb->len) {
-				// Frame sent
-				bc->txskb = NULL;
-				spin_unlock_irqrestore(&bc->txskb_lock,
-						       flags);
-				auerisdn_b_l1l2(bc, PH_DATA | CONFIRM,
-						(void *) skb->truesize);
-				dev_kfree_skb_any(skb);
-				continue;	//while
-			}
-		} else {
-			if (bc->mode == L1_MODE_TRANS) {
-				memset(ucp, bc->lastbyte, buf_size - len);
-				ucp += buf_size - len;
-				len = buf_size;
-				/* dbg ("fill = 0xFF"); */
-			} else {
-				// Send flags
-				int bs =
-				    isdnhdlc_encode(&bc->outp_hdlc_state,
-						    NULL, 0, &bytes_sent,
-						    ucp, buf_size - len);
-				/* dbg ("fill = 0x%02X", (int)*ucp); */
-				len += bs;
-				ucp += bs;
-			}
-		}
-		spin_unlock_irqrestore(&bc->txskb_lock, flags);
-	}
-	/* dbg ("%d Bytes to TX buffer", len); */
-}
-
-
-/* INT OUT completion handler */
-static void auerisdn_bintbo_complete(struct urb *urbp)
-{
-	struct auerisdn *ip = urbp->context;
-
-	/* unlink completion? */
-	if ((urbp->status == -ENOENT) || (urbp->status == -ECONNRESET)) {
-		/* should we restart with another size? */
-		if (ip->intbo_state == INTBOS_CHANGE) {
-			dbg("state => RESTART");
-			ip->intbo_state = INTBOS_RESTART;
-		} else {
-			/* set up variables for later restart */
-			dbg("INTBO stopped");
-			ip->intbo_state = INTBOS_IDLE;
-		}
-		/* nothing more to do */
-		return;
-	}
-
-	/* other state != 0? */
-	if (urbp->status) {
-		warn("auerisdn_bintbo_complete: status = %d",
-		     urbp->status);
-		return;
-	}
-
-	/* Should we fill in new data? */
-	if (ip->intbo_state == INTBOS_CHANGE) {
-		dbg("state == INTBOS_CHANGE, no new data");
-		return;
-	}
-
-	/* fill in new data */
-	auerisdn_bintbo_newdata(ip);
-}
-
-/* set up the INT OUT URB the first time */
-/* Don't start the URB */
-static void auerisdn_bintbo_setup(struct auerisdn *ip, unsigned int len)
-{
-	ip->intbo_state = INTBOS_IDLE;
-	FILL_INT_URB(ip->intbo_urbp, ip->usbdev,
-		     usb_sndintpipe(ip->usbdev, ip->intbo_endp),
-		     ip->intbo_bufp, len, auerisdn_bintbo_complete, ip,
-		     ip->outInterval);
-	ip->intbo_urbp->transfer_flags |= USB_ASYNC_UNLINK;
-	ip->intbo_urbp->status = 0;
-}
-
-/* restart the INT OUT endpoint */
-static void auerisdn_bintbo_restart(struct auerisdn *ip)
-{
-	struct urb *urbp = ip->intbo_urbp;
-	int status;
-
-	/* dbg ("auerisdn_intbo_restart"); */
-
-	/* fresh restart */
-	auerisdn_bintbo_setup(ip, ip->paketsize + AUH_SIZE);
-
-	/* Fill in new data */
-	auerisdn_bintbo_newdata(ip);
-
-	/* restart the urb */
-	ip->intbo_state = INTBOS_RUNNING;
-	status = usb_submit_urb(urbp);
-	if (status < 0) {
-		err("can't submit INT OUT urb, status = %d", status);
-		urbp->status = status;
-		urbp->complete(urbp);
-	}
-}
-
-/* change the size of the INT OUT endpoint */
-static void auerisdn_bchange(struct auerisdn *ip, unsigned int paketsize)
-{
-	/* changing... */
-	dbg("txfree[0] = %d, txfree[1] = %d, old size = %d, new size = %d",
-	    ip->bc[0].txfree, ip->bc[1].txfree, ip->paketsize, paketsize);
-	ip->paketsize = paketsize;
-
-	if (paketsize == 0) {
-		/* stop the INT OUT endpoint */
-		dbg("stop unlinking INT out urb");
-		ip->intbo_state = INTBOS_IDLE;
-		usb_unlink_urb(ip->intbo_urbp);
-		return;
-	}
-	if (ip->intbo_state != INTBOS_IDLE) {
-		/* dbg ("unlinking INT out urb"); */
-		ip->intbo_state = INTBOS_CHANGE;
-		usb_unlink_urb(ip->intbo_urbp);
-	} else {
-		/* dbg ("restart immediately"); */
-		auerisdn_bintbo_restart(ip);
-	}
-}
-
-/* serve the outgoing B channel interrupt */
-/* Called from the INT IN completion handler */
-static void auerisdn_bserv(struct auerisdn *ip)
-{
-	struct auerisdnbc *bc;
-	unsigned int u;
-	unsigned int paketsize;
-
-	/* should we start the INT OUT endpoint again? */
-	if (ip->intbo_state == INTBOS_RESTART) {
-		/* dbg ("Restart INT OUT from INT IN"); */
-		auerisdn_bintbo_restart(ip);
-		return;
-	}
-	/* no new calculation if change already in progress */
-	if (ip->intbo_state == INTBOS_CHANGE)
-		return;
-
-	/* calculation of transfer parameters for INT OUT endpoint */
-	paketsize = 0;
-	for (u = 0; u < AUISDN_BCHANNELS; u++) {
-		bc = &ip->bc[u];
-		if (bc->mode != L1_MODE_NULL) {	/* B channel is active */
-			unsigned int bpp = AUISDN_BC_1MS * ip->outInterval;
-			if (bc->txfree < bpp) {	/* buffer is full, throttle */
-				bc->txsize = bpp - AUISDN_BC_INC;
-				paketsize += bpp - AUISDN_BC_INC;
-			} else if (bc->txfree < bpp * 2) {
-				paketsize += bc->txsize;	/* schmidt-trigger, continue */
-			} else if (bc->txfree < bpp * 4) {	/* we are in synch */
-				bc->txsize = bpp;
-				paketsize += bpp;
-			} else if (bc->txfree > bc->ofsize / 2) {/* we have to fill the buffer */
-				bc->txsize = bpp + AUISDN_BC_INC;
-				paketsize += bpp + AUISDN_BC_INC;
-			} else {
-				paketsize += bc->txsize;	/* schmidt-trigger, continue */
-			}
-		}
-	}
-
-	/* check if we have to change the paket size */
-	if (paketsize != ip->paketsize)
-		auerisdn_bchange(ip, paketsize);
-}
-
-/* Send activation/deactivation state to L2 */
-static void auerisdn_bconf(struct auerisdnbc *bc)
-{
-	unsigned long flags;
-	struct sk_buff *skb;
-
-	if (bc->mode == L1_MODE_NULL) {
-		auerisdn_b_l1l2(bc, PH_DEACTIVATE | INDICATION, NULL);
-		/* recycle old txskb */
-		spin_lock_irqsave(&bc->txskb_lock, flags);
-		skb = bc->txskb;
-		bc->txskb = NULL;
-		spin_unlock_irqrestore(&bc->txskb_lock, flags);
-		if (skb) {
-			skb_pull(skb, skb->len);
-			auerisdn_b_l1l2(bc, PH_DATA | CONFIRM,
-					(void *) skb->truesize);
-			dev_kfree_skb_any(skb);
-		}
-	} else {
-		auerisdn_b_l1l2(bc, PH_ACTIVATE | INDICATION, NULL);
-	}
-}
-
-/* B channel setup completion handler */
-static void auerisdn_bmode_complete(struct urb *urb)
-{
-	struct auerswald *cp;
-	struct auerbuf *bp = (struct auerbuf *) urb->context;
-	struct auerisdnbc *bc;
-	int channel;
-
-	dbg("auerisdn_bmode_complete called");
-	cp = ((struct auerswald *) ((char *) (bp->list) -
-				    (unsigned
-				     long) (&((struct auerswald *) 0)->
-					    bufctl)));
-
-	/* select the B-channel */
-	channel = le16_to_cpu(bp->dr->wIndex);
-	channel -= AUH_B1CHANNEL;
-	if (channel < 0)
-		goto rel;
-	if (channel >= AUISDN_BCHANNELS)
-		goto rel;
-	bc = &cp->isdn.bc[channel];
-
-	/* Check for success */
-	if (urb->status) {
-		err("complete with non-zero status: %d", urb->status);
-	} else {
-		bc->mode = *bp->bufp;
-	}
-	/* Signal current mode to L2 */
-	auerisdn_bconf(bc);
-
-	/* reuse the buffer */
-      rel:auerbuf_releasebuf(bp);
-
-	/* Wake up all processes waiting for a buffer */
-	wake_up(&cp->bufferwait);
-}
-
-/* Setup a B channel transfer mode */
-static void auerisdn_bmode(struct auerisdnbc *bc, unsigned int mode)
-{
-	struct auerswald *cp = bc->cp;
-	struct auerbuf *bp;
-	int ret;
-
-	/* don't allow activation on disconnect */
-	if (cp->disconnecting) {
-		mode = L1_MODE_NULL;
-
-		/* Else check if something changed */
-	} else if (bc->mode != mode) {
-		if ((mode != L1_MODE_NULL) && (mode != L1_MODE_TRANS)) {
-			/* init RX hdlc decoder */
-			dbg("rcv init");
-			isdnhdlc_rcv_init(&bc->inp_hdlc_state, 0);
-			/* init TX hdlc decoder */
-			dbg("out init");
-			isdnhdlc_out_init(&bc->outp_hdlc_state, 0, 0);
-		}
-		/* stop ASAP */
-		if (mode == L1_MODE_NULL)
-			bc->mode = mode;
-		if ((bc->mode == L1_MODE_NULL) || (mode == L1_MODE_NULL)) {
-			/* Activation or deactivation required */
-
-			/* get a buffer for the command */
-			bp = auerbuf_getbuf(&cp->bufctl);
-			/* if no buffer available: can't change the mode */
-			if (!bp) {
-				err("auerisdn_bmode: no data buffer available");
-				return;
-			}
-
-			/* fill the control message */
-			bp->dr->bRequestType = AUT_WREQ;
-			bp->dr->bRequest = AUV_CHANNELCTL;
-			if (mode != L1_MODE_NULL)
-				bp->dr->wValue = cpu_to_le16(1);
-			else
-				bp->dr->wValue = cpu_to_le16(0);
-			bp->dr->wIndex =
-			    cpu_to_le16(AUH_B1CHANNEL + bc->channel);
-			bp->dr->wLength = cpu_to_le16(0);
-			*bp->bufp = mode;
-			FILL_CONTROL_URB(bp->urbp, cp->usbdev,
-					 usb_sndctrlpipe(cp->usbdev, 0),
-					 (unsigned char *) bp->dr,
-					 bp->bufp, 0,
-					 (usb_complete_t)
-					 auerisdn_bmode_complete, bp);
-
-			/* submit the control msg */
-			ret =
-			    auerchain_submit_urb(&cp->controlchain,
-						 bp->urbp);
-			if (ret) {
-				bp->urbp->status = ret;
-				auerisdn_bmode_complete(bp->urbp);
-			}
-			return;
-		}
-	}
-	/* new mode is set */
-	bc->mode = mode;
-
-	/* send confirmation to L2 */
-	auerisdn_bconf(bc);
-}
-
-/* B-channel transfer function L2->L1 */
-void auerisdn_b_l2l1(struct hisax_if *ifc, int pr, void *arg,
-		     unsigned int channel)
-{
-	struct auerhisax *ahp;
-	struct auerisdnbc *bc;
-	struct auerswald *cp;
-	struct sk_buff *skb;
-	unsigned long flags;
-	int mode;
-
-	cp = NULL;
-	ahp = (struct auerhisax *) ifc->priv;
-	if (ahp)
-		cp = ahp->cp;
-	if (cp && !cp->disconnecting) {
-		/* normal execution */
-		bc = &cp->isdn.bc[channel];
-		switch (pr) {
-		case PH_ACTIVATE | REQUEST:	/* activation request */
-			mode = (int) arg;	/* one of the L1_MODE constants */
-			dbg("B%d, PH_ACTIVATE_REQUEST Mode = %d",
-			    bc->channel + 1, mode);
-			auerisdn_bmode(bc, mode);
-			break;
-		case PH_DEACTIVATE | REQUEST:	/* deactivation request */
-			dbg("B%d, PH_DEACTIVATE_REQUEST", bc->channel + 1);
-			auerisdn_bmode(bc, L1_MODE_NULL);
-			break;
-		case PH_DATA | REQUEST:	/* Transmit data request */
-			skb = (struct sk_buff *) arg;
-			spin_lock_irqsave(&bc->txskb_lock, flags);
-			if (bc->txskb) {
-				err("Overflow in B channel TX");
-				skb_pull(skb, skb->len);
-				dev_kfree_skb_any(skb);
-			} else {
-				if (cp->disconnecting
-				    || (bc->mode == L1_MODE_NULL)) {
-					skb_pull(skb, skb->len);
-					spin_unlock_irqrestore(&bc->
-							       txskb_lock,
-							       flags);
-					auerisdn_b_l1l2(bc,
-							PH_DATA | CONFIRM,
-							(void *) skb->
-							truesize);
-					dev_kfree_skb_any(skb);
-					goto next;
-				} else
-					bc->txskb = skb;
-			}
-			spin_unlock_irqrestore(&bc->txskb_lock, flags);
-		      next:break;
-		default:
-			warn("pr %#x\n", pr);
-			break;
-		}
-	} else {
-		/* hisax interface is down */
-		switch (pr) {
-		case PH_ACTIVATE | REQUEST:	/* activation request */
-			dbg("B channel: PH_ACTIVATE | REQUEST with interface down");
-			/* don't answer this request! Endless... */
-			break;
-		case PH_DEACTIVATE | REQUEST:	/* deactivation request */
-			dbg("B channel: PH_DEACTIVATE | REQUEST with interface down");
-			ifc->l1l2(ifc, PH_DEACTIVATE | INDICATION, NULL);
-			break;
-		case PH_DATA | REQUEST:	/* Transmit data request */
-			dbg("B channel: PH_DATA | REQUEST with interface down");
-			skb = (struct sk_buff *) arg;
-			/* free data buffer */
-			if (skb) {
-				skb_pull(skb, skb->len);
-				dev_kfree_skb_any(skb);
-			}
-			/* send confirmation back to layer 2 */
-			ifc->l1l2(ifc, PH_DATA | CONFIRM, NULL);
-			break;
-		default:
-			warn("pr %#x\n", pr);
-			break;
-		}
-	}
-}
-
-/* Completion handler for B channel input endpoint */
-void auerisdn_intbi_complete(struct urb *urb)
-{
-	unsigned int bytecount;
-	unsigned char *ucp;
-	int channel;
-	unsigned int syncbit;
-	unsigned int syncdata;
-	struct auerisdnbc *bc;
-	struct sk_buff *skb;
-	int count;
-	int status;
-	struct auerswald *cp = (struct auerswald *) urb->context;
-	/* do not respond to an error condition */
-	if (urb->status != 0) {
-		dbg("nonzero URB status = %d", urb->status);
-		return;
-	}
-	if (cp->disconnecting)
-		return;
-
-	/* Parse and extract the header information */
-	bytecount = urb->actual_length;
-	ucp = cp->isdn.intbi_bufp;
-	if (!bytecount)
-		return;		/* no data */
-	channel = *ucp & AUH_TYPEMASK;
-	syncbit = *ucp & AUH_SYNC;
-	ucp++;
-	bytecount--;
-	channel -= AUH_B1CHANNEL;
-	if (channel < 0)
-		return;		/* unknown data channel, no B1,B2 */
-	if (channel >= AUISDN_BCHANNELS)
-		return;		/* unknown data channel, no B1,B2 */
-	bc = &cp->isdn.bc[channel];
-	if (!bytecount)
-		return;
-	/* Calculate amount of bytes which are free in tx device buffer */
-	bc->txfree = ((255 - *ucp++) * bc->ofsize) / 256;
-	/* dbg ("%d Bytes free in TX buffer", bc->txfree); */
-	bytecount--;
-
-	/* Next Byte: TX sync information */
-	if (syncbit) {
-		if (!bytecount)
-			goto int_tx;
-		syncdata = *ucp++;
-		dbg("Sync data = %d", syncdata);
-		bytecount--;
-	}
-	/* The rest of the paket is plain data */
-	if (!bytecount)
-		goto int_tx;
-	/* dump ("RX Data is:", ucp, bytecount); */
-
-	/* Send B channel data to upper layers */
-	while (bytecount > 0) {
-		if (bc->mode == L1_MODE_NULL) {
-			/* skip the data. Nobody needs them */
-			status = 0;
-			bytecount = 0;
-		} else if (bc->mode == L1_MODE_TRANS) {
-			{	/* swap rx bytes */
-				register unsigned char *dest = bc->rxbuf;
-				status = bytecount;
-				for (; bytecount; bytecount--)
-					*dest++ =
-					    isdnhdlc_bit_rev_tab[*ucp++];
-			}
-
-		} else {
-			status = isdnhdlc_decode(&bc->inp_hdlc_state, ucp,
-						 bytecount, &count,
-						 bc->rxbuf, AUISDN_RXSIZE);
-			ucp += count;
-			bytecount -= count;
-		}
-		if (status > 0) {
-			/* Good frame received */
-			if (!(skb = dev_alloc_skb(status))) {
-				warn("receive out of memory");
-				break;
-			}
-			memcpy(skb_put(skb, status), bc->rxbuf, status);
-			/* dump ("HDLC Paket", bc->rxbuf, status); */
-			auerisdn_b_l1l2(bc, PH_DATA | INDICATION, skb);
-			/* these errors may actually happen at the start of a connection! */
-		} else if (status == -HDLC_CRC_ERROR) {
-			dbg("CRC error");
-		} else if (status == -HDLC_FRAMING_ERROR) {
-			dbg("framing error");
-		} else if (status == -HDLC_LENGTH_ERROR) {
-			dbg("length error");
-		}
-	}
-
-      int_tx:			/* serve the outgoing B channel */
-	auerisdn_bserv(&cp->isdn);
-}
-
-/* Stop the B channel activity. The device is disconnecting */
-/* This function is called after cp->disconnecting is true */
-unsigned int auerisdn_b_disconnect(struct auerswald *cp)
-{
-	unsigned int u;
-	struct auerisdnbc *bc;
-	unsigned int result = 0;
-
-	/* Close the B channels */
-	for (u = 0; u < AUISDN_BCHANNELS; u++) {
-		bc = &cp->isdn.bc[u];
-		if (bc->mode != L1_MODE_NULL) {	/* B channel is active */
-			auerisdn_bmode(bc, L1_MODE_NULL);
-			result = 1;
-		}
-	}
-	/* return 1 if there is B channel traffic */
-	return result;
-}
diff -ruN linux-2.4.20-WRTup/drivers/usb/auerisdn_b.h linux-2.4.20-WRTstp/drivers/usb/auerisdn_b.h
--- linux-2.4.20-WRTup/drivers/usb/auerisdn_b.h	2006-06-12 18:04:59.000000000 -0700
+++ linux-2.4.20-WRTstp/drivers/usb/auerisdn_b.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,66 +0,0 @@
-/*****************************************************************************/
-/*
- *      auerisdn_b.h  --  Auerswald PBX/System Telephone ISDN B channel interface.
- *
- *      Copyright (C) 2002  Wolfgang Mües (wolfgang@iksw-muees.de)
- *
- *      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.
- */
- /*****************************************************************************/
-
-#ifndef AUERISDN_B_H
-#define AUERISDN_B_H
-
-#include <../drivers/isdn/hisax/hisax_if.h>
-#include <linux/skbuff.h>
-#include "auerbuf.h"
-#include <../drivers/isdn/hisax/isdnhdlc.h>
-
-#define AUISDN_RXSIZE	4096	/* RX buffer size */
-#define AUISDN_BCHANNELS   2	/* Number of supported B channels */
-
-/* states for intbo_state */
-#define INTBOS_IDLE	0
-#define INTBOS_RUNNING	1
-#define INTBOS_CHANGE 	2
-#define INTBOS_RESTART	3
-
-/* ...................................................................*/
-/* B channel state data */
-struct auerswald;
-struct auerisdnbc {
-	struct auerswald *cp;	/* Context to usb device */
-	struct sk_buff *txskb;	/* sk buff to transmitt */
-	spinlock_t txskb_lock;	/* protect against races */
-	unsigned int mode;	/* B-channel mode */
-	unsigned int channel;	/* Number of this B-channel */
-	unsigned int ofsize;	/* Size of device OUT fifo in Bytes */
-	int txfree;		/* free bytes in tx buffer of device */
-	unsigned int txsize;	/* size of data paket for this channel */
-	unsigned char *rxbuf;	/* Receiver input buffer */
-	struct isdnhdlc_vars inp_hdlc_state;	/* state for RX software HDLC */
-	struct isdnhdlc_vars outp_hdlc_state;	/* state for TX software HDLC */
-	unsigned int lastbyte;	/* last byte sent out to trans. B channel */
-};
-
-/* Function Prototypes */
-void auerisdn_b_l2l1(struct hisax_if *ifc, int pr, void *arg,
-		     unsigned int channel);
-void auerisdn_b_l1l2(struct auerisdnbc *bc, int pr, void *arg);
-
-void auerisdn_intbi_complete(struct urb *urb);
-unsigned int auerisdn_b_disconnect(struct auerswald *cp);
-
-#endif	/* AUERISDN_B_H */
diff -ruN linux-2.4.20-WRTup/drivers/usb/auerisdn.c linux-2.4.20-WRTstp/drivers/usb/auerisdn.c
--- linux-2.4.20-WRTup/drivers/usb/auerisdn.c	2006-06-12 18:04:59.000000000 -0700
+++ linux-2.4.20-WRTstp/drivers/usb/auerisdn.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,1076 +0,0 @@
-/*****************************************************************************/
-/*
- *      auerisdn.c  --  Auerswald PBX/System Telephone ISDN interface.
- *
- *      Copyright (C) 2002  Wolfgang Mües (wolfgang@iksw-muees.de)
- *
- *      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.
- */
- /*****************************************************************************/
-
-#include <linux/isdnif.h>
-#include <linux/netdevice.h>
-#include <linux/sched.h>
-
-#undef	DEBUG			/* include debug macros until it's done */
-#include <linux/usb.h>
-
-#include "auerisdn.h"
-#include "auermain.h"
-
-/*-------------------------------------------------------------------*/
-/* ISDN support defines                                              */
-#define AUISDN_TEI	64	/* use a constant TEI */
-
-/*-------------------------------------------------------------------*/
-/* Debug support 						     */
-#ifdef DEBUG
-#define dump( desc, adr, len) \
-do {			\
-	unsigned int u;	\
-	printk (KERN_DEBUG); \
-	printk (desc); \
-	for (u = 0; u < len; u++) \
-		printk (" %02X", adr[u] & 0xFF); \
-	printk ("\n"); \
-} while (0)
-#else
-#define dump( desc, adr, len)
-#endif
-
-/*-------------------------------------------------------------------*/
-/* Hisax Interface.     					     */
-
-/* The interface to hisax is long-lasting because hisax_unregister()
-   don't work well in Linux 2.4.x. So we have to hold each registered
-   hisax interface until driver removal. */
-static struct auerhisax auerhisax_table[AUER_MAX_DEVICES];
-
-
-/*-------------------------------------------------------------------*/
-
-/* Callback to L2 for HISAX */
-/* This callback can be called from 3 sources:
-   a) from hisax context (answer from a l2l1 function)
-   b) from interrupt context (a D channel paket arrived)
-   c) from kernel daemon context (probe/disconnecting)
-*/
-static void auerisdn_d_l1l2(struct auerisdn *ip, int pr, void *arg)
-{
-	struct sk_buff *skb;
-	struct auerhisax *ahp;
-
-	/* do the callback */
-	ahp = ip->ahp;
-	if (ahp) {
-		ahp->hisax_d_if.ifc.l1l2(&ahp->hisax_d_if.ifc, pr, arg);
-	} else {
-		dbg("auerisdn_d_l1l2 with ahp == NULL");
-		if (pr == (PH_DATA | INDICATION)) {
-			skb = (struct sk_buff *) arg;
-			if (skb) {
-				skb_pull(skb, skb->len);
-				dev_kfree_skb_any(skb);
-			}
-		}
-	}
-}
-
-
-/* D-Channel sending completion function */
-static void auerisdn_dcw_complete(struct urb *urb)
-{
-	struct auerbuf *bp = (struct auerbuf *) urb->context;
-	struct auerswald *cp =
-	    ((struct auerswald *) ((char *) (bp->list) -
-				   (unsigned
-				    long) (&((struct auerswald *) 0)->
-					   bufctl)));
-
-	dbg("auerisdn_dcw_complete with status %d", urb->status);
-
-	/* reuse the buffer */
-	auerbuf_releasebuf(bp);
-
-	/* Wake up all processes waiting for a buffer */
-	wake_up(&cp->bufferwait);
-}
-
-
-/* Translate non-ETSI ISDN messages from the device */
-static void auerisdn_translate_incoming(struct auerswald *cp,
-					unsigned char *msg,
-					unsigned int len)
-{
-	struct auerbuf *bp;
-	int ret;
-
-	/* Translate incomming CONNECT -> CONNECT_ACK */
-	/* Format:   0   1    2     3     4        5        6    7      */
-	/*         SAPI TEI TXSEQ RXSEQ PID=08 CREFLEN=01 CREF MSG=7 ...*/
-	/* CREF.7 == 0 -> Incoming Call                                 */
-
-	/* Check for minimum length */
-	if (len < 8)
-		return;
-
-	/* Check for a CONNECT, call originated from device */
-	if (((msg[6] & 0x80) == 0) && (msg[7] == 0x07)) {
-		dbg("false CONNECT from device found");
-		/* change into CONNECT_ACK */
-		msg[7] = 0x0F;
-
-		/* Send a CONNECT_ACK back to the device */
-
-		/* get a new data buffer */
-		bp = auerbuf_getbuf(&cp->bufctl);
-		if (!bp) {
-			warn("no auerbuf free");
-			return;
-		}
-
-		/* Form a CONNECT ACK */
-		bp->bufp[0] =
-		    cp->isdn.dchannelservice.id | AUH_DIRECT | AUH_UNSPLIT;
-		bp->bufp[1] = 0x08;
-		bp->bufp[2] = 0x01;
-		bp->bufp[3] = msg[6] | 0x80;
-		bp->bufp[4] = 0x0F;
-
-		/* Set the transfer Parameters */
-		bp->len = 5;
-		bp->dr->bRequestType = AUT_WREQ;
-		bp->dr->bRequest = AUV_WBLOCK;
-		bp->dr->wValue = cpu_to_le16(0);
-		bp->dr->wIndex =
-		    cpu_to_le16(cp->isdn.dchannelservice.
-				id | AUH_DIRECT | AUH_UNSPLIT);
-		bp->dr->wLength = cpu_to_le16(5);
-		FILL_CONTROL_URB(bp->urbp, cp->usbdev,
-				 usb_sndctrlpipe(cp->usbdev, 0),
-				 (unsigned char *) bp->dr, bp->bufp, 5,
-				 auerisdn_dcw_complete, bp);
-		/* up we go */
-		ret = auerchain_submit_urb(&cp->controlchain, bp->urbp);
-		if (ret)
-			auerisdn_dcw_complete(bp->urbp);
-		else
-			dbg("auerisdn_translate: Write OK");
-	}
-	/* Check for a DISCONNECT and change to RELEASE */
-	if (msg[7] == 0x45) {
-		dbg("DISCONNECT changed to RELEASE");
-		msg[7] = 0x4D;
-		return;
-	}
-}
-
-
-/* a D-channel paket arrived from the device */
-static void auerisdn_dispatch_dc(struct auerscon *scp, struct auerbuf *bp)
-{
-	struct sk_buff *skb;
-	struct auerhisax *ahp;
-	struct auerswald *cp =
-	    ((struct auerswald *) ((char *) (scp) -
-				   (unsigned
-				    long) (&((struct auerswald *) 0)->isdn.
-					   dchannelservice)));
-	unsigned char *sp;
-	unsigned int l2_index;
-	unsigned char c;
-	unsigned char l2_header[10];
-	unsigned long flags;
-
-	dump("D-Channel paket arrived:", bp->bufp, bp->len);
-	if (cp->disconnecting)
-		return;
-
-	/* add a self-generated L2 message header */
-	l2_index = 0;
-	l2_header[l2_index++] = 0x02;	/* SAPI 0, C/R = 1 */
-
-	/* Parse the L3 message */
-	sp = bp->bufp + AUH_SIZE;
-
-	c = *sp++;		/* Protocol discriminator */
-	if (c != 0x08) {
-		warn("D channel paket is not ETSI");
-		return;
-	}
-	c = *sp++;		/* Call Reference length byte */
-	sp += c;		/* Skip Call Reference */
-
-	/* translate charge IEs */
-	/* Format of Auerswald Header:
-	   0x32 len=0x0B 0xFF 0xFF 0x73 len=0x07 0x27 */
-	/* Format of IE2_UNIT:
-	   0x49 len=0x04 uu1 uu2 uu3 uu4 */
-	/* Translate into: (?? Bytes)
-	   0x1C Facility
-	   0x?? restlen
-	   0x91 Sup. Services
-	   0xA1 Invoke
-	   0x?? restlen
-	   0x02 Invoke ID Tag
-	   0x02 Invoke ID len
-	   0x12 Invoke ID = 0x1234
-	   0x34
-	   0x02 OP Value Tag
-	   0x01 Length of OPvalue
-	   0x24 OpValue = AOCE
-	   0x30 Universal Constructor Sequence
-	   0x?? restlen
-	   0x30 Universal Constructor Sequence
-	   0x?? restlen
-	   0xA1 Context Specific Constructor Recorded Units List
-	   0x?? restlen
-	   0x30 Universal Constructor Sequence
-	   0x?? restlen
-	   0x02 Universal Primitive Integer
-	   0x?? len from IE2_UNIT
-	   uu1  Recorded Units List
-	   uu2
-	   uu3
-	   uu4
-	 */
-	{
-		unsigned char *ucp = sp;	// pointer to start of msg
-		int l = bp->len;	// length until EOP
-		unsigned char alen;	// length of auerswald msg
-		l -= (int) (ucp - bp->bufp);
-		// scan for Auerswald Header
-		for (; l >= 9; l--, ucp++) {	// 9 = minimal length of auerswald msg
-			if (ucp[0] != 0x32)
-				continue;
-			if (ucp[2] != 0xFF)
-				continue;
-			if (ucp[3] != 0xFF)
-				continue;
-			if (ucp[4] != 0x73)
-				continue;
-			if (ucp[6] != 0x27)
-				continue;
-			// Auerswald Header found. Is it units?
-			dbg("Auerswald msg header found");
-			alen = ucp[1] + 2;
-			if (ucp[7] == 0x49) {
-				// yes
-				unsigned char ul = ucp[8] + 1;	// length of charge integer
-				unsigned char charge[32];
-				// Copy charge info into new buffer
-				unsigned char *xp = &ucp[8];
-				int count;
-				for (count = 0; count < ul; count++)
-					charge[count] = *xp++;
-				// Erase auerswald msg
-				count = l - alen;
-				xp = ucp;
-				for (; count; count--, xp++)
-					xp[0] = xp[alen];
-				l -= alen;
-				bp->len -= alen;
-				// make room for new message
-				count = l;
-				xp = &ucp[l - 1];
-				for (; count; count--, xp--);
-				xp[21 + ul] = xp[0];
-				l += (21 + ul);
-				bp->len += (21 + ul);
-				// insert IE header
-				ucp[0] = 0x1C;
-				ucp[1] = 19 + ul;
-				ucp[2] = 0x91;
-				ucp[3] = 0xA1;
-				ucp[4] = 16 + ul;
-				ucp[5] = 0x02;
-				ucp[6] = 0x02;
-				ucp[7] = 0x12;
-				ucp[8] = 0x34;
-				ucp[9] = 0x02;
-				ucp[10] = 0x01;
-				ucp[11] = 0x24;
-				ucp[12] = 0x30;
-				ucp[13] = 7 + ul;
-				ucp[14] = 0x30;
-				ucp[15] = 5 + ul;
-				ucp[16] = 0xA1;
-				ucp[17] = 3 + ul;
-				ucp[18] = 0x30;
-				ucp[19] = 1 + ul;
-				ucp[20] = 0x02;
-				// Insert charge units
-				xp = &ucp[21];
-				for (count = 0; count < ul; count++)
-					*xp++ = charge[count];
-				dump("Rearranged message:", bp->bufp,
-				     bp->len);
-				break;
-			} else {
-				// we can't handle something else, erase it
-				int count = l - alen;
-				unsigned char *xp = ucp;
-				for (; count; count--, xp++)
-					xp[0] = xp[alen];
-				l -= alen;
-				bp->len -= alen;
-				dump("Shortened message:", bp->bufp,
-				     bp->len);
-			}
-		}
-	}
-
-
-	c = *sp;		/* Message type */
-	if (c == 0x05) {
-		/* SETUP. Use an UI frame */
-		dbg("SETUP");
-		l2_header[l2_index++] = 0xFF;	/* TEI 127 */
-		l2_header[l2_index++] = 0x03;	/* UI control field */
-		skb = dev_alloc_skb(bp->len - AUH_SIZE + l2_index);
-	} else {
-		/* use an I frame */
-		dbg("I Frame");
-		l2_header[l2_index++] = (AUISDN_TEI << 1) | 0x01;	/* TEI byte */
-		skb = dev_alloc_skb(bp->len - AUH_SIZE + l2_index + 2);
-		if (skb) {
-			ahp = cp->isdn.ahp;
-			if (!ahp) {
-				err("ahp == NULL");
-				return;
-			}
-			spin_lock_irqsave(&ahp->seq_lock, flags);
-			l2_header[l2_index++] = ahp->txseq;	/* transmitt sequence number */
-			l2_header[l2_index++] = ahp->rxseq;	/* receive sequence number */
-			ahp->txseq += 2;			/* next paket gets next number */
-			spin_unlock_irqrestore(&ahp->seq_lock, flags);
-		}
-	}
-	if (!skb) {
-		err("no memory - skipped");
-		return;
-	}
-	sp = skb_put(skb, bp->len - AUH_SIZE + l2_index);
-	/* Add L2 header */
-	memcpy(sp, l2_header, l2_index);
-	memcpy(sp + l2_index, bp->bufp + AUH_SIZE, bp->len - AUH_SIZE);
-	/* Translate false messages */
-	auerisdn_translate_incoming(cp, sp, bp->len - AUH_SIZE + l2_index);
-	/* Send message to L2 */
-	auerisdn_d_l1l2(&cp->isdn, PH_DATA | INDICATION, skb);
-}
-
-/* D-channel is closed because the device is removed */
-/* This is a no-op because ISDN close is handled different */
-static void auerisdn_disconnect_dc(struct auerscon *scp)
-{
-}
-
-
-/* confirmation helper function. */
-static void auerisdn_d_confirmskb(struct auerswald *cp,
-				  struct sk_buff *skb)
-{
-	/* free the skb */
-	if (skb) {
-		skb_pull(skb, skb->len);
-		dev_kfree_skb_any(skb);
-	}
-
-	/* confirm the sending of data */
-	dbg("Confirm PH_DATA");
-	auerisdn_d_l1l2(&cp->isdn, PH_DATA | CONFIRM, NULL);
-}
-
-/* D-channel transfer function L2->L1 */
-static void auerisdn_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg)
-{
-	struct auerhisax *ahp;
-	struct sk_buff *skb;
-	unsigned int len;
-	int ret;
-	struct auerbuf *bp;
-	struct auerswald *cp;
-	unsigned long flags;
-	unsigned int l2_index;
-	unsigned char c;
-	unsigned char l2_header[32];
-	unsigned char *sp;
-
-	dbg("hisax D-Channel l2l1 called");
-
-	/* Get reference to auerhisax struct */
-	cp = NULL;
-	ahp = hisax_d_if->priv;
-	if (ahp)
-		cp = ahp->cp;
-	if (cp && !cp->disconnecting) {
-		/* normal usage */
-		switch (pr) {
-		case PH_ACTIVATE | REQUEST:	/* activation request */
-			dbg("Activation Request");
-			cp->isdn.dc_activated = 1;
-			/* send activation back to layer 2 */
-			auerisdn_d_l1l2(&cp->isdn,
-					PH_ACTIVATE | INDICATION, NULL);
-			break;
-		case PH_DEACTIVATE | REQUEST:	/* deactivation request */
-			dbg("Deactivation Request");
-			cp->isdn.dc_activated = 0;
-			/* send deactivation back to layer 2 */
-			auerisdn_d_l1l2(&cp->isdn,
-					PH_DEACTIVATE | INDICATION, NULL);
-			break;
-		case PH_DATA | REQUEST:	/* Transmit data request */
-			skb = (struct sk_buff *) arg;
-			len = skb->len;
-			l2_index = 0;
-			sp = skb->data;
-			dump("Data Request:", sp, len);
-
-			/* Parse the L2 header */
-			if (!len)
-				goto phd_free;
-			c = *sp++;	/* SAPI */
-			l2_header[l2_index++] = c;
-			len--;
-			if (!len)
-				goto phd_free;
-			c = *sp++;	/* TEI */
-			l2_header[l2_index++] = c;
-			len--;
-			if (!len)
-				goto phd_free;
-			c = *sp++;	/* Control Field, Byte 1 */
-			len--;
-			if (!(c & 0x01)) {
-				/* I FRAME */
-				dbg("I Frame");
-				if (!len)
-					goto phd_free;
-				spin_lock_irqsave(&ahp->seq_lock, flags);
-				ahp->rxseq = c + 2;	/* store new sequence info */
-				spin_unlock_irqrestore(&ahp->seq_lock,
-						       flags);
-				sp++;	/* skip Control Field, Byte 2 */
-				len--;
-				/* Check for RELEASE command */
-				/* and change to RELEASE_COMPLETE */
-				if (sp[3] == 0x4D)
-					sp[3] = 0x5A;
-				goto phd_send;
-			}
-			/* check the frame type */
-			switch (c) {
-			case 0x03:	/* UI frame */
-				dbg("UI Frame");
-				if (l2_header[0] == 0xFC) {
-					dbg("TEI Managment");
-					l2_header[0] = 0xFE;	/* set C/R bit in answer */
-					l2_header[l2_index++] = c;	/* Answer is UI frame */
-					if (!len)
-						break;
-					c = *sp++;	/* Managment ID */
-					len--;
-					if (c != 0x0F)
-						break;
-					l2_header[l2_index++] = c;
-					/* Read Reference Number */
-					if (!len)
-						break;
-					l2_header[l2_index++] = *sp++;
-					len--;
-					if (!len)
-						break;
-					l2_header[l2_index++] = *sp++;
-					len--;
-					if (!len)
-						break;
-					c = *sp++;	/* Message Type */
-					len--;
-					switch (c) {
-					case 0x01:	/* Identity Request */
-						dbg("Identity Request");
-						l2_header[l2_index++] = 0x02;	/* Identity Assign */
-						l2_header[l2_index++] =
-						    (AUISDN_TEI << 1) |
-						    0x01;
-						goto phd_answer;
-					default:
-						dbg("Unhandled TEI Managment %X", (int) c);
-						break;
-					}
-					// throw away
-					goto phd_free;
-				}
-				/* else send UI frame out */
-				goto phd_send;
-			case 0x01:	/* RR frame */
-			case 0x05:	/* RNR frame */
-				dbg("RR/RNR Frame");
-				if (!len)
-					break;
-				c = *sp++;	/* Control Field, Byte 2 */
-				len--;
-				if (!(c & 0x01))
-					break;	/* P/F = 1 in commands */
-				if (l2_header[0] & 0x02)
-					break;	/* C/R = 0 from TE */
-				dbg("Send RR as answer");
-				l2_header[l2_index++] = 0x01;	/* send an RR as Answer */
-				spin_lock_irqsave(&ahp->seq_lock, flags);
-				l2_header[l2_index++] = ahp->rxseq | 0x01;
-				spin_unlock_irqrestore(&ahp->seq_lock,
-						       flags);
-				goto phd_answer;
-			case 0x7F:	/* SABME */
-				dbg("SABME");
-				spin_lock_irqsave(&ahp->seq_lock, flags);
-				ahp->txseq = 0;
-				ahp->rxseq = 0;
-				spin_unlock_irqrestore(&ahp->seq_lock,
-						       flags);
-				l2_header[l2_index++] = 0x73;	/* UA */
-				goto phd_answer;
-			case 0x53:	/* DISC */
-				dbg("DISC");
-				/* Send back a UA */
-				l2_header[l2_index++] = 0x73;	/* UA */
-				goto phd_answer;
-			default:
-				dbg("Unhandled L2 Message %X", (int) c);
-				break;
-			}
-			/* all done */
-			goto phd_free;
-
-			/* we have to generate a local answer */
-			/* first, confirm old message, free old skb */
-		      phd_answer:auerisdn_d_confirmskb(cp,
-					      skb);
-
-			/* allocate a new skbuff */
-			skb = dev_alloc_skb(l2_index);
-			if (!skb) {
-				err("no memory for new skb");
-				break;
-			}
-			dump("local answer to L2 is:", l2_header,
-			     l2_index);
-			memcpy(skb_put(skb, l2_index), l2_header,
-			       l2_index);
-			auerisdn_d_l1l2(&cp->isdn, PH_DATA | INDICATION,
-					skb);
-			break;
-
-			/* we have to send the L3 message out */
-		      phd_send:if (!len)
-				goto phd_free;	/* no message left */
-
-			/* get a new data buffer */
-			bp = auerbuf_getbuf(&cp->bufctl);
-			if (!bp) {
-				warn("no auerbuf free");
-				goto phd_free;
-			}
-			/* protect against too big write requests */
-			/* Should not happen */
-			if (len > cp->maxControlLength) {
-				err("too long D-channel paket truncated");
-				len = cp->maxControlLength;
-			}
-
-			/* Copy the data */
-			memcpy(bp->bufp + AUH_SIZE, sp, len);
-
-			/* set the header byte */
-			*(bp->bufp) =
-			    cp->isdn.dchannelservice.
-			    id | AUH_DIRECT | AUH_UNSPLIT;
-
-			/* Set the transfer Parameters */
-			bp->len = len + AUH_SIZE;
-			bp->dr->bRequestType = AUT_WREQ;
-			bp->dr->bRequest = AUV_WBLOCK;
-			bp->dr->wValue = cpu_to_le16(0);
-			bp->dr->wIndex =
-			    cpu_to_le16(cp->isdn.dchannelservice.
-					id | AUH_DIRECT | AUH_UNSPLIT);
-			bp->dr->wLength = cpu_to_le16(len + AUH_SIZE);
-			FILL_CONTROL_URB(bp->urbp, cp->usbdev,
-					 usb_sndctrlpipe(cp->usbdev, 0),
-					 (unsigned char *) bp->dr,
-					 bp->bufp, len + AUH_SIZE,
-					 auerisdn_dcw_complete, bp);
-			/* up we go */
-			ret =
-			    auerchain_submit_urb(&cp->controlchain,
-						 bp->urbp);
-			if (ret)
-				auerisdn_dcw_complete(bp->urbp);
-			else
-				dbg("auerisdn_dwrite: Write OK");
-			/* confirm message, free skb */
-		      phd_free:auerisdn_d_confirmskb(cp,
-					      skb);
-			break;
-
-		default:
-			warn("pr %#x\n", pr);
-			break;
-		}
-	} else {
-		/* hisax interface is down */
-		switch (pr) {
-		case PH_ACTIVATE | REQUEST:	/* activation request */
-			dbg("D channel PH_ACTIVATE | REQUEST with interface down");
-			/* don't answer this request! Endless... */
-			break;
-		case PH_DEACTIVATE | REQUEST:	/* deactivation request */
-			dbg("D channel PH_DEACTIVATE | REQUEST with interface down");
-			hisax_d_if->l1l2(hisax_d_if,
-					 PH_DEACTIVATE | INDICATION, NULL);
-			break;
-		case PH_DATA | REQUEST:	/* Transmit data request */
-			dbg("D channel PH_DATA | REQUEST with interface down");
-			skb = (struct sk_buff *) arg;
-			/* free data buffer */
-			if (skb) {
-				skb_pull(skb, skb->len);
-				dev_kfree_skb_any(skb);
-			}
-			/* send confirmation back to layer 2 */
-			hisax_d_if->l1l2(hisax_d_if, PH_DATA | CONFIRM,
-					 NULL);
-			break;
-		default:
-			warn("pr %#x\n", pr);
-			break;
-		}
-	}
-}
-
-
-/* Completion function for D channel open */
-static void auerisdn_dcopen_complete(struct urb *urbp)
-{
-	struct auerbuf *bp = (struct auerbuf *) urbp->context;
-	struct auerswald *cp =
-	    ((struct auerswald *) ((char *) (bp->list) -
-				   (unsigned
-				    long) (&((struct auerswald *) 0)->
-					   bufctl)));
-	dbg("auerisdn_dcopen_complete called");
-
-	auerbuf_releasebuf(bp);
-
-	/* Wake up all processes waiting for a buffer */
-	wake_up(&cp->bufferwait);
-}
-
-
-/* Open the D-channel once more */
-static void auerisdn_dcopen(unsigned long data)
-{
-	struct auerswald *cp = (struct auerswald *) data;
-	struct auerbuf *bp;
-	int ret;
-
-	if (cp->disconnecting)
-		return;
-	dbg("auerisdn_dcopen running");
-
-	/* get a buffer for the command */
-	bp = auerbuf_getbuf(&cp->bufctl);
-	/* if no buffer available: can't change the mode */
-	if (!bp) {
-		err("auerisdn_dcopen: no data buffer available");
-		return;
-	}
-
-	/* fill the control message */
-	bp->dr->bRequestType = AUT_WREQ;
-	bp->dr->bRequest = AUV_CHANNELCTL;
-	bp->dr->wValue = cpu_to_le16(1);
-	bp->dr->wIndex = cpu_to_le16(0);
-	bp->dr->wLength = cpu_to_le16(0);
-	FILL_CONTROL_URB(bp->urbp, cp->usbdev,
-			 usb_sndctrlpipe(cp->usbdev, 0),
-			 (unsigned char *) bp->dr, bp->bufp, 0,
-			 (usb_complete_t) auerisdn_dcopen_complete, bp);
-
-	/* submit the control msg */
-	ret = auerchain_submit_urb(&cp->controlchain, bp->urbp);
-	dbg("dcopen submitted");
-	if (ret) {
-		bp->urbp->status = ret;
-		auerisdn_dcopen_complete(bp->urbp);
-	}
-	return;
-}
-
-
-/* Initialize the isdn related items in struct auerswald */
-void auerisdn_init_dev(struct auerswald *cp)
-{
-	unsigned int u;
-	cp->isdn.dchannelservice.id = AUH_UNASSIGNED;
-	cp->isdn.dchannelservice.dispatch = auerisdn_dispatch_dc;
-	cp->isdn.dchannelservice.disconnect = auerisdn_disconnect_dc;
-	init_timer(&cp->isdn.dcopen_timer);
-	cp->isdn.dcopen_timer.data = (unsigned long) cp;
-	cp->isdn.dcopen_timer.function = auerisdn_dcopen;
-	for (u = 0; u < AUISDN_BCHANNELS; u++) {
-		cp->isdn.bc[u].cp = cp;
-		cp->isdn.bc[u].mode = L1_MODE_NULL;
-		cp->isdn.bc[u].channel = u;
-		spin_lock_init(&cp->isdn.bc[u].txskb_lock);
-	}
-}
-
-
-/* Connect to the HISAX interface. Returns 0 if successfull */
-int auerisdn_probe(struct auerswald *cp)
-{
-	struct hisax_b_if *b_if[AUISDN_BCHANNELS];
-	struct usb_endpoint_descriptor *ep;
-	struct auerhisax *ahp;
-	DECLARE_WAIT_QUEUE_HEAD(wqh);
-	unsigned int u;
-	unsigned char *ucp;
-	unsigned int first_time;
-	int ret;
-
-	/* First allocate resources, then register hisax interface */
-
-	/* Allocate RX buffers */
-	for (u = 0; u < AUISDN_BCHANNELS; u++) {
-		if (!cp->isdn.bc[u].rxbuf) {
-			cp->isdn.bc[u].rxbuf =
-			    (char *) kmalloc(AUISDN_RXSIZE, GFP_KERNEL);
-			if (!cp->isdn.bc[u].rxbuf) {
-				err("can't allocate buffer for B channel RX data");
-				return -1;
-			}
-		}
-	}
-
-	/* Read out B-Channel output fifo size */
-	ucp = kmalloc(32, GFP_KERNEL);
-	if (!ucp) {
-		err("Out of memory");
-		return -3;
-	}
-	ret = usb_control_msg(cp->usbdev,			/* pointer to device */
-			      usb_rcvctrlpipe(cp->usbdev, 0),	/* pipe to control endpoint */
-			      AUV_GETINFO,			/* USB message request value */
-			      AUT_RREQ,				/* USB message request type value */
-			      0,				/* USB message value */
-			      AUDI_OUTFSIZE,			/* USB message index value */
-			      ucp,				/* pointer to the receive buffer */
-			      32,				/* length of the buffer */
-			      HZ * 2);				/* time to wait for the message to complete before timing out */
-	if (ret < 4) {
-		kfree(ucp);
-		err("can't read TX Fifo sizes for B1,B2");
-		return -4;
-	}
-	for (u = 0; u < AUISDN_BCHANNELS; u++) {
-		ret = le16_to_cpup(ucp + u * 2);
-		cp->isdn.bc[u].ofsize = ret;
-		cp->isdn.bc[u].txfree = ret;
-	}
-	kfree(ucp);
-	for (u = 0; u < AUISDN_BCHANNELS; u++) {
-		dbg("B%d buffer size is %d", u, cp->isdn.bc[u].ofsize);
-	}
-
-	/* get the B channel output INT size */
-	cp->isdn.intbo_endp = AU_IRQENDPBO;
-	ep = usb_epnum_to_ep_desc(cp->usbdev, USB_DIR_OUT | AU_IRQENDPBO);
-	if (!ep) {
-		/* Some devices have another endpoint number here ... */
-		cp->isdn.intbo_endp = AU_IRQENDPBO_2;
-		ep = usb_epnum_to_ep_desc(cp->usbdev,
-					  USB_DIR_OUT | AU_IRQENDPBO_2);
-		if (!ep) {
-			err("can't get B channel OUT endpoint");
-			return -5;
-		}
-	}
-	cp->isdn.outsize = ep->wMaxPacketSize;
-	cp->isdn.outInterval = ep->bInterval;
-	cp->isdn.usbdev = cp->usbdev;
-
-	/* allocate the urb and data buffer */
-	if (!cp->isdn.intbo_urbp) {
-		cp->isdn.intbo_urbp = usb_alloc_urb(0);
-		if (!cp->isdn.intbo_urbp) {
-			err("can't allocate urb for B channel output endpoint");
-			return -6;
-		}
-	}
-	if (!cp->isdn.intbo_bufp) {
-		cp->isdn.intbo_bufp =
-		    (char *) kmalloc(cp->isdn.outsize, GFP_KERNEL);
-		if (!cp->isdn.intbo_bufp) {
-			err("can't allocate buffer for B channel output endpoint");
-			return -7;
-		}
-	}
-
-	/* get the B channel input INT size */
-	ep = usb_epnum_to_ep_desc(cp->usbdev, USB_DIR_IN | AU_IRQENDPBI);
-	if (!ep) {
-		err("can't get B channel IN endpoint");
-		return -8;
-	}
-	cp->isdn.insize = ep->wMaxPacketSize;
-
-	/* allocate the urb and data buffer */
-	if (!cp->isdn.intbi_urbp) {
-		cp->isdn.intbi_urbp = usb_alloc_urb(0);
-		if (!cp->isdn.intbi_urbp) {
-			err("can't allocate urb for B channel input endpoint");
-			return -9;
-		}
-	}
-	if (!cp->isdn.intbi_bufp) {
-		cp->isdn.intbi_bufp =
-		    (char *) kmalloc(cp->isdn.insize, GFP_KERNEL);
-		if (!cp->isdn.intbi_bufp) {
-			err("can't allocate buffer for B channel input endpoint");
-			return -10;
-		}
-	}
-
-	/* setup urb */
-	FILL_INT_URB(cp->isdn.intbi_urbp, cp->usbdev,
-		     usb_rcvintpipe(cp->usbdev, AU_IRQENDPBI),
-		     cp->isdn.intbi_bufp, cp->isdn.insize,
-		     auerisdn_intbi_complete, cp, ep->bInterval);
-	/* start the urb */
-	cp->isdn.intbi_urbp->status = 0;	/* needed! */
-	ret = usb_submit_urb(cp->isdn.intbi_urbp);
-	if (ret < 0) {
-		err("activation of B channel input int failed %d", ret);
-		usb_free_urb(cp->isdn.intbi_urbp);
-		cp->isdn.intbi_urbp = NULL;
-		return -11;
-	}
-
-	/* request the D-channel service now */
-	dbg("Requesting D channel now");
-	cp->isdn.dchannelservice.id = AUH_DCHANNEL;
-	if (auerswald_addservice(cp, &cp->isdn.dchannelservice)) {
-		err("can not open D-channel");
-		cp->isdn.dchannelservice.id = AUH_UNASSIGNED;
-		return -2;
-	}
-
-	/* Find a free hisax interface */
-	for (u = 0; u < AUER_MAX_DEVICES; u++) {
-		ahp = &auerhisax_table[u];
-		if (!ahp->cp) {
-			first_time = (u == 0);
-			goto ahp_found;
-		}
-	}
-	/* no free interface found */
-	return -12;
-
-	/* we found a free hisax interface */
-      ahp_found:
-	/* Wait until ipppd timeout expired. The reason behind this ugly construct:
-	   If we connect to a hisax device without waiting for ipppd we are not able
-	   to make a new IP connection. */
-	if (ahp->last_close) {
-		unsigned long timeout = jiffies - ahp->last_close;
-		if (timeout < AUISDN_IPTIMEOUT) {
-			info("waiting for ipppd to timeout");
-			sleep_on_timeout(&wqh, AUISDN_IPTIMEOUT - timeout);
-		}
-	}
-
-	cp->isdn.ahp = ahp;
-	u = ahp->hisax_registered;
-	ahp->hisax_registered = 1;
-	ahp->cp = cp;
-
-	/* now do the registration */
-	if (!u) {
-		for (u = 0; u < AUISDN_BCHANNELS; u++) {
-			b_if[u] = &ahp->hisax_b_if[u];
-		}
-		if (hisax_register
-		    (&ahp->hisax_d_if, b_if, "auerswald_usb",
-		     ISDN_PTYPE_EURO)) {
-			err("hisax registration failed");
-			ahp->cp = NULL;
-			cp->isdn.ahp = NULL;
-			ahp->hisax_registered = 0;
-			return -13;
-		}
-		dbg("hisax interface registered");
-	}
-
-	/* send a D channel L1 activation indication to hisax */
-	auerisdn_d_l1l2(&cp->isdn, PH_ACTIVATE | INDICATION, NULL);
-	cp->isdn.dc_activated = 1;
-
-	/* do another D channel activation for problematic devices */
-	cp->isdn.dcopen_timer.expires = jiffies + HZ;
-	dbg("add timer");
-	add_timer(&cp->isdn.dcopen_timer);
-
-	return 0;
-}
-
-/* The USB device was disconnected */
-void auerisdn_disconnect(struct auerswald *cp)
-{
-	struct auerhisax *ahp;
-	DECLARE_WAIT_QUEUE_HEAD(wqh);
-	unsigned long flags;
-	unsigned int u;
-	int ret;
-	unsigned int stop_bc;
-
-	dbg("auerisdn_disconnect called");
-
-	/* stop a running timer */
-	del_timer_sync(&cp->isdn.dcopen_timer);
-
-	/* first, stop the B channels */
-	stop_bc = auerisdn_b_disconnect(cp);
-
-	/* stop the D channels */
-	auerisdn_d_l1l2(&cp->isdn, PH_DEACTIVATE | INDICATION, NULL);
-	cp->isdn.dc_activated = 0;
-	dbg("D-Channel disconnected");
-
-	/* Wait a moment */
-	sleep_on_timeout(&wqh, HZ / 10);
-
-	/* Shut the connection to the hisax interface */
-	ahp = cp->isdn.ahp;
-	if (ahp) {
-		dbg("closing connection to hisax interface");
-		ahp->cp = NULL;
-		cp->isdn.ahp = NULL;
-		/* time of last closure */
-		if (stop_bc)
-			/* if we kill a running connection ... */
-			ahp->last_close = jiffies;
-		else
-			ahp->last_close = 0;
-	}
-
-	/* Now free the memory */
-	if (cp->isdn.intbi_urbp) {
-		ret = usb_unlink_urb(cp->isdn.intbi_urbp);
-		if (ret)
-			dbg("B in: nonzero int unlink result received: %d",
-			    ret);
-		usb_free_urb(cp->isdn.intbi_urbp);
-		cp->isdn.intbi_urbp = NULL;
-	}
-	kfree(cp->isdn.intbi_bufp);
-	cp->isdn.intbi_bufp = NULL;
-	
-	if (cp->isdn.intbo_urbp) {
-		cp->isdn.intbo_urbp->transfer_flags &= ~USB_ASYNC_UNLINK;
-		ret = usb_unlink_urb(cp->isdn.intbo_urbp);
-		if (ret)
-			dbg("B out: nonzero int unlink result received: %d", ret);
-		usb_free_urb(cp->isdn.intbo_urbp);
-		cp->isdn.intbo_urbp = NULL;
-	}
-	kfree(cp->isdn.intbo_bufp);
-	cp->isdn.intbo_bufp = NULL;
-
-	/* Remove the rx and tx buffers */
-	for (u = 0; u < AUISDN_BCHANNELS; u++) {
-		kfree(cp->isdn.bc[u].rxbuf);
-		cp->isdn.bc[u].rxbuf = NULL;
-		spin_lock_irqsave(&cp->isdn.bc[u].txskb_lock, flags);
-		if (cp->isdn.bc[u].txskb) {
-			skb_pull(cp->isdn.bc[u].txskb,
-				 cp->isdn.bc[u].txskb->len);
-			dev_kfree_skb_any(cp->isdn.bc[u].txskb);
-			cp->isdn.bc[u].txskb = NULL;
-		}
-		spin_unlock_irqrestore(&cp->isdn.bc[u].txskb_lock, flags);
-	}
-
-	/* Remove the D-channel connection */
-	auerswald_removeservice(cp, &cp->isdn.dchannelservice);
-}
-
-
-/*-------------------------------------------------------------------*/
-/* Environment for long-lasting hisax interface                      */
-
-/* Wrapper for hisax B0 channel L2L1 */
-static void auerisdn_b0_l2l1_wrapper(struct hisax_if *ifc, int pr,
-				     void *arg)
-{
-	auerisdn_b_l2l1(ifc, pr, arg, 0);
-}
-
-/* Wrapper for hisax B1 channel L2L1 */
-static void auerisdn_b1_l2l1_wrapper(struct hisax_if *ifc, int pr,
-				     void *arg)
-{
-	auerisdn_b_l2l1(ifc, pr, arg, 1);
-}
-
-/* Init the global variables */
-void auerisdn_init(void)
-{
-	struct auerhisax *ahp;
-	unsigned int u;
-
-	memset(&auerhisax_table, 0, sizeof(auerhisax_table));
-	for (u = 0; u < AUER_MAX_DEVICES; u++) {
-		ahp = &auerhisax_table[u];
-		spin_lock_init(&ahp->seq_lock);
-		ahp->hisax_d_if.ifc.priv = ahp;
-		ahp->hisax_d_if.ifc.l2l1 = auerisdn_d_l2l1;
-		ahp->hisax_b_if[0].ifc.priv = ahp;
-		ahp->hisax_b_if[0].ifc.l2l1 = auerisdn_b0_l2l1_wrapper;
-		ahp->hisax_b_if[1].ifc.priv = ahp;
-		ahp->hisax_b_if[1].ifc.l2l1 = auerisdn_b1_l2l1_wrapper;
-	}
-}
-
-/* Deinit the global variables */
-void auerisdn_cleanup(void)
-{
-	struct auerhisax *ahp;
-	int i;
-
-	/* cleanup last allocated device first */
-	for (i = AUER_MAX_DEVICES - 1; i >= 0; i--) {
-		ahp = &auerhisax_table[i];
-		if (ahp->cp) {
-			err("hisax device %d open at cleanup", i);
-		}
-		if (ahp->hisax_registered) {
-			hisax_unregister(&ahp->hisax_d_if);
-			dbg("hisax interface %d freed", i);
-		}
-	}
-}
diff -ruN linux-2.4.20-WRTup/drivers/usb/auerisdn.h linux-2.4.20-WRTstp/drivers/usb/auerisdn.h
--- linux-2.4.20-WRTup/drivers/usb/auerisdn.h	2006-06-12 18:04:59.000000000 -0700
+++ linux-2.4.20-WRTstp/drivers/usb/auerisdn.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,94 +0,0 @@
-/*****************************************************************************/
-/*
- *      auerisdn.h  --  Auerswald PBX/System Telephone ISDN interface.
- *
- *      Copyright (C) 2002  Wolfgang Mües (wolfgang@iksw-muees.de)
- *
- *      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.
- */
- /*****************************************************************************/
-
-#ifndef AUERISDN_H
-#define AUERISDN_H
-
-#if (CONFIG_USB_AUERISDN || CONFIG_USB_AUERISDN_MODULE)
-
-#include <linux/timer.h>
-#include "auerserv.h"
-#include "auerisdn_b.h"
-
-#define AUISDN_IPTIMEOUT (HZ * 60)	/* IP Timeout is 40s */
-
-struct auerswald;
-struct auerhisax;
-
-struct auerisdn {
-	struct auerscon dchannelservice;	/* serving the D channel */
-	struct auerhisax *ahp;			/* Reference to hisax interface */
-	unsigned int dc_activated;		/* 1 if D-Channel is activated */
-	struct auerisdnbc bc[AUISDN_BCHANNELS];	/* B channel data */
-	unsigned int insize;			/* Max. Block Size of Input INT */
-	unsigned int outsize;			/* Max. Block Size of Output INT */
-	unsigned int outInterval;		/* nr. of ms between INT OUT transfers */
-	struct urb *intbi_urbp;			/* B channel Input Interrupt urb */
-	unsigned char *intbi_bufp;		/* B channel Input data buffer */
-	unsigned int paketsize;			/* Data size of the INT OUT pakets */
-	struct usb_device *usbdev;		/* USB device handle */
-	unsigned int intbo_state;		/* Status of INT OUT urb */
-	struct urb *intbo_urbp;			/* B channel Output Interrupt urb */
-	unsigned char *intbo_bufp;		/* B channel Output data buffer */
-	unsigned int intbo_index;		/* Index of last served B channel */
-	unsigned int intbo_toggletimer;		/* data toggle timer for 2 b channels */
-	unsigned int intbo_endp;		/* grrr.. different on some devices */
-	struct timer_list dcopen_timer;		/* Open D-channel once more later... */
-};
-
-struct auerhisax {
-	struct hisax_d_if hisax_d_if;		/* Hisax D-Channel interface */
-	struct hisax_b_if hisax_b_if[AUISDN_BCHANNELS];	/* Hisax B-channel interfaces */
-	struct auerswald *cp;			/* Context to usb device */
-	unsigned int hisax_registered;		/* 1 if registered at hisax interface */
-	unsigned char txseq;			/* L2 emulation: tx sequence byte */
-	unsigned char rxseq;			/* L2 emulation: rx sequence byte */
-	spinlock_t seq_lock;			/* Lock sequence numbers */
-	unsigned long last_close;		/* Time of last close in jiffies */
-};
-
-/* Function Prototypes */
-void auerisdn_init_dev(struct auerswald *cp);
-
-int auerisdn_probe(struct auerswald *cp);
-
-void auerisdn_disconnect(struct auerswald *cp);
-
-void auerisdn_init(void);
-
-void auerisdn_cleanup(void);
-
-#else	/* no CONFIG_USB_AUERISDN */
-
-struct auerisdn {
-	int dummy;
-};
-
-/* Dummy ISDN functions */
-#define auerisdn_init_dev( cp)
-#define auerisdn_probe( cp) 0
-#define auerisdn_disconnect( cp)
-#define auerisdn_init()
-#define auerisdn_cleanup()
-#endif	/* CONFIG_USB_AUERISDN */
-
-#endif	/* AUERISDN_H */
diff -ruN linux-2.4.20-WRTup/drivers/usb/auermain.c linux-2.4.20-WRTstp/drivers/usb/auermain.c
--- linux-2.4.20-WRTup/drivers/usb/auermain.c	2006-06-12 18:04:59.000000000 -0700
+++ linux-2.4.20-WRTstp/drivers/usb/auermain.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,898 +0,0 @@
-/*****************************************************************************/
-/*
- *      auermain.c  --  Auerswald PBX/System Telephone usb driver.
- *
- *      Copyright (C) 2002-2004  Wolfgang Mües (wolfgang@iksw-muees.de)
- *
- *      Very much code of this driver is borrowed from dabusb.c (Deti Fliegl)
- *      and from the USB Skeleton driver (Greg Kroah-Hartman). Thank you.
- *
- *      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.
- */
- /*****************************************************************************/
-
-/* Standard Linux module include files */
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/devfs_fs_kernel.h>
-#undef DEBUG			/* include debug macros until it's done */
-#include <linux/usb.h>
-#include "auerchain.h"
-#include "auerbuf.h"
-#include "auerchar.h"
-#include "auerserv.h"
-#include "auermain.h"
-#include "auerisdn.h"
-
-/*-------------------------------------------------------------------*/
-/* Debug support 						     */
-#ifdef DEBUG
-#define dump( desc, adr, len) \
-do {			\
-	unsigned int u;	\
-	printk (KERN_DEBUG); \
-	printk (desc); \
-	for (u = 0; u < len; u++) \
-		printk (" %02X", adr[u] & 0xFF); \
-	printk ("\n"); \
-} while (0)
-#else
-#define dump( desc, adr, len)
-#endif
-
-/*-------------------------------------------------------------------*/
-/* Version Information */
-#define DRIVER_VERSION "1.2.6"
-#define DRIVER_AUTHOR  "Wolfgang Mües <wolfgang@iksw-muees.de>"
-#define DRIVER_DESC    "Auerswald PBX/System Telephone usb driver"
-
-/*-------------------------------------------------------------------*/
-/* Internal data structures                                          */
-
-/* the global usb devfs handle */
-extern devfs_handle_t usb_devfs_handle;
-
-/* array of pointers to our devices that are currently connected */
-struct auerswald *auerdev_table[AUER_MAX_DEVICES];
-
-/* lock to protect the auerdev_table structure */
-struct semaphore auerdev_table_mutex;
-
-/*-------------------------------------------------------------------*/
-/* Forwards */
-static void auerswald_ctrlread_complete(struct urb *urb);
-
-/*-------------------------------------------------------------------*/
-/* Completion handlers */
-
-/* Values of urb->status or results of usb_submit_urb():
-0		Initial, OK
--EINPROGRESS	during submission until end
--ENOENT		if urb is unlinked
--ETIMEDOUT	Transfer timed out, NAK
--ENOMEM		Memory Overflow
--ENODEV		Specified USB-device or bus doesn't exist
--ENXIO		URB already queued
--EINVAL		a) Invalid transfer type specified (or not supported)
-		b) Invalid interrupt interval (0n256)
--EAGAIN		a) Specified ISO start frame too early
-		b) (using ISO-ASAP) Too much scheduled for the future wait some time and try again.
--EFBIG		Too much ISO frames requested (currently uhci900)
--EPIPE		Specified pipe-handle/Endpoint is already stalled
--EMSGSIZE	Endpoint message size is zero, do interface/alternate setting
--EPROTO		a) Bitstuff error
-		b) Unknown USB error
--EILSEQ		CRC mismatch
--ENOSR		Buffer error
--EREMOTEIO	Short packet detected
--EXDEV		ISO transfer only partially completed look at individual frame status for details
--EINVAL		ISO madness, if this happens: Log off and go home
--EOVERFLOW	babble
-*/
-
-/* check if a status code allows a retry */
-static int auerswald_status_retry(int status)
-{
-	switch (status) {
-	case 0:
-	case -ETIMEDOUT:
-	case -EOVERFLOW:
-	case -EAGAIN:
-	case -EPIPE:
-	case -EPROTO:
-	case -EILSEQ:
-	case -ENOSR:
-	case -EREMOTEIO:
-		return 1;	/* do a retry */
-	}
-	return 0;		/* no retry possible */
-}
-
-
-/* Completion of asynchronous write block */
-void auerchar_ctrlwrite_complete(struct urb *urb)
-{
-	struct auerbuf *bp = (struct auerbuf *) urb->context;
-	struct auerswald *cp =
-	    ((struct auerswald *) ((char *) (bp->list) -
-				   (unsigned
-				    long) (&((struct auerswald *) 0)->
-					   bufctl)));
-	dbg("auerchar_ctrlwrite_complete called");
-
-	/* reuse the buffer */
-	auerbuf_releasebuf(bp);
-	/* Wake up all processes waiting for a buffer */
-	wake_up(&cp->bufferwait);
-}
-
-/* Completion handler for dummy retry packet */
-static void auerswald_ctrlread_wretcomplete(struct urb *urb)
-{
-	struct auerbuf *bp = (struct auerbuf *) urb->context;
-	struct auerswald *cp;
-	int ret;
-	dbg("auerswald_ctrlread_wretcomplete called");
-	dbg("complete with status: %d", urb->status);
-	cp = ((struct auerswald *) ((char *) (bp->list) -
-				    (unsigned
-				     long) (&((struct auerswald *) 0)->
-					    bufctl)));
-
-	/* check if it is possible to advance */
-	if (!auerswald_status_retry(urb->status) || !cp->usbdev) {
-		/* reuse the buffer */
-		err("control dummy: transmission error %d, can not retry",
-		    urb->status);
-		auerbuf_releasebuf(bp);
-		/* Wake up all processes waiting for a buffer */
-		wake_up(&cp->bufferwait);
-		return;
-	}
-
-	/* fill the control message */
-	bp->dr->bRequestType = AUT_RREQ;
-	bp->dr->bRequest = AUV_RBLOCK;
-	bp->dr->wLength = bp->dr->wValue;	/* temporary stored */
-	bp->dr->wValue = cpu_to_le16(1);	/* Retry Flag */
-	/* bp->dr->wIndex    = channel id;          remains */
-	FILL_CONTROL_URB(bp->urbp, cp->usbdev,
-			 usb_rcvctrlpipe(cp->usbdev, 0),
-			 (unsigned char *) bp->dr, bp->bufp,
-			 le16_to_cpu(bp->dr->wLength),
-			 (usb_complete_t) auerswald_ctrlread_complete, bp);
-
-	/* submit the control msg as next paket */
-	ret = auerchain_submit_urb_list(&cp->controlchain, bp->urbp, 1);
-	if (ret) {
-		dbg("auerswald_ctrlread_complete: nonzero result of auerchain_submit_urb_list %d", ret);
-		bp->urbp->status = ret;
-		auerswald_ctrlread_complete(bp->urbp);
-	}
-}
-
-/* completion handler for receiving of control messages */
-static void auerswald_ctrlread_complete(struct urb *urb)
-{
-	unsigned int serviceid;
-	struct auerswald *cp;
-	struct auerscon *scp;
-	struct auerbuf *bp = (struct auerbuf *) urb->context;
-	int ret;
-	dbg("auerswald_ctrlread_complete called");
-
-	cp = ((struct auerswald *) ((char *) (bp->list) -
-				    (unsigned
-				     long) (&((struct auerswald *) 0)->
-					    bufctl)));
-
-	/* check if there is valid data in this urb */
-	if (urb->status) {
-		dbg("complete with non-zero status: %d", urb->status);
-		/* should we do a retry? */
-		if (!auerswald_status_retry(urb->status)
-		    || !cp->usbdev || (cp->version < AUV_RETRY)
-		    || (bp->retries >= AU_RETRIES)) {
-			/* reuse the buffer */
-			err("control read: transmission error %d, can not retry", urb->status);
-			auerbuf_releasebuf(bp);
-			/* Wake up all processes waiting for a buffer */
-			wake_up(&cp->bufferwait);
-			return;
-		}
-		bp->retries++;
-		dbg("Retry count = %d", bp->retries);
-		/* send a long dummy control-write-message to allow device firmware to react */
-		bp->dr->bRequestType = AUT_WREQ;
-		bp->dr->bRequest = AUV_DUMMY;
-		bp->dr->wValue = bp->dr->wLength;	/* temporary storage */
-		// bp->dr->wIndex    channel ID remains
-		bp->dr->wLength = cpu_to_le16(32);	/* >= 8 bytes */
-		FILL_CONTROL_URB(bp->urbp, cp->usbdev,
-				 usb_sndctrlpipe(cp->usbdev, 0),
-				 (unsigned char *) bp->dr, bp->bufp, 32,
-				 (usb_complete_t)
-				 auerswald_ctrlread_wretcomplete, bp);
-
-		/* submit the control msg as next paket */
-		ret =
-		    auerchain_submit_urb_list(&cp->controlchain, bp->urbp,
-					      1);
-		if (ret) {
-			dbg("auerswald_ctrlread_complete: nonzero result of auerchain_submit_urb_list %d", ret);
-			bp->urbp->status = ret;
-			auerswald_ctrlread_wretcomplete(bp->urbp);
-		}
-		return;
-	}
-
-	/* get the actual bytecount (incl. headerbyte) */
-	bp->len = urb->actual_length;
-	serviceid = bp->bufp[0] & AUH_TYPEMASK;
-	dbg("Paket with serviceid %d and %d bytes received", serviceid,
-	    bp->len);
-
-	/* dispatch the paket */
-	scp = cp->services[serviceid];
-	if (scp) {
-		/* look, Ma, a listener! */
-		scp->dispatch(scp, bp);
-	}
-
-	/* release the paket */
-	auerbuf_releasebuf(bp);
-	/* Wake up all processes waiting for a buffer */
-	wake_up(&cp->bufferwait);
-}
-
-/*-------------------------------------------------------------------*/
-/* Handling of Interrupt Endpoint                                    */
-/* This interrupt Endpoint is used to inform the host about waiting
-   messages from the USB device.
-*/
-/* int completion handler. */
-static void auerswald_int_complete(struct urb *urb)
-{
-	unsigned int channelid;
-	unsigned int bytecount;
-	int ret;
-	struct auerbuf *bp = NULL;
-	struct auerswald *cp = (struct auerswald *) urb->context;
-
-	dbg("auerswald_int_complete called");
-
-	/* do not respond to an error condition */
-	if (urb->status != 0) {
-		dbg("nonzero URB status = %d", urb->status);
-		return;
-	}
-
-	/* check if all needed data was received */
-	if (urb->actual_length < AU_IRQMINSIZE) {
-		dbg("invalid data length received: %d bytes",
-		    urb->actual_length);
-		return;
-	}
-
-	/* check the command code */
-	if (cp->intbufp[0] != AU_IRQCMDID) {
-		dbg("invalid command received: %d", cp->intbufp[0]);
-		return;
-	}
-
-	/* check the command type */
-	if (cp->intbufp[1] != AU_BLOCKRDY) {
-		dbg("invalid command type received: %d", cp->intbufp[1]);
-		return;
-	}
-
-	/* now extract the information */
-	channelid = cp->intbufp[2];
-	bytecount = le16_to_cpup(&cp->intbufp[3]);
-
-	/* check the channel id */
-	if (channelid >= AUH_TYPESIZE) {
-		dbg("invalid channel id received: %d", channelid);
-		return;
-	}
-
-	/* check the byte count */
-	if (bytecount > (cp->maxControlLength + AUH_SIZE)) {
-		dbg("invalid byte count received: %d", bytecount);
-		return;
-	}
-	dbg("Service Channel = %d", channelid);
-	dbg("Byte Count = %d", bytecount);
-
-	/* get a buffer for the next data paket */
-	bp = auerbuf_getbuf(&cp->bufctl);
-	/* if no buffer available: skip it */
-	if (!bp) {
-		dbg("auerswald_int_complete: no data buffer available");
-		/* can we do something more?
-		   This is a big problem: if this int packet is ignored, the
-		   device will wait forever and not signal any more data.
-		   The only real solution is: having enought buffers!
-		   Or perhaps temporary disabling the int endpoint?
-		 */
-		return;
-	}
-
-	/* fill the control message */
-	bp->dr->bRequestType = AUT_RREQ;
-	bp->dr->bRequest = AUV_RBLOCK;
-	bp->dr->wValue = cpu_to_le16(0);
-	bp->dr->wIndex = cpu_to_le16(channelid | AUH_DIRECT | AUH_UNSPLIT);
-	bp->dr->wLength = cpu_to_le16(bytecount);
-	FILL_CONTROL_URB(bp->urbp, cp->usbdev,
-			 usb_rcvctrlpipe(cp->usbdev, 0),
-			 (unsigned char *) bp->dr, bp->bufp, bytecount,
-			 (usb_complete_t) auerswald_ctrlread_complete, bp);
-
-	/* submit the control msg */
-	ret = auerchain_submit_urb(&cp->controlchain, bp->urbp);
-	if (ret) {
-		dbg("auerswald_int_complete: nonzero result of auerchain_submit_urb %d", ret);
-		bp->urbp->status = ret;
-		auerswald_ctrlread_complete(bp->urbp);
-		/* here applies the same problem as above: device locking! */
-	}
-}
-
-/* int memory deallocation
-   NOTE: no mutex please!
-*/
-static void auerswald_int_free(struct auerswald *cp)
-{
-	if (cp->inturbp) {
-		usb_free_urb(cp->inturbp);
-		cp->inturbp = NULL;
-	}
-	kfree(cp->intbufp);
-}
-
-/* This function is called to activate the interrupt
-   endpoint. This function returns 0 if successfull or an error code.
-   NOTE: no mutex please!
-*/
-static int auerswald_int_open(struct auerswald *cp)
-{
-	int ret;
-	struct usb_endpoint_descriptor *ep;
-	int irqsize;
-	dbg("auerswald_int_open");
-
-	ep = usb_epnum_to_ep_desc(cp->usbdev, USB_DIR_IN | AU_IRQENDP);
-	if (!ep) {
-		ret = -EFAULT;
-		goto intoend;
-	}
-	irqsize = ep->wMaxPacketSize;
-	cp->irqsize = irqsize;
-
-	/* allocate the urb and data buffer */
-	if (!cp->inturbp) {
-		cp->inturbp = usb_alloc_urb(0);
-		if (!cp->inturbp) {
-			ret = -ENOMEM;
-			goto intoend;
-		}
-	}
-	if (!cp->intbufp) {
-		cp->intbufp = (char *) kmalloc(irqsize, GFP_KERNEL);
-		if (!cp->intbufp) {
-			ret = -ENOMEM;
-			goto intoend;
-		}
-	}
-	/* setup urb */
-	FILL_INT_URB(cp->inturbp, cp->usbdev,
-		     usb_rcvintpipe(cp->usbdev, AU_IRQENDP), cp->intbufp,
-		     irqsize, auerswald_int_complete, cp, ep->bInterval);
-	/* start the urb */
-	cp->inturbp->status = 0;	/* needed! */
-	ret = usb_submit_urb(cp->inturbp);
-
-      intoend:
-	if (ret < 0) {
-		/* activation of interrupt endpoint has failed. Now clean up. */
-		dbg("auerswald_int_open: activation of int endpoint failed");
-
-		/* deallocate memory */
-		auerswald_int_free(cp);
-	}
-	return ret;
-}
-
-/* This function is called to deactivate the interrupt
-   endpoint. This function returns 0 if successfull or an error code.
-   NOTE: no mutex please!
-*/
-static int auerswald_int_release(struct auerswald *cp)
-{
-	int ret = 0;
-	dbg("auerswald_int_release");
-
-	/* stop the int endpoint */
-	if (cp->inturbp) {
-		ret = usb_unlink_urb(cp->inturbp);
-		if (ret)
-			dbg("nonzero int unlink result received: %d", ret);
-	}
-
-	/* deallocate memory */
-	auerswald_int_free(cp);
-
-	return ret;
-}
-
-/* --------------------------------------------------------------------- */
-/* Helper functions                                                      */
-
-/* Delete an auerswald driver context */
-void auerswald_delete(struct auerswald *cp)
-{
-	dbg("auerswald_delete");
-	if (cp == NULL)
-		return;
-
-	/* Wake up all processes waiting for a buffer */
-	wake_up(&cp->bufferwait);
-
-	/* Cleaning up */
-	auerisdn_disconnect(cp);
-	auerswald_int_release(cp);
-	auerchain_free(&cp->controlchain);
-	auerbuf_free_buffers(&cp->bufctl);
-
-	/* release the memory */
-	kfree(cp);
-}
-
-
-/* add a new service to the device
-   scp->id must be set!
-   return: 0 if OK, else error code
-*/
-int auerswald_addservice(struct auerswald *cp, struct auerscon *scp)
-{
-	int ret;
-
-	/* is the device available? */
-	if (!cp->usbdev) {
-		dbg("usbdev == NULL");
-		return -EIO;	/*no: can not add a service, sorry */
-	}
-
-	/* is the service available? */
-	if (cp->services[scp->id]) {
-		dbg("service is busy");
-		return -EBUSY;
-	}
-
-	/* device is available, service is free */
-	cp->services[scp->id] = scp;
-
-	/* register service in device */
-	ret = auerchain_control_msg(&cp->controlchain,			/* pointer to control chain */
-				    cp->usbdev,				/* pointer to device */
-				    usb_sndctrlpipe(cp->usbdev, 0),	/* pipe to control endpoint */
-				    AUV_CHANNELCTL,			/* USB message request value */
-				    AUT_WREQ,				/* USB message request type value */
-				    0x01,	/* open */		/* USB message value */
-				    scp->id,				/* USB message index value */
-				    NULL,				/* pointer to the data to send */
-				    0,					/* length in bytes of the data to send */
-				    HZ * 2);				/* time to wait for the message to complete before timing out */
-	if (ret < 0) {
-		dbg("auerswald_addservice: auerchain_control_msg returned error code %d", ret);
-		/* undo above actions */
-		cp->services[scp->id] = NULL;
-		return ret;
-	}
-
-	dbg("auerswald_addservice: channel open OK");
-	return 0;
-}
-
-
-/* remove a service from the the device
-   scp->id must be set! */
-void auerswald_removeservice(struct auerswald *cp, struct auerscon *scp)
-{
-	dbg("auerswald_removeservice called");
-
-	/* check if we have a service allocated */
-	if (scp->id == AUH_UNASSIGNED)
-		return;
-
-	/* If there is a device: close the channel */
-	if (cp->usbdev && !cp->disconnecting) {
-		/* Close the service channel inside the device */
-		int ret = auerchain_control_msg(&cp->controlchain,		/* pointer to control chain */
-						cp->usbdev,			/* pointer to device */
-						usb_sndctrlpipe(cp->usbdev, 0),	/* pipe to control endpoint */
-						AUV_CHANNELCTL,			/* USB message request value */
-						AUT_WREQ,			/* USB message request type value */
-						0x00,	/* close */		/* USB message value */
-						scp->id,			/* USB message index value */
-						NULL,				/* pointer to the data to send */
-						0,				/* length in bytes of the data to send */
-						HZ * 2);			/* time to wait for the message to complete before timing out */
-		if (ret < 0) {
-			dbg("auerswald_removeservice: auerchain_control_msg returned error code %d", ret);
-		} else {
-			dbg("auerswald_removeservice: channel close OK");
-		}
-	}
-
-	/* remove the service from the device */
-	cp->services[scp->id] = NULL;
-	scp->id = AUH_UNASSIGNED;
-}
-
-
-/*----------------------------------------------------------------------*/
-/* File operation structure                                             */
-static struct file_operations auerswald_fops = {
-	owner:THIS_MODULE,
-	llseek:auerchar_llseek,
-	read:auerchar_read,
-	write:auerchar_write,
-	ioctl:auerchar_ioctl,
-	open:auerchar_open,
-	release:auerchar_release,
-};
-
-/* --------------------------------------------------------------------- */
-/* Special USB driver functions                                          */
-
-/* Probe if this driver wants to serve an USB device
-
-   This entry point is called whenever a new device is attached to the bus.
-   Then the device driver has to create a new instance of its internal data
-   structures for the new device.
-
-   The  dev argument specifies the device context, which contains pointers
-   to all USB descriptors. The  interface argument specifies the interface
-   number. If a USB driver wants to bind itself to a particular device and
-   interface it has to return a pointer. This pointer normally references
-   the device driver's context structure.
-
-   Probing normally is done by checking the vendor and product identifications
-   or the class and subclass definitions. If they match the interface number
-   is compared with the ones supported by the driver. When probing is done
-   class based it might be necessary to parse some more USB descriptors because
-   the device properties can differ in a wide range.
-*/
-static void *auerswald_probe(struct usb_device *usbdev, unsigned int ifnum,
-			     const struct usb_device_id *id)
-{
-	struct auerswald *cp = NULL;
-	DECLARE_WAIT_QUEUE_HEAD(wqh);
-	unsigned int dtindex;
-	unsigned int u = 0;
-	char *pbuf;
-	int ret;
-
-	dbg("probe: vendor id 0x%x, device id 0x%x ifnum:%d",
-	    usbdev->descriptor.idVendor, usbdev->descriptor.idProduct,
-	    ifnum);
-
-	/* See if the device offered us matches that we can accept */
-	if (usbdev->descriptor.idVendor != ID_AUERSWALD)
-		return NULL;
-
-	/* we use only the first -and only- interface */
-	if (ifnum != 0)
-		return NULL;
-
-	/* prevent module unloading while sleeping */
-	MOD_INC_USE_COUNT;
-
-	/* allocate memory for our device and intialize it */
-	cp = kmalloc(sizeof(struct auerswald), GFP_KERNEL);
-	if (cp == NULL) {
-		err("out of memory");
-		goto pfail;
-	}
-
-	/* Initialize device descriptor */
-	memset(cp, 0, sizeof(struct auerswald));
-	init_MUTEX(&cp->mutex);
-	cp->usbdev = usbdev;
-	auerchain_init(&cp->controlchain);
-	auerbuf_init(&cp->bufctl);
-	init_waitqueue_head(&cp->bufferwait);
-	auerisdn_init_dev(cp);
-
-	/* find a free slot in the device table */
-	down(&auerdev_table_mutex);
-	for (dtindex = 0; dtindex < AUER_MAX_DEVICES; ++dtindex) {
-		if (auerdev_table[dtindex] == NULL)
-			break;
-	}
-	if (dtindex >= AUER_MAX_DEVICES) {
-		err("more than %d devices plugged in, can not handle this device", AUER_MAX_DEVICES);
-		up(&auerdev_table_mutex);
-		goto pfail;
-	}
-
-	/* Give the device a name */
-	sprintf(cp->name, AU_PREFIX "%d", dtindex);
-
-	/* Store the index */
-	cp->dtindex = dtindex;
-	auerdev_table[dtindex] = cp;
-	up(&auerdev_table_mutex);
-
-	/* initialize the devfs node for this device and register it */
-	cp->devfs = devfs_register(usb_devfs_handle, cp->name,
-				   DEVFS_FL_DEFAULT, USB_MAJOR,
-				   AUER_MINOR_BASE + dtindex,
-				   S_IFCHR | S_IRUGO | S_IWUGO,
-				   &auerswald_fops, NULL);
-
-	/* Get the usb version of the device */
-	cp->version = cp->usbdev->descriptor.bcdDevice;
-	dbg("Version is %X", cp->version);
-
-	/* allow some time to settle the device */
-	sleep_on_timeout(&wqh, HZ / 3);
-
-	/* Try to get a suitable textual description of the device */
-	/* Device name: */
-	ret =
-	    usb_string(cp->usbdev, AUSI_DEVICE, cp->dev_desc,
-		       AUSI_DLEN - 1);
-	if (ret >= 0) {
-		u += ret;
-		/* Append Serial Number */
-		memcpy(&cp->dev_desc[u], ",Ser# ", 6);
-		u += 6;
-		ret =
-		    usb_string(cp->usbdev, AUSI_SERIALNR, &cp->dev_desc[u],
-			       AUSI_DLEN - u - 1);
-		if (ret >= 0) {
-			u += ret;
-			/* Append subscriber number */
-			memcpy(&cp->dev_desc[u], ", ", 2);
-			u += 2;
-			ret =
-			    usb_string(cp->usbdev, AUSI_MSN,
-				       &cp->dev_desc[u],
-				       AUSI_DLEN - u - 1);
-			if (ret >= 0) {
-				u += ret;
-			}
-		}
-	}
-	cp->dev_desc[u] = '\0';
-	info("device is a %s", cp->dev_desc);
-
-	/* get the maximum allowed control transfer length */
-	pbuf = (char *) kmalloc(2, GFP_KERNEL);	/* use an allocated buffer because of urb target */
-	if (!pbuf) {
-		err("out of memory");
-		goto pfail;
-	}
-	ret = usb_control_msg(cp->usbdev,			/* pointer to device */
-			      usb_rcvctrlpipe(cp->usbdev, 0),	/* pipe to control endpoint */
-			      AUV_GETINFO,			/* USB message request value */
-			      AUT_RREQ,				/* USB message request type value */
-			      0,				/* USB message value */
-			      AUDI_MBCTRANS,			/* USB message index value */
-			      pbuf,				/* pointer to the receive buffer */
-			      2,				/* length of the buffer */
-			      HZ * 2);				/* time to wait for the message to complete before timing out */
-	if (ret == 2) {
-		cp->maxControlLength = le16_to_cpup(pbuf);
-		kfree(pbuf);
-		dbg("setup: max. allowed control transfersize is %d bytes",
-		    cp->maxControlLength);
-	} else {
-		kfree(pbuf);
-		err("setup: getting max. allowed control transfer length failed with error %d", ret);
-		goto pfail;
-	}
-	/* allocate a chain for the control messages */
-	if (auerchain_setup(&cp->controlchain, AUCH_ELEMENTS)) {
-		err("out of memory");
-		goto pfail;
-	}
-
-	/* allocate buffers for control messages */
-	if (auerbuf_setup
-	    (&cp->bufctl, AU_RBUFFERS * 2,
-	     cp->maxControlLength + AUH_SIZE)) {
-		err("out of memory");
-		goto pfail;
-	}
-
-	/* start the interrupt endpoint */
-	if (auerswald_int_open(cp)) {
-		err("int endpoint failed");
-		goto pfail;
-	}
-
-	/* Try to connect to hisax interface */
-	if (auerisdn_probe(cp)) {
-		err("hisax connect failed");
-		goto pfail;
-	}
-
-	/* all OK */
-	return cp;
-
-	/* Error exit: clean up the memory */
-      pfail:auerswald_delete(cp);
-	MOD_DEC_USE_COUNT;
-	return NULL;
-}
-
-
-/* Disconnect driver from a served device
-
-   This function is called whenever a device which was served by this driver
-   is disconnected.
-
-   The argument  dev specifies the device context and the  driver_context
-   returns a pointer to the previously registered  driver_context of the
-   probe function. After returning from the disconnect function the USB
-   framework completly deallocates all data structures associated with
-   this device. So especially the usb_device structure must not be used
-   any longer by the usb driver.
-*/
-static void auerswald_disconnect(struct usb_device *usbdev,
-				 void *driver_context)
-{
-	struct auerswald *cp = (struct auerswald *) driver_context;
-	unsigned int u;
-
-	/* all parallel tasks can react on disconnect ASAP */
-	cp->disconnecting = 1;
-	down(&cp->mutex);
-	info("device /dev/usb/%s now disconnecting", cp->name);
-
-	/* remove from device table */
-	/* Nobody can open() this device any more */
-	down(&auerdev_table_mutex);
-	auerdev_table[cp->dtindex] = NULL;
-	up(&auerdev_table_mutex);
-
-	/* remove our devfs node */
-	/* Nobody can see this device any more */
-	devfs_unregister(cp->devfs);
-
-	/* stop the ISDN connection */
-	auerisdn_disconnect(cp);
-
-	/* Stop the interrupt endpoint 0 */
-	auerswald_int_release(cp);
-
-	/* remove the control chain allocated in auerswald_probe
-	   This has the benefit of
-	   a) all pending (a)synchronous urbs are unlinked
-	   b) all buffers dealing with urbs are reclaimed
-	 */
-	auerchain_free(&cp->controlchain);
-
-	if (cp->open_count == 0) {
-		struct auerscon *scp;
-		/* nobody is using this device. So we can clean up now */
-		up(&cp->mutex);	/* up() is possible here because no other task
-				   can open the device (see above). I don't want
-				   to kfree() a locked mutex. */
-		/* disconnect the D channel */
-		scp = cp->services[AUH_DCHANNEL];
-		if (scp)
-			scp->disconnect(scp);
-		auerswald_delete(cp);
-	} else {
-		/* device is used. Remove the pointer to the
-		   usb device (it's not valid any more). The last
-		   release() will do the clean up */
-		cp->usbdev = NULL;
-		up(&cp->mutex);
-		/* Terminate waiting writers */
-		wake_up(&cp->bufferwait);
-		/* Inform all waiting readers */
-		for (u = 0; u < AUH_TYPESIZE; u++) {
-			struct auerscon *scp = cp->services[u];
-			if (scp)
-				scp->disconnect(scp);
-		}
-	}
-
-	/* The device releases this module */
-	MOD_DEC_USE_COUNT;
-}
-
-/* Descriptor for the devices which are served by this driver.
-   NOTE: this struct is parsed by the usbmanager install scripts.
-         Don't change without caution!
-*/
-static struct usb_device_id auerswald_ids[] = {
-	{USB_DEVICE(ID_AUERSWALD, 0x00C0)},	/* COMpact 2104 USB/DSL */
-	{USB_DEVICE(ID_AUERSWALD, 0x00DB)},	/* COMpact 4410/2206 USB */
-	{USB_DEVICE(ID_AUERSWALD, 0x00DC)},	/* COMpact 4406 DSL */
-	{USB_DEVICE(ID_AUERSWALD, 0x00DD)},	/* COMpact 2204 USB */
-	{USB_DEVICE(ID_AUERSWALD, 0x00F1)},	/* COMfort 2000 System Telephone */
-	{USB_DEVICE(ID_AUERSWALD, 0x00F2)},	/* COMfort 1200 System Telephone */
-	{}					/* Terminating entry */
-};
-
-/* Standard module device table */
-MODULE_DEVICE_TABLE(usb, auerswald_ids);
-
-/* Standard usb driver struct */
-static struct usb_driver auerswald_driver = {
-	name:"auerswald",
-	probe:auerswald_probe,
-	disconnect:auerswald_disconnect,
-	fops:&auerswald_fops,
-	minor:AUER_MINOR_BASE,
-	id_table:auerswald_ids,
-};
-
-
-/* --------------------------------------------------------------------- */
-/* Module loading/unloading                                              */
-
-/* Driver initialisation. Called after module loading.
-   NOTE: there is no concurrency at _init
-*/
-static int __init auerswald_init(void)
-{
-	int result;
-	dbg("init");
-
-	/* initialize the device table */
-	memset(&auerdev_table, 0, sizeof(auerdev_table));
-	init_MUTEX(&auerdev_table_mutex);
-	auerisdn_init();
-
-	/* register driver at the USB subsystem */
-	/* NOTE: usb_register() may call probe()! */
-	result = usb_register(&auerswald_driver);
-	if (result < 0) {
-		err("driver could not be registered");
-		return -1;
-	}
-	return 0;
-}
-
-/* Driver deinit. Called before module removal.
-   NOTE: there is no concurrency at _cleanup
-*/
-static void __exit auerswald_cleanup(void)
-{
-	dbg("cleanup");
-	auerisdn_cleanup();
-	usb_deregister(&auerswald_driver);
-}
-
-/* --------------------------------------------------------------------- */
-/* Linux device driver module description                                */
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-
-module_init(auerswald_init);
-module_exit(auerswald_cleanup);
-
-/* --------------------------------------------------------------------- */
diff -ruN linux-2.4.20-WRTup/drivers/usb/auermain.h linux-2.4.20-WRTstp/drivers/usb/auermain.h
--- linux-2.4.20-WRTup/drivers/usb/auermain.h	2006-06-12 18:04:59.000000000 -0700
+++ linux-2.4.20-WRTstp/drivers/usb/auermain.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,172 +0,0 @@
-/*****************************************************************************/
-/*
- *      auermain.h  --  Auerswald PBX/System Telephone usb driver.
- *
- *      Copyright (C) 2002  Wolfgang Mües (wolfgang@iksw-muees.de)
- *
- *      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.
- */
- /*****************************************************************************/
-
-#ifndef AUERMAIN_H
-#define AUERMAIN_H
-
-#include <linux/devfs_fs_kernel.h>
-#include <linux/usb.h>
-#include "auerchain.h"
-#include "auerbuf.h"
-#include "auerserv.h"
-#include "auerisdn.h"
-
-/*-------------------------------------------------------------------*/
-/* Private declarations for Auerswald USB driver                     */
-
-/* Auerswald Vendor ID */
-#define ID_AUERSWALD  	0x09BF
-
-#ifndef AUER_MINOR_BASE		/* allow external override */
-#define AUER_MINOR_BASE	112	/* auerswald driver minor number */
-#endif
-
-/* we can have up to this number of device plugged in at once */
-#define AUER_MAX_DEVICES 16
-
-/* prefix for the device descriptors in /dev/usb */
-#define AU_PREFIX	"auer"
-
-/* Number of read buffers for each device */
-#define AU_RBUFFERS     10
-
-/* Number of chain elements for each control chain */
-#define AUCH_ELEMENTS   20
-
-/* Number of retries in communication */
-#define AU_RETRIES	10
-
-/*-------------------------------------------------------------------*/
-/* vendor specific protocol                                          */
-/* Header Byte */
-#define AUH_INDIRMASK   0x80	/* mask for direct/indirect bit */
-#define AUH_DIRECT      0x00	/* data is for USB device */
-#define AUH_INDIRECT    0x80	/* USB device is relay */
-
-#define AUH_SPLITMASK   0x40	/* mask for split bit */
-#define AUH_UNSPLIT     0x00	/* data block is full-size */
-#define AUH_SPLIT       0x40	/* data block is part of a larger one,
-				   split-byte follows */
-#define AUH_SYNC	0x40	/* Sync to start of HDLC frame for B1,B2 */
-
-#define AUH_TYPEMASK    0x3F	/* mask for type of data transfer */
-#define AUH_TYPESIZE    0x40	/* different types */
-#define AUH_DCHANNEL    0x00	/* D channel data */
-#define AUH_B1CHANNEL   0x01	/* B1 channel transparent */
-#define AUH_B2CHANNEL   0x02	/* B2 channel transparent */
-/*                0x03..0x0F       reserved for driver internal use */
-#define AUH_COMMAND     0x10	/* Command channel */
-#define AUH_BPROT       0x11	/* Configuration block protocol */
-#define AUH_DPROTANA    0x12	/* D channel protocol analyzer */
-#define AUH_TAPI        0x13	/* telephone api data (ATD) */
-/*                0x14..0x3F       reserved for other protocols */
-#define AUH_UNASSIGNED  0xFF	/* if char device has no assigned service */
-#define AUH_FIRSTUSERCH 0x11	/* first channel which is available for driver users */
-
-#define AUH_SIZE	1	/* Size of Header Byte */
-
-/* Split Byte. Only present if split bit in header byte set.*/
-#define AUS_STARTMASK   0x80	/* mask for first block of splitted frame */
-#define AUS_FIRST       0x80	/* first block */
-#define AUS_FOLLOW      0x00	/* following block */
-
-#define AUS_ENDMASK     0x40	/* mask for last block of splitted frame */
-#define AUS_END         0x40	/* last block */
-#define AUS_NOEND       0x00	/* not the last block */
-
-#define AUS_LENMASK     0x3F	/* mask for block length information */
-
-/* Request types */
-#define AUT_RREQ        (USB_DIR_IN  | USB_TYPE_VENDOR | USB_RECIP_OTHER)	/* Read Request */
-#define AUT_WREQ        (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER)	/* Write Request */
-
-/* Vendor Requests */
-#define AUV_GETINFO     0x00	/* GetDeviceInfo */
-#define AUV_WBLOCK      0x01	/* Write Block */
-#define AUV_RBLOCK      0x02	/* Read Block */
-#define AUV_CHANNELCTL  0x03	/* Channel Control */
-#define AUV_DUMMY	0x04	/* Dummy Out for retry */
-
-/* Device Info Types */
-#define AUDI_NUMBCH     0x0000	/* Number of supported B channels */
-#define AUDI_OUTFSIZE   0x0001	/* Size of OUT B channel fifos */
-#define AUDI_MBCTRANS   0x0002	/* max. Blocklength of control transfer */
-
-/* Interrupt endpoint definitions */
-#define AU_IRQENDP      1	/* Endpoint number */
-#define AU_IRQCMDID     16	/* Command-block ID */
-#define AU_BLOCKRDY     0	/* Command: Block data ready on ctl endpoint */
-#define AU_IRQMINSIZE	5	/* Nr. of bytes decoded in this driver */
-
-/* B channel Interrupt endpoint definitions */
-#define AU_IRQENDPBI	2	/* Input Endpoint number */
-#define AU_IRQENDPBO	3	/* Output Endpoint number for 4410, 2206 */
-#define AU_IRQENDPBO_2	2	/* Output Endpoint number for 2104 */
-
-/* Device String Descriptors */
-#define AUSI_VENDOR   	1	/* "Auerswald GmbH & Co. KG" */
-#define AUSI_DEVICE   	2	/* Name of the Device */
-#define AUSI_SERIALNR 	3	/* Serial Number */
-#define AUSI_MSN      	4	/* "MSN ..." (first) Multiple Subscriber Number */
-
-#define AUSI_DLEN	100	/* Max. Length of Device Description */
-
-#define AUV_RETRY	0x101	/* First Firmware version which can do control retries */
-
-/* ...................................................................*/
-/* USB device context */
-struct auerswald {
-	struct semaphore mutex;		/* protection in user context */
-	char name[16];			/* name of the /dev/usb entry */
-	unsigned int dtindex;		/* index in the device table */
-	devfs_handle_t devfs;		/* devfs device node */
-	struct usb_device *usbdev;	/* USB device handle */
-	int open_count;			/* count the number of open character channels */
-	char dev_desc[AUSI_DLEN];	/* for storing a textual description */
-	unsigned int maxControlLength;	/* max. Length of control paket (without header) */
-	struct urb *inturbp;		/* interrupt urb */
-	char *intbufp;			/* data buffer for interrupt urb */
-	unsigned int irqsize;		/* size of interrupt endpoint 1 */
-	struct auerchain controlchain;	/* for chaining of control messages */
-	struct auerbufctl bufctl;	/* Buffer control for control transfers */
-	struct auerscon *services[AUH_TYPESIZE];/* context pointers for each service */
-	unsigned int version;		/* Version of the device */
-	wait_queue_head_t bufferwait;	/* wait for a control buffer */
-	volatile unsigned int disconnecting;/* 1: removal in progress */
-	struct auerisdn isdn;		/* ISDN-Related parameters */
-};
-
-/* array of pointers to our devices that are currently connected */
-extern struct auerswald *auerdev_table[AUER_MAX_DEVICES];
-
-/* lock to protect the auerdev_table structure */
-extern struct semaphore auerdev_table_mutex;
-
-void auerswald_removeservice(struct auerswald *cp, struct auerscon *scp);
-
-int auerswald_addservice(struct auerswald *cp, struct auerscon *scp);
-
-void auerchar_ctrlwrite_complete(struct urb *urb);
-
-void auerswald_delete(struct auerswald *cp);
-
-#endif	/* AUERMAIN_H */
diff -ruN linux-2.4.20-WRTup/drivers/usb/auerserv.h linux-2.4.20-WRTstp/drivers/usb/auerserv.h
--- linux-2.4.20-WRTup/drivers/usb/auerserv.h	2006-06-12 18:04:59.000000000 -0700
+++ linux-2.4.20-WRTstp/drivers/usb/auerserv.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,47 +0,0 @@
-/*****************************************************************************/
-/*
- *      auerserv.h  --  Auerswald PBX/System Telephone service request structure.
- *
- *      Copyright (C) 2002  Wolfgang Mües (wolfgang@iksw-muees.de)
- *
- *      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.
- */
- /*****************************************************************************/
-
-/* The auerswald ISDN devices have a logical channel concept. Many channels are
- * realized via one control endpoint or INT endpoint. At the receiver side, these
- * messages must be dispatched. Some data may be for an application which is
- * connected through the char interface, other data may be D-channel information
- * routed to ISDN4LINUX. The auerscon struct is used to dispatch the data.
- */
-
-#ifndef AUERSERV_H
-#define AUERSERV_H
-
-#include "auerbuf.h"
-
-/* service context */
-struct auerscon;
-typedef void (*auer_dispatch_t) (struct auerscon *, struct auerbuf *);
-typedef void (*auer_disconn_t) (struct auerscon *);
-
-struct auerscon {
-	unsigned int id;		/* protocol service id AUH_xxxx */
-	auer_dispatch_t dispatch;	/* dispatch read buffer */
-	auer_disconn_t disconnect;	/* disconnect from device, wake up all readers */
-};
-
-
-#endif	/* AUERSERV_H */
diff -ruN linux-2.4.20-WRTup/drivers/usb/Config.in linux-2.4.20-WRTstp/drivers/usb/Config.in
--- linux-2.4.20-WRTup/drivers/usb/Config.in	2006-06-12 18:04:59.000000000 -0700
+++ linux-2.4.20-WRTstp/drivers/usb/Config.in	2005-11-08 06:24:41.000000000 -0800
@@ -108,7 +108,4 @@
    dep_tristate '  Tieman Voyager USB Braille display support (EXPERIMENTAL)' CONFIG_USB_BRLVGER $CONFIG_USB $CONFIG_EXPERIMENTAL
    dep_tristate '  USB LCD device support' CONFIG_USB_LCD $CONFIG_USB
 fi
-
-source drivers/usb/gadget/Config.in
-
 endmenu
diff -ruN linux-2.4.20-WRTup/drivers/usb/gadget/config.c linux-2.4.20-WRTstp/drivers/usb/gadget/config.c
--- linux-2.4.20-WRTup/drivers/usb/gadget/config.c	2006-06-12 18:04:59.000000000 -0700
+++ linux-2.4.20-WRTstp/drivers/usb/gadget/config.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,115 +0,0 @@
-/*
- * usb/gadget/config.c -- simplify building config descriptors
- *
- * Copyright (C) 2003 David Brownell
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/string.h>
-
-#include <linux/usb_ch9.h>
-
-
-/**
- * usb_descriptor_fillbuf - fill buffer with descriptors
- * @buf: Buffer to be filled
- * @buflen: Size of buf
- * @src: Array of descriptor pointers, terminated by null pointer.
- *
- * Copies descriptors into the buffer, returning the length or a
- * negative error code if they can't all be copied.  Useful when
- * assembling descriptors for an associated set of interfaces used
- * as part of configuring a composite device; or in other cases where
- * sets of descriptors need to be marshaled.
- */
-int
-usb_descriptor_fillbuf(void *buf, unsigned buflen,
-		const struct usb_descriptor_header **src)
-{
-	u8	*dest = buf;
-
-	if (!src)
-		return -EINVAL;
-
-	/* fill buffer from src[] until null descriptor ptr */
-	for (; 0 != *src; src++) {
-		unsigned		len = (*src)->bLength;
-
-		if (len > buflen);
-			return -EINVAL;
-		memcpy(dest, *src, len);
-		buflen -= len;
-		dest += len;
-	}
-	return dest - (u8 *)buf;
-}
-
-
-/**
- * usb_gadget_config_buf - builts a complete configuration descriptor
- * @config: Header for the descriptor, including characteristics such
- *	as power requirements and number of interfaces.
- * @desc: Null-terminated vector of pointers to the descriptors (interface,
- *	endpoint, etc) defining all functions in this device configuration.
- * @buf: Buffer for the resulting configuration descriptor.
- * @length: Length of buffer.  If this is not big enough to hold the
- *	entire configuration descriptor, an error code will be returned.
- *
- * This copies descriptors into the response buffer, building a descriptor
- * for that configuration.  It returns the buffer length or a negative
- * status code.  The config.wTotalLength field is set to match the length
- * of the result, but other descriptor fields (including power usage and
- * interface count) must be set by the caller.
- *
- * Gadget drivers could use this when constructing a config descriptor
- * in response to USB_REQ_GET_DESCRIPTOR.  They will need to patch the
- * resulting bDescriptorType value if USB_DT_OTHER_SPEED_CONFIG is needed.
- */
-int usb_gadget_config_buf(
-	const struct usb_config_descriptor	*config,
-	void					*buf,
-	unsigned				length,
-	const struct usb_descriptor_header	**desc
-)
-{
-	struct usb_config_descriptor		*cp = buf;
-	int					len;
-
-	/* config descriptor first */
-	if (length < USB_DT_CONFIG_SIZE || !desc)
-		return -EINVAL;
-	*cp = *config; 
-
-	/* then interface/endpoint/class/vendor/... */
-	len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf,
-			length - USB_DT_CONFIG_SIZE, desc);
-	if (len < 0)
-		return len;
-	len += USB_DT_CONFIG_SIZE;
-	if (len > 0xffff)
-		return -EINVAL;
-
-	/* patch up the config descriptor */
-	cp->bLength = USB_DT_CONFIG_SIZE;
-	cp->bDescriptorType = USB_DT_CONFIG;
-	cp->wTotalLength = cpu_to_le16(len);
-	cp->bmAttributes |= USB_CONFIG_ATT_ONE;
-	return len;
-}
-
diff -ruN linux-2.4.20-WRTup/drivers/usb/gadget/Config.in linux-2.4.20-WRTstp/drivers/usb/gadget/Config.in
--- linux-2.4.20-WRTup/drivers/usb/gadget/Config.in	2006-06-12 18:04:59.000000000 -0700
+++ linux-2.4.20-WRTstp/drivers/usb/gadget/Config.in	1969-12-31 16:00:00.000000000 -0800
@@ -1,93 +0,0 @@
-#
-# USB device-side configuration
-# for 2.4 kbuild, drivers/usb/gadget/Config.in
-#
-# Long term, this likely doesn't all belong in one directory
-# Plan to split it up eventually.
-#
-mainmenu_option next_comment
-comment 'Support for USB gadgets'
-
-bool 'Support for USB Gadgets' CONFIG_USB_GADGET
-if [ "$CONFIG_USB_GADGET" = "y" ]; then
-  
-  #
-  # really want _exactly one_ device controller driver at a time,
-  # since they control compile options for gadget drivers.
-  #
-  comment 'USB Peripheral Controller Drivers'
-  
-  # assume all the dependencies may be undefined ("== true", yeech)
-  if [ "$CONFIG_PCI" = "y" ] ; then
-    tristate '  NetChip 2280 support' CONFIG_USB_NET2280
-    define_tristate CONFIG_USB_GADGET_CONTROLLER $CONFIG_USB_NET2280
-  fi
-  if [ "$CONFIG_ARCH_PXA" = "y" ] ; then
-    tristate '  PXA 210/25x/26x UDC support' CONFIG_USB_PXA2XX
-    define_tristate CONFIG_USB_GADGET_CONTROLLER $CONFIG_USB_PXA2XX
-  fi
-  if [ "$CONFIG_HND" = "y" ] ; then
-    tristate '  Broadcom USB device support' CONFIG_USBDEV
-  fi
-
-  if [ "$CONFIG_USB_GADGET_CONTROLLER" = "y" -o \
-       "$CONFIG_USB_GADGET_CONTROLLER" = "m" -o \
-       "$CONFIG_USBDEV" = "y" -o \
-       "$CONFIG_USBDEV" = "m" ] ; then
-
-  #
-  # no reason not to enable more than one gadget driver module, but
-  # for static linking that would make no sense since the usb model
-  # has exactly one of these upstream connections and only one
-  # lowest-level driver can control it.
-  #
-  # gadget drivers are compiled to work on specific hardware, since
-  #
-  # (a) gadget driver need hardware-specific configuration, like what
-  #     endpoint names and numbers to use, maxpacket sizes, etc
-  #
-  # (b) specific hardware features like iso endpoints may be required
-  #
-  comment 'USB Gadget Drivers'
-
-  dep_tristate '  Gadget Zero (DEVELOPMENT)' CONFIG_USB_ZERO $CONFIG_USB_GADGET_CONTROLLER
-  if [ "$CONFIG_USB_ZERO" = "y" -o "$CONFIG_USB_ZERO" = "m" ]; then
-      if [ "$CONFIG_USB_NET2280" = "y" -o "$CONFIG_USB_NET2280" = "m" ]; then
-  	define_bool CONFIG_USB_ZERO_NET2280 y
-      fi
-      if [ "$CONFIG_USB_PXA2XX" = "y" -o "$CONFIG_USB_PXA2XX" = "m" ]; then
-  	define_bool CONFIG_USB_ZERO_PXA2XX y
-      fi
-      # ...
-  fi
-  
-  dep_tristate '  Ethernet Gadget (EXPERIMENTAL)' CONFIG_USB_ETH $CONFIG_USB_GADGET_CONTROLLER
-  if [ "$CONFIG_USB_ETH" = "y" -o "$CONFIG_USB_ETH" = "m" ]; then
-      if [ "$CONFIG_USB_NET2280" = "y" -o "$CONFIG_USB_NET2280" = "m" ]; then
-  	define_bool CONFIG_USB_ETH_NET2280 y
-      fi
-      if [ "$CONFIG_USB_PXA2XX" = "y" -o "$CONFIG_USB_PXA2XX" = "m" ]; then
-  	define_bool CONFIG_USB_ETH_PXA2XX y
-      fi
-      # ...
-  fi
-
-  tristate '  Simple Gadget' CONFIG_USB_SIMPLE
-  tristate '  RNDIS Gadget' CONFIG_USB_RNDIS
-  
-  dep_tristate '  Gadget Filesystem API (EXPERIMENTAL)' CONFIG_USB_GADGETFS $CONFIG_USB_GADGET_CONTROLLER
-  if [ "$CONFIG_USB_GADGETFS" = "y" -o "$CONFIG_USB_GADGETFS" = "m" ]; then
-      if [ "$CONFIG_USB_NET2280" = "y" -o "$CONFIG_USB_NET2280" = "m" ]; then
-  	define_bool CONFIG_USB_GADGETFS_NET2280 y
-      fi
-      if [ "$CONFIG_USB_PXA2XX" = "y" -o "$CONFIG_USB_PXA2XX" = "m" ]; then
-  	define_bool CONFIG_USB_GADGETFS_PXA2XX y
-      fi
-      # ...
-  fi
-  
-  # ... or other gadget drivers:  printer class, storage, hid, etc ...
-
-  fi
-fi
-endmenu
diff -ruN linux-2.4.20-WRTup/drivers/usb/gadget/ether.c linux-2.4.20-WRTstp/drivers/usb/gadget/ether.c
--- linux-2.4.20-WRTup/drivers/usb/gadget/ether.c	2006-06-12 18:04:59.000000000 -0700
+++ linux-2.4.20-WRTstp/drivers/usb/gadget/ether.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,1861 +0,0 @@
-/*
- * ether.c -- Ethernet gadget driver, with CDC and non-CDC options
- *
- * Copyright (C) 2003 David Brownell
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-
-#define DEBUG 1
-// #define VERBOSE
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/uts.h>
-#include <linux/version.h>
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/unaligned.h>
-
-#include <linux/usb_ch9.h>
-#include <linux/usb_gadget.h>
-
-#include <linux/random.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/ethtool.h>
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * Ethernet gadget driver -- with CDC and non-CDC options
- *
- * CDC Ethernet is the standard USB solution for sending Ethernet frames
- * using USB.  Real hardware tends to use the same framing protocol but look
- * different for control features.  And Microsoft pushes their own approach
- * (RNDIS) instead of the standard.
- *
- * There's some hardware that can't talk CDC.  We make that hardware
- * implement a "minimalist" vendor-agnostic CDC core:  same framing, but
- * link-level setup only requires activating the configuration.
- */
-
-#define DRIVER_DESC		"Ethernet Gadget"
-#define DRIVER_VERSION		"Bastille Day 2003"
-
-static const char shortname [] = "ether";
-static const char driver_desc [] = DRIVER_DESC;
-
-#define MIN_PACKET	sizeof(struct ethhdr)
-#define	MAX_PACKET	ETH_DATA_LEN	/* biggest packet we'll rx/tx */
-#define RX_EXTRA	20		/* guard against rx overflows */
-
-
-/*-------------------------------------------------------------------------*/
-
-#ifndef container_of
-#define container_of		list_entry
-#endif
-
-/* 2.5 modified and renamed these */
-
-#define work_struct		tq_struct
-#define INIT_WORK		INIT_TQUEUE
-#define schedule_work		schedule_task
-#define	flush_scheduled_work	flush_scheduled_tasks
-
-/*-------------------------------------------------------------------------*/
-
-struct eth_dev {
-	spinlock_t		lock;
-	struct usb_gadget	*gadget;
-	struct usb_request	*req;		/* for control responses */
-
-	u8			config;
-	struct usb_ep		*in_ep, *out_ep, *status_ep;
-	const struct usb_endpoint_descriptor
-				*in, *out, *status;
-	struct list_head	tx_reqs, rx_reqs;
-
-	struct net_device	*net;
-	struct net_device_stats	stats;
-	atomic_t		tx_qlen;
-
-	struct work_struct	work;
-	unsigned long		todo;
-#define	WORK_RX_MEMORY		0
-};
-
-/*-------------------------------------------------------------------------*/
-
-/* This driver keeps a variable number of requests queued, more at
- * high speeds.  (Numbers are just educated guesses, untuned.)
- * Shrink the queue if memory is tight, or make it bigger to
- * handle bigger traffic bursts between IRQs.
- */
-
-static unsigned qmult = 4;
-
-#define HS_FACTOR	5
-
-#define qlen(gadget) \
-	(qmult*((gadget->speed == USB_SPEED_HIGH) ? HS_FACTOR : 1))
-
-/* defer IRQs on highspeed TX */
-#define TX_DELAY	8
-
-
-MODULE_PARM (qmult, "i");
-MODULE_PARM_DESC (qmult, "rx/tx buffering factor");
-
-/*-------------------------------------------------------------------------*/
-
-/* Thanks to NetChip Technologies for donating this product ID.
- *
- * DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
- * Instead:  allocate your own, using normal USB-IF procedures.
- */
-#define DRIVER_VENDOR_NUM	0x0525		/* NetChip */
-#define DRIVER_PRODUCT_NUM	0xa4a1		/* Linux-USB Ethernet Gadget */
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * hardware-specific configuration, controlled by which device
- * controller driver was configured.
- *
- * CHIP ... hardware identifier
- * DRIVER_VERSION_NUM ... alerts the host side driver to differences
- * EP0_MAXPACKET ... controls packetization of control requests
- * EP_*_NAME ... which endpoints do we use for which purpose?
- * EP_*_NUM ... numbers for them (often limited by hardware)
- * HIGHSPEED ... define if ep0 and descriptors need high speed support
- * MAX_USB_POWER ... define if we use other than 100 mA bus current
- * SELFPOWER ... unless we can run on bus power, USB_CONFIG_ATT_SELFPOWER
- * WAKEUP ... if hardware supports remote wakeup AND we will issue the
- * 	usb_gadget_wakeup() call to initiate it, USB_CONFIG_ATT_WAKEUP
- *
- * hw_optimize(gadget) ... for any hardware tweaks we want to kick in
- * 	before we enable our endpoints
- *
- * add other defines for other portability issues, like hardware that
- * for some reason doesn't handle full speed bulk maxpacket of 64.
- */
-
-#define DEV_CONFIG_VALUE	3	/* some hardware cares */
-
-/* #undef on hardware that can't implement CDC */
-#define	DEV_CONFIG_CDC
-
-/*
- * NetChip 2280, PCI based.
- *
- * use DMA with fat fifos for all data traffic, PIO for the status channel
- * where its 64 byte maxpacket ceiling is no issue.
- *
- * performance note:  only PIO needs per-usb-packet IRQs (ep0, ep-e, ep-f)
- * otherwise IRQs are per-Ethernet-packet unless TX_DELAY and chaining help.
- */
-#ifdef	CONFIG_USB_ETH_NET2280
-#define CHIP			"net2280"
-#define DRIVER_VERSION_NUM	0x0101
-#define EP0_MAXPACKET		64
-static const char EP_OUT_NAME [] = "ep-a";
-#define EP_OUT_NUM	1
-static const char EP_IN_NAME [] = "ep-b";
-#define EP_IN_NUM	2
-static const char EP_STATUS_NAME [] = "ep-f";
-#define EP_STATUS_NUM	3
-#define HIGHSPEED
-/* specific hardware configs could be bus-powered */
-#define SELFPOWER USB_CONFIG_ATT_SELFPOWER
-/* supports remote wakeup, but this driver doesn't */
-
-extern int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode);
-
-static inline void hw_optimize (struct usb_gadget *gadget)
-{
-	/* we can have bigger ep-a/ep-b fifos (2KB each, 4 USB packets
-	 * for highspeed bulk) because we're not using ep-c/ep-d.
-	 */
-	net2280_set_fifo_mode (gadget, 1);
-}
-#endif
-
-/*
- * PXA-2xx UDC:  widely used in second gen Linux-capable ARM PDAs
- * and other products.
- *
- * multiple interfaces (or altsettings) aren't usable.  so this hardware
- * can't implement CDC, which needs both capabilities.
- */
-#ifdef	CONFIG_USB_ETH_PXA2XX
-#undef	DEV_CONFIG_CDC
-#define CHIP			"pxa2xx"
-#define DRIVER_VERSION_NUM	0x0103
-#define EP0_MAXPACKET		16
-static const char EP_OUT_NAME [] = "ep2out-bulk";
-#define EP_OUT_NUM	2
-static const char EP_IN_NAME [] = "ep1in-bulk";
-#define EP_IN_NUM	1
-/* doesn't support bus-powered operation */
-#define SELFPOWER USB_CONFIG_ATT_SELFPOWER
-/* supports remote wakeup, but this driver doesn't */
-
-/* no hw optimizations to apply */
-#define hw_optimize(g) do {} while (0);
-#endif
-
-/*
- * SA-1100 UDC:  widely used in first gen Linux-capable PDAs.
- *
- * can't have a notification endpoint, since there are only the two
- * bulk-capable ones.  the CDC spec allows that.
- */
-#ifdef	CONFIG_USB_ETH_SA1100
-#define CHIP			"sa1100"
-#define DRIVER_VERSION_NUM	0x0105
-#define EP0_MAXPACKET		8
-static const char EP_OUT_NAME [] = "ep1out-bulk";
-#define EP_OUT_NUM	1
-static const char EP_IN_NAME [] = "ep2in-bulk";
-#define EP_IN_NUM	2
-// EP_STATUS_NUM is undefined
-/* doesn't support bus-powered operation */
-#define SELFPOWER USB_CONFIG_ATT_SELFPOWER
-/* doesn't support remote wakeup? */
-
-/* no hw optimizations to apply */
-#define hw_optimize(g) do {} while (0);
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-#ifndef EP0_MAXPACKET
-#	error Configure some USB peripheral controller driver!
-#endif
-
-/* We normally expect hardware that can talk CDC.  That involves
- * using multiple interfaces and altsettings, and maybe a status
- * interrupt.  Driver binding to be done according to USB-IF class,
- * though you can use different VENDOR and PRODUCT numbers if you
- * want (and they're officially assigned).
- * 
- * For hardware that can't talk CDC, we use the same vendor ID that
- * ARM Linux has used for ethernet-over-usb, both with sa1100 and
- * with pxa250.  We're protocol-compatible, if the host-side drivers
- * use the endpoint descriptors.  DRIVER_VERSION_NUM is nonzero, so
- * drivers that need to hard-wire endpoint numbers have a hook.
- */
-#ifdef	DEV_CONFIG_CDC
-#define	DEV_CONFIG_CLASS	USB_CLASS_COMM
-#else	
-#define	DEV_CONFIG_CLASS	USB_CLASS_VENDOR_SPEC
-#undef	EP_STATUS_NUM
-#undef	DRIVER_VENDOR_NUM
-#undef	DRIVER_PRODUCT_NUM
-#define	DRIVER_VENDOR_NUM	0x049f
-#define	DRIVER_PRODUCT_NUM	0x505a
-#endif /* CONFIG_CDC_ETHER */
-
-/* power usage is config specific.
- * hardware that supports remote wakeup defaults to disabling it.
- */
-
-#ifndef	SELFPOWER
-/* default: say we rely on bus power */
-#define SELFPOWER	0
-/* else:
- * - SELFPOWER value must be USB_CONFIG_ATT_SELFPOWER
- * - MAX_USB_POWER may be nonzero.
- */
-#endif
-
-#ifndef	MAX_USB_POWER
-/* any hub supports this steady state bus power consumption */
-#define MAX_USB_POWER	100	/* mA */
-#endif
-
-#ifndef	WAKEUP
-/* default: this driver won't do remote wakeup */
-#define WAKEUP		0
-/* else value must be USB_CONFIG_ATT_WAKEUP */
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-#define xprintk(d,level,fmt,args...) \
-	printk(level "%s %s: " fmt , shortname , (d)->gadget->dev.bus_id , \
-		## args)
-
-#ifdef DEBUG
-#undef DEBUG
-#define DEBUG(dev,fmt,args...) \
-	xprintk(dev , KERN_DEBUG , fmt , ## args)
-#else
-#define DEBUG(dev,fmt,args...) \
-	do { } while (0)
-#endif /* DEBUG */
-
-#ifdef VERBOSE
-#define VDEBUG	DEBUG
-#else
-#define VDEBUG(dev,fmt,args...) \
-	do { } while (0)
-#endif /* DEBUG */
-
-#define ERROR(dev,fmt,args...) \
-	xprintk(dev , KERN_ERR , fmt , ## args)
-#define WARN(dev,fmt,args...) \
-	xprintk(dev , KERN_WARNING , fmt , ## args)
-#define INFO(dev,fmt,args...) \
-	xprintk(dev , KERN_INFO , fmt , ## args)
-
-/*-------------------------------------------------------------------------*/
-
-/* USB DRIVER HOOKUP (to the hardware driver, below us), mostly
- * ep0 implementation:  descriptors, config management, setup().
- * also optional class-specific notification interrupt transfer.
- */
-
-/*
- * DESCRIPTORS ... most are static, but strings and (full) configuration
- * descriptors are built on demand.  Notice how most of the cdc descriptors
- * aren't needed in the "minimalist" mode.
- */
-
-#define STRING_MANUFACTURER		1
-#define STRING_PRODUCT			2
-#define STRING_ETHADDR			3
-#define STRING_DATA			4
-#define STRING_CONTROL			5
-
-#define USB_BUFSIZ	256		/* holds our biggest descriptor */
-
-/*
- * This device advertises one configuration.
- */
-static const struct usb_device_descriptor
-device_desc = {
-	.bLength =		sizeof device_desc,
-	.bDescriptorType =	USB_DT_DEVICE,
-
-	.bcdUSB =		__constant_cpu_to_le16 (0x0200),
-
-	.bDeviceClass =		DEV_CONFIG_CLASS,
-	.bDeviceSubClass =	0,
-	.bDeviceProtocol =	0,
-	.bMaxPacketSize0 =	EP0_MAXPACKET,
-
-	.idVendor =		__constant_cpu_to_le16 (DRIVER_VENDOR_NUM),
-	.idProduct =		__constant_cpu_to_le16 (DRIVER_PRODUCT_NUM),
-	.bcdDevice =		__constant_cpu_to_le16 (DRIVER_VERSION_NUM),
-	.iManufacturer =	STRING_MANUFACTURER,
-	.iProduct =		STRING_PRODUCT,
-	.bNumConfigurations =	1,
-};
-
-static const struct usb_config_descriptor
-eth_config = {
-	.bLength =		sizeof eth_config,
-	.bDescriptorType =	USB_DT_CONFIG,
-
-	/* compute wTotalLength on the fly */
-#ifdef	DEV_CONFIG_CDC
-	.bNumInterfaces =	2,
-#else
-	.bNumInterfaces =	1,
-#endif
-	.bConfigurationValue =	DEV_CONFIG_VALUE,
-	.iConfiguration =	STRING_PRODUCT,
-	.bmAttributes =		USB_CONFIG_ATT_ONE | SELFPOWER | WAKEUP,
-	.bMaxPower =		(MAX_USB_POWER + 1) / 2,
-};
-
-#ifdef	DEV_CONFIG_CDC
-
-/*
- * Compared to the "minimalist" non-CDC model, the CDC model adds
- * three class descriptors, two interface descrioptors, and a status
- * endpoint.  Both have a "data" interface and two bulk endpoints.
- * There are also differences in how control requests are handled.
- */
-
-/* master comm interface optionally has a status notification endpoint */
-
-static const struct usb_interface_descriptor
-control_intf = {
-	.bLength =		sizeof control_intf,
-	.bDescriptorType =	USB_DT_INTERFACE,
-
-	.bInterfaceNumber =	0,
-#ifdef	EP_STATUS_NUM
-	.bNumEndpoints =	1,
-#else
-	.bNumEndpoints =	0,
-#endif
-	.bInterfaceClass =	USB_CLASS_COMM,
-	.bInterfaceSubClass =	6,	/* ethernet control model */
-	.bInterfaceProtocol =	0,
-	.iInterface =		STRING_CONTROL,
-};
-
-/* "Header Functional Descriptor" from CDC spec  5.2.3.1 */
-struct header_desc {
-	u8	bLength;
-	u8	bDescriptorType;
-	u8	bDescriptorSubType;
-
-	u16	bcdCDC;
-} __attribute__ ((packed));
-
-static const struct header_desc header_desc = {
-	.bLength =		sizeof header_desc,
-	.bDescriptorType =	0x24,
-	.bDescriptorSubType =	0,
-
-	.bcdCDC =		__constant_cpu_to_le16 (0x0110),
-};
-
-/* "Union Functional Descriptor" from CDC spec 5.2.3.X */
-struct union_desc {
-	u8	bLength;
-	u8	bDescriptorType;
-	u8	bDescriptorSubType;
-
-	u8	bMasterInterface0;
-	u8	bSlaveInterface0;
-	/* ... and there could be other slave interfaces */
-} __attribute__ ((packed));
-
-static const struct union_desc union_desc = {
-	.bLength =		sizeof union_desc,
-	.bDescriptorType =	0x24,
-	.bDescriptorSubType =	6,
-
-	.bMasterInterface0 =	0,	/* index of control interface */
-	.bSlaveInterface0 =	1,	/* index of DATA interface */
-};
-
-/* "Ethernet Networking Functional Descriptor" from CDC spec 5.2.3.16 */
-struct ether_desc {
-	u8	bLength;
-	u8	bDescriptorType;
-	u8	bDescriptorSubType;
-
-	u8	iMACAddress;
-	u32	bmEthernetStatistics;
-	u16	wMaxSegmentSize;
-	u16	wNumberMCFilters;
-	u8	bNumberPowerFilters;
-} __attribute__ ((packed));
-
-static const struct ether_desc ether_desc = {
-	.bLength =		sizeof ether_desc,
-	.bDescriptorType =	0x24,
-	.bDescriptorSubType =	0x0f,
-
-	/* this descriptor actually adds value, surprise! */
-	.iMACAddress =		STRING_ETHADDR,
-	.bmEthernetStatistics =	__constant_cpu_to_le32 (0), /* no statistics */
-	.wMaxSegmentSize =	__constant_cpu_to_le16 (MAX_PACKET + ETH_HLEN),
-	.wNumberMCFilters =	__constant_cpu_to_le16 (0),
-	.bNumberPowerFilters =	0,
-};
-
-#ifdef	EP_STATUS_NUM
-
-/* include the status endpoint if we can, even though it's optional.
- *
- * some drivers (like current Linux cdc-ether!) "need" it to exist even
- * if they ignore the connect/disconnect notifications that real aether
- * can provide.  more advanced cdc configurations might want to support
- * encapsulated commands (vendor-specific, using control-OUT).
- */
- 
-#define LOG2_STATUS_INTERVAL_MSEC	6
-#define STATUS_BYTECOUNT		16	/* 8 byte header + data */
-static const struct usb_endpoint_descriptor
-fs_status_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	EP_STATUS_NUM | USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	__constant_cpu_to_le16 (STATUS_BYTECOUNT),
-	.bInterval =		1 << LOG2_STATUS_INTERVAL_MSEC,
-};
-#endif
-
-/* the default data interface has no endpoints ... */
-
-static const struct usb_interface_descriptor
-data_nop_intf = {
-	.bLength =		sizeof data_nop_intf,
-	.bDescriptorType =	USB_DT_INTERFACE,
-
-	.bInterfaceNumber =	1,
-	.bAlternateSetting =	0,
-	.bNumEndpoints =	0,
-	.bInterfaceClass =	USB_CLASS_CDC_DATA,
-	.bInterfaceSubClass =	0,
-	.bInterfaceProtocol =	0,
-	.iInterface =		STRING_DATA,
-};
-
-/* ... but the "real" data interface has two full speed bulk endpoints */
-
-static const struct usb_interface_descriptor
-data_intf = {
-	.bLength =		sizeof data_intf,
-	.bDescriptorType =	USB_DT_INTERFACE,
-
-	.bInterfaceNumber =	1,
-	.bAlternateSetting =	1,
-	.bNumEndpoints =	2,
-	.bInterfaceClass =	USB_CLASS_CDC_DATA,
-	.bInterfaceSubClass =	0,
-	.bInterfaceProtocol =	0,
-	.iInterface =		STRING_DATA,
-};
-#else
-
-/*
- * "Minimalist" non-CDC option is a simple vendor-neutral model that most
- * full speed controllers can handle:  one interface, two bulk endpoints.
- */
-
-static const struct usb_interface_descriptor
-data_intf = {
-	.bLength =		sizeof data_intf,
-	.bDescriptorType =	USB_DT_INTERFACE,
-
-	.bInterfaceNumber =	0,
-	.bAlternateSetting =	0,
-	.bNumEndpoints =	2,
-	.bInterfaceClass =	USB_CLASS_VENDOR_SPEC,
-	.bInterfaceSubClass =	0,
-	.bInterfaceProtocol =	0,
-	.iInterface =		STRING_DATA,
-};
-
-#endif	/* DEV_CONFIG_CDC */
-
-
-static const struct usb_endpoint_descriptor
-fs_source_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	EP_IN_NUM | USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16 (64),
-};
-
-static const struct usb_endpoint_descriptor
-fs_sink_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	EP_OUT_NUM,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16 (64),
-};
-
-#ifdef	HIGHSPEED
-
-/*
- * usb 2.0 devices need to expose both high speed and full speed
- * descriptors, unless they only run at full speed.
- */
-
-#ifdef	EP_STATUS_NUM
-static const struct usb_endpoint_descriptor
-hs_status_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	EP_STATUS_NUM | USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	__constant_cpu_to_le16 (STATUS_BYTECOUNT),
-	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 3,
-};
-#endif
-
-static const struct usb_endpoint_descriptor
-hs_source_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	EP_IN_NUM | USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16 (512),
-	.bInterval =		1,
-};
-
-static const struct usb_endpoint_descriptor
-hs_sink_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	EP_OUT_NUM,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16 (512),
-	.bInterval =		1,
-};
-
-static const struct usb_qualifier_descriptor
-dev_qualifier = {
-	.bLength =		sizeof dev_qualifier,
-	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,
-
-	.bcdUSB =		__constant_cpu_to_le16 (0x0200),
-	.bDeviceClass =		DEV_CONFIG_CLASS,
-
-	/* assumes ep0 uses the same value for both speeds ... */
-	.bMaxPacketSize0 =	EP0_MAXPACKET,
-
-	.bNumConfigurations =	1,
-};
-
-/* maxpacket and other transfer characteristics vary by speed. */
-#define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs))
-
-#else
-
-/* if there's no high speed support, maxpacket doesn't change. */
-#define ep_desc(g,hs,fs) fs
-
-#endif	/* !HIGHSPEED */
-
-/*-------------------------------------------------------------------------*/
-
-/* descriptors that are built on-demand */
-
-#ifdef	DEV_CONFIG_CDC
-/* address that the host will use ... usually assigned at random */
-static char				ethaddr [2 * ETH_ALEN + 1];
-#endif
-
-/* static strings, in iso 8859/1 */
-static struct usb_string		strings [] = {
-	{ STRING_MANUFACTURER,	UTS_SYSNAME " " UTS_RELEASE "/" CHIP, },
-	{ STRING_PRODUCT,	driver_desc, },
-#ifdef	DEV_CONFIG_CDC
-	{ STRING_ETHADDR,	ethaddr, },
-	{ STRING_CONTROL,	"CDC Communications Control", },
-#endif
-	{ STRING_DATA,		"Ethernet Data", },
-	{  }		/* end of list */
-};
-
-static struct usb_gadget_strings	stringtab = {
-	.language	= 0x0409,	/* en-us */
-	.strings	= strings,
-};
-
-/*
- * one config, two interfaces:  control, data.
- * complications: class descriptors, and an altsetting.
- */
-static int
-config_buf (enum usb_device_speed speed, u8 *buf, u8 type, unsigned index)
-{
-	const unsigned	config_len = USB_DT_CONFIG_SIZE
-#ifdef DEV_CONFIG_CDC
-				+ 2 * USB_DT_INTERFACE_SIZE
-				+ sizeof header_desc
-				+ sizeof union_desc
-				+ sizeof ether_desc
-#ifdef	EP_STATUS_NUM
-				+ USB_DT_ENDPOINT_SIZE
-#endif
-#endif /* DEV_CONFIG_CDC */
-				+ USB_DT_INTERFACE_SIZE
-				+ 2 * USB_DT_ENDPOINT_SIZE;
-
-#ifdef HIGHSPEED
-	int		hs;
-#endif
-	/* a single configuration must always be index 0 */
-	if (index > 0)
-		return -EINVAL;
-	if (config_len > USB_BUFSIZ)
-		return -EDOM;
-
-	/* config (or other speed config) */
-	memcpy (buf, &eth_config, USB_DT_CONFIG_SIZE);
-	buf [1] = type;
-	((struct usb_config_descriptor *) buf)->wTotalLength
-		= __constant_cpu_to_le16 (config_len);
-	buf += USB_DT_CONFIG_SIZE;
-#ifdef	HIGHSPEED
-	hs = (speed == USB_SPEED_HIGH);
-	if (type == USB_DT_OTHER_SPEED_CONFIG)
-		hs = !hs;
-#endif
-
-#ifdef DEV_CONFIG_CDC
-	/* control interface, class descriptors, optional status endpoint */
-	memcpy (buf, &control_intf, USB_DT_INTERFACE_SIZE);
-	buf += USB_DT_INTERFACE_SIZE;
-
-	memcpy (buf, &header_desc, sizeof header_desc);
-	buf += sizeof header_desc;
-	memcpy (buf, &union_desc, sizeof union_desc);
-	buf += sizeof union_desc;
-	memcpy (buf, &ether_desc, sizeof ether_desc);
-	buf += sizeof ether_desc;
-
-#ifdef	EP_STATUS_NUM
-#ifdef	HIGHSPEED
-	if (hs)
-		memcpy (buf, &hs_status_desc, USB_DT_ENDPOINT_SIZE);
-	else
-#endif	/* HIGHSPEED */
-		memcpy (buf, &fs_status_desc, USB_DT_ENDPOINT_SIZE);
-	buf += USB_DT_ENDPOINT_SIZE;
-#endif	/* EP_STATUS_NUM */
-
-	/* default data altsetting has no endpoints */
-	memcpy (buf, &data_nop_intf, USB_DT_INTERFACE_SIZE);
-	buf += USB_DT_INTERFACE_SIZE;
-#endif /* DEV_CONFIG_CDC */
-
-	/* the "real" data interface has two endpoints */
-	memcpy (buf, &data_intf, USB_DT_INTERFACE_SIZE);
-	buf += USB_DT_INTERFACE_SIZE;
-#ifdef HIGHSPEED
-	if (hs) {
-		memcpy (buf, &hs_source_desc, USB_DT_ENDPOINT_SIZE);
-		buf += USB_DT_ENDPOINT_SIZE;
-		memcpy (buf, &hs_sink_desc, USB_DT_ENDPOINT_SIZE);
-		buf += USB_DT_ENDPOINT_SIZE;
-	} else
-#endif
-	{
-		memcpy (buf, &fs_source_desc, USB_DT_ENDPOINT_SIZE);
-		buf += USB_DT_ENDPOINT_SIZE;
-		memcpy (buf, &fs_sink_desc, USB_DT_ENDPOINT_SIZE);
-		buf += USB_DT_ENDPOINT_SIZE;
-	}
-
-	return config_len;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void eth_start (struct eth_dev *dev, int gfp_flags);
-static int alloc_requests (struct eth_dev *dev, unsigned n, int gfp_flags);
-
-static int
-set_ether_config (struct eth_dev *dev, int gfp_flags)
-{
-	int			result = 0;
-	struct usb_ep		*ep;
-	struct usb_gadget	*gadget = dev->gadget;
-
-	gadget_for_each_ep (ep, gadget) {
-		const struct usb_endpoint_descriptor	*d;
-
-#ifdef	DEV_CONFIG_CDC
-		/* With CDC,  the host isn't allowed to use these two data
-		 * endpoints in the default altsetting for the interface.
-		 * so we don't activate them yet.
-		 */
-
-		/* one endpoint writes data back IN to the host */
-		if (strcmp (ep->name, EP_IN_NAME) == 0) {
-			d = ep_desc (gadget, &hs_source_desc, &fs_source_desc);
-			ep->driver_data = dev;
-			dev->in_ep = ep;
-			dev->in = d;
-			continue;
-
-		/* one endpoint just reads OUT packets */
-		} else if (strcmp (ep->name, EP_OUT_NAME) == 0) {
-			d = ep_desc (gadget, &hs_sink_desc, &fs_sink_desc);
-			ep->driver_data = dev;
-			dev->out_ep = ep;
-			dev->out = d;
-			continue;
-		}
-
-#ifdef	EP_STATUS_NUM
-		/* optional status/notification endpoint */
-		else if (strcmp (ep->name, EP_STATUS_NAME) == 0) {
-			d = ep_desc (gadget, &hs_status_desc, &fs_status_desc);
-			result = usb_ep_enable (ep, d);
-			if (result == 0) {
-				ep->driver_data = dev;
-				dev->status_ep = ep;
-				dev->status = d;
-				continue;
-			}
-		}
-#endif
-
-#else	/* !CONFIG_CDC_ETHER */
-
-		/* non-CDC is simpler:  if the device is there,
-		 * it's live with rx and tx endpoints.
-		 */
-		/* one endpoint writes data back IN to the host */
-		if (strcmp (ep->name, EP_IN_NAME) == 0) {
-			d = ep_desc (gadget, &hs_source_desc, &fs_source_desc);
-			result = usb_ep_enable (ep, d);
-			if (result == 0) {
-				ep->driver_data = dev;
-				dev->in_ep = ep;
-				dev->in = d;
-				continue;
-			}
-
-		/* one endpoint just reads OUT packets */
-		} else if (strcmp (ep->name, EP_OUT_NAME) == 0) {
-			d = ep_desc (gadget, &hs_sink_desc, &fs_sink_desc);
-			result = usb_ep_enable (ep, d);
-			if (result == 0) {
-				ep->driver_data = dev;
-				dev->out_ep = ep;
-				dev->out = d;
-				continue;
-			}
-		}
-
-#endif /* !CONFIG_CDC_ETHER */
-
-		/* ignore any other endpoints */
-		else
-			continue;
-
-		/* stop on error */
-		ERROR (dev, "can't enable %s, result %d\n", ep->name, result);
-		break;
-	}
-	if (!result && (!dev->in_ep || !dev->out_ep))
-		result = -ENODEV;
-
-	if (result == 0)
-		result = alloc_requests (dev, qlen (gadget), gfp_flags);
-
-#ifndef	DEV_CONFIG_CDC
-	if (result == 0) {
-		netif_carrier_on (dev->net);
-		if (netif_running (dev->net))
-			eth_start (dev, GFP_ATOMIC);
-	} else {
-		(void) usb_ep_disable (dev->in_ep);
-		dev->in_ep = 0;
-		dev->in = 0;
-		(void) usb_ep_disable (dev->out_ep);
-		dev->out_ep = 0;
-		dev->out = 0;
-	}
-#endif /* !CONFIG_CDC_ETHER */
-
-	if (result == 0)
-		DEBUG (dev, "qlen %d\n", qlen (gadget));
-
-	/* caller is responsible for cleanup on error */
-	return result;
-}
-
-static void eth_reset_config (struct eth_dev *dev)
-{
-	if (dev->config == 0)
-		return;
-
-	DEBUG (dev, "%s\n", __FUNCTION__);
-
-	netif_stop_queue (dev->net);
-	netif_carrier_off (dev->net);
-
-	/* just disable endpoints, forcing completion of pending i/o.
-	 * all our completion handlers free their requests in this case.
-	 */
-	if (dev->in_ep) {
-		usb_ep_disable (dev->in_ep);
-		dev->in_ep = 0;
-	}
-	if (dev->out_ep) {
-		usb_ep_disable (dev->out_ep);
-		dev->out_ep = 0;
-	}
-#ifdef	EP_STATUS_NUM
-	if (dev->status_ep) {
-		usb_ep_disable (dev->status_ep);
-		dev->status_ep = 0;
-	}
-#endif
-	dev->config = 0;
-}
-
-/* change our operational config.  must agree with the code
- * that returns config descriptors, and altsetting code.
- */
-static int
-eth_set_config (struct eth_dev *dev, unsigned number, int gfp_flags)
-{
-	int			result = 0;
-	struct usb_gadget	*gadget = dev->gadget;
-
-	if (number == dev->config)
-		return 0;
-
-#ifdef CONFIG_USB_ETH_SA1100
-	if (dev->config && atomic_read (&dev->tx_qlen) != 0) {
-		/* tx fifo is full, but we can't clear it...*/
-		INFO (dev, "can't change configurations\n");
-		return -ESPIPE;
-	}
-#endif
-	eth_reset_config (dev);
-	hw_optimize (gadget);
-
-	switch (number) {
-	case DEV_CONFIG_VALUE:
-		result = set_ether_config (dev, gfp_flags);
-		break;
-	default:
-		result = -EINVAL;
-		/* FALL THROUGH */
-	case 0:
-		return result;
-	}
-
-	if (result)
-		eth_reset_config (dev);
-	else {
-		char *speed;
-
-		switch (gadget->speed) {
-		case USB_SPEED_FULL:	speed = "full"; break;
-#ifdef HIGHSPEED
-		case USB_SPEED_HIGH:	speed = "high"; break;
-#endif
-		default: 		speed = "?"; break;
-		}
-
-		dev->config = number;
-		INFO (dev, "%s speed config #%d: %s\n", speed, number,
-				driver_desc);
-	}
-	return result;
-}
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef	EP_STATUS_NUM
-
-/* section 3.8.2 table 11 of the CDC spec lists Ethernet notifications */
-#define CDC_NOTIFY_NETWORK_CONNECTION	0x00	/* required; 6.3.1 */
-#define CDC_NOTIFY_SPEED_CHANGE		0x2a	/* required; 6.3.8 */
-
-struct cdc_notification {
-	u8	bmRequestType;
-	u8	bNotificationType;
-	u16	wValue;
-	u16	wIndex;
-	u16	wLength;
-
-	/* SPEED_CHANGE data looks like this */
-	u32	data [2];
-};
-
-static void eth_status_complete (struct usb_ep *ep, struct usb_request *req)
-{
-	struct cdc_notification	*event = req->buf;
-	int			value = req->status;
-	struct eth_dev		*dev = ep->driver_data;
-
-	/* issue the second notification if host reads the first */
-	if (event->bNotificationType == CDC_NOTIFY_NETWORK_CONNECTION
-			&& value == 0) {
-		event->bmRequestType = 0xA1;
-		event->bNotificationType = CDC_NOTIFY_SPEED_CHANGE;
-		event->wValue = __constant_cpu_to_le16 (0);
-		event->wIndex = __constant_cpu_to_le16 (1);
-		event->wLength = __constant_cpu_to_le16 (8);
-
-		/* SPEED_CHANGE data is up/down speeds in bits/sec */
-		event->data [0] = event->data [1] =
-			(dev->gadget->speed == USB_SPEED_HIGH)
-				? (13 * 512 * 8 * 1000 * 8)
-				: (19 *  64 * 1 * 1000 * 8);
-
-		req->length = 16;
-		value = usb_ep_queue (ep, req, GFP_ATOMIC);
-		DEBUG (dev, "send SPEED_CHANGE --> %d\n", value);
-		if (value == 0)
-			return;
-	} else
-		DEBUG (dev, "event %02x --> %d\n",
-			event->bNotificationType, value);
-
-	/* free when done */
-	usb_ep_free_buffer (ep, req->buf, req->dma, 16);
-	usb_ep_free_request (ep, req);
-}
-
-static void issue_start_status (struct eth_dev *dev)
-{
-	struct usb_request	*req;
-	struct cdc_notification	*event;
-	int			value;
- 
-	DEBUG (dev, "%s, flush old status first\n", __FUNCTION__);
-
-	usb_ep_disable (dev->status_ep);
-	usb_ep_enable (dev->status_ep, dev->status);
-
-	req = usb_ep_alloc_request (dev->status_ep, GFP_ATOMIC);
-	if (req == 0) {
-		DEBUG (dev, "status ENOMEM\n");
-		return;
-	}
-	req->buf = usb_ep_alloc_buffer (dev->status_ep, 16,
-				&dev->req->dma, GFP_ATOMIC);
-	if (req->buf == 0) {
-		DEBUG (dev, "status buf ENOMEM\n");
-free_req:
-		usb_ep_free_request (dev->status_ep, req);
-		return;
-	}
-
-	/* 3.8.1 says to issue first NETWORK_CONNECTION, then
-	 * a SPEED_CHANGE.  could be useful in some configs.
-	 */
-	event = req->buf;
-	event->bmRequestType = 0xA1;
-	event->bNotificationType = CDC_NOTIFY_NETWORK_CONNECTION;
-	event->wValue = __constant_cpu_to_le16 (1);	/* connected */
-	event->wIndex = __constant_cpu_to_le16 (1);
-	event->wLength = 0;
-
-	req->length = 8;
-	req->complete = eth_status_complete;
-	value = usb_ep_queue (dev->status_ep, req, GFP_ATOMIC);
-	if (value < 0) {
-		DEBUG (dev, "status buf queue --> %d\n", value);
-		usb_ep_free_buffer (dev->status_ep,
-				req->buf, dev->req->dma, 16);
-		goto free_req;
-	}
-}
-
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-static void eth_setup_complete (struct usb_ep *ep, struct usb_request *req)
-{
-	if (req->status || req->actual != req->length)
-		DEBUG ((struct eth_dev *) ep->driver_data,
-				"setup complete --> %d, %d/%d\n",
-				req->status, req->actual, req->length);
-}
-
-/* see section 3.8.2 table 10 of the CDC spec for more ethernet
- * requests, mostly for filters (multicast, pm) and statistics
- */
-#define CDC_SET_ETHERNET_PACKET_FILTER	0x43	/* required */
-
-/*
- * The setup() callback implements all the ep0 functionality that's not
- * handled lower down.  CDC has a number of less-common features:
- *
- *  - two interfaces:  control, and ethernet data
- *  - data interface has two altsettings:  default, and active
- *  - class-specific descriptors for the control interface
- *  - a mandatory class-specific control request
- */
-static int
-eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
-{
-	struct eth_dev		*dev = get_gadget_data (gadget);
-	struct usb_request	*req = dev->req;
-	int			value = -EOPNOTSUPP;
-
-	/* descriptors just go into the pre-allocated ep0 buffer,
-	 * while config change events may enable network traffic.
-	 */
-	switch (ctrl->bRequest) {
-
-	case USB_REQ_GET_DESCRIPTOR:
-		if (ctrl->bRequestType != USB_DIR_IN)
-			break;
-		switch (ctrl->wValue >> 8) {
-
-		case USB_DT_DEVICE:
-			value = min (ctrl->wLength, (u16) sizeof device_desc);
-			memcpy (req->buf, &device_desc, value);
-			break;
-#ifdef HIGHSPEED
-		case USB_DT_DEVICE_QUALIFIER:
-			value = min (ctrl->wLength, (u16) sizeof dev_qualifier);
-			memcpy (req->buf, &dev_qualifier, value);
-			break;
-
-		case USB_DT_OTHER_SPEED_CONFIG:
-			// FALLTHROUGH
-#endif /* HIGHSPEED */
-		case USB_DT_CONFIG:
-			value = config_buf (gadget->speed, req->buf,
-					ctrl->wValue >> 8,
-					ctrl->wValue & 0xff);
-			if (value >= 0)
-				value = min (ctrl->wLength, (u16) value);
-			break;
-
-		case USB_DT_STRING:
-			value = usb_gadget_get_string (&stringtab,
-					ctrl->wValue & 0xff, req->buf);
-			if (value >= 0)
-				value = min (ctrl->wLength, (u16) value);
-			break;
-		}
-		break;
-
-	case USB_REQ_SET_CONFIGURATION:
-		if (ctrl->bRequestType != 0)
-			break;
-		spin_lock (&dev->lock);
-		value = eth_set_config (dev, ctrl->wValue, GFP_ATOMIC);
-		spin_unlock (&dev->lock);
-		break;
-#ifdef	CONFIG_USB_ETH_PXA2XX
-	/* PXA UDC prevents us from using SET_INTERFACE in normal ways.
-	 * And it hides GET_CONFIGURATION and GET_INTERFACE too.
-	 */
-	case USB_REQ_SET_INTERFACE:
-		spin_lock (&dev->lock);
-		value = eth_set_config (dev, DEV_CONFIG_VALUE, GFP_ATOMIC);
-		spin_unlock (&dev->lock);
-		break;
-
-#else	/* hardware that that stays out of our way */
-	case USB_REQ_GET_CONFIGURATION:
-		if (ctrl->bRequestType != USB_DIR_IN)
-			break;
-		*(u8 *)req->buf = dev->config;
-		value = min (ctrl->wLength, (u16) 1);
-		break;
-
-	case USB_REQ_SET_INTERFACE:
-		if (ctrl->bRequestType != USB_RECIP_INTERFACE
-				|| !dev->config
-				|| ctrl->wIndex > 1)
-			break;
-		spin_lock (&dev->lock);
-		switch (ctrl->wIndex) {
-		case 0:		/* control/master intf */
-			if (ctrl->wValue != 0)
-				break;
-#ifdef	EP_STATUS_NUM
-			if (dev->status_ep) {
-				usb_ep_disable (dev->status_ep);
-				usb_ep_enable (dev->status_ep, dev->status);
-			}
-#endif
-			value = 0;
-			break;
-		case 1:		/* data intf */
-			if (ctrl->wValue > 1)
-				break;
-			usb_ep_disable (dev->in_ep);
-			usb_ep_disable (dev->out_ep);
-
-			/* CDC requires the data transfers not be done from
-			 * the default interface setting ... also, setting
-			 * the non-default interface clears filters etc.
-			 */
-			if (ctrl->wValue == 1) {
-				usb_ep_enable (dev->in_ep, dev->in);
-				usb_ep_enable (dev->out_ep, dev->out);
-				netif_carrier_on (dev->net);
-#ifdef	EP_STATUS_NUM
-				issue_start_status (dev);
-#endif
-				if (netif_running (dev->net))
-					eth_start (dev, GFP_ATOMIC);
-			} else {
-				netif_stop_queue (dev->net);
-				netif_carrier_off (dev->net);
-			}
-			value = 0;
-			break;
-		}
-		spin_unlock (&dev->lock);
-		break;
-	case USB_REQ_GET_INTERFACE:
-		if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)
-				|| !dev->config
-				|| ctrl->wIndex > 1)
-			break;
-
-		/* if carrier is on, data interface is active. */
-		*(u8 *)req->buf =
-			((ctrl->wIndex == 1) && netif_carrier_ok (dev->net))
-				? 1
-				: 0,
-		value = min (ctrl->wLength, (u16) 1);
-		break;
-#endif
-
-#ifdef DEV_CONFIG_CDC
-	case CDC_SET_ETHERNET_PACKET_FILTER:
-		/* see 6.2.30: no data, wIndex = interface,
-		 * wValue = packet filter bitmap
-		 */
-		if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE)
-				|| ctrl->wLength != 0
-				|| ctrl->wIndex > 1)
-		DEBUG (dev, "NOP packet filter %04x\n", ctrl->wValue);
-		/* NOTE: table 62 has 5 filter bits to reduce traffic,
-		 * and we "must" support multicast and promiscuous.
-		 * this NOP implements a bad filter...
-		 */
-		value = 0;
-		break;
-#endif /* DEV_CONFIG_CDC */
-
-	default:
-		VDEBUG (dev,
-			"unknown control req%02x.%02x v%04x i%04x l%d\n",
-			ctrl->bRequestType, ctrl->bRequest,
-			ctrl->wValue, ctrl->wIndex, ctrl->wLength);
-	}
-
-	/* respond with data transfer before status phase? */
-	if (value >= 0) {
-		req->length = value;
-		value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
-		if (value < 0) {
-			DEBUG (dev, "ep_queue --> %d\n", value);
-			req->status = 0;
-			eth_setup_complete (gadget->ep0, req);
-		}
-	}
-
-	/* host either stalls (value < 0) or reports success */
-	return value;
-}
-
-static void
-eth_disconnect (struct usb_gadget *gadget)
-{
-	struct eth_dev		*dev = get_gadget_data (gadget);
-	unsigned long		flags;
-
-	spin_lock_irqsave (&dev->lock, flags);
-	netif_stop_queue (dev->net);
-	netif_carrier_off (dev->net);
-	eth_reset_config (dev);
-	spin_unlock_irqrestore (&dev->lock, flags);
-
-	/* next we may get setup() calls to enumerate new connections;
-	 * or an unbind() during shutdown (including removing module).
-	 */
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* NETWORK DRIVER HOOKUP (to the layer above this driver) */
-
-static int eth_change_mtu (struct net_device *net, int new_mtu)
-{
-	struct eth_dev	*dev = (struct eth_dev *) net->priv;
-
-	if (new_mtu <= MIN_PACKET || new_mtu > MAX_PACKET)
-		return -ERANGE;
-	/* no zero-length packet read wanted after mtu-sized packets */
-	if (((new_mtu + sizeof (struct ethhdr)) % dev->in_ep->maxpacket) == 0)
-		return -EDOM;
-	net->mtu = new_mtu;
-	return 0;
-}
-
-static struct net_device_stats *eth_get_stats (struct net_device *net)
-{
-	return &((struct eth_dev *) net->priv)->stats;
-}
-
-static int eth_ethtool_ioctl (struct net_device *net, void *useraddr)
-{
-	struct eth_dev	*dev = (struct eth_dev *) net->priv;
-	u32		cmd;
-
-	if (get_user (cmd, (u32 *)useraddr))
-		return -EFAULT;
-	switch (cmd) {
-
-	case ETHTOOL_GDRVINFO: {	/* get driver info */
-		struct ethtool_drvinfo		info;
-
-		memset (&info, 0, sizeof info);
-		info.cmd = ETHTOOL_GDRVINFO;
-		strncpy (info.driver, shortname, sizeof info.driver);
-		strncpy (info.version, DRIVER_VERSION, sizeof info.version);
-		strncpy (info.fw_version, CHIP, sizeof info.fw_version);
-		strncpy (info.bus_info, dev->gadget->dev.bus_id,
-			sizeof info.bus_info);
-		if (copy_to_user (useraddr, &info, sizeof (info)))
-			return -EFAULT;
-		return 0;
-		}
-
-	case ETHTOOL_GLINK: {		/* get link status */
-		struct ethtool_value	edata = { ETHTOOL_GLINK };
-
-		edata.data = (dev->gadget->speed != USB_SPEED_UNKNOWN);
-		if (copy_to_user (useraddr, &edata, sizeof (edata)))
-			return -EFAULT;
-		return 0;
-		}
-
-	}
-	/* Note that the ethtool user space code requires EOPNOTSUPP */
-	return -EOPNOTSUPP;
-}
-
-static int eth_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
-{
-	switch (cmd) {
-	case SIOCETHTOOL:
-		return eth_ethtool_ioctl (net, (void *)rq->ifr_data);
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-static void defer_kevent (struct eth_dev *dev, int flag)
-{
-	if (test_and_set_bit (flag, &dev->todo))
-		return;
-	if (!schedule_work (&dev->work))
-		ERROR (dev, "kevent %d may have been dropped\n", flag);
-	else
-		DEBUG (dev, "kevent %d scheduled\n", flag);
-}
-
-static void rx_complete (struct usb_ep *ep, struct usb_request *req);
-
-static int
-rx_submit (struct eth_dev *dev, struct usb_request *req, int gfp_flags)
-{
-	struct sk_buff		*skb;
-	int			retval = 0;
-	size_t			size;
-
-	size = (sizeof (struct ethhdr) + dev->net->mtu + RX_EXTRA);
-
-	if ((skb = alloc_skb (size, gfp_flags)) == 0) {
-		DEBUG (dev, "no rx skb\n");
-		defer_kevent (dev, WORK_RX_MEMORY);
-		list_add (&req->list, &dev->rx_reqs);
-		return -ENOMEM;
-	}
-
-	req->buf = skb->data;
-	req->length = size;
-	req->complete = rx_complete;
-	req->context = skb;
-
-	retval = usb_ep_queue (dev->out_ep, req, gfp_flags);
-	if (retval == -ENOMEM)
-		defer_kevent (dev, WORK_RX_MEMORY);
-	if (retval) {
-		DEBUG (dev, "rx submit --> %d\n", retval);
-		dev_kfree_skb_any (skb);
-		list_add (&req->list, &dev->rx_reqs);
-	}
-	return retval;
-}
-
-static void rx_complete (struct usb_ep *ep, struct usb_request *req)
-{
-	struct sk_buff	*skb = req->context;
-	struct eth_dev	*dev = ep->driver_data;
-	int		status = req->status;
-
-	switch (status) {
-
-	/* normal completion */
-	case 0:
-		skb_put (skb, req->actual);
-		if (MIN_PACKET > skb->len
-				|| skb->len > (MAX_PACKET + ETH_HLEN)) {
-			dev->stats.rx_errors++;
-			dev->stats.rx_length_errors++;
-			DEBUG (dev, "rx length %d\n", skb->len);
-			break;
-		}
-
-		skb->dev = dev->net;
-		skb->protocol = eth_type_trans (skb, dev->net);
-		dev->stats.rx_packets++;
-		dev->stats.rx_bytes += skb->len;
-
-		/* no buffer copies needed, unless hardware can't
-		 * use skb buffers.
-		 */
-		status = netif_rx (skb);
-		skb = 0;
-		break;
-
-	/* software-driven interface shutdown */
-	case -ECONNRESET:		// unlink
-	case -ESHUTDOWN:		// disconnect etc
-		VDEBUG (dev, "rx shutdown, code %d\n", status);
-		goto quiesce;
-
-	/* for hardware automagic (such as pxa) */
-	case -ECONNABORTED:		// endpoint reset
-		DEBUG (dev, "rx %s reset\n", ep->name);
-		defer_kevent (dev, WORK_RX_MEMORY);
-quiesce:
-		dev_kfree_skb_any (skb);
-		goto clean;
-
-	/* data overrun */
-	case -EOVERFLOW:
-		dev->stats.rx_over_errors++;
-		// FALLTHROUGH
-	    
-	default:
-		dev->stats.rx_errors++;
-		DEBUG (dev, "rx status %d\n", status);
-		break;
-	}
-
-	if (skb)
-		dev_kfree_skb_any (skb);
-	if (!netif_running (dev->net)) {
-clean:
-		list_add (&req->list, &dev->rx_reqs);
-		req = 0;
-	}
-	if (req)
-		rx_submit (dev, req, GFP_ATOMIC);
-}
-
-static int prealloc (struct list_head *list, struct usb_ep *ep,
-			unsigned n, int gfp_flags)
-{
-	unsigned		i;
-	struct usb_request	*req;
-
-	/* we want the list to have N requests */
-	i = n;
-	list_for_each_entry (req, list, list) {
-		if (i-- == 0)
-			goto extra;
-	}
-	while (i--) {
-		req = usb_ep_alloc_request (ep, gfp_flags);
-		if (!req)
-			return -ENOMEM;
-		list_add (&req->list, list);
-	}
-	return 0;
-
-extra:
-	/* free extras */
-	for (;;) {
-		struct list_head	*next;
-
-		next = req->list.next;
-		list_del (&req->list);
-		usb_ep_free_request (ep, req);
-
-		if (next == list)
-			break;
-
-		req = container_of (next, struct usb_request, list);
-	}
-	return 0;
-}
-
-static int alloc_requests (struct eth_dev *dev, unsigned n, int gfp_flags)
-{
-	int status;
-
-	status = prealloc (&dev->tx_reqs, dev->in_ep, n, gfp_flags);
-	if (status < 0)
-		goto fail;
-	status = prealloc (&dev->rx_reqs, dev->out_ep, n, gfp_flags);
-	if (status < 0)
-		goto fail;
-	return 0;
-fail:
-	DEBUG (dev, "can't alloc requests\n");
-	return status;
-}
-
-static void rx_fill (struct eth_dev *dev, int gfp_flags)
-{
-	struct usb_request	*req;
-
-	/* fill unused rxq slots with some skb */
-	while (!list_empty (&dev->rx_reqs)) {
-		req = container_of (dev->rx_reqs.next,
-				struct usb_request, list);
-		list_del_init (&req->list);
-		if (rx_submit (dev, req, gfp_flags) < 0)
-			return;
-	}
-	clear_bit (WORK_RX_MEMORY, &dev->todo);
-}
-
-static void eth_work (void *_dev)
-{
-	struct eth_dev		*dev = _dev;
-
-	if (test_bit (WORK_RX_MEMORY, &dev->todo)) {
-		if (netif_running (dev->net))
-			rx_fill (dev, GFP_KERNEL);
-		else
-			clear_bit (WORK_RX_MEMORY, &dev->todo);
-	}
-
-	if (dev->todo)
-		DEBUG (dev, "work done, flags = 0x%lx\n", dev->todo);
-}
-
-static void tx_complete (struct usb_ep *ep, struct usb_request *req)
-{
-	struct sk_buff	*skb = req->context;
-	struct eth_dev	*dev = ep->driver_data;
-
-	switch (req->status) {
-	default:
-		dev->stats.tx_errors++;
-		VDEBUG (dev, "tx err %d\n", req->status);
-		/* FALLTHROUGH */
-	case -ECONNRESET:		// unlink
-	case -ESHUTDOWN:		// disconnect etc
-		break;
-	case 0:
-		dev->stats.tx_bytes += skb->len;
-	}
-	dev->stats.tx_packets++;
-
-	list_add (&req->list, &dev->tx_reqs);
-	dev_kfree_skb_any (skb);
-
-	atomic_dec (&dev->tx_qlen);
-	if (netif_carrier_ok (dev->net))
-		netif_wake_queue (dev->net);
-}
-
-static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
-{
-	struct eth_dev		*dev = (struct eth_dev *) net->priv;
-	int			length = skb->len;
-	int			retval;
-	struct usb_request	*req = 0;
-
-	req = container_of (dev->tx_reqs.next, struct usb_request, list);
-	list_del (&req->list);
-	if (list_empty (&dev->tx_reqs))
-		netif_stop_queue (net);
-
-	/* no buffer copies needed, unless the network stack did it
-	 * or the hardware can't use skb buffers.
-	 */
-	req->buf = skb->data;
-	req->context = skb;
-	req->complete = tx_complete;
-
-#ifdef	CONFIG_USB_ETH_SA1100
-	/* don't demand zlp (req->zero) support from all hardware */
-	if ((length % dev->in_ep->maxpacket) == 0)
-		length++;
-#else
-	/* use zlp framing on tx for strict CDC-Ether conformance,
-	 * though any robust network rx path ignores extra padding.
-	 */
-	req->zero = 1;
-#endif
-	req->length = length;
-
-#ifdef	HIGHSPEED
-	/* throttle highspeed IRQ rate back slightly */
-	req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH)
-		? ((atomic_read (&dev->tx_qlen) % TX_DELAY) != 0)
-		: 0;
-#endif
-
-	retval = usb_ep_queue (dev->in_ep, req, GFP_ATOMIC);
-	switch (retval) {
-	default:
-		DEBUG (dev, "tx queue err %d\n", retval);
-		break;
-	case 0:
-		net->trans_start = jiffies;
-		atomic_inc (&dev->tx_qlen);
-	}
-
-	if (retval) {
-		dev->stats.tx_dropped++;
-		dev_kfree_skb_any (skb);
-		if (list_empty (&dev->tx_reqs))
-			netif_start_queue (net);
-		list_add (&req->list, &dev->tx_reqs);
-	}
-	return 0;
-}
-
-static void eth_start (struct eth_dev *dev, int gfp_flags)
-{
-	rx_fill (dev, gfp_flags);
-
-	/* and open the tx floodgates */ 
-	atomic_set (&dev->tx_qlen, 0);
-	netif_wake_queue (dev->net);
-}
-
-static int eth_open (struct net_device *net)
-{
-	struct eth_dev		*dev = (struct eth_dev *) net->priv;
-
-	DEBUG (dev, "%s\n", __FUNCTION__);
-	if (netif_carrier_ok (dev->net))
-		eth_start (dev, GFP_KERNEL);
-	return 0;
-}
-
-static int eth_stop (struct net_device *net)
-{
-	struct eth_dev		*dev = (struct eth_dev *) net->priv;
-
-	DEBUG (dev, "%s\n", __FUNCTION__);
-	netif_stop_queue (net);
-
-	DEBUG (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n",
-		dev->stats.rx_packets, dev->stats.tx_packets, 
-		dev->stats.rx_errors, dev->stats.tx_errors
-		);
-
-	/* ensure there are no more active requests */
-	if (dev->gadget->speed != USB_SPEED_UNKNOWN) {
-		usb_ep_disable (dev->in_ep);
-		usb_ep_disable (dev->out_ep);
-		if (netif_carrier_ok (dev->net)) {
-			DEBUG (dev, "host still using in/out endpoints\n");
-			usb_ep_enable (dev->in_ep, dev->in);
-			usb_ep_enable (dev->out_ep, dev->out);
-		}
-#ifdef	EP_STATUS_NUM
-		usb_ep_disable (dev->status_ep);
-		usb_ep_enable (dev->status_ep, dev->status);
-#endif
-	}
-
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void
-eth_unbind (struct usb_gadget *gadget)
-{
-	struct eth_dev		*dev = get_gadget_data (gadget);
-	struct usb_request	*req;
-
-	DEBUG (dev, "unbind\n");
-
-	/* we've already been disconnected ... no i/o is active */
-	if (dev->req) {
-		usb_ep_free_buffer (gadget->ep0,
-				dev->req->buf, dev->req->dma,
-				USB_BUFSIZ);
-		usb_ep_free_request (gadget->ep0, dev->req);
-		dev->req = 0;
-	}
-
-	while (!list_empty (&dev->tx_reqs)) {
-		req = container_of (dev->tx_reqs.next,
-					struct usb_request, list);
-		list_del (&req->list);
-		usb_ep_free_request (dev->in_ep, req);
-	}
-	while (!list_empty (&dev->rx_reqs)) {
-		req = container_of (dev->rx_reqs.next,
-					struct usb_request, list);
-		list_del (&req->list);
-		usb_ep_free_request (dev->out_ep, req);
-	}
-
-	unregister_netdev (dev->net);
-	dev_put (dev->net);
-
-	/* assuming we used keventd, it must quiesce too */
-	flush_scheduled_work ();
-	set_gadget_data (gadget, 0);
-}
-
-static int
-eth_bind (struct usb_gadget *gadget)
-{
-	struct eth_dev		*dev;
-	struct net_device	*net;
-	int			status = -ENOMEM;
-#ifdef	DEV_CONFIG_CDC
-	u8			node_id [ETH_ALEN];
-
-	/* just one upstream link at a time */
-	if (ethaddr [0] != 0)
-		return -ENODEV;
-#endif
-
- 	net = alloc_etherdev (sizeof *dev);
- 	if (!net)
-		return status;
-	dev = net->priv;
-	spin_lock_init (&dev->lock);
-	INIT_WORK (&dev->work, eth_work, dev);
-	INIT_LIST_HEAD (&dev->tx_reqs);
-	INIT_LIST_HEAD (&dev->rx_reqs);
-
-	/* network device setup */
-	dev->net = net;
-	SET_MODULE_OWNER (net);
-	net->priv = dev;
-	strcpy (net->name, "usb%d");
-	ether_setup (net);
-
-	/* one random address for the gadget device ... both of these could
-	 * reasonably come from an id prom or a module parameter.
-	 */
-	get_random_bytes (net->dev_addr, ETH_ALEN);
-	net->dev_addr [0] &= 0xfe;	// clear multicast bit
-	net->dev_addr [0] |= 0x02;	// set local assignment bit (IEEE802)
-
-#ifdef	DEV_CONFIG_CDC
-	/* ... another address for the host, on the other end of the
-	 * link, gets exported through CDC (see CDC spec table 41)
-	 */
-	get_random_bytes (node_id, sizeof node_id);
-	node_id [0] &= 0xfe;	// clear multicast bit
-	node_id [0] |= 0x02;    // set local assignment bit (IEEE802)
-	snprintf (ethaddr, sizeof ethaddr, "%02X%02X%02X%02X%02X%02X",
-		node_id [0], node_id [1], node_id [2],
-		node_id [3], node_id [4], node_id [5]);
-#endif
-
-	net->change_mtu = eth_change_mtu;
-	net->get_stats = eth_get_stats;
-	net->hard_start_xmit = eth_start_xmit;
-	net->open = eth_open;
-	net->stop = eth_stop;
-	// watchdog_timeo, tx_timeout ...
-	// set_multicast_list
-	net->do_ioctl = eth_ioctl;
-
-	/* preallocate control response and buffer */
-	dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);
-	if (!dev->req)
-		goto fail;
-	dev->req->complete = eth_setup_complete;
-	dev->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ,
-				&dev->req->dma, GFP_KERNEL);
-	if (!dev->req->buf) {
-		usb_ep_free_request (gadget->ep0, dev->req);
-		goto fail;
-	}
-
-	/* finish hookup to lower layer ... */
-	dev->gadget = gadget;
-	set_gadget_data (gadget, dev);
-	gadget->ep0->driver_data = dev;
-	INFO (dev, "%s, " CHIP ", version: " DRIVER_VERSION "\n", driver_desc);
-#ifdef	DEV_CONFIG_CDC
-	INFO (dev, "CDC host enet %s\n", ethaddr);
-#endif
-	
-	/* two kinds of host-initiated state changes:
-	 *  - iff DATA transfer is active, carrier is "on"
-	 *  - tx queueing enabled if open *and* carrier is "on"
-	 */
-	netif_stop_queue (dev->net);
-	netif_carrier_off (dev->net);
-
- 	// SET_NETDEV_DEV (dev->net, &gadget->dev);
- 	status = register_netdev (dev->net);
- 	if (status == 0)
- 		return status;
-fail:
-	eth_unbind (gadget);
-	return status;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static struct usb_gadget_driver eth_driver = {
-#ifdef HIGHSPEED
-	.speed		= USB_SPEED_HIGH,
-#else
-	.speed		= USB_SPEED_FULL,
-#endif
-	.function	= (char *) driver_desc,
-	.bind		= eth_bind,
-	.unbind		= eth_unbind,
-
-	.setup		= eth_setup,
-	.disconnect	= eth_disconnect,
-
-	.driver 	= {
-		.name		= (char *) shortname,
-		// .shutdown = ...
-		// .suspend = ...
-		// .resume = ...
-	},
-};
-
-MODULE_DESCRIPTION (DRIVER_DESC);
-MODULE_AUTHOR ("David Brownell");
-MODULE_LICENSE ("GPL");
-
-
-static int __init init (void)
-{
-	return usb_gadget_register_driver (&eth_driver);
-}
-module_init (init);
-
-static void __exit cleanup (void)
-{
-	usb_gadget_unregister_driver (&eth_driver);
-}
-module_exit (cleanup);
-
diff -ruN linux-2.4.20-WRTup/drivers/usb/gadget/file_storage.c linux-2.4.20-WRTstp/drivers/usb/gadget/file_storage.c
--- linux-2.4.20-WRTup/drivers/usb/gadget/file_storage.c	2006-06-12 18:04:59.000000000 -0700
+++ linux-2.4.20-WRTstp/drivers/usb/gadget/file_storage.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,4047 +0,0 @@
-/*
- * file_storage.c -- File-backed USB Storage Gadget, for USB development
- *
- * Copyright (C) 2003 Alan Stern
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The names of the above-listed copyright holders may not be used
- *    to endorse or promote products derived from this software without
- *    specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-/*
- * The File-backed Storage Gadget acts as a USB Mass Storage device,
- * appearing to the host as a disk drive.  In addition to providing an
- * example of a genuinely useful gadget driver for a USB device, it also
- * illustrates a technique of double-buffering for increased throughput.
- * Last but not least, it gives an easy way to probe the behavior of the
- * Mass Storage drivers in a USB host.
- *
- * Backing storage is provided by a regular file or a block device, specified
- * by the "file" module parameter.  Access can be limited to read-only by
- * setting the optional "ro" module parameter.
- *
- * The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI),
- * and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected
- * by the optional "transport" module parameter.  It also supports the
- * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03),
- * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by
- * the optional "protocol" module parameter.  For testing purposes the
- * gadget will indicate that it has removable media if the optional
- * "removable" module parameter is set.  In addition, the default Vendor ID,
- * Product ID, and release number can be overridden.
- *
- * There is support for multiple logical units (LUNs), each of which has
- * its own backing file.  The number of LUNs can be set using the optional
- * "luns" module parameter (anywhere from 1 to 8), and the corresponding
- * files are specified using comma-separated lists for "file" and "ro".
- * The default number of LUNs is taken from the number of "file" elements;
- * it is 1 if "file" is not given.  If "removable" is not set then a backing
- * file must be specified for each LUN.  If it is set, then an unspecified
- * or empty backing filename means the LUN's medium is not loaded.
- *
- * Requirements are modest; only a bulk-in and a bulk-out endpoint are
- * needed (an interrupt-out endpoint is also needed for CBI).  The memory
- * requirement amounts to two 16K buffers, size configurable by a parameter.
- * Support is included for both full-speed and high-speed operation.
- *
- * Module options:
- *
- *	file=filename[,filename...]
- *				Required if "removable" is not set, names of
- *					the files or block devices used for
- *					backing storage
- *	ro=b[,b...]		Default false, booleans for read-only access
- *	luns=N			Default N = number of filenames, number of
- *					LUNs to support
- *	transport=XXX		Default BBB, transport name (CB, CBI, or BBB)
- *	protocol=YYY		Default SCSI, protocol name (RBC, 8020 or
- *					ATAPI, QIC, UFI, 8070, or SCSI;
- *					also 1 - 6)
- *	removable		Default false, boolean for removable media
- *	vendor=0xVVVV		Default 0x0525 (NetChip), USB Vendor ID
- *	product=0xPPPP		Default 0xa4a5 (FSG), USB Product ID
- *	release=0xRRRR		Override the USB release number (bcdDevice)
- *	buflen=N		Default N=16384, buffer size used (will be
- *					rounded down to a multiple of
- *					PAGE_CACHE_SIZE)
- *	stall			Default determined according to the type of
- *					USB device controller (usually true),
- *					boolean to permit the driver to halt
- *					bulk endpoints
- *
- * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file" and "ro"
- * options are available; default values are used for everything else.
- *
- * This gadget driver is heavily based on "Gadget Zero" by David Brownell.
- */
-
-
-/*
- *				Driver Design
- *
- * The FSG driver is fairly straightforward.  There is a main kernel
- * thread that handles most of the work.  Interrupt routines field
- * callbacks from the controller driver: bulk- and interrupt-request
- * completion notifications, endpoint-0 events, and disconnect events.
- * Completion events are passed to the main thread by wakeup calls.  Many
- * ep0 requests are handled at interrupt time, but SetInterface,
- * SetConfiguration, and device reset requests are forwarded to the
- * thread in the form of "exceptions" using SIGUSR1 signals (since they
- * should interrupt any ongoing file I/O operations).
- *
- * The thread's main routine implements the standard command/data/status
- * parts of a SCSI interaction.  It and its subroutines are full of tests
- * for pending signals/exceptions -- all this polling is necessary since
- * the kernel has no setjmp/longjmp equivalents.  (Maybe this is an
- * indication that the driver really wants to be running in userspace.)
- * An important point is that so long as the thread is alive it keeps an
- * open reference to the backing file.  This will prevent unmounting
- * the backing file's underlying filesystem and could cause problems
- * during system shutdown, for example.  To prevent such problems, the
- * thread catches INT, TERM, and KILL signals and converts them into
- * an EXIT exception.
- *
- * In normal operation the main thread is started during the gadget's
- * fsg_bind() callback and stopped during fsg_unbind().  But it can also
- * exit when it receives a signal, and there's no point leaving the
- * gadget running when the thread is dead.  So just before the thread
- * exits, it deregisters the gadget driver.  This makes things a little
- * tricky: The driver is deregistered at two places, and the exiting
- * thread can indirectly call fsg_unbind() which in turn can tell the
- * thread to exit.  The first problem is resolved through the use of the
- * REGISTERED atomic bitflag; the driver will only be deregistered once.
- * The second problem is resolved by having fsg_unbind() check
- * fsg->state; it won't try to stop the thread if the state is already
- * FSG_STATE_TERMINATED.
- *
- * To provide maximum throughput, the driver uses a circular pipeline of
- * buffer heads (struct fsg_buffhd).  In principle the pipeline can be
- * arbitrarily long; in practice the benefits don't justify having more
- * than 2 stages (i.e., double buffering).  But it helps to think of the
- * pipeline as being a long one.  Each buffer head contains a bulk-in and
- * a bulk-out request pointer (since the buffer can be used for both
- * output and input -- directions always are given from the host's
- * point of view) as well as a pointer to the buffer and various state
- * variables.
- *
- * Use of the pipeline follows a simple protocol.  There is a variable
- * (fsg->next_buffhd_to_fill) that points to the next buffer head to use.
- * At any time that buffer head may still be in use from an earlier
- * request, so each buffer head has a state variable indicating whether
- * it is EMPTY, FULL, or BUSY.  Typical use involves waiting for the
- * buffer head to be EMPTY, filling the buffer either by file I/O or by
- * USB I/O (during which the buffer head is BUSY), and marking the buffer
- * head FULL when the I/O is complete.  Then the buffer will be emptied
- * (again possibly by USB I/O, during which it is marked BUSY) and
- * finally marked EMPTY again (possibly by a completion routine).
- *
- * A module parameter tells the driver to avoid stalling the bulk
- * endpoints wherever the transport specification allows.  This is
- * necessary for some UDCs like the SuperH, which cannot reliably clear a
- * halt on a bulk endpoint.  However, under certain circumstances the
- * Bulk-only specification requires a stall.  In such cases the driver
- * will halt the endpoint and set a flag indicating that it should clear
- * the halt in software during the next device reset.  Hopefully this
- * will permit everything to work correctly.
- *
- * One subtle point concerns sending status-stage responses for ep0
- * requests.  Some of these requests, such as device reset, can involve
- * interrupting an ongoing file I/O operation, which might take an
- * arbitrarily long time.  During that delay the host might give up on
- * the original ep0 request and issue a new one.  When that happens the
- * driver should not notify the host about completion of the original
- * request, as the host will no longer be waiting for it.  So the driver
- * assigns to each ep0 request a unique tag, and it keeps track of the
- * tag value of the request associated with a long-running exception
- * (device-reset, interface-change, or configuration-change).  When the
- * exception handler is finished, the status-stage response is submitted
- * only if the current ep0 request tag is equal to the exception request
- * tag.  Thus only the most recently received ep0 request will get a
- * status-stage response.
- *
- * Warning: This driver source file is too long.  It ought to be split up
- * into a header file plus about 3 separate .c files, to handle the details
- * of the Gadget, USB Mass Storage, and SCSI protocols.
- */
-
-
-#undef DEBUG
-#undef VERBOSE
-#undef DUMP_MSGS
-
-#include <linux/config.h>
-
-#include <asm/system.h>
-#include <asm/uaccess.h>
-
-#include <linux/bitops.h>
-#include <linux/blkdev.h>
-#include <linux/compiler.h>
-#include <linux/completion.h>
-#include <linux/dcache.h>
-#include <linux/fcntl.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/limits.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/pagemap.h>
-#include <linux/rwsem.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-#include <linux/uts.h>
-#include <linux/version.h>
-#include <linux/wait.h>
-
-#include <linux/usb_ch9.h>
-#include <linux/usb_gadget.h>
-
-
-/*-------------------------------------------------------------------------*/
-
-#define DRIVER_DESC		"File-backed Storage Gadget"
-#define DRIVER_NAME		"g_file_storage"
-#define DRIVER_VERSION		"14 January 2004"
-
-static const char longname[] = DRIVER_DESC;
-static const char shortname[] = DRIVER_NAME;
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR("Alan Stern");
-MODULE_LICENSE("Dual BSD/GPL");
-
-/* Thanks to NetChip Technologies for donating this product ID.
- *
- * DO NOT REUSE THESE IDs with any other driver!!  Ever!!
- * Instead:  allocate your own, using normal USB-IF procedures. */
-#define DRIVER_VENDOR_ID	0x0525	// NetChip
-#define DRIVER_PRODUCT_ID	0xa4a5	// Linux-USB File-backed Storage Gadget
-
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * Hardware-specific configuration, controlled by which device
- * controller driver was configured.
- *
- * CHIP ... hardware identifier
- * DRIVER_VERSION_NUM ... alerts the host side driver to differences
- * EP_*_NAME ... which endpoints do we use for which purpose?
- * EP_*_NUM ... numbers for them (often limited by hardware)
- * FS_BULK_IN_MAXPACKET ... maxpacket value for full-speed bulk-in ep
- * FS_BULK_OUT_MAXPACKET ... maxpacket value for full-speed bulk-out ep
- * HIGHSPEED ... define if ep0 and descriptors need high speed support
- * MAX_USB_POWER ... define if we use other than 100 mA bus current
- * SELFPOWER ... if we can run on bus power, zero
- * NO_BULK_STALL ... bulk endpoint halts don't work well so avoid them
- */
-
-
-/*
- * NetChip 2280, PCI based.
- *
- * This has half a dozen configurable endpoints, four with dedicated
- * DMA channels to manage their FIFOs.  It supports high speed.
- * Those endpoints can be arranged in any desired configuration.
- */
-#ifdef	CONFIG_USB_GADGET_NET2280
-#define CHIP			"net2280"
-#define DRIVER_VERSION_NUM	0x0211
-static const char EP_BULK_IN_NAME[] = "ep-a";
-#define EP_BULK_IN_NUM		1
-#define FS_BULK_IN_MAXPACKET	64
-static const char EP_BULK_OUT_NAME[] = "ep-b";
-#define EP_BULK_OUT_NUM		2
-#define FS_BULK_OUT_MAXPACKET	64
-static const char EP_INTR_IN_NAME[] = "ep-e";
-#define EP_INTR_IN_NUM		5
-#define HIGHSPEED
-#endif
-
-
-/*
- * Dummy_hcd, software-based loopback controller.
- *
- * This imitates the abilities of the NetChip 2280, so we will use
- * the same configuration.
- */
-#ifdef	CONFIG_USB_GADGET_DUMMY
-#define CHIP			"dummy"
-#define DRIVER_VERSION_NUM	0x0212
-static const char EP_BULK_IN_NAME[] = "ep-a";
-#define EP_BULK_IN_NUM		1
-#define FS_BULK_IN_MAXPACKET	64
-static const char EP_BULK_OUT_NAME[] = "ep-b";
-#define EP_BULK_OUT_NUM		2
-#define FS_BULK_OUT_MAXPACKET	64
-static const char EP_INTR_IN_NAME[] = "ep-e";
-#define EP_INTR_IN_NUM		5
-#define HIGHSPEED
-#endif
-
-
-/*
- * PXA-2xx UDC:  widely used in second gen Linux-capable PDAs.
- *
- * This has fifteen fixed-function full speed endpoints, and it
- * can support all USB transfer types.
- *
- * These supports three or four configurations, with fixed numbers.
- * The hardware interprets SET_INTERFACE, net effect is that you
- * can't use altsettings or reset the interfaces independently.
- * So stick to a single interface.
- */
-#ifdef	CONFIG_USB_GADGET_PXA2XX
-#define CHIP			"pxa2xx"
-#define DRIVER_VERSION_NUM	0x0213
-static const char EP_BULK_IN_NAME[] = "ep1in-bulk";
-#define EP_BULK_IN_NUM		1
-#define FS_BULK_IN_MAXPACKET	64
-static const char EP_BULK_OUT_NAME[] = "ep2out-bulk";
-#define EP_BULK_OUT_NUM		2
-#define FS_BULK_OUT_MAXPACKET	64
-static const char EP_INTR_IN_NAME[] = "ep6in-bulk";
-#define EP_INTR_IN_NUM		6
-#endif
-
-
-/*
- * SuperH UDC:  UDC built-in to some Renesas SH processors.
- *
- * This has three fixed-function full speed bulk/interrupt endpoints.
- *
- * Only one configuration and interface is supported (SET_CONFIGURATION
- * and SET_INTERFACE are handled completely by the hardware).
- */
-#ifdef	CONFIG_USB_GADGET_SUPERH
-#define CHIP			"superh"
-#define DRIVER_VERSION_NUM	0x0215
-static const char EP_BULK_IN_NAME[] = "ep2in-bulk";
-#define EP_BULK_IN_NUM		2
-#define FS_BULK_IN_MAXPACKET	64
-static const char EP_BULK_OUT_NAME[] = "ep1out-bulk";
-#define EP_BULK_OUT_NUM		1
-#define FS_BULK_OUT_MAXPACKET	64
-static const char EP_INTR_IN_NAME[] = "ep3in-bulk";
-#define EP_INTR_IN_NUM		3
-#define NO_BULK_STALL
-#endif
-
-
-/*
- * Toshiba TC86C001 ("Goku-S") UDC
- *
- * This has three semi-configurable full speed bulk/interrupt endpoints.
- */
-#ifdef	CONFIG_USB_GADGET_GOKU
-#define CHIP			"goku"
-#define DRIVER_VERSION_NUM	0x0216
-static const char EP_BULK_OUT_NAME [] = "ep1-bulk";
-#define EP_BULK_OUT_NUM		1
-#define FS_BULK_IN_MAXPACKET	64
-static const char EP_BULK_IN_NAME [] = "ep2-bulk";
-#define EP_BULK_IN_NUM		2
-#define FS_BULK_OUT_MAXPACKET	64
-static const char EP_INTR_IN_NAME [] = "ep3-bulk";
-#define EP_INTR_IN_NUM		3
-#endif
-
-
-/*-------------------------------------------------------------------------*/
-
-#ifndef CHIP
-#	error Configure some USB peripheral controller driver!
-#endif
-
-/* Power usage is config specific.
- * Hardware that supports remote wakeup defaults to disabling it.
- */
-#ifndef	SELFPOWER
-/* default: say we're self-powered */
-#define SELFPOWER USB_CONFIG_ATT_SELFPOWER
-/* else:
- * - SELFPOWER value must be zero
- * - MAX_USB_POWER may be nonzero.
- */
-#endif
-
-#ifndef	MAX_USB_POWER
-/* Any hub supports this steady state bus power consumption */
-#define MAX_USB_POWER	100	/* mA */
-#endif
-
-/* We don't support remote wake-up */
-
-#ifdef NO_BULK_STALL
-#define CAN_STALL	0
-#else
-#define CAN_STALL	1
-#endif
-
-
-/*-------------------------------------------------------------------------*/
-
-#define fakedev_printk(level, dev, format, args...) \
-	printk(level "%s %s: " format , DRIVER_NAME , (dev)->name , ## args)
-
-#define xprintk(f,level,fmt,args...) \
-	fakedev_printk(level , (f)->gadget , fmt , ## args)
-#define yprintk(l,level,fmt,args...) \
-	fakedev_printk(level , &(l)->dev , fmt , ## args)
-
-#ifdef DEBUG
-#define DBG(fsg,fmt,args...) \
-	xprintk(fsg , KERN_DEBUG , fmt , ## args)
-#define LDBG(lun,fmt,args...) \
-	yprintk(lun , KERN_DEBUG , fmt , ## args)
-#define MDBG(fmt,args...) \
-	printk(KERN_DEBUG DRIVER_NAME ": " fmt , ## args)
-#else
-#define DBG(fsg,fmt,args...) \
-	do { } while (0)
-#define LDBG(lun,fmt,args...) \
-	do { } while (0)
-#define MDBG(fmt,args...) \
-	do { } while (0)
-#undef VERBOSE
-#undef DUMP_MSGS
-#endif /* DEBUG */
-
-#ifdef VERBOSE
-#define VDBG	DBG
-#define VLDBG	LDBG
-#else
-#define VDBG(fsg,fmt,args...) \
-	do { } while (0)
-#define VLDBG(lun,fmt,args...) \
-	do { } while (0)
-#endif /* VERBOSE */
-
-#define ERROR(fsg,fmt,args...) \
-	xprintk(fsg , KERN_ERR , fmt , ## args)
-#define LERROR(lun,fmt,args...) \
-	yprintk(lun , KERN_ERR , fmt , ## args)
-
-#define WARN(fsg,fmt,args...) \
-	xprintk(fsg , KERN_WARNING , fmt , ## args)
-#define LWARN(lun,fmt,args...) \
-	yprintk(lun , KERN_WARNING , fmt , ## args)
-
-#define INFO(fsg,fmt,args...) \
-	xprintk(fsg , KERN_INFO , fmt , ## args)
-#define LINFO(lun,fmt,args...) \
-	yprintk(lun , KERN_INFO , fmt , ## args)
-
-#define MINFO(fmt,args...) \
-	printk(KERN_INFO DRIVER_NAME ": " fmt , ## args)
-
-
-/*-------------------------------------------------------------------------*/
-
-/* Encapsulate the module parameter settings */
-
-#define MAX_LUNS	8
-
-static char		*file[MAX_LUNS] = {NULL, };
-static int		ro[MAX_LUNS] = {0, };
-static unsigned int	luns = 0;
-static char 		*transport = "BBB";
-static char 		*protocol = "SCSI";
-static int 		removable = 0;
-static unsigned short	vendor = DRIVER_VENDOR_ID;
-static unsigned short	product = DRIVER_PRODUCT_ID;
-static unsigned short	release = DRIVER_VERSION_NUM;
-static unsigned int	buflen = 16384;
-static int		stall = CAN_STALL;
-
-static struct {
-	unsigned int	nluns;
-
-	char		*transport_parm;
-	char		*protocol_parm;
-	int		removable;
-	unsigned short	vendor;
-	unsigned short	product;
-	unsigned short	release;
-	unsigned int	buflen;
-	int		can_stall;
-
-	int		transport_type;
-	char		*transport_name;
-	int		protocol_type;
-	char		*protocol_name;
-
-} mod_data;
-
-
-MODULE_PARM(file, "1-8s");
-MODULE_PARM_DESC(file, "names of backing files or devices");
-
-MODULE_PARM(ro, "1-8b");
-MODULE_PARM_DESC(ro, "true to force read-only");
-
-
-/* In the non-TEST version, only the file and ro module parameters
- * are available. */
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
-
-MODULE_PARM(luns, "i");
-MODULE_PARM_DESC(luns, "number of LUNs");
-
-MODULE_PARM(transport, "s");
-MODULE_PARM_DESC(transport, "type of transport (BBB, CBI, or CB)");
-
-MODULE_PARM(protocol, "s");
-MODULE_PARM_DESC(protocol, "type of protocol (RBC, 8020, QIC, UFI, "
-		"8070, or SCSI)");
-
-MODULE_PARM(removable, "b");
-MODULE_PARM_DESC(removable, "true to simulate removable media");
-
-MODULE_PARM(vendor, "h");
-MODULE_PARM_DESC(vendor, "USB Vendor ID");
-
-MODULE_PARM(product, "h");
-MODULE_PARM_DESC(product, "USB Product ID");
-
-MODULE_PARM(release, "h");
-MODULE_PARM_DESC(release, "USB release number");
-
-MODULE_PARM(buflen, "i");
-MODULE_PARM_DESC(buflen, "I/O buffer size");
-
-MODULE_PARM(stall, "i");
-MODULE_PARM_DESC(stall, "false to prevent bulk stalls");
-
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
-
-
-/*-------------------------------------------------------------------------*/
-
-/* USB protocol value = the transport method */
-#define USB_PR_CBI	0x00		// Control/Bulk/Interrupt
-#define USB_PR_CB	0x01		// Control/Bulk w/o interrupt
-#define USB_PR_BULK	0x50		// Bulk-only
-
-/* USB subclass value = the protocol encapsulation */
-#define USB_SC_RBC	0x01		// Reduced Block Commands (flash)
-#define USB_SC_8020	0x02		// SFF-8020i, MMC-2, ATAPI (CD-ROM)
-#define USB_SC_QIC	0x03		// QIC-157 (tape)
-#define USB_SC_UFI	0x04		// UFI (floppy)
-#define USB_SC_8070	0x05		// SFF-8070i (removable)
-#define USB_SC_SCSI	0x06		// Transparent SCSI
-
-/* Bulk-only data structures */
-
-/* Command Block Wrapper */
-struct bulk_cb_wrap {
-	u32	Signature;		// Contains 'USBC'
-	u32	Tag;			// Unique per command id
-	u32	DataTransferLength;	// Size of the data
-	u8	Flags;			// Direction in bit 7
-	u8	Lun;			// LUN (normally 0)
-	u8	Length;			// Of the CDB, <= MAX_COMMAND_SIZE
-	u8	CDB[16];		// Command Data Block
-};
-
-#define USB_BULK_CB_WRAP_LEN	31
-#define USB_BULK_CB_SIG		0x43425355	// Spells out USBC
-#define USB_BULK_IN_FLAG	0x80
-
-/* Command Status Wrapper */
-struct bulk_cs_wrap {
-	u32	Signature;		// Should = 'USBS'
-	u32	Tag;			// Same as original command
-	u32	Residue;		// Amount not transferred
-	u8	Status;			// See below
-};
-
-#define USB_BULK_CS_WRAP_LEN	13
-#define USB_BULK_CS_SIG		0x53425355	// Spells out 'USBS'
-#define USB_STATUS_PASS		0
-#define USB_STATUS_FAIL		1
-#define USB_STATUS_PHASE_ERROR	2
-
-/* Bulk-only class specific requests */
-#define USB_BULK_RESET_REQUEST		0xff
-#define USB_BULK_GET_MAX_LUN_REQUEST	0xfe
-
-
-/* CBI Interrupt data structure */
-struct interrupt_data {
-	u8	bType;
-	u8	bValue;
-};
-
-#define CBI_INTERRUPT_DATA_LEN		2
-
-/* CBI Accept Device-Specific Command request */
-#define USB_CBI_ADSC_REQUEST		0x00
-
-
-#define MAX_COMMAND_SIZE	16	// Length of a SCSI Command Data Block
-
-/* SCSI commands that we recognize */
-#define SC_FORMAT_UNIT			0x04
-#define SC_INQUIRY			0x12
-#define SC_MODE_SELECT_6		0x15
-#define SC_MODE_SELECT_10		0x55
-#define SC_MODE_SENSE_6			0x1a
-#define SC_MODE_SENSE_10		0x5a
-#define SC_PREVENT_ALLOW_MEDIUM_REMOVAL	0x1e
-#define SC_READ_6			0x08
-#define SC_READ_10			0x28
-#define SC_READ_12			0xa8
-#define SC_READ_CAPACITY		0x25
-#define SC_READ_FORMAT_CAPACITIES	0x23
-#define SC_RELEASE			0x17
-#define SC_REQUEST_SENSE		0x03
-#define SC_RESERVE			0x16
-#define SC_SEND_DIAGNOSTIC		0x1d
-#define SC_START_STOP_UNIT		0x1b
-#define SC_SYNCHRONIZE_CACHE		0x35
-#define SC_TEST_UNIT_READY		0x00
-#define SC_VERIFY			0x2f
-#define SC_WRITE_6			0x0a
-#define SC_WRITE_10			0x2a
-#define SC_WRITE_12			0xaa
-
-/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */
-#define SS_NO_SENSE				0
-#define SS_COMMUNICATION_FAILURE		0x040800
-#define SS_INVALID_COMMAND			0x052000
-#define SS_INVALID_FIELD_IN_CDB			0x052400
-#define SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE	0x052100
-#define SS_LOGICAL_UNIT_NOT_SUPPORTED		0x052500
-#define SS_MEDIUM_NOT_PRESENT			0x023a00
-#define SS_MEDIUM_REMOVAL_PREVENTED		0x055302
-#define SS_NOT_READY_TO_READY_TRANSITION	0x062800
-#define SS_RESET_OCCURRED			0x062900
-#define SS_SAVING_PARAMETERS_NOT_SUPPORTED	0x053900
-#define SS_UNRECOVERED_READ_ERROR		0x031100
-#define SS_WRITE_ERROR				0x030c02
-#define SS_WRITE_PROTECTED			0x072700
-
-#define SK(x)		((u8) ((x) >> 16))	// Sense Key byte, etc.
-#define ASC(x)		((u8) ((x) >> 8))
-#define ASCQ(x)		((u8) (x))
-
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * These definitions will permit the compiler to avoid generating code for
- * parts of the driver that aren't used in the non-TEST version.  Even gcc
- * can recognize when a test of a constant expression yields a dead code
- * path.
- *
- * Also, in the non-TEST version, open_backing_file() is only used during
- * initialization and the sysfs attribute store_xxx routines aren't used
- * at all.  We will define NORMALLY_INIT to mark them as __init so they
- * don't occupy kernel code space unnecessarily.
- */
-
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
-
-#define transport_is_bbb()	(mod_data.transport_type == USB_PR_BULK)
-#define transport_is_cbi()	(mod_data.transport_type == USB_PR_CBI)
-#define protocol_is_scsi()	(mod_data.protocol_type == USB_SC_SCSI)
-#define backing_file_is_open(curlun)	((curlun)->filp != NULL)
-#define NORMALLY_INIT
-
-#else
-
-#define transport_is_bbb()	1
-#define transport_is_cbi()	0
-#define protocol_is_scsi()	1
-#define backing_file_is_open(curlun)	1
-#define NORMALLY_INIT		__init
-
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
-
-
-struct lun {
-	struct file	*filp;
-	loff_t		file_length;
-	loff_t		num_sectors;
-
-	unsigned int	ro : 1;
-	unsigned int	prevent_medium_removal : 1;
-	unsigned int	registered : 1;
-
-	u32		sense_data;
-	u32		sense_data_info;
-	u32		unit_attention_data;
-
-#define BUS_ID_SIZE	20
-	struct __lun_device {
-		char	name[BUS_ID_SIZE];
-		void	*driver_data;
-	} dev;
-};
-
-
-/* Big enough to hold our biggest descriptor */
-#define EP0_BUFSIZE	256
-#define DELAYED_STATUS	(EP0_BUFSIZE + 999)	// An impossibly large value
-
-/* Number of buffers we will use.  2 is enough for double-buffering */
-#define NUM_BUFFERS	2
-
-enum fsg_buffer_state {
-	BUF_STATE_EMPTY = 0,
-	BUF_STATE_FULL,
-	BUF_STATE_BUSY
-};
-
-struct fsg_buffhd {
-	void				*buf;
-	dma_addr_t			dma;
-	volatile enum fsg_buffer_state	state;
-	struct fsg_buffhd		*next;
-
-	/* The NetChip 2280 is faster, and handles some protocol faults
-	 * better, if we don't submit any short bulk-out read requests.
-	 * So we will record the intended request length here. */
-	unsigned int			bulk_out_intended_length;
-
-	struct usb_request		*inreq;
-	volatile int			inreq_busy;
-	struct usb_request		*outreq;
-	volatile int			outreq_busy;
-};
-
-enum fsg_state {
-	FSG_STATE_COMMAND_PHASE = -10,		// This one isn't used anywhere
-	FSG_STATE_DATA_PHASE,
-	FSG_STATE_STATUS_PHASE,
-
-	FSG_STATE_IDLE = 0,
-	FSG_STATE_ABORT_BULK_OUT,
-	FSG_STATE_RESET,
-	FSG_STATE_INTERFACE_CHANGE,
-	FSG_STATE_CONFIG_CHANGE,
-	FSG_STATE_DISCONNECT,
-	FSG_STATE_EXIT,
-	FSG_STATE_TERMINATED
-};
-
-enum data_direction {
-	DATA_DIR_UNKNOWN = 0,
-	DATA_DIR_FROM_HOST,
-	DATA_DIR_TO_HOST,
-	DATA_DIR_NONE
-};
-
-struct fsg_dev {
-	/* lock protects: state, all the req_busy's, and cbbuf_cmnd */
-	spinlock_t		lock;
-	struct usb_gadget	*gadget;
-
-	/* filesem protects: backing files in use */
-	struct rw_semaphore	filesem;
-
-	struct usb_ep		*ep0;		// Handy copy of gadget->ep0
-	struct usb_request	*ep0req;	// For control responses
-	volatile unsigned int	ep0_req_tag;
-	const char		*ep0req_name;
-
-	struct usb_request	*intreq;	// For interrupt responses
-	volatile int		intreq_busy;
-	struct fsg_buffhd	*intr_buffhd;
-
- 	unsigned int		bulk_out_maxpacket;
-	enum fsg_state		state;		// For exception handling
-	unsigned int		exception_req_tag;
-
-	u8			config, new_config;
-
-	unsigned int		running : 1;
-	unsigned int		bulk_in_enabled : 1;
-	unsigned int		bulk_out_enabled : 1;
-	unsigned int		intr_in_enabled : 1;
-	unsigned int		phase_error : 1;
-	unsigned int		short_packet_received : 1;
-	unsigned int		bad_lun_okay : 1;
-
-	unsigned long		atomic_bitflags;
-#define REGISTERED		0
-#define CLEAR_BULK_HALTS	1
-
-	struct usb_ep		*bulk_in;
-	struct usb_ep		*bulk_out;
-	struct usb_ep		*intr_in;
-
-	struct fsg_buffhd	*next_buffhd_to_fill;
-	struct fsg_buffhd	*next_buffhd_to_drain;
-	struct fsg_buffhd	buffhds[NUM_BUFFERS];
-
-	wait_queue_head_t	thread_wqh;
-	int			thread_wakeup_needed;
-	struct completion	thread_notifier;
-	int			thread_pid;
-	struct task_struct	*thread_task;
-	sigset_t		thread_signal_mask;
-
-	int			cmnd_size;
-	u8			cmnd[MAX_COMMAND_SIZE];
-	enum data_direction	data_dir;
-	u32			data_size;
-	u32			data_size_from_cmnd;
-	u32			tag;
-	unsigned int		lun;
-	u32			residue;
-	u32			usb_amount_left;
-
-	/* The CB protocol offers no way for a host to know when a command
-	 * has completed.  As a result the next command may arrive early,
-	 * and we will still have to handle it.  For that reason we need
-	 * a buffer to store new commands when using CB (or CBI, which
-	 * does not oblige a host to wait for command completion either). */
-	int			cbbuf_cmnd_size;
-	u8			cbbuf_cmnd[MAX_COMMAND_SIZE];
-
-	unsigned int		nluns;
-	struct lun		*luns;
-	struct lun		*curlun;
-};
-
-typedef void (*fsg_routine_t)(struct fsg_dev *);
-
-static int inline exception_in_progress(struct fsg_dev *fsg)
-{
-	return (fsg->state > FSG_STATE_IDLE);
-}
-
-/* Make bulk-out requests be divisible by the maxpacket size */
-static void inline set_bulk_out_req_length(struct fsg_dev *fsg,
-		struct fsg_buffhd *bh, unsigned int length)
-{
-	unsigned int	rem;
-
-	bh->bulk_out_intended_length = length;
-	rem = length % fsg->bulk_out_maxpacket;
-	if (rem > 0)
-		length += fsg->bulk_out_maxpacket - rem;
-	bh->outreq->length = length;
-}
-
-static struct fsg_dev			*the_fsg;
-static struct usb_gadget_driver		fsg_driver;
-
-static void	close_backing_file(struct lun *curlun);
-static void	close_all_backing_files(struct fsg_dev *fsg);
-
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef DUMP_MSGS
-
-static void dump_msg(struct fsg_dev *fsg, const char *label,
-		const u8 *buf, unsigned int length)
-{
-	unsigned int	start, num, i;
-	char		line[52], *p;
-
-	if (length >= 512)
-		return;
-	DBG(fsg, "%s, length %u:\n", label, length);
-
-	start = 0;
-	while (length > 0) {
-		num = min(length, 16u);
-		p = line;
-		for (i = 0; i < num; ++i) {
-			if (i == 8)
-				*p++ = ' ';
-			sprintf(p, " %02x", buf[i]);
-			p += 3;
-		}
-		*p = 0;
-		printk(KERN_DEBUG "%6x: %s\n", start, line);
-		buf += num;
-		start += num;
-		length -= num;
-	}
-}
-
-static void inline dump_cdb(struct fsg_dev *fsg)
-{}
-
-#else
-
-static void inline dump_msg(struct fsg_dev *fsg, const char *label,
-		const u8 *buf, unsigned int length)
-{}
-
-static void inline dump_cdb(struct fsg_dev *fsg)
-{
-	int	i;
-	char	cmdbuf[3*MAX_COMMAND_SIZE + 1];
-
-	for (i = 0; i < fsg->cmnd_size; ++i)
-		sprintf(cmdbuf + i*3, " %02x", fsg->cmnd[i]);
-	VDBG(fsg, "SCSI CDB: %s\n", cmdbuf);
-}
-
-#endif /* DUMP_MSGS */
-
-
-static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
-{
-	const char	*name;
-
-	if (ep == fsg->bulk_in)
-		name = "bulk-in";
-	else if (ep == fsg->bulk_out)
-		name = "bulk-out";
-	else
-		name = ep->name;
-	DBG(fsg, "%s set halt\n", name);
-	return usb_ep_set_halt(ep);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* Routines for unaligned data access */
-
-static u16 inline get_be16(u8 *buf)
-{
-	return ((u16) buf[0] << 8) | ((u16) buf[1]);
-}
-
-static u32 inline get_be32(u8 *buf)
-{
-	return ((u32) buf[0] << 24) | ((u32) buf[1] << 16) |
-			((u32) buf[2] << 8) | ((u32) buf[3]);
-}
-
-static void inline put_be16(u8 *buf, u16 val)
-{
-	buf[0] = val >> 8;
-	buf[1] = val;
-}
-
-static void inline put_be32(u8 *buf, u32 val)
-{
-	buf[0] = val >> 24;
-	buf[1] = val >> 16;
-	buf[2] = val >> 8;
-	buf[3] = val;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * DESCRIPTORS ... most are static, but strings and (full) configuration
- * descriptors are built on demand.  Also the (static) config and interface
- * descriptors are adjusted during fsg_bind().
- */
-#define STRING_MANUFACTURER	1
-#define STRING_PRODUCT		2
-#define STRING_SERIAL		3
-
-/* There is only one configuration. */
-#define	CONFIG_VALUE		1
-
-static struct usb_device_descriptor
-device_desc = {
-	.bLength =		sizeof device_desc,
-	.bDescriptorType =	USB_DT_DEVICE,
-
-	.bcdUSB =		__constant_cpu_to_le16(0x0200),
-	.bDeviceClass =		USB_CLASS_PER_INTERFACE,
-
-	/* The next three values can be overridden by module parameters */
-	.idVendor =		__constant_cpu_to_le16(DRIVER_VENDOR_ID),
-	.idProduct =		__constant_cpu_to_le16(DRIVER_PRODUCT_ID),
-	.bcdDevice =		__constant_cpu_to_le16(DRIVER_VERSION_NUM),
-
-	.iManufacturer =	STRING_MANUFACTURER,
-	.iProduct =		STRING_PRODUCT,
-	.iSerialNumber =	STRING_SERIAL,
-	.bNumConfigurations =	1,
-};
-
-static struct usb_config_descriptor
-config_desc = {
-	.bLength =		sizeof config_desc,
-	.bDescriptorType =	USB_DT_CONFIG,
-
-	/* wTotalLength adjusted during bind() */
-	.bNumInterfaces =	1,
-	.bConfigurationValue =	CONFIG_VALUE,
-	.bmAttributes =		USB_CONFIG_ATT_ONE | SELFPOWER,
-	.bMaxPower =		(MAX_USB_POWER + 1) / 2,
-};
-
-/* There is only one interface. */
-
-static struct usb_interface_descriptor
-intf_desc = {
-	.bLength =		sizeof intf_desc,
-	.bDescriptorType =	USB_DT_INTERFACE,
-
-	.bNumEndpoints =	2,		// Adjusted during bind()
-	.bInterfaceClass =	USB_CLASS_MASS_STORAGE,
-	.bInterfaceSubClass =	USB_SC_SCSI,	// Adjusted during bind()
-	.bInterfaceProtocol =	USB_PR_BULK,	// Adjusted during bind()
-};
-
-/* Three full-speed endpoint descriptors: bulk-in, bulk-out,
- * and interrupt-in. */
-
-static const struct usb_endpoint_descriptor
-fs_bulk_in_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	EP_BULK_IN_NUM | USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(FS_BULK_IN_MAXPACKET),
-};
-
-static const struct usb_endpoint_descriptor
-fs_bulk_out_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	EP_BULK_OUT_NUM,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(FS_BULK_OUT_MAXPACKET),
-};
-
-static const struct usb_endpoint_descriptor
-fs_intr_in_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	EP_INTR_IN_NUM | USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	__constant_cpu_to_le16(2),
-	.bInterval =		32,	// frames -> 32 ms
-};
-
-#ifdef	HIGHSPEED
-
-/*
- * USB 2.0 devices need to expose both high speed and full speed
- * descriptors, unless they only run at full speed.
- *
- * That means alternate endpoint descriptors (bigger packets)
- * and a "device qualifier" ... plus more construction options
- * for the config descriptor.
- */
-static const struct usb_endpoint_descriptor
-hs_bulk_in_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	EP_BULK_IN_NUM | USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512),
-};
-
-static const struct usb_endpoint_descriptor
-hs_bulk_out_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	EP_BULK_OUT_NUM,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512),
-	.bInterval =		1,	// NAK every 1 uframe
-};
-
-static const struct usb_endpoint_descriptor
-hs_intr_in_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	EP_INTR_IN_NUM | USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	__constant_cpu_to_le16(2),
-	.bInterval =		9,	// 2**(9-1) = 256 uframes -> 32 ms
-};
-
-static struct usb_qualifier_descriptor
-dev_qualifier = {
-	.bLength =		sizeof dev_qualifier,
-	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,
-
-	.bcdUSB =		__constant_cpu_to_le16(0x0200),
-	.bDeviceClass =		USB_CLASS_PER_INTERFACE,
-
-	.bNumConfigurations =	1,
-};
-
-/* Maxpacket and other transfer characteristics vary by speed. */
-#define ep_desc(g,fs,hs)	(((g)->speed==USB_SPEED_HIGH) ? (hs) : (fs))
-
-#else
-
-/* If there's no high speed support, maxpacket doesn't change. */
-#define ep_desc(g,fs,hs)	fs
-
-#endif	/* !HIGHSPEED */
-
-
-/* The CBI specification limits the serial string to 12 uppercase hexadecimal
- * characters. */
-static char				serial[13];
-
-/* Static strings, in ISO 8859/1 */
-static struct usb_string		strings[] = {
-	{ STRING_MANUFACTURER, UTS_SYSNAME " " UTS_RELEASE " with " CHIP, },
-	{ STRING_PRODUCT, longname, },
-	{ STRING_SERIAL, serial, },
-	{ }			// end of list
-};
-
-static struct usb_gadget_strings	stringtab = {
-	.language	= 0x0409,		// en-us
-	.strings	= strings,
-};
-
-
-/*
- * Config descriptors are handcrafted.  They must agree with the code
- * that sets configurations and with code managing interfaces and their
- * altsettings.  They must also handle different speeds and other-speed
- * requests.
- */
-static int populate_config_buf(enum usb_device_speed speed,
-		u8 *buf0, u8 type, unsigned index)
-{
-	u8	*buf = buf0;
-#ifdef HIGHSPEED
-	int	hs;
-#endif
-
-	if (index > 0)
-		return -EINVAL;
-	if (config_desc.wTotalLength  > EP0_BUFSIZE)
-		return -EDOM;
-
-	/* Config (or other speed config) */
-	memcpy(buf, &config_desc, USB_DT_CONFIG_SIZE);
-	buf[1] = type;
-	buf += USB_DT_CONFIG_SIZE;
-
-	/* Interface */
-	memcpy(buf, &intf_desc, USB_DT_INTERFACE_SIZE);
-	buf += USB_DT_INTERFACE_SIZE;
-
-	/* The endpoints in the interface (at that speed) */
-#ifdef HIGHSPEED
-	hs = (speed == USB_SPEED_HIGH);
-	if (type == USB_DT_OTHER_SPEED_CONFIG)
-		hs = !hs;
-	if (hs) {
-		memcpy(buf, &hs_bulk_in_desc, USB_DT_ENDPOINT_SIZE);
-		buf += USB_DT_ENDPOINT_SIZE;
-		memcpy(buf, &hs_bulk_out_desc, USB_DT_ENDPOINT_SIZE);
-		buf += USB_DT_ENDPOINT_SIZE;
-		if (transport_is_cbi()) {
-			memcpy(buf, &hs_intr_in_desc, USB_DT_ENDPOINT_SIZE);
-			buf += USB_DT_ENDPOINT_SIZE;
-		}
-	} else
-#endif
-	{
-		memcpy(buf, &fs_bulk_in_desc, USB_DT_ENDPOINT_SIZE);
-		buf += USB_DT_ENDPOINT_SIZE;
-		memcpy(buf, &fs_bulk_out_desc, USB_DT_ENDPOINT_SIZE);
-		buf += USB_DT_ENDPOINT_SIZE;
-		if (transport_is_cbi()) {
-			memcpy(buf, &fs_intr_in_desc, USB_DT_ENDPOINT_SIZE);
-			buf += USB_DT_ENDPOINT_SIZE;
-		}
-	}
-
-	return buf - buf0;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* These routines may be called in process context or in_irq */
-
-static void wakeup_thread(struct fsg_dev *fsg)
-{
-	/* Tell the main thread that something has happened */
-	fsg->thread_wakeup_needed = 1;
-	wake_up_all(&fsg->thread_wqh);
-}
-
-
-static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state)
-{
-	unsigned long		flags;
-	struct task_struct	*thread_task;
-
-	/* Do nothing if a higher-priority exception is already in progress.
-	 * If a lower-or-equal priority exception is in progress, preempt it
-	 * and notify the main thread by sending it a signal. */
-	spin_lock_irqsave(&fsg->lock, flags);
-	if (fsg->state <= new_state) {
-		fsg->exception_req_tag = fsg->ep0_req_tag;
-		fsg->state = new_state;
-		thread_task = fsg->thread_task;
-		if (thread_task)
-			send_sig_info(SIGUSR1, (void *) 1L, thread_task);
-	}
-	spin_unlock_irqrestore(&fsg->lock, flags);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* The disconnect callback and ep0 routines.  These always run in_irq,
- * except that ep0_queue() is called in the main thread to acknowledge
- * completion of various requests: set config, set interface, and
- * Bulk-only device reset. */
-
-static void fsg_disconnect(struct usb_gadget *gadget)
-{
-	struct fsg_dev		*fsg = get_gadget_data(gadget);
-
-	DBG(fsg, "disconnect or port reset\n");
-	raise_exception(fsg, FSG_STATE_DISCONNECT);
-}
-
-
-static int ep0_queue(struct fsg_dev *fsg)
-{
-	int	rc;
-
-	rc = usb_ep_queue(fsg->ep0, fsg->ep0req, GFP_ATOMIC);
-	if (rc != 0 && rc != -ESHUTDOWN) {
-
-		/* We can't do much more than wait for a reset */
-		WARN(fsg, "error in submission: %s --> %d\n",
-				fsg->ep0->name, rc);
-	}
-	return rc;
-}
-
-static void ep0_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	struct fsg_dev		*fsg = (struct fsg_dev *) ep->driver_data;
-
-	if (req->actual > 0)
-		dump_msg(fsg, fsg->ep0req_name, req->buf, req->actual);
-	if (req->status || req->actual != req->length)
-		DBG(fsg, "%s --> %d, %u/%u\n", __FUNCTION__,
-				req->status, req->actual, req->length);
-	if (req->status == -ECONNRESET)		// Request was cancelled
-		usb_ep_fifo_flush(ep);
-
-	if (req->status == 0 && req->context)
-		((fsg_routine_t) (req->context))(fsg);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* Bulk and interrupt endpoint completion handlers.
- * These always run in_irq. */
-
-static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	struct fsg_dev		*fsg = (struct fsg_dev *) ep->driver_data;
-	struct fsg_buffhd	*bh = (struct fsg_buffhd *) req->context;
-
-	if (req->status || req->actual != req->length)
-		DBG(fsg, "%s --> %d, %u/%u\n", __FUNCTION__,
-				req->status, req->actual, req->length);
-	if (req->status == -ECONNRESET)		// Request was cancelled
-		usb_ep_fifo_flush(ep);
-
-	/* Hold the lock while we update the request and buffer states */
-	spin_lock(&fsg->lock);
-	bh->inreq_busy = 0;
-	bh->state = BUF_STATE_EMPTY;
-	spin_unlock(&fsg->lock);
-	wakeup_thread(fsg);
-}
-
-static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	struct fsg_dev		*fsg = (struct fsg_dev *) ep->driver_data;
-	struct fsg_buffhd	*bh = (struct fsg_buffhd *) req->context;
-
-	dump_msg(fsg, "bulk-out", req->buf, req->actual);
-	if (req->status || req->actual != bh->bulk_out_intended_length)
-		DBG(fsg, "%s --> %d, %u/%u\n", __FUNCTION__,
-				req->status, req->actual,
-				bh->bulk_out_intended_length);
-	if (req->status == -ECONNRESET)		// Request was cancelled
-		usb_ep_fifo_flush(ep);
-
-	/* Hold the lock while we update the request and buffer states */
-	spin_lock(&fsg->lock);
-	bh->outreq_busy = 0;
-	bh->state = BUF_STATE_FULL;
-	spin_unlock(&fsg->lock);
-	wakeup_thread(fsg);
-}
-
-static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
-{
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
-	struct fsg_dev		*fsg = (struct fsg_dev *) ep->driver_data;
-	struct fsg_buffhd	*bh = (struct fsg_buffhd *) req->context;
-
-	if (req->status || req->actual != req->length)
-		DBG(fsg, "%s --> %d, %u/%u\n", __FUNCTION__,
-				req->status, req->actual, req->length);
-	if (req->status == -ECONNRESET)		// Request was cancelled
-		usb_ep_fifo_flush(ep);
-
-	/* Hold the lock while we update the request and buffer states */
-	spin_lock(&fsg->lock);
-	fsg->intreq_busy = 0;
-	bh->state = BUF_STATE_EMPTY;
-	spin_unlock(&fsg->lock);
-	wakeup_thread(fsg);
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* Ep0 class-specific handlers.  These always run in_irq. */
-
-static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
-	struct usb_request	*req = fsg->ep0req;
-	static u8		cbi_reset_cmnd[6] = {
-			SC_SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff};
-
-	/* Error in command transfer? */
-	if (req->status || req->length != req->actual ||
-			req->actual < 6 || req->actual > MAX_COMMAND_SIZE) {
-
-		/* Not all controllers allow a protocol stall after
-		 * receiving control-out data, but we'll try anyway. */
-		fsg_set_halt(fsg, fsg->ep0);
-		return;			// Wait for reset
-	}
-
-	/* Is it the special reset command? */
-	if (req->actual >= sizeof cbi_reset_cmnd &&
-			memcmp(req->buf, cbi_reset_cmnd,
-				sizeof cbi_reset_cmnd) == 0) {
-
-		/* Raise an exception to stop the current operation
-		 * and reinitialize our state. */
-		DBG(fsg, "cbi reset request\n");
-		raise_exception(fsg, FSG_STATE_RESET);
-		return;
-	}
-
-	VDBG(fsg, "CB[I] accept device-specific command\n");
-	spin_lock(&fsg->lock);
-
-	/* Save the command for later */
-	if (fsg->cbbuf_cmnd_size)
-		WARN(fsg, "CB[I] overwriting previous command\n");
-	fsg->cbbuf_cmnd_size = req->actual;
-	memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size);
-
-	spin_unlock(&fsg->lock);
-	wakeup_thread(fsg);
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
-}
-
-
-static int class_setup_req(struct fsg_dev *fsg,
-		const struct usb_ctrlrequest *ctrl)
-{
-	struct usb_request	*req = fsg->ep0req;
-	int			value = -EOPNOTSUPP;
-
-	if (!fsg->config)
-		return value;
-
-	/* Handle Bulk-only class-specific requests */
-	if (transport_is_bbb()) {
-		switch (ctrl->bRequest) {
-
-		case USB_BULK_RESET_REQUEST:
-			if (ctrl->bRequestType != (USB_DIR_OUT |
-					USB_TYPE_CLASS | USB_RECIP_INTERFACE))
-				break;
-			if (ctrl->wIndex != 0) {
-				value = -EDOM;
-				break;
-			}
-
-			/* Raise an exception to stop the current operation
-			 * and reinitialize our state. */
-			DBG(fsg, "bulk reset request\n");
-			raise_exception(fsg, FSG_STATE_RESET);
-			value = DELAYED_STATUS;
-			break;
-
-		case USB_BULK_GET_MAX_LUN_REQUEST:
-			if (ctrl->bRequestType != (USB_DIR_IN |
-					USB_TYPE_CLASS | USB_RECIP_INTERFACE))
-				break;
-			if (ctrl->wIndex != 0) {
-				value = -EDOM;
-				break;
-			}
-			VDBG(fsg, "get max LUN\n");
-			*(u8 *) req->buf = fsg->nluns - 1;
-			value = min(ctrl->wLength, (u16) 1);
-			break;
-		}
-	}
-
-	/* Handle CBI class-specific requests */
-	else {
-		switch (ctrl->bRequest) {
-
-		case USB_CBI_ADSC_REQUEST:
-			if (ctrl->bRequestType != (USB_DIR_OUT |
-					USB_TYPE_CLASS | USB_RECIP_INTERFACE))
-				break;
-			if (ctrl->wIndex != 0) {
-				value = -EDOM;
-				break;
-			}
-			if (ctrl->wLength > MAX_COMMAND_SIZE) {
-				value = -EOVERFLOW;
-				break;
-			}
-			value = ctrl->wLength;
-			fsg->ep0req->context = received_cbi_adsc;
-			break;
-		}
-	}
-
-	if (value == -EOPNOTSUPP)
-		VDBG(fsg,
-			"unknown class-specific control req "
-			"%02x.%02x v%04x i%04x l%u\n",
-			ctrl->bRequestType, ctrl->bRequest,
-			ctrl->wValue, ctrl->wIndex, ctrl->wLength);
-	return value;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* Ep0 standard request handlers.  These always run in_irq. */
-
-static int standard_setup_req(struct fsg_dev *fsg,
-		const struct usb_ctrlrequest *ctrl)
-{
-	struct usb_request	*req = fsg->ep0req;
-	int			value = -EOPNOTSUPP;
-
-	/* Usually this just stores reply data in the pre-allocated ep0 buffer,
-	 * but config change events will also reconfigure hardware. */
-	switch (ctrl->bRequest) {
-
-	case USB_REQ_GET_DESCRIPTOR:
-		if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
-				USB_RECIP_DEVICE))
-			break;
-		switch (ctrl->wValue >> 8) {
-
-		case USB_DT_DEVICE:
-			VDBG(fsg, "get device descriptor\n");
-			value = min(ctrl->wLength, (u16) sizeof device_desc);
-			memcpy(req->buf, &device_desc, value);
-			break;
-#ifdef HIGHSPEED
-		case USB_DT_DEVICE_QUALIFIER:
-			VDBG(fsg, "get device qualifier\n");
-			value = min(ctrl->wLength, (u16) sizeof dev_qualifier);
-			memcpy(req->buf, &dev_qualifier, value);
-			break;
-
-		case USB_DT_OTHER_SPEED_CONFIG:
-			VDBG(fsg, "get other-speed config descriptor\n");
-			goto get_config;
-#endif /* HIGHSPEED */
-		case USB_DT_CONFIG:
-			VDBG(fsg, "get configuration descriptor\n");
-#ifdef HIGHSPEED
-		get_config:
-#endif /* HIGHSPEED */
-			value = populate_config_buf(fsg->gadget->speed,
-					req->buf,
-					ctrl->wValue >> 8,
-					ctrl->wValue & 0xff);
-			if (value >= 0)
-				value = min(ctrl->wLength, (u16) value);
-			break;
-
-		case USB_DT_STRING:
-			VDBG(fsg, "get string descriptor\n");
-
-			/* wIndex == language code */
-			value = usb_gadget_get_string(&stringtab,
-					ctrl->wValue & 0xff, req->buf);
-			if (value >= 0)
-				value = min(ctrl->wLength, (u16) value);
-			break;
-		}
-		break;
-
-	/* One config, two speeds */
-	case USB_REQ_SET_CONFIGURATION:
-		if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD |
-				USB_RECIP_DEVICE))
-			break;
-		VDBG(fsg, "set configuration\n");
-		if (ctrl->wValue == CONFIG_VALUE || ctrl->wValue == 0) {
-			fsg->new_config = ctrl->wValue;
-
-			/* Raise an exception to wipe out previous transaction
-			 * state (queued bufs, etc) and set the new config. */
-			raise_exception(fsg, FSG_STATE_CONFIG_CHANGE);
-			value = DELAYED_STATUS;
-		}
-		break;
-	case USB_REQ_GET_CONFIGURATION:
-		if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
-				USB_RECIP_DEVICE))
-			break;
-		VDBG(fsg, "get configuration\n");
-		*(u8 *) req->buf = fsg->config;
-		value = min(ctrl->wLength, (u16) 1);
-		break;
-
-	case USB_REQ_SET_INTERFACE:
-		if (ctrl->bRequestType != (USB_DIR_OUT| USB_TYPE_STANDARD |
-				USB_RECIP_INTERFACE))
-			break;
-		if (fsg->config && ctrl->wIndex == 0) {
-
-			/* Raise an exception to wipe out previous transaction
-			 * state (queued bufs, etc) and install the new
-			 * interface altsetting. */
-			raise_exception(fsg, FSG_STATE_INTERFACE_CHANGE);
-			value = DELAYED_STATUS;
-		}
-		break;
-	case USB_REQ_GET_INTERFACE:
-		if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
-				USB_RECIP_INTERFACE))
-			break;
-		if (!fsg->config)
-			break;
-		if (ctrl->wIndex != 0) {
-			value = -EDOM;
-			break;
-		}
-		VDBG(fsg, "get interface\n");
-		*(u8 *) req->buf = 0;
-		value = min(ctrl->wLength, (u16) 1);
-		break;
-
-	default:
-		VDBG(fsg,
-			"unknown control req %02x.%02x v%04x i%04x l%u\n",
-			ctrl->bRequestType, ctrl->bRequest,
-			ctrl->wValue, ctrl->wIndex, ctrl->wLength);
-	}
-
-	return value;
-}
-
-
-static int fsg_setup(struct usb_gadget *gadget,
-		const struct usb_ctrlrequest *ctrl)
-{
-	struct fsg_dev		*fsg = get_gadget_data(gadget);
-	int			rc;
-
-	++fsg->ep0_req_tag;		// Record arrival of a new request
-	fsg->ep0req->context = NULL;
-	fsg->ep0req->length = 0;
-	dump_msg(fsg, "ep0-setup", (u8 *) ctrl, sizeof(*ctrl));
-
-	if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS)
-		rc = class_setup_req(fsg, ctrl);
-	else
-		rc = standard_setup_req(fsg, ctrl);
-
-	/* Respond with data/status or defer until later? */
-	if (rc >= 0 && rc != DELAYED_STATUS) {
-		fsg->ep0req->length = rc;
-		fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ?
-				"ep0-in" : "ep0-out");
-		rc = ep0_queue(fsg);
-	}
-
-	/* Device either stalls (rc < 0) or reports success */
-	return rc;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* All the following routines run in process context */
-
-
-/* Use this for bulk or interrupt transfers, not ep0 */
-static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
-		struct usb_request *req, volatile int *pbusy,
-		volatile enum fsg_buffer_state *state)
-{
-	int	rc;
-
-	if (ep == fsg->bulk_in)
-		dump_msg(fsg, "bulk-in", req->buf, req->length);
-	else if (ep == fsg->intr_in)
-		dump_msg(fsg, "intr-in", req->buf, req->length);
-	*pbusy = 1;
-	*state = BUF_STATE_BUSY;
-	rc = usb_ep_queue(ep, req, GFP_KERNEL);
-	if (rc != 0) {
-		*pbusy = 0;
-		*state = BUF_STATE_EMPTY;
-
-		/* We can't do much more than wait for a reset */
-
-		/* Note: currently the net2280 driver fails zero-length
-		 * submissions if DMA is enabled. */
-		if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP &&
-						req->length == 0))
-			WARN(fsg, "error in submission: %s --> %d\n",
-					ep->name, rc);
-	}
-}
-
-
-static int sleep_thread(struct fsg_dev *fsg)
-{
-	int	rc;
-
-	/* Wait until a signal arrives or we are woken up */
-	rc = wait_event_interruptible(fsg->thread_wqh,
-			fsg->thread_wakeup_needed);
-	fsg->thread_wakeup_needed = 0;
-	return (rc ? -EINTR : 0);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int do_read(struct fsg_dev *fsg)
-{
-	struct lun		*curlun = fsg->curlun;
-	u32			lba;
-	struct fsg_buffhd	*bh;
-	int			rc;
-	u32			amount_left;
-	loff_t			file_offset, file_offset_tmp;
-	unsigned int		amount;
-	unsigned int		partial_page;
-	ssize_t			nread;
-
-	/* Get the starting Logical Block Address and check that it's
-	 * not too big */
-	if (fsg->cmnd[0] == SC_READ_6)
-		lba = (fsg->cmnd[1] << 16) | get_be16(&fsg->cmnd[2]);
-	else {
-		lba = get_be32(&fsg->cmnd[2]);
-
-		/* We allow DPO (Disable Page Out = don't save data in the
-		 * cache) and FUA (Force Unit Access = don't read from the
-		 * cache), but we don't implement them. */
-		if ((fsg->cmnd[1] & ~0x18) != 0) {
-			curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-			return -EINVAL;
-		}
-	}
-	if (lba >= curlun->num_sectors) {
-		curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-		return -EINVAL;
-	}
-	file_offset = ((loff_t) lba) << 9;
-
-	/* Carry out the file reads */
-	amount_left = fsg->data_size_from_cmnd;
-	if (unlikely(amount_left == 0))
-		return -EIO;		// No default reply
-
-	for (;;) {
-
-		/* Figure out how much we need to read:
-		 * Try to read the remaining amount.
-		 * But don't read more than the buffer size.
-		 * And don't try to read past the end of the file.
-		 * Finally, if we're not at a page boundary, don't read past
-		 *	the next page.
-		 * If this means reading 0 then we were asked to read past
-		 *	the end of file. */
-		amount = min((unsigned int) amount_left, mod_data.buflen);
-		amount = min((loff_t) amount,
-				curlun->file_length - file_offset);
-		partial_page = file_offset & (PAGE_CACHE_SIZE - 1);
-		if (partial_page > 0)
-			amount = min(amount, (unsigned int) PAGE_CACHE_SIZE -
-					partial_page);
-
-		/* Wait for the next buffer to become available */
-		bh = fsg->next_buffhd_to_fill;
-		while (bh->state != BUF_STATE_EMPTY) {
-			if ((rc = sleep_thread(fsg)) != 0)
-				return rc;
-		}
-
-		/* If we were asked to read past the end of file,
-		 * end with an empty buffer. */
-		if (amount == 0) {
-			curlun->sense_data =
-					SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-			curlun->sense_data_info = file_offset >> 9;
-			bh->inreq->length = 0;
-			bh->state = BUF_STATE_FULL;
-			break;
-		}
-
-		/* Perform the read */
-		file_offset_tmp = file_offset;
-		nread = curlun->filp->f_op->read(curlun->filp,
-				(char *) bh->buf,
-				amount, &file_offset_tmp);
-		VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
-				(unsigned long long) file_offset,
-				(int) nread);
-		if (signal_pending(current))
-			return -EINTR;
-
-		if (nread < 0) {
-			LDBG(curlun, "error in file read: %d\n",
-					(int) nread);
-			nread = 0;
-		} else if (nread < amount) {
-			LDBG(curlun, "partial file read: %d/%u\n",
-					(int) nread, amount);
-			nread -= (nread & 511);	// Round down to a block
-		}
-		file_offset  += nread;
-		amount_left  -= nread;
-		fsg->residue -= nread;
-		bh->inreq->length = nread;
-		bh->state = BUF_STATE_FULL;
-
-		/* If an error occurred, report it and its position */
-		if (nread < amount) {
-			curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
-			curlun->sense_data_info = file_offset >> 9;
-			break;
-		}
-
-		if (amount_left == 0)
-			break;		// No more left to read
-
-		/* Send this buffer and go read some more */
-		bh->inreq->zero = 0;
-		start_transfer(fsg, fsg->bulk_in, bh->inreq,
-				&bh->inreq_busy, &bh->state);
-		fsg->next_buffhd_to_fill = bh->next;
-	}
-
-	return -EIO;		// No default reply
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int do_write(struct fsg_dev *fsg)
-{
-	struct lun		*curlun = fsg->curlun;
-	u32			lba;
-	struct fsg_buffhd	*bh;
-	int			get_some_more;
-	u32			amount_left_to_req, amount_left_to_write;
-	loff_t			usb_offset, file_offset, file_offset_tmp;
-	unsigned int		amount;
-	unsigned int		partial_page;
-	ssize_t			nwritten;
-	int			rc;
-
-	if (curlun->ro) {
-		curlun->sense_data = SS_WRITE_PROTECTED;
-		return -EINVAL;
-	}
-	curlun->filp->f_flags &= ~O_SYNC;	// Default is not to wait
-
-	/* Get the starting Logical Block Address and check that it's
-	 * not too big */
-	if (fsg->cmnd[0] == SC_WRITE_6)
-		lba = (fsg->cmnd[1] << 16) | get_be16(&fsg->cmnd[2]);
-	else {
-		lba = get_be32(&fsg->cmnd[2]);
-
-		/* We allow DPO (Disable Page Out = don't save data in the
-		 * cache) and FUA (Force Unit Access = write directly to the
-		 * medium).  We don't implement DPO; we implement FUA by
-		 * performing synchronous output. */
-		if ((fsg->cmnd[1] & ~0x18) != 0) {
-			curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-			return -EINVAL;
-		}
-		if (fsg->cmnd[1] & 0x08)	// FUA
-			curlun->filp->f_flags |= O_SYNC;
-	}
-	if (lba >= curlun->num_sectors) {
-		curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-		return -EINVAL;
-	}
-
-	/* Carry out the file writes */
-	get_some_more = 1;
-	file_offset = usb_offset = ((loff_t) lba) << 9;
-	amount_left_to_req = amount_left_to_write = fsg->data_size_from_cmnd;
-
-	while (amount_left_to_write > 0) {
-
-		/* Queue a request for more data from the host */
-		bh = fsg->next_buffhd_to_fill;
-		if (bh->state == BUF_STATE_EMPTY && get_some_more) {
-
-			/* Figure out how much we want to get:
-			 * Try to get the remaining amount.
-			 * But don't get more than the buffer size.
-			 * And don't try to go past the end of the file.
-			 * If we're not at a page boundary,
-			 *	don't go past the next page.
-			 * If this means getting 0, then we were asked
-			 *	to write past the end of file.
-			 * Finally, round down to a block boundary. */
-			amount = min(amount_left_to_req, mod_data.buflen);
-			amount = min((loff_t) amount, curlun->file_length -
-					usb_offset);
-			partial_page = usb_offset & (PAGE_CACHE_SIZE - 1);
-			if (partial_page > 0)
-				amount = min(amount,
-	(unsigned int) PAGE_CACHE_SIZE - partial_page);
-
-			if (amount == 0) {
-				get_some_more = 0;
-				curlun->sense_data =
-					SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-				curlun->sense_data_info = usb_offset >> 9;
-				continue;
-			}
-			amount -= (amount & 511);
-			if (amount == 0) {
-
-				/* Why were we were asked to transfer a
-				 * partial block? */
-				get_some_more = 0;
-				continue;
-			}
-
-			/* Get the next buffer */
-			usb_offset += amount;
-			fsg->usb_amount_left -= amount;
-			amount_left_to_req -= amount;
-			if (amount_left_to_req == 0)
-				get_some_more = 0;
-
-			/* amount is always divisible by 512, hence by
-			 * the bulk-out maxpacket size */
-			bh->outreq->length = bh->bulk_out_intended_length =
-					amount;
-			start_transfer(fsg, fsg->bulk_out, bh->outreq,
-					&bh->outreq_busy, &bh->state);
-			fsg->next_buffhd_to_fill = bh->next;
-			continue;
-		}
-
-		/* Write the received data to the backing file */
-		bh = fsg->next_buffhd_to_drain;
-		if (bh->state == BUF_STATE_EMPTY && !get_some_more)
-			break;			// We stopped early
-		if (bh->state == BUF_STATE_FULL) {
-			fsg->next_buffhd_to_drain = bh->next;
-			bh->state = BUF_STATE_EMPTY;
-
-			/* Did something go wrong with the transfer? */
-			if (bh->outreq->status != 0) {
-				curlun->sense_data = SS_COMMUNICATION_FAILURE;
-				curlun->sense_data_info = file_offset >> 9;
-				break;
-			}
-
-			amount = bh->outreq->actual;
-			if (curlun->file_length - file_offset < amount) {
-				LERROR(curlun,
-	"write %u @ %llu beyond end %llu\n",
-	amount, (unsigned long long) file_offset,
-	(unsigned long long) curlun->file_length);
-				amount = curlun->file_length - file_offset;
-			}
-
-			/* Perform the write */
-			file_offset_tmp = file_offset;
-			nwritten = curlun->filp->f_op->write(curlun->filp,
-					(char *) bh->buf,
-					amount, &file_offset_tmp);
-			VLDBG(curlun, "file write %u @ %llu -> %d\n", amount,
-					(unsigned long long) file_offset,
-					(int) nwritten);
-			if (signal_pending(current))
-				return -EINTR;		// Interrupted!
-
-			if (nwritten < 0) {
-				LDBG(curlun, "error in file write: %d\n",
-						(int) nwritten);
-				nwritten = 0;
-			} else if (nwritten < amount) {
-				LDBG(curlun, "partial file write: %d/%u\n",
-						(int) nwritten, amount);
-				nwritten -= (nwritten & 511);
-						// Round down to a block
-			}
-			file_offset += nwritten;
-			amount_left_to_write -= nwritten;
-			fsg->residue -= nwritten;
-
-			/* If an error occurred, report it and its position */
-			if (nwritten < amount) {
-				curlun->sense_data = SS_WRITE_ERROR;
-				curlun->sense_data_info = file_offset >> 9;
-				break;
-			}
-
-			/* Did the host decide to stop early? */
-			if (bh->outreq->actual != bh->outreq->length) {
-				fsg->short_packet_received = 1;
-				break;
-			}
-			continue;
-		}
-
-		/* Wait for something to happen */
-		if ((rc = sleep_thread(fsg)) != 0)
-			return rc;
-	}
-
-	return -EIO;		// No default reply
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* Sync the file data, don't bother with the metadata.
- * This code was copied from fs/buffer.c:sys_fdatasync(). */
-static int fsync_sub(struct lun *curlun)
-{
-	struct file	*filp = curlun->filp;
-	struct inode	*inode;
-	int		rc, err;
-
-	if (curlun->ro || !filp)
-		return 0;
-	if (!filp->f_op->fsync)
-		return -EINVAL;
-
-	inode = filp->f_dentry->d_inode;
-	down(&inode->i_sem);
-	rc = filemap_fdatasync(inode->i_mapping);
-	err = filp->f_op->fsync(filp, filp->f_dentry, 1);
-	if (!rc)
-		rc = err;
-	err = filemap_fdatawait(inode->i_mapping);
-	if (!rc)
-		rc = err;
-	up(&inode->i_sem);
-	VLDBG(curlun, "fdatasync -> %d\n", rc);
-	return rc;
-}
-
-static void fsync_all(struct fsg_dev *fsg)
-{
-	int	i;
-
-	for (i = 0; i < fsg->nluns; ++i)
-		fsync_sub(&fsg->luns[i]);
-}
-
-static int do_synchronize_cache(struct fsg_dev *fsg)
-{
-	struct lun	*curlun = fsg->curlun;
-	int		rc;
-
-	/* We ignore the requested LBA and write out all file's
-	 * dirty data buffers. */
-	rc = fsync_sub(curlun);
-	if (rc)
-		curlun->sense_data = SS_WRITE_ERROR;
-	return 0;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static void invalidate_sub(struct lun *curlun)
-{
-	struct file	*filp = curlun->filp;
-	struct inode	*inode = filp->f_dentry->d_inode;
-
-	invalidate_inode_pages(inode);
-}
-
-static int do_verify(struct fsg_dev *fsg)
-{
-	struct lun		*curlun = fsg->curlun;
-	u32			lba;
-	u32			verification_length;
-	struct fsg_buffhd	*bh = fsg->next_buffhd_to_fill;
-	loff_t			file_offset, file_offset_tmp;
-	u32			amount_left;
-	unsigned int		amount;
-	ssize_t			nread;
-
-	/* Get the starting Logical Block Address and check that it's
-	 * not too big */
-	lba = get_be32(&fsg->cmnd[2]);
-	if (lba >= curlun->num_sectors) {
-		curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-		return -EINVAL;
-	}
-
-	/* We allow DPO (Disable Page Out = don't save data in the
-	 * cache) but we don't implement it. */
-	if ((fsg->cmnd[1] & ~0x10) != 0) {
-		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-		return -EINVAL;
-	}
-
-	verification_length = get_be16(&fsg->cmnd[7]);
-	if (unlikely(verification_length == 0))
-		return -EIO;		// No default reply
-
-	/* Prepare to carry out the file verify */
-	amount_left = verification_length << 9;
-	file_offset = ((loff_t) lba) << 9;
-
-	/* Write out all the dirty buffers before invalidating them */
-	fsync_sub(curlun);
-	if (signal_pending(current))
-		return -EINTR;
-
-	invalidate_sub(curlun);
-	if (signal_pending(current))
-		return -EINTR;
-
-	/* Just try to read the requested blocks */
-	while (amount_left > 0) {
-
-		/* Figure out how much we need to read:
-		 * Try to read the remaining amount, but not more than
-		 * the buffer size.
-		 * And don't try to read past the end of the file.
-		 * If this means reading 0 then we were asked to read
-		 * past the end of file. */
-		amount = min((unsigned int) amount_left, mod_data.buflen);
-		amount = min((loff_t) amount,
-				curlun->file_length - file_offset);
-		if (amount == 0) {
-			curlun->sense_data =
-					SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-			curlun->sense_data_info = file_offset >> 9;
-			break;
-		}
-
-		/* Perform the read */
-		file_offset_tmp = file_offset;
-		nread = curlun->filp->f_op->read(curlun->filp,
-				(char *) bh->buf,
-				amount, &file_offset_tmp);
-		VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
-				(unsigned long long) file_offset,
-				(int) nread);
-		if (signal_pending(current))
-			return -EINTR;
-
-		if (nread < 0) {
-			LDBG(curlun, "error in file verify: %d\n",
-					(int) nread);
-			nread = 0;
-		} else if (nread < amount) {
-			LDBG(curlun, "partial file verify: %d/%u\n",
-					(int) nread, amount);
-			nread -= (nread & 511);	// Round down to a sector
-		}
-		if (nread == 0) {
-			curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
-			curlun->sense_data_info = file_offset >> 9;
-			break;
-		}
-		file_offset += nread;
-		amount_left -= nread;
-	}
-	return 0;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
-	u8	*buf = (u8 *) bh->buf;
-
-	static char vendor_id[] = "Linux   ";
-	static char product_id[] = "File-Stor Gadget";
-
-	if (!fsg->curlun) {		// Unsupported LUNs are okay
-		fsg->bad_lun_okay = 1;
-		memset(buf, 0, 36);
-		buf[0] = 0x7f;		// Unsupported, no device-type
-		return 36;
-	}
-
-	memset(buf, 0, 8);	// Non-removable, direct-access device
-	if (mod_data.removable)
-		buf[1] = 0x80;
-	buf[2] = 2;		// ANSI SCSI level 2
-	buf[3] = 2;		// SCSI-2 INQUIRY data format
-	buf[4] = 31;		// Additional length
-				// No special options
-	sprintf(buf + 8, "%-8s%-16s%04x", vendor_id, product_id,
-			DRIVER_VERSION_NUM);
-	return 36;
-}
-
-
-static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
-	struct lun	*curlun = fsg->curlun;
-	u8		*buf = (u8 *) bh->buf;
-	u32		sd, sdinfo;
-
-	/*
-	 * From the SCSI-2 spec., section 7.9 (Unit attention condition):
-	 *
-	 * If a REQUEST SENSE command is received from an initiator
-	 * with a pending unit attention condition (before the target
-	 * generates the contingent allegiance condition), then the
-	 * target shall either:
-	 *   a) report any pending sense data and preserve the unit
-	 *	attention condition on the logical unit, or,
-	 *   b) report the unit attention condition, may discard any
-	 *	pending sense data, and clear the unit attention
-	 *	condition on the logical unit for that initiator.
-	 *
-	 * FSG normally uses option a); enable this code to use option b).
-	 */
-#if 0
-	if (curlun && curlun->unit_attention_data != SS_NO_SENSE) {
-		curlun->sense_data = curlun->unit_attention_data;
-		curlun->unit_attention_data = SS_NO_SENSE;
-	}
-#endif
-
-	if (!curlun) {		// Unsupported LUNs are okay
-		fsg->bad_lun_okay = 1;
-		sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
-		sdinfo = 0;
-	} else {
-		sd = curlun->sense_data;
-		sdinfo = curlun->sense_data_info;
-		curlun->sense_data = SS_NO_SENSE;
-		curlun->sense_data_info = 0;
-	}
-
-	memset(buf, 0, 18);
-	buf[0] = 0x80 | 0x70;			// Valid, current error
-	buf[2] = SK(sd);
-	put_be32(&buf[3], sdinfo);		// Sense information
-	buf[7] = 18 - 7;			// Additional sense length
-	buf[12] = ASC(sd);
-	buf[13] = ASCQ(sd);
-	return 18;
-}
-
-
-static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
-	struct lun	*curlun = fsg->curlun;
-	u32		lba = get_be32(&fsg->cmnd[2]);
-	int		pmi = fsg->cmnd[8];
-	u8		*buf = (u8 *) bh->buf;
-
-	/* Check the PMI and LBA fields */
-	if (pmi > 1 || (pmi == 0 && lba != 0)) {
-		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-		return -EINVAL;
-	}
-
-	put_be32(&buf[0], curlun->num_sectors - 1);	// Max logical block
-	put_be32(&buf[4], 512);				// Block length
-	return 8;
-}
-
-
-static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
-	struct lun	*curlun = fsg->curlun;
-	int		mscmnd = fsg->cmnd[0];
-	u8		*buf = (u8 *) bh->buf;
-	u8		*buf0 = buf;
-	int		pc, page_code;
-	int		changeable_values, all_pages;
-	int		valid_page = 0;
-	int		len, limit;
-
-	if ((fsg->cmnd[1] & ~0x08) != 0) {		// Mask away DBD
-		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-		return -EINVAL;
-	}
-	pc = fsg->cmnd[2] >> 6;
-	page_code = fsg->cmnd[2] & 0x3f;
-	if (pc == 3) {
-		curlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED;
-		return -EINVAL;
-	}
-	changeable_values = (pc == 1);
-	all_pages = (page_code == 0x3f);
-
-	/* Write the mode parameter header.  Fixed values are: default
-	 * medium type, no cache control (DPOFUA), and no block descriptors.
-	 * The only variable value is the WriteProtect bit.  We will fill in
-	 * the mode data length later. */
-	memset(buf, 0, 8);
-	if (mscmnd == SC_MODE_SENSE_6) {
-		buf[2] = (curlun->ro ? 0x80 : 0x00);		// WP, DPOFUA
-		buf += 4;
-		limit = 255;
-	} else {			// SC_MODE_SENSE_10
-		buf[3] = (curlun->ro ? 0x80 : 0x00);		// WP, DPOFUA
-		buf += 8;
-		limit = 65535;		// Should really be mod_data.buflen
-	}
-
-	/* No block descriptors */
-
-	/* The mode pages, in numerical order.  The only page we support
-	 * is the Caching page. */
-	if (page_code == 0x08 || all_pages) {
-		valid_page = 1;
-		buf[0] = 0x08;		// Page code
-		buf[1] = 10;		// Page length
-		memset(buf+2, 0, 10);	// None of the fields are changeable
-
-		if (!changeable_values) {
-			buf[2] = 0x04;	// Write cache enable,
-					// Read cache not disabled
-					// No cache retention priorities
-			put_be16(&buf[4], 0xffff);  // Don't disable prefetch
-					// Minimum prefetch = 0
-			put_be16(&buf[8], 0xffff);  // Maximum prefetch
-			put_be16(&buf[10], 0xffff); // Maximum prefetch ceiling
-		}
-		buf += 12;
-	}
-
-	/* Check that a valid page was requested and the mode data length
-	 * isn't too long. */
-	len = buf - buf0;
-	if (!valid_page || len > limit) {
-		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-		return -EINVAL;
-	}
-
-	/*  Store the mode data length */
-	if (mscmnd == SC_MODE_SENSE_6)
-		buf0[0] = len - 1;
-	else
-		put_be16(buf0, len - 2);
-	return len;
-}
-
-
-static int do_start_stop(struct fsg_dev *fsg)
-{
-	struct lun	*curlun = fsg->curlun;
-	int		loej, start;
-
-	if (!mod_data.removable) {
-		curlun->sense_data = SS_INVALID_COMMAND;
-		return -EINVAL;
-	}
-
-	// int immed = fsg->cmnd[1] & 0x01;
-	loej = fsg->cmnd[4] & 0x02;
-	start = fsg->cmnd[4] & 0x01;
-
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
-	if ((fsg->cmnd[1] & ~0x01) != 0 ||		// Mask away Immed
-			(fsg->cmnd[4] & ~0x03) != 0) {	// Mask LoEj, Start
-		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-		return -EINVAL;
-	}
-
-	if (!start) {
-
-		/* Are we allowed to unload the media? */
-		if (curlun->prevent_medium_removal) {
-			LDBG(curlun, "unload attempt prevented\n");
-			curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED;
-			return -EINVAL;
-		}
-		if (loej) {		// Simulate an unload/eject
-			up_read(&fsg->filesem);
-			down_write(&fsg->filesem);
-			close_backing_file(curlun);
-			up_write(&fsg->filesem);
-			down_read(&fsg->filesem);
-		}
-	} else {
-
-		/* Our emulation doesn't support mounting; the medium is
-		 * available for use as soon as it is loaded. */
-		if (!backing_file_is_open(curlun)) {
-			curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
-			return -EINVAL;
-		}
-	}
-#endif
-	return 0;
-}
-
-
-static int do_prevent_allow(struct fsg_dev *fsg)
-{
-	struct lun	*curlun = fsg->curlun;
-	int		prevent;
-
-	if (!mod_data.removable) {
-		curlun->sense_data = SS_INVALID_COMMAND;
-		return -EINVAL;
-	}
-
-	prevent = fsg->cmnd[4] & 0x01;
-	if ((fsg->cmnd[4] & ~0x01) != 0) {		// Mask away Prevent
-		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-		return -EINVAL;
-	}
-
-	if (curlun->prevent_medium_removal && !prevent)
-		fsync_sub(curlun);
-	curlun->prevent_medium_removal = prevent;
-	return 0;
-}
-
-
-static int do_read_format_capacities(struct fsg_dev *fsg,
-			struct fsg_buffhd *bh)
-{
-	struct lun	*curlun = fsg->curlun;
-	u8		*buf = (u8 *) bh->buf;
-
-	buf[0] = buf[1] = buf[2] = 0;
-	buf[3] = 8;		// Only the Current/Maximum Capacity Descriptor
-	buf += 4;
-
-	put_be32(&buf[0], curlun->num_sectors);		// Number of blocks
-	put_be32(&buf[4], 512);				// Block length
-	buf[4] = 0x02;					// Current capacity
-	return 12;
-}
-
-
-static int do_mode_select(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
-	struct lun	*curlun = fsg->curlun;
-
-	/* We don't support MODE SELECT */
-	curlun->sense_data = SS_INVALID_COMMAND;
-	return -EINVAL;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int halt_bulk_in_endpoint(struct fsg_dev *fsg)
-{
-	int	rc;
-
-	rc = fsg_set_halt(fsg, fsg->bulk_in);
-	if (rc == -EAGAIN)
-		VDBG(fsg, "delayed bulk-in endpoint halt\n");
-	while (rc != 0) {
-		if (rc != -EAGAIN) {
-			WARN(fsg, "usb_ep_set_halt -> %d\n", rc);
-			rc = 0;
-			break;
-		}
-
-		/* Wait for a short time and then try again */
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (schedule_timeout(HZ / 10) != 0)
-			return -EINTR;
-		rc = usb_ep_set_halt(fsg->bulk_in);
-	}
-	return rc;
-}
-
-static int pad_with_zeros(struct fsg_dev *fsg)
-{
-	struct fsg_buffhd	*bh = fsg->next_buffhd_to_fill;
-	u32			nkeep = bh->inreq->length;
-	u32			nsend;
-	int			rc;
-
-	bh->state = BUF_STATE_EMPTY;		// For the first iteration
-	fsg->usb_amount_left = nkeep + fsg->residue;
-	while (fsg->usb_amount_left > 0) {
-
-		/* Wait for the next buffer to be free */
-		while (bh->state != BUF_STATE_EMPTY) {
-			if ((rc = sleep_thread(fsg)) != 0)
-				return rc;
-		}
-
-		nsend = min(fsg->usb_amount_left, (u32) mod_data.buflen);
-		memset(bh->buf + nkeep, 0, nsend - nkeep);
-		bh->inreq->length = nsend;
-		bh->inreq->zero = 0;
-		start_transfer(fsg, fsg->bulk_in, bh->inreq,
-				&bh->inreq_busy, &bh->state);
-		bh = fsg->next_buffhd_to_fill = bh->next;
-		fsg->usb_amount_left -= nsend;
-		nkeep = 0;
-	}
-	return 0;
-}
-
-static int throw_away_data(struct fsg_dev *fsg)
-{
-	struct fsg_buffhd	*bh;
-	u32			amount;
-	int			rc;
-
-	while ((bh = fsg->next_buffhd_to_drain)->state != BUF_STATE_EMPTY ||
-			fsg->usb_amount_left > 0) {
-
-		/* Throw away the data in a filled buffer */
-		if (bh->state == BUF_STATE_FULL) {
-			bh->state = BUF_STATE_EMPTY;
-			fsg->next_buffhd_to_drain = bh->next;
-
-			/* A short packet or an error ends everything */
-			if (bh->outreq->actual != bh->outreq->length ||
-					bh->outreq->status != 0) {
-				raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
-				return -EINTR;
-			}
-			continue;
-		}
-
-		/* Try to submit another request if we need one */
-		bh = fsg->next_buffhd_to_fill;
-		if (bh->state == BUF_STATE_EMPTY && fsg->usb_amount_left > 0) {
-			amount = min(fsg->usb_amount_left,
-					(u32) mod_data.buflen);
-
-			/* amount is always divisible by 512, hence by
-			 * the bulk-out maxpacket size */
-			bh->outreq->length = bh->bulk_out_intended_length =
-					amount;
-			start_transfer(fsg, fsg->bulk_out, bh->outreq,
-					&bh->outreq_busy, &bh->state);
-			fsg->next_buffhd_to_fill = bh->next;
-			fsg->usb_amount_left -= amount;
-			continue;
-		}
-
-		/* Otherwise wait for something to happen */
-		if ((rc = sleep_thread(fsg)) != 0)
-			return rc;
-	}
-	return 0;
-}
-
-
-static int finish_reply(struct fsg_dev *fsg)
-{
-	struct fsg_buffhd	*bh = fsg->next_buffhd_to_fill;
-	int			rc = 0;
-
-	switch (fsg->data_dir) {
-	case DATA_DIR_NONE:
-		break;			// Nothing to send
-
-	/* If we don't know whether the host wants to read or write,
-	 * this must be CB or CBI with an unknown command.  We mustn't
-	 * try to send or receive any data.  So stall both bulk pipes
-	 * if we can and wait for a reset. */
-	case DATA_DIR_UNKNOWN:
-		if (mod_data.can_stall) {
-			fsg_set_halt(fsg, fsg->bulk_out);
-			rc = halt_bulk_in_endpoint(fsg);
-		}
-		break;
-
-	/* All but the last buffer of data must have already been sent */
-	case DATA_DIR_TO_HOST:
-		if (fsg->data_size == 0)
-			;		// Nothing to send
-
-		/* If there's no residue, simply send the last buffer */
-		else if (fsg->residue == 0) {
-			bh->inreq->zero = 0;
-			start_transfer(fsg, fsg->bulk_in, bh->inreq,
-					&bh->inreq_busy, &bh->state);
-			fsg->next_buffhd_to_fill = bh->next;
-		}
-
-		/* There is a residue.  For CB and CBI, simply mark the end
-		 * of the data with a short packet.  However, if we are
-		 * allowed to stall, there was no data at all (residue ==
-		 * data_size), and the command failed (invalid LUN or
-		 * sense data is set), then halt the bulk-in endpoint
-		 * instead. */
-		else if (!transport_is_bbb()) {
-			if (mod_data.can_stall &&
-					fsg->residue == fsg->data_size &&
-	(!fsg->curlun || fsg->curlun->sense_data != SS_NO_SENSE)) {
-				bh->state = BUF_STATE_EMPTY;
-				rc = halt_bulk_in_endpoint(fsg);
-			} else {
-				bh->inreq->zero = 1;
-				start_transfer(fsg, fsg->bulk_in, bh->inreq,
-						&bh->inreq_busy, &bh->state);
-				fsg->next_buffhd_to_fill = bh->next;
-			}
-		}
-
-		/* For Bulk-only, if we're allowed to stall then send the
-		 * short packet and halt the bulk-in endpoint.  If we can't
-		 * stall, pad out the remaining data with 0's. */
-		else {
-			if (mod_data.can_stall) {
-				bh->inreq->zero = 1;
-				start_transfer(fsg, fsg->bulk_in, bh->inreq,
-						&bh->inreq_busy, &bh->state);
-				fsg->next_buffhd_to_fill = bh->next;
-				rc = halt_bulk_in_endpoint(fsg);
-			} else
-				rc = pad_with_zeros(fsg);
-		}
-		break;
-
-	/* We have processed all we want from the data the host has sent.
-	 * There may still be outstanding bulk-out requests. */
-	case DATA_DIR_FROM_HOST:
-		if (fsg->residue == 0)
-			;		// Nothing to receive
-
-		/* Did the host stop sending unexpectedly early? */
-		else if (fsg->short_packet_received) {
-			raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
-			rc = -EINTR;
-		}
-
-		/* We haven't processed all the incoming data.  If we are
-		 * allowed to stall, halt the bulk-out endpoint and cancel
-		 * any outstanding requests. */
-		else if (mod_data.can_stall) {
-			fsg_set_halt(fsg, fsg->bulk_out);
-			raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
-			rc = -EINTR;
-		}
-
-		/* We can't stall.  Read in the excess data and throw it
-		 * all away. */
-		else
-			rc = throw_away_data(fsg);
-		break;
-	}
-	return rc;
-}
-
-
-static int send_status(struct fsg_dev *fsg)
-{
-	struct lun		*curlun = fsg->curlun;
-	struct fsg_buffhd	*bh;
-	int			rc;
-	u8			status = USB_STATUS_PASS;
-	u32			sd, sdinfo = 0;
-
-	/* Wait for the next buffer to become available */
-	bh = fsg->next_buffhd_to_fill;
-	while (bh->state != BUF_STATE_EMPTY) {
-		if ((rc = sleep_thread(fsg)) != 0)
-			return rc;
-	}
-
-	if (curlun) {
-		sd = curlun->sense_data;
-		sdinfo = curlun->sense_data_info;
-	} else if (fsg->bad_lun_okay)
-		sd = SS_NO_SENSE;
-	else
-		sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
-
-	if (fsg->phase_error) {
-		DBG(fsg, "sending phase-error status\n");
-		status = USB_STATUS_PHASE_ERROR;
-		sd = SS_INVALID_COMMAND;
-	} else if (sd != SS_NO_SENSE) {
-		DBG(fsg, "sending command-failure status\n");
-		status = USB_STATUS_FAIL;
-		VDBG(fsg, "  sense data: SK x%02x, ASC x%02x, ASCQ x%02x;"
-				"  info x%x\n",
-				SK(sd), ASC(sd), ASCQ(sd), sdinfo);
-	}
-
-	if (transport_is_bbb()) {
-		struct bulk_cs_wrap	*csw = (struct bulk_cs_wrap *) bh->buf;
-
-		/* Store and send the Bulk-only CSW */
-		csw->Signature = __constant_cpu_to_le32(USB_BULK_CS_SIG);
-		csw->Tag = fsg->tag;
-		csw->Residue = fsg->residue;
-		csw->Status = status;
-
-		bh->inreq->length = USB_BULK_CS_WRAP_LEN;
-		bh->inreq->zero = 0;
-		start_transfer(fsg, fsg->bulk_in, bh->inreq,
-				&bh->inreq_busy, &bh->state);
-
-	} else if (mod_data.transport_type == USB_PR_CB) {
-
-		/* Control-Bulk transport has no status stage! */
-		return 0;
-
-	} else {			// USB_PR_CBI
-		struct interrupt_data	*buf = (struct interrupt_data *)
-						bh->buf;
-
-		/* Store and send the Interrupt data.  UFI sends the ASC
-		 * and ASCQ bytes.  Everything else sends a Type (which
-		 * is always 0) and the status Value. */
-		if (mod_data.protocol_type == USB_SC_UFI) {
-			buf->bType = ASC(sd);
-			buf->bValue = ASCQ(sd);
-		} else {
-			buf->bType = 0;
-			buf->bValue = status;
-		}
-		fsg->intreq->length = CBI_INTERRUPT_DATA_LEN;
-
-		fsg->intr_buffhd = bh;		// Point to the right buffhd
-		fsg->intreq->buf = bh->inreq->buf;
-		fsg->intreq->dma = bh->inreq->dma;
-		fsg->intreq->context = bh;
-		start_transfer(fsg, fsg->intr_in, fsg->intreq,
-				&fsg->intreq_busy, &bh->state);
-	}
-
-	fsg->next_buffhd_to_fill = bh->next;
-	return 0;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* Check whether the command is properly formed and whether its data size
- * and direction agree with the values we already have. */
-static int check_command(struct fsg_dev *fsg, int cmnd_size,
-		enum data_direction data_dir, unsigned int mask,
-		int needs_medium, const char *name)
-{
-	int			i;
-	int			lun = fsg->cmnd[1] >> 5;
-	static const char	dirletter[4] = {'u', 'o', 'i', 'n'};
-	char			hdlen[20];
-	struct lun		*curlun;
-
-	/* Adjust the expected cmnd_size for protocol encapsulation padding.
-	 * Transparent SCSI doesn't pad. */
-	if (protocol_is_scsi())
-		;
-
-	/* There's some disagreement as to whether RBC pads commands or not.
-	 * We'll play it safe and accept either form. */
-	else if (mod_data.protocol_type == USB_SC_RBC) {
-		if (fsg->cmnd_size == 12)
-			cmnd_size = 12;
-
-	/* All the other protocols pad to 12 bytes */
-	} else
-		cmnd_size = 12;
-
-	hdlen[0] = 0;
-	if (fsg->data_dir != DATA_DIR_UNKNOWN)
-		sprintf(hdlen, ", H%c=%u", dirletter[(int) fsg->data_dir],
-				fsg->data_size);
-	VDBG(fsg, "SCSI command: %s;  Dc=%d, D%c=%u;  Hc=%d%s\n",
-			name, cmnd_size, dirletter[(int) data_dir],
-			fsg->data_size_from_cmnd, fsg->cmnd_size, hdlen);
-
-	/* We can't reply at all until we know the correct data direction
-	 * and size. */
-	if (fsg->data_size_from_cmnd == 0)
-		data_dir = DATA_DIR_NONE;
-	if (fsg->data_dir == DATA_DIR_UNKNOWN) {	// CB or CBI
-		fsg->data_dir = data_dir;
-		fsg->data_size = fsg->data_size_from_cmnd;
-
-	} else {					// Bulk-only
-		if (fsg->data_size < fsg->data_size_from_cmnd) {
-
-			/* Host data size < Device data size is a phase error.
-			 * Carry out the command, but only transfer as much
-			 * as we are allowed. */
-			fsg->data_size_from_cmnd = fsg->data_size;
-			fsg->phase_error = 1;
-		}
-	}
-	fsg->residue = fsg->usb_amount_left = fsg->data_size;
-
-	/* Conflicting data directions is a phase error */
-	if (fsg->data_dir != data_dir && fsg->data_size_from_cmnd > 0)
-		goto phase_error;
-
-	/* Verify the length of the command itself */
-	if (cmnd_size != fsg->cmnd_size) {
-
-		/* Special case workaround: MS-Windows issues REQUEST SENSE
-		 * with cbw->Length == 12 (it should be 6). */
-		if (fsg->cmnd[0] == SC_REQUEST_SENSE && fsg->cmnd_size == 12)
-			cmnd_size = fsg->cmnd_size;
-		else
-			goto phase_error;
-	}
-
-	/* Check that the LUN values are oonsistent */
-	if (transport_is_bbb()) {
-		if (fsg->lun != lun)
-			DBG(fsg, "using LUN %d from CBW, "
-					"not LUN %d from CDB\n",
-					fsg->lun, lun);
-	} else
-		fsg->lun = lun;		// Use LUN from the command
-
-	/* Check the LUN */
-	if (fsg->lun >= 0 && fsg->lun < fsg->nluns) {
-		fsg->curlun = curlun = &fsg->luns[fsg->lun];
-		if (fsg->cmnd[0] != SC_REQUEST_SENSE) {
-			curlun->sense_data = SS_NO_SENSE;
-			curlun->sense_data_info = 0;
-		}
-	} else {
-		fsg->curlun = curlun = NULL;
-		fsg->bad_lun_okay = 0;
-
-		/* INQUIRY and REQUEST SENSE commands are explicitly allowed
-		 * to use unsupported LUNs; all others may not. */
-		if (fsg->cmnd[0] != SC_INQUIRY &&
-				fsg->cmnd[0] != SC_REQUEST_SENSE) {
-			DBG(fsg, "unsupported LUN %d\n", fsg->lun);
-			return -EINVAL;
-		}
-	}
-
-	/* If a unit attention condition exists, only INQUIRY and
-	 * REQUEST SENSE commands are allowed; anything else must fail. */
-	if (curlun && curlun->unit_attention_data != SS_NO_SENSE &&
-			fsg->cmnd[0] != SC_INQUIRY &&
-			fsg->cmnd[0] != SC_REQUEST_SENSE) {
-		curlun->sense_data = curlun->unit_attention_data;
-		curlun->unit_attention_data = SS_NO_SENSE;
-		return -EINVAL;
-	}
-
-	/* Check that only command bytes listed in the mask are non-zero */
-	fsg->cmnd[1] &= 0x1f;			// Mask away the LUN
-	for (i = 1; i < cmnd_size; ++i) {
-		if (fsg->cmnd[i] && !(mask & (1 << i))) {
-			if (curlun)
-				curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-			return -EINVAL;
-		}
-	}
-
-	/* If the medium isn't mounted and the command needs to access
-	 * it, return an error. */
-	if (curlun && !backing_file_is_open(curlun) && needs_medium) {
-		curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
-		return -EINVAL;
-	}
-
-	return 0;
-
-phase_error:
-	fsg->phase_error = 1;
-	return -EINVAL;
-}
-
-
-static int do_scsi_command(struct fsg_dev *fsg)
-{
-	struct fsg_buffhd	*bh;
-	int			rc;
-	int			reply = -EINVAL;
-	int			i;
-	static char		unknown[16];
-
-	dump_cdb(fsg);
-
-	/* Wait for the next buffer to become available for data or status */
-	bh = fsg->next_buffhd_to_drain = fsg->next_buffhd_to_fill;
-	while (bh->state != BUF_STATE_EMPTY) {
-		if ((rc = sleep_thread(fsg)) != 0)
-			return rc;
-		}
-	fsg->phase_error = 0;
-	fsg->short_packet_received = 0;
-
-	down_read(&fsg->filesem);	// We're using the backing file
-	switch (fsg->cmnd[0]) {
-
-	case SC_INQUIRY:
-		fsg->data_size_from_cmnd = fsg->cmnd[4];
-		if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
-				(1<<4), 0,
-				"INQUIRY")) == 0)
-			reply = do_inquiry(fsg, bh);
-		break;
-
-	case SC_MODE_SELECT_6:
-		fsg->data_size_from_cmnd = fsg->cmnd[4];
-		if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST,
-				(1<<1) | (1<<4), 0,
-				"MODE SELECT(6)")) == 0)
-			reply = do_mode_select(fsg, bh);
-		break;
-
-	case SC_MODE_SELECT_10:
-		fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]);
-		if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST,
-				(1<<1) | (3<<7), 0,
-				"MODE SELECT(10)")) == 0)
-			reply = do_mode_select(fsg, bh);
-		break;
-
-	case SC_MODE_SENSE_6:
-		fsg->data_size_from_cmnd = fsg->cmnd[4];
-		if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
-				(1<<1) | (1<<2) | (1<<4), 0,
-				"MODE SENSE(6)")) == 0)
-			reply = do_mode_sense(fsg, bh);
-		break;
-
-	case SC_MODE_SENSE_10:
-		fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]);
-		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
-				(1<<1) | (1<<2) | (3<<7), 0,
-				"MODE SENSE(10)")) == 0)
-			reply = do_mode_sense(fsg, bh);
-		break;
-
-	case SC_PREVENT_ALLOW_MEDIUM_REMOVAL:
-		fsg->data_size_from_cmnd = 0;
-		if ((reply = check_command(fsg, 6, DATA_DIR_NONE,
-				(1<<4), 0,
-				"PREVENT-ALLOW MEDIUM REMOVAL")) == 0)
-			reply = do_prevent_allow(fsg);
-		break;
-
-	case SC_READ_6:
-		i = fsg->cmnd[4];
-		fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << 9;
-		if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
-				(7<<1) | (1<<4), 1,
-				"READ(6)")) == 0)
-			reply = do_read(fsg);
-		break;
-
-	case SC_READ_10:
-		fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]) << 9;
-		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
-				(1<<1) | (0xf<<2) | (3<<7), 1,
-				"READ(10)")) == 0)
-			reply = do_read(fsg);
-		break;
-
-	case SC_READ_12:
-		fsg->data_size_from_cmnd = get_be32(&fsg->cmnd[6]) << 9;
-		if ((reply = check_command(fsg, 12, DATA_DIR_TO_HOST,
-				(1<<1) | (0xf<<2) | (0xf<<6), 1,
-				"READ(12)")) == 0)
-			reply = do_read(fsg);
-		break;
-
-	case SC_READ_CAPACITY:
-		fsg->data_size_from_cmnd = 8;
-		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
-				(0xf<<2) | (1<<8), 1,
-				"READ CAPACITY")) == 0)
-			reply = do_read_capacity(fsg, bh);
-		break;
-
-	case SC_READ_FORMAT_CAPACITIES:
-		fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]);
-		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
-				(3<<7), 1,
-				"READ FORMAT CAPACITIES")) == 0)
-			reply = do_read_format_capacities(fsg, bh);
-		break;
-
-	case SC_REQUEST_SENSE:
-		fsg->data_size_from_cmnd = fsg->cmnd[4];
-		if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
-				(1<<4), 0,
-				"REQUEST SENSE")) == 0)
-			reply = do_request_sense(fsg, bh);
-		break;
-
-	case SC_START_STOP_UNIT:
-		fsg->data_size_from_cmnd = 0;
-		if ((reply = check_command(fsg, 6, DATA_DIR_NONE,
-				(1<<1) | (1<<4), 0,
-				"START-STOP UNIT")) == 0)
-			reply = do_start_stop(fsg);
-		break;
-
-	case SC_SYNCHRONIZE_CACHE:
-		fsg->data_size_from_cmnd = 0;
-		if ((reply = check_command(fsg, 10, DATA_DIR_NONE,
-				(0xf<<2) | (3<<7), 1,
-				"SYNCHRONIZE CACHE")) == 0)
-			reply = do_synchronize_cache(fsg);
-		break;
-
-	case SC_TEST_UNIT_READY:
-		fsg->data_size_from_cmnd = 0;
-		reply = check_command(fsg, 6, DATA_DIR_NONE,
-				0, 1,
-				"TEST UNIT READY");
-		break;
-
-	/* Although optional, this command is used by MS-Windows.  We
-	 * support a minimal version: BytChk must be 0. */
-	case SC_VERIFY:
-		fsg->data_size_from_cmnd = 0;
-		if ((reply = check_command(fsg, 10, DATA_DIR_NONE,
-				(1<<1) | (0xf<<2) | (3<<7), 1,
-				"VERIFY")) == 0)
-			reply = do_verify(fsg);
-		break;
-
-	case SC_WRITE_6:
-		i = fsg->cmnd[4];
-		fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << 9;
-		if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST,
-				(7<<1) | (1<<4), 1,
-				"WRITE(6)")) == 0)
-			reply = do_write(fsg);
-		break;
-
-	case SC_WRITE_10:
-		fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]) << 9;
-		if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST,
-				(1<<1) | (0xf<<2) | (3<<7), 1,
-				"WRITE(10)")) == 0)
-			reply = do_write(fsg);
-		break;
-
-	case SC_WRITE_12:
-		fsg->data_size_from_cmnd = get_be32(&fsg->cmnd[6]) << 9;
-		if ((reply = check_command(fsg, 12, DATA_DIR_FROM_HOST,
-				(1<<1) | (0xf<<2) | (0xf<<6), 1,
-				"WRITE(12)")) == 0)
-			reply = do_write(fsg);
-		break;
-
-	/* Some mandatory commands that we recognize but don't implement.
-	 * They don't mean much in this setting.  It's left as an exercise
-	 * for anyone interested to implement RESERVE and RELEASE in terms
-	 * of Posix locks. */
-	case SC_FORMAT_UNIT:
-	case SC_RELEASE:
-	case SC_RESERVE:
-	case SC_SEND_DIAGNOSTIC:
-		// Fall through
-
-	default:
-		fsg->data_size_from_cmnd = 0;
-		sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]);
-		if ((reply = check_command(fsg, fsg->cmnd_size,
-				DATA_DIR_UNKNOWN, 0xff, 0, unknown)) == 0) {
-			fsg->curlun->sense_data = SS_INVALID_COMMAND;
-			reply = -EINVAL;
-		}
-		break;
-	}
-	up_read(&fsg->filesem);
-
-	if (reply == -EINTR || signal_pending(current))
-		return -EINTR;
-
-	/* Set up the single reply buffer for finish_reply() */
-	if (reply == -EINVAL)
-		reply = 0;		// Error reply length
-	if (reply >= 0 && fsg->data_dir == DATA_DIR_TO_HOST) {
-		reply = min((u32) reply, fsg->data_size_from_cmnd);
-		bh->inreq->length = reply;
-		bh->state = BUF_STATE_FULL;
-		fsg->residue -= reply;
-	}				// Otherwise it's already set
-
-	return 0;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
-	struct usb_request	*req = bh->outreq;
-	struct bulk_cb_wrap	*cbw = (struct bulk_cb_wrap *) req->buf;
-
-	/* Was this a real packet? */
-	if (req->status)
-		return -EINVAL;
-
-	/* Is the CBW valid? */
-	if (req->actual != USB_BULK_CB_WRAP_LEN ||
-			cbw->Signature != __constant_cpu_to_le32(
-				USB_BULK_CB_SIG)) {
-		DBG(fsg, "invalid CBW: len %u sig 0x%x\n",
-				req->actual,
-				le32_to_cpu(cbw->Signature));
-
-		/* The Bulk-only spec says we MUST stall the bulk pipes!
-		 * If we want to avoid stalls, set a flag so that we will
-		 * clear the endpoint halts at the next reset. */
-		if (!mod_data.can_stall)
-			set_bit(CLEAR_BULK_HALTS, &fsg->atomic_bitflags);
-		fsg_set_halt(fsg, fsg->bulk_out);
-		halt_bulk_in_endpoint(fsg);
-		return -EINVAL;
-	}
-
-	/* Is the CBW meaningful? */
-	if (cbw->Lun >= MAX_LUNS || cbw->Flags & ~USB_BULK_IN_FLAG ||
-			cbw->Length < 6 || cbw->Length > MAX_COMMAND_SIZE) {
-		DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, "
-				"cmdlen %u\n",
-				cbw->Lun, cbw->Flags, cbw->Length);
-
-		/* We can do anything we want here, so let's stall the
-		 * bulk pipes if we are allowed to. */
-		if (mod_data.can_stall) {
-			fsg_set_halt(fsg, fsg->bulk_out);
-			halt_bulk_in_endpoint(fsg);
-		}
-		return -EINVAL;
-	}
-
-	/* Save the command for later */
-	fsg->cmnd_size = cbw->Length;
-	memcpy(fsg->cmnd, cbw->CDB, fsg->cmnd_size);
-	if (cbw->Flags & USB_BULK_IN_FLAG)
-		fsg->data_dir = DATA_DIR_TO_HOST;
-	else
-		fsg->data_dir = DATA_DIR_FROM_HOST;
-	fsg->data_size = cbw->DataTransferLength;
-	if (fsg->data_size == 0)
-		fsg->data_dir = DATA_DIR_NONE;
-	fsg->lun = cbw->Lun;
-	fsg->tag = cbw->Tag;
-	return 0;
-}
-
-
-static int get_next_command(struct fsg_dev *fsg)
-{
-	struct fsg_buffhd	*bh;
-	int			rc = 0;
-
-	if (transport_is_bbb()) {
-
-		/* Wait for the next buffer to become available */
-		bh = fsg->next_buffhd_to_fill;
-		while (bh->state != BUF_STATE_EMPTY) {
-			if ((rc = sleep_thread(fsg)) != 0)
-				return rc;
-			}
-
-		/* Queue a request to read a Bulk-only CBW */
-		set_bulk_out_req_length(fsg, bh, USB_BULK_CB_WRAP_LEN);
-		start_transfer(fsg, fsg->bulk_out, bh->outreq,
-				&bh->outreq_busy, &bh->state);
-
-		/* We will drain the buffer in software, which means we
-		 * can reuse it for the next filling.  No need to advance
-		 * next_buffhd_to_fill. */
-
-		/* Wait for the CBW to arrive */
-		while (bh->state != BUF_STATE_FULL) {
-			if ((rc = sleep_thread(fsg)) != 0)
-				return rc;
-			}
-		rc = received_cbw(fsg, bh);
-		bh->state = BUF_STATE_EMPTY;
-
-	} else {		// USB_PR_CB or USB_PR_CBI
-
-		/* Wait for the next command to arrive */
-		while (fsg->cbbuf_cmnd_size == 0) {
-			if ((rc = sleep_thread(fsg)) != 0)
-				return rc;
-			}
-
-		/* Is the previous status interrupt request still busy?
-		 * The host is allowed to skip reading the status,
-		 * so we must cancel it. */
-		if (fsg->intreq_busy)
-			usb_ep_dequeue(fsg->intr_in, fsg->intreq);
-
-		/* Copy the command and mark the buffer empty */
-		fsg->data_dir = DATA_DIR_UNKNOWN;
-		spin_lock_irq(&fsg->lock);
-		fsg->cmnd_size = fsg->cbbuf_cmnd_size;
-		memcpy(fsg->cmnd, fsg->cbbuf_cmnd, fsg->cmnd_size);
-		fsg->cbbuf_cmnd_size = 0;
-		spin_unlock_irq(&fsg->lock);
-	}
-	return rc;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int enable_endpoint(struct fsg_dev *fsg, struct usb_ep *ep,
-		const struct usb_endpoint_descriptor *d)
-{
-	int	rc;
-
-	ep->driver_data = fsg;
-	rc = usb_ep_enable(ep, d);
-	if (rc)
-		ERROR(fsg, "can't enable %s, result %d\n", ep->name, rc);
-	return rc;
-}
-
-static int alloc_request(struct fsg_dev *fsg, struct usb_ep *ep,
-		struct usb_request **preq)
-{
-	*preq = usb_ep_alloc_request(ep, GFP_ATOMIC);
-	if (*preq)
-		return 0;
-	ERROR(fsg, "can't allocate request for %s\n", ep->name);
-	return -ENOMEM;
-}
-
-/*
- * Reset interface setting and re-init endpoint state (toggle etc).
- * Call with altsetting < 0 to disable the interface.  The only other
- * available altsetting is 0, which enables the interface.
- */
-static int do_set_interface(struct fsg_dev *fsg, int altsetting)
-{
-	int	rc = 0;
-	int	i;
-	const struct usb_endpoint_descriptor	*d;
-
-	if (fsg->running)
-		DBG(fsg, "reset interface\n");
-
-reset:
-	/* Deallocate the requests */
-	for (i = 0; i < NUM_BUFFERS; ++i) {
-		struct fsg_buffhd *bh = &fsg->buffhds[i];
-
-		if (bh->inreq) {
-			usb_ep_free_request(fsg->bulk_in, bh->inreq);
-			bh->inreq = NULL;
-		}
-		if (bh->outreq) {
-			usb_ep_free_request(fsg->bulk_out, bh->outreq);
-			bh->outreq = NULL;
-		}
-	}
-	if (fsg->intreq) {
-		usb_ep_free_request(fsg->intr_in, fsg->intreq);
-		fsg->intreq = NULL;
-	}
-
-	/* Disable the endpoints */
-	if (fsg->bulk_in_enabled) {
-		usb_ep_disable(fsg->bulk_in);
-		fsg->bulk_in_enabled = 0;
-	}
-	if (fsg->bulk_out_enabled) {
-		usb_ep_disable(fsg->bulk_out);
-		fsg->bulk_out_enabled = 0;
-	}
-	if (fsg->intr_in_enabled) {
-		usb_ep_disable(fsg->intr_in);
-		fsg->intr_in_enabled = 0;
-	}
-
-	fsg->running = 0;
-	if (altsetting < 0 || rc != 0)
-		return rc;
-
-	DBG(fsg, "set interface %d\n", altsetting);
-
-	/* Enable the endpoints */
-	d = ep_desc(fsg->gadget, &fs_bulk_in_desc, &hs_bulk_in_desc);
-	if ((rc = enable_endpoint(fsg, fsg->bulk_in, d)) != 0)
-		goto reset;
-	fsg->bulk_in_enabled = 1;
-
-	d = ep_desc(fsg->gadget, &fs_bulk_out_desc, &hs_bulk_out_desc);
-	if ((rc = enable_endpoint(fsg, fsg->bulk_out, d)) != 0)
-		goto reset;
-	fsg->bulk_out_enabled = 1;
-
-	if (transport_is_cbi()) {
-		d = ep_desc(fsg->gadget, &fs_intr_in_desc, &hs_intr_in_desc);
-		if ((rc = enable_endpoint(fsg, fsg->intr_in, d)) != 0)
-			goto reset;
-		fsg->intr_in_enabled = 1;
-	}
-
-	/* Allocate the requests */
-	for (i = 0; i < NUM_BUFFERS; ++i) {
-		struct fsg_buffhd	*bh = &fsg->buffhds[i];
-
-		if ((rc = alloc_request(fsg, fsg->bulk_in, &bh->inreq)) != 0)
-			goto reset;
-		if ((rc = alloc_request(fsg, fsg->bulk_out, &bh->outreq)) != 0)
-			goto reset;
-		bh->inreq->buf = bh->outreq->buf = bh->buf;
-		bh->inreq->dma = bh->outreq->dma = bh->dma;
-		bh->inreq->context = bh->outreq->context = bh;
-		bh->inreq->complete = bulk_in_complete;
-		bh->outreq->complete = bulk_out_complete;
-	}
-	if (transport_is_cbi()) {
-		if ((rc = alloc_request(fsg, fsg->intr_in, &fsg->intreq)) != 0)
-			goto reset;
-		fsg->intreq->complete = intr_in_complete;
-	}
-
-	fsg->running = 1;
-	for (i = 0; i < fsg->nluns; ++i)
-		fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED;
-	return rc;
-}
-
-
-/*
- * Change our operational configuration.  This code must agree with the code
- * that returns config descriptors, and with interface altsetting code.
- *
- * It's also responsible for power management interactions.  Some
- * configurations might not work with our current power sources.
- * For now we just assume the gadget is always self-powered.
- */
-static int do_set_config(struct fsg_dev *fsg, u8 new_config)
-{
-	int	rc = 0;
-
-	/* Disable the single interface */
-	if (fsg->config != 0) {
-		DBG(fsg, "reset config\n");
-		fsg->config = 0;
-		rc = do_set_interface(fsg, -1);
-	}
-
-	/* Enable the interface */
-	if (new_config != 0) {
-		fsg->config = new_config;
-		if ((rc = do_set_interface(fsg, 0)) != 0)
-			fsg->config = 0;	// Reset on errors
-		else {
-			char *speed;
-
-			switch (fsg->gadget->speed) {
-			case USB_SPEED_LOW:	speed = "low";	break;
-			case USB_SPEED_FULL:	speed = "full";	break;
-			case USB_SPEED_HIGH:	speed = "high";	break;
-			default: 		speed = "?";	break;
-			}
-			INFO(fsg, "%s speed config #%d\n", speed, fsg->config);
-		}
-	}
-	return rc;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static void handle_exception(struct fsg_dev *fsg)
-{
-	siginfo_t		info;
-	int			sig;
-	int			i;
-	int			num_active;
-	struct fsg_buffhd	*bh;
-	enum fsg_state		old_state;
-	u8			new_config;
-	struct lun		*curlun;
-	unsigned int		exception_req_tag;
-	int			rc;
-
-	/* Clear the existing signals.  Anything but SIGUSR1 is converted
-	 * into a high-priority EXIT exception. */
-	for (;;) {
-		spin_lock_irq(&current->sigmask_lock);
-		sig = dequeue_signal(&fsg->thread_signal_mask, &info);
-		spin_unlock_irq(&current->sigmask_lock);
-		if (!sig)
-			break;
-		if (sig != SIGUSR1) {
-			if (fsg->state < FSG_STATE_EXIT)
-				DBG(fsg, "Main thread exiting on signal\n");
-			raise_exception(fsg, FSG_STATE_EXIT);
-		}
-	}
-
-	/* Cancel all the pending transfers */
-	if (fsg->intreq_busy)
-		usb_ep_dequeue(fsg->intr_in, fsg->intreq);
-	for (i = 0; i < NUM_BUFFERS; ++i) {
-		bh = &fsg->buffhds[i];
-		if (bh->inreq_busy)
-			usb_ep_dequeue(fsg->bulk_in, bh->inreq);
-		if (bh->outreq_busy)
-			usb_ep_dequeue(fsg->bulk_out, bh->outreq);
-	}
-
-	/* Wait until everything is idle */
-	for (;;) {
-		num_active = fsg->intreq_busy;
-		for (i = 0; i < NUM_BUFFERS; ++i) {
-			bh = &fsg->buffhds[i];
-			num_active += bh->inreq_busy + bh->outreq_busy;
-		}
-		if (num_active == 0)
-			break;
-		if (sleep_thread(fsg))
-			return;
-	}
-
-	/* Clear out the controller's fifos */
-	if (fsg->bulk_in_enabled)
-		usb_ep_fifo_flush(fsg->bulk_in);
-	if (fsg->bulk_out_enabled)
-		usb_ep_fifo_flush(fsg->bulk_out);
-	if (fsg->intr_in_enabled)
-		usb_ep_fifo_flush(fsg->intr_in);
-
-	/* Reset the I/O buffer states and pointers, the SCSI
-	 * state, and the exception.  Then invoke the handler. */
-	spin_lock_irq(&fsg->lock);
-
-	for (i = 0; i < NUM_BUFFERS; ++i) {
-		bh = &fsg->buffhds[i];
-		bh->state = BUF_STATE_EMPTY;
-	}
-	fsg->next_buffhd_to_fill = fsg->next_buffhd_to_drain =
-			&fsg->buffhds[0];
-
-	exception_req_tag = fsg->exception_req_tag;
-	new_config = fsg->new_config;
-	old_state = fsg->state;
-
-	if (old_state == FSG_STATE_ABORT_BULK_OUT)
-		fsg->state = FSG_STATE_STATUS_PHASE;
-	else {
-		for (i = 0; i < fsg->nluns; ++i) {
-			curlun = &fsg->luns[i];
-			curlun->prevent_medium_removal = 0;
-			curlun->sense_data = curlun->unit_attention_data =
-					SS_NO_SENSE;
-			curlun->sense_data_info = 0;
-		}
-		fsg->state = FSG_STATE_IDLE;
-	}
-	spin_unlock_irq(&fsg->lock);
-
-	/* Carry out any extra actions required for the exception */
-	switch (old_state) {
-	default:
-		break;
-
-	case FSG_STATE_ABORT_BULK_OUT:
-		send_status(fsg);
-		spin_lock_irq(&fsg->lock);
-		if (fsg->state == FSG_STATE_STATUS_PHASE)
-			fsg->state = FSG_STATE_IDLE;
-		spin_unlock_irq(&fsg->lock);
-		break;
-
-	case FSG_STATE_RESET:
-		/* In case we were forced against our will to halt a
-		 * bulk endpoint, clear the halt now.  (The SuperH UDC
-		 * requires this.) */
-		if (test_and_clear_bit(CLEAR_BULK_HALTS,
-				&fsg->atomic_bitflags)) {
-			usb_ep_clear_halt(fsg->bulk_in);
-			usb_ep_clear_halt(fsg->bulk_out);
-		}
-
-		if (transport_is_bbb()) {
-			if (fsg->ep0_req_tag == exception_req_tag)
-				ep0_queue(fsg);	// Complete the status stage
-
-		} else if (transport_is_cbi())
-			send_status(fsg);	// Status by interrupt pipe
-
-		/* Technically this should go here, but it would only be
-		 * a waste of time.  Ditto for the INTERFACE_CHANGE and
-		 * CONFIG_CHANGE cases. */
-		// for (i = 0; i < fsg->nluns; ++i)
-		//	fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED;
-		break;
-
-	case FSG_STATE_INTERFACE_CHANGE:
-		rc = do_set_interface(fsg, 0);
-		if (fsg->ep0_req_tag != exception_req_tag)
-			break;
-		if (rc != 0)			// STALL on errors
-			fsg_set_halt(fsg, fsg->ep0);
-		else				// Complete the status stage
-			ep0_queue(fsg);
-		break;
-
-	case FSG_STATE_CONFIG_CHANGE:
-		rc = do_set_config(fsg, new_config);
-		if (fsg->ep0_req_tag != exception_req_tag)
-			break;
-		if (rc != 0)			// STALL on errors
-			fsg_set_halt(fsg, fsg->ep0);
-		else				// Complete the status stage
-			ep0_queue(fsg);
-		break;
-
-	case FSG_STATE_DISCONNECT:
-		fsync_all(fsg);
-		do_set_config(fsg, 0);		// Unconfigured state
-		break;
-
-	case FSG_STATE_EXIT:
-	case FSG_STATE_TERMINATED:
-		do_set_config(fsg, 0);			// Free resources
-		spin_lock_irq(&fsg->lock);
-		fsg->state = FSG_STATE_TERMINATED;	// Stop the thread
-		spin_unlock_irq(&fsg->lock);
-		break;
-	}
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int fsg_main_thread(void *fsg_)
-{
-	struct fsg_dev		*fsg = (struct fsg_dev *) fsg_;
-
-	fsg->thread_task = current;
-
-	/* Release all our userspace resources */
-	daemonize();
-	reparent_to_init();
-	strncpy(current->comm, "file-storage-gadget",
-			sizeof(current->comm) - 1);
-
-	/* Allow the thread to be killed by a signal, but set the signal mask
-	 * to block everything but INT, TERM, KILL, and USR1. */
-	siginitsetinv(&fsg->thread_signal_mask, sigmask(SIGINT) |
-			sigmask(SIGTERM) | sigmask(SIGKILL) |
-			sigmask(SIGUSR1));
-	spin_lock_irq(&current->sigmask_lock);
-	flush_signals(current);
-	current->blocked = fsg->thread_signal_mask;
-	recalc_sigpending(current);
-	spin_unlock_irq(&current->sigmask_lock);
-
-	/* Arrange for userspace references to be interpreted as kernel
-	 * pointers.  That way we can pass a kernel pointer to a routine
-	 * that expects a __user pointer and it will work okay. */
-	set_fs(get_ds());
-
-	/* Wait for the gadget registration to finish up */
-	wait_for_completion(&fsg->thread_notifier);
-
-	/* The main loop */
-	while (fsg->state != FSG_STATE_TERMINATED) {
-		if (exception_in_progress(fsg) || signal_pending(current)) {
-			handle_exception(fsg);
-			continue;
-		}
-
-		if (!fsg->running) {
-			sleep_thread(fsg);
-			continue;
-		}
-
-		if (get_next_command(fsg))
-			continue;
-
-		spin_lock_irq(&fsg->lock);
-		if (!exception_in_progress(fsg))
-			fsg->state = FSG_STATE_DATA_PHASE;
-		spin_unlock_irq(&fsg->lock);
-
-		if (do_scsi_command(fsg) || finish_reply(fsg))
-			continue;
-
-		spin_lock_irq(&fsg->lock);
-		if (!exception_in_progress(fsg))
-			fsg->state = FSG_STATE_STATUS_PHASE;
-		spin_unlock_irq(&fsg->lock);
-
-		if (send_status(fsg))
-			continue;
-
-		spin_lock_irq(&fsg->lock);
-		if (!exception_in_progress(fsg))
-			fsg->state = FSG_STATE_IDLE;
-		spin_unlock_irq(&fsg->lock);
-		}
-
-	fsg->thread_task = NULL;
-	flush_signals(current);
-
-	/* In case we are exiting because of a signal, unregister the
-	 * gadget driver and close the backing file. */
-	if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags)) {
-		usb_gadget_unregister_driver(&fsg_driver);
-		close_all_backing_files(fsg);
-	}
-
-	/* Let the unbind and cleanup routines know the thread has exited */
-	complete_and_exit(&fsg->thread_notifier, 0);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* If the next two routines are called while the gadget is registered,
- * the caller must own fsg->filesem for writing. */
-
-static int NORMALLY_INIT open_backing_file(struct lun *curlun,
-		const char *filename)
-{
-	int				ro;
-	struct file			*filp = NULL;
-	int				rc = -EINVAL;
-	struct inode			*inode = NULL;
-	loff_t				size;
-	loff_t				num_sectors;
-
-	/* R/W if we can, R/O if we must */
-	ro = curlun->ro;
-	if (!ro) {
-		filp = filp_open(filename, O_RDWR | O_LARGEFILE, 0);
-		if (-EROFS == PTR_ERR(filp))
-			ro = 1;
-	}
-	if (ro)
-		filp = filp_open(filename, O_RDONLY | O_LARGEFILE, 0);
-	if (IS_ERR(filp)) {
-		LINFO(curlun, "unable to open backing file: %s\n", filename);
-		return PTR_ERR(filp);
-	}
-
-	if (!(filp->f_mode & FMODE_WRITE))
-		ro = 1;
-
-	if (filp->f_dentry)
-		inode = filp->f_dentry->d_inode;
-	if (inode && S_ISBLK(inode->i_mode)) {
-		kdev_t		dev = inode->i_rdev;
-
-		if (blk_size[MAJOR(dev)])
-			size = (loff_t) blk_size[MAJOR(dev)][MINOR(dev)] <<
-					BLOCK_SIZE_BITS;
-		else {
-			LINFO(curlun, "unable to find file size: %s\n",
-					filename);
-			goto out;
-		}
-	} else if (inode && S_ISREG(inode->i_mode))
-		size = inode->i_size;
-	else {
-		LINFO(curlun, "invalid file type: %s\n", filename);
-		goto out;
-	}
-
-	/* If we can't read the file, it's no good.
-	 * If we can't write the file, use it read-only. */
-	if (!filp->f_op || !filp->f_op->read) {
-		LINFO(curlun, "file not readable: %s\n", filename);
-		goto out;
-	}
-	if (IS_RDONLY(inode) || !filp->f_op->write)
-		ro = 1;
-
-	num_sectors = size >> 9;	// File size in 512-byte sectors
-	if (num_sectors == 0) {
-		LINFO(curlun, "file too small: %s\n", filename);
-		rc = -ETOOSMALL;
-		goto out;
-	}
-
-	get_file(filp);
-	curlun->ro = ro;
-	curlun->filp = filp;
-	curlun->file_length = size;
-	curlun->num_sectors = num_sectors;
-	LDBG(curlun, "open backing file: %s\n", filename);
-	rc = 0;
-
-out:
-	filp_close(filp, current->files);
-	return rc;
-}
-
-
-static void close_backing_file(struct lun *curlun)
-{
-	if (curlun->filp) {
-		LDBG(curlun, "close backing file\n");
-		fput(curlun->filp);
-		curlun->filp = NULL;
-	}
-}
-
-static void close_all_backing_files(struct fsg_dev *fsg)
-{
-	int	i;
-
-	for (i = 0; i < fsg->nluns; ++i)
-		close_backing_file(&fsg->luns[i]);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static void fsg_unbind(struct usb_gadget *gadget)
-{
-	struct fsg_dev		*fsg = get_gadget_data(gadget);
-	int			i;
-	struct usb_request	*req = fsg->ep0req;
-
-	DBG(fsg, "unbind\n");
-	clear_bit(REGISTERED, &fsg->atomic_bitflags);
-
-	/* If the thread isn't already dead, tell it to exit now */
-	if (fsg->state != FSG_STATE_TERMINATED) {
-		raise_exception(fsg, FSG_STATE_EXIT);
-		wait_for_completion(&fsg->thread_notifier);
-
-		/* The cleanup routine waits for this completion also */
-		complete(&fsg->thread_notifier);
-	}
-
-	/* Free the data buffers */
-	for (i = 0; i < NUM_BUFFERS; ++i) {
-		struct fsg_buffhd	*bh = &fsg->buffhds[i];
-
-		if (bh->buf)
-			usb_ep_free_buffer(fsg->bulk_in, bh->buf, bh->dma,
-					mod_data.buflen);
-	}
-
-	/* Free the request and buffer for endpoint 0 */
-	if (req) {
-		if (req->buf)
-			usb_ep_free_buffer(fsg->ep0, req->buf,
-					req->dma, EP0_BUFSIZE);
-		usb_ep_free_request(fsg->ep0, req);
-	}
-
-	set_gadget_data(gadget, 0);
-}
-
-
-static int __init check_parameters(struct fsg_dev *fsg)
-{
-	int	prot;
-
-	/* Store the default values */
-	mod_data.transport_type = USB_PR_BULK;
-	mod_data.transport_name = "Bulk-only";
-	mod_data.protocol_type = USB_SC_SCSI;
-	mod_data.protocol_name = "Transparent SCSI";
-
-	prot = simple_strtol(mod_data.protocol_parm, NULL, 0);
-
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
-	if (strnicmp(mod_data.transport_parm, "BBB", 10) == 0) {
-		;		// Use default setting
-	} else if (strnicmp(mod_data.transport_parm, "CB", 10) == 0) {
-		mod_data.transport_type = USB_PR_CB;
-		mod_data.transport_name = "Control-Bulk";
-	} else if (strnicmp(mod_data.transport_parm, "CBI", 10) == 0) {
-		mod_data.transport_type = USB_PR_CBI;
-		mod_data.transport_name = "Control-Bulk-Interrupt";
-	} else {
-		INFO(fsg, "invalid transport: %s\n", mod_data.transport_parm);
-		return -EINVAL;
-	}
-
-	if (strnicmp(mod_data.protocol_parm, "SCSI", 10) == 0 ||
-			prot == USB_SC_SCSI) {
-		;		// Use default setting
-	} else if (strnicmp(mod_data.protocol_parm, "RBC", 10) == 0 ||
-			prot == USB_SC_RBC) {
-		mod_data.protocol_type = USB_SC_RBC;
-		mod_data.protocol_name = "RBC";
-	} else if (strnicmp(mod_data.protocol_parm, "8020", 4) == 0 ||
-			strnicmp(mod_data.protocol_parm, "ATAPI", 10) == 0 ||
-			prot == USB_SC_8020) {
-		mod_data.protocol_type = USB_SC_8020;
-		mod_data.protocol_name = "8020i (ATAPI)";
-	} else if (strnicmp(mod_data.protocol_parm, "QIC", 3) == 0 ||
-			prot == USB_SC_QIC) {
-		mod_data.protocol_type = USB_SC_QIC;
-		mod_data.protocol_name = "QIC-157";
-	} else if (strnicmp(mod_data.protocol_parm, "UFI", 10) == 0 ||
-			prot == USB_SC_UFI) {
-		mod_data.protocol_type = USB_SC_UFI;
-		mod_data.protocol_name = "UFI";
-	} else if (strnicmp(mod_data.protocol_parm, "8070", 4) == 0 ||
-			prot == USB_SC_8070) {
-		mod_data.protocol_type = USB_SC_8070;
-		mod_data.protocol_name = "8070i";
-	} else {
-		INFO(fsg, "invalid protocol: %s\n", mod_data.protocol_parm);
-		return -EINVAL;
-	}
-
-	mod_data.buflen &= PAGE_CACHE_MASK;
-	if (mod_data.buflen <= 0) {
-		INFO(fsg, "invalid buflen\n");
-		return -ETOOSMALL;
-	}
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
-
-	return 0;
-}
-
-
-static int __init fsg_bind(struct usb_gadget *gadget)
-{
-	struct fsg_dev		*fsg = the_fsg;
-	int			rc;
-	int			i;
-	struct lun		*curlun;
-	struct usb_ep		*ep;
-	struct usb_request	*req;
-	char			*pathbuf, *p;
-
-	fsg->gadget = gadget;
-	set_gadget_data(gadget, fsg);
-	fsg->ep0 = gadget->ep0;
-	fsg->ep0->driver_data = fsg;
-
-	if ((rc = check_parameters(fsg)) != 0)
-		goto out;
-
-	/* Find out how many LUNs there should be */
-	i = mod_data.nluns;
-	if (i == 0) {
-		for (i = MAX_LUNS; i > 1; --i) {
-			if (file[i - 1])
-				break;
-		}
-	}
-	if (i > MAX_LUNS) {
-		INFO(fsg, "invalid number of LUNs: %d\n", i);
-		rc = -EINVAL;
-		goto out;
-	}
-
-	/* Create the LUNs and open their backing files.  We can't register
-	 * the LUN devices until the gadget itself is registered, which
-	 * doesn't happen until after fsg_bind() returns. */
-	fsg->luns = kmalloc(i * sizeof(struct lun), GFP_KERNEL);
-	if (!fsg->luns) {
-		rc = -ENOMEM;
-		goto out;
-	}
-	memset(fsg->luns, 0, i * sizeof(struct lun));
-	fsg->nluns = i;
-
-	for (i = 0; i < fsg->nluns; ++i) {
-		curlun = &fsg->luns[i];
-		curlun->ro = ro[i];
-		curlun->dev.driver_data = fsg;
-		snprintf(curlun->dev.name, BUS_ID_SIZE,
-				"%s-lun%d", gadget->name, i);
-
-		if (file[i] && *file[i]) {
-			if ((rc = open_backing_file(curlun, file[i])) != 0)
-				goto out;
-		} else if (!mod_data.removable) {
-			INFO(fsg, "no file given for LUN%d\n", i);
-			rc = -EINVAL;
-			goto out;
-		}
-	}
-
-	/* Fix up the descriptors */
-	device_desc.bMaxPacketSize0 = fsg->ep0->maxpacket;
-#ifdef HIGHSPEED
-	dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket;		// ???
-#endif
-	device_desc.idVendor = cpu_to_le16(mod_data.vendor);
-	device_desc.idProduct = cpu_to_le16(mod_data.product);
-	device_desc.bcdDevice = cpu_to_le16(mod_data.release);
-
-	i = (transport_is_cbi() ? 3 : 2);	// Number of endpoints
-	config_desc.wTotalLength = USB_DT_CONFIG_SIZE + USB_DT_INTERFACE_SIZE
-			+ USB_DT_ENDPOINT_SIZE * i;
-	intf_desc.bNumEndpoints = i;
-	intf_desc.bInterfaceSubClass = mod_data.protocol_type;
-	intf_desc.bInterfaceProtocol = mod_data.transport_type;
-
-	/* Find all the endpoints we will use */
-	gadget_for_each_ep(ep, gadget) {
-		if (strcmp(ep->name, EP_BULK_IN_NAME) == 0)
-			fsg->bulk_in = ep;
-		else if (strcmp(ep->name, EP_BULK_OUT_NAME) == 0)
-			fsg->bulk_out = ep;
-		else if (strcmp(ep->name, EP_INTR_IN_NAME) == 0)
-			fsg->intr_in = ep;
-	}
-	if (!fsg->bulk_in || !fsg->bulk_out ||
-			(transport_is_cbi() && !fsg->intr_in)) {
-		DBG(fsg, "unable to find all endpoints\n");
-		rc = -ENOTSUPP;
-		goto out;
-	}
-	fsg->bulk_out_maxpacket = (gadget->speed == USB_SPEED_HIGH ? 512 :
-			FS_BULK_OUT_MAXPACKET);
-
-	rc = -ENOMEM;
-
-	/* Allocate the request and buffer for endpoint 0 */
-	fsg->ep0req = req = usb_ep_alloc_request(fsg->ep0, GFP_KERNEL);
-	if (!req)
-		goto out;
-	req->buf = usb_ep_alloc_buffer(fsg->ep0, EP0_BUFSIZE,
-			&req->dma, GFP_KERNEL);
-	if (!req->buf)
-		goto out;
-	req->complete = ep0_complete;
-
-	/* Allocate the data buffers */
-	for (i = 0; i < NUM_BUFFERS; ++i) {
-		struct fsg_buffhd	*bh = &fsg->buffhds[i];
-
-		bh->buf = usb_ep_alloc_buffer(fsg->bulk_in, mod_data.buflen,
-				&bh->dma, GFP_KERNEL);
-		if (!bh->buf)
-			goto out;
-		bh->next = bh + 1;
-	}
-	fsg->buffhds[NUM_BUFFERS - 1].next = &fsg->buffhds[0];
-
-	/* This should reflect the actual gadget power source */
-	usb_gadget_set_selfpowered(gadget);
-
-	/* On a real device, serial[] would be loaded from permanent
-	 * storage.  We just encode it from the driver version string. */
-	for (i = 0; i < sizeof(serial) - 2; i += 2) {
-		unsigned char		c = DRIVER_VERSION[i / 2];
-
-		if (!c)
-			break;
-		sprintf(&serial[i], "%02X", c);
-	}
-
-	if ((rc = kernel_thread(fsg_main_thread, fsg, (CLONE_VM | CLONE_FS |
-			CLONE_FILES))) < 0)
-		goto out;
-	fsg->thread_pid = rc;
-
-	INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
-	INFO(fsg, "Number of LUNs=%d\n", fsg->nluns);
-
-	pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
-	for (i = 0; i < fsg->nluns; ++i) {
-		curlun = &fsg->luns[i];
-		if (backing_file_is_open(curlun)) {
-			p = NULL;
-			if (pathbuf) {
-				p = d_path(curlun->filp->f_dentry,
-					curlun->filp->f_vfsmnt,
-					pathbuf, PATH_MAX);
-				if (IS_ERR(p))
-					p = NULL;
-			}
-			LINFO(curlun, "ro=%d, file: %s\n",
-					curlun->ro, (p ? p : "(error)"));
-		}
-	}
-	kfree(pathbuf);
-
-	DBG(fsg, "transport=%s (x%02x)\n",
-			mod_data.transport_name, mod_data.transport_type);
-	DBG(fsg, "protocol=%s (x%02x)\n",
-			mod_data.protocol_name, mod_data.protocol_type);
-	DBG(fsg, "VendorID=x%04x, ProductID=x%04x, Release=x%04x\n",
-			mod_data.vendor, mod_data.product, mod_data.release);
-	DBG(fsg, "removable=%d, stall=%d, buflen=%u\n",
-			mod_data.removable, mod_data.can_stall,
-			mod_data.buflen);
-	DBG(fsg, "I/O thread pid: %d\n", fsg->thread_pid);
-	return 0;
-
-out:
-	fsg->state = FSG_STATE_TERMINATED;	// The thread is dead
-	fsg_unbind(gadget);
-	close_all_backing_files(fsg);
-	return rc;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static struct usb_gadget_driver		fsg_driver = {
-#ifdef HIGHSPEED
-	.speed		= USB_SPEED_HIGH,
-#else
-	.speed		= USB_SPEED_FULL,
-#endif
-	.function	= (char *) longname,
-	.bind		= fsg_bind,
-	.unbind		= fsg_unbind,
-	.disconnect	= fsg_disconnect,
-	.setup		= fsg_setup,
-
-	.driver		= {
-		.name		= (char *) shortname,
-		// .release = ...
-		// .suspend = ...
-		// .resume = ...
-	},
-};
-
-
-static int __init fsg_alloc(void)
-{
-	struct fsg_dev		*fsg;
-
-	fsg = kmalloc(sizeof *fsg, GFP_KERNEL);
-	if (!fsg)
-		return -ENOMEM;
-	memset(fsg, 0, sizeof *fsg);
-	spin_lock_init(&fsg->lock);
-	init_rwsem(&fsg->filesem);
-	init_waitqueue_head(&fsg->thread_wqh);
-	init_completion(&fsg->thread_notifier);
-
-	the_fsg = fsg;
-	return 0;
-}
-
-
-static void fsg_free(struct fsg_dev *fsg)
-{
-	kfree(fsg->luns);
-	kfree(fsg);
-}
-
-
-static int __init fsg_init(void)
-{
-	int		rc;
-	struct fsg_dev	*fsg;
-
-	/* Put the module parameters where they belong -- arghh! */
-	mod_data.nluns = luns;
-	mod_data.transport_parm = transport;
-	mod_data.protocol_parm = protocol;
-	mod_data.removable = removable;
-	mod_data.vendor = vendor;
-	mod_data.product = product;
-	mod_data.release = release;
-	mod_data.buflen = buflen;
-	mod_data.can_stall = stall;
-
-	if ((rc = fsg_alloc()) != 0)
-		return rc;
-	fsg = the_fsg;
-	if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0) {
-		fsg_free(fsg);
-		return rc;
-	}
-	set_bit(REGISTERED, &fsg->atomic_bitflags);
-
-	/* Tell the thread to start working */
-	complete(&fsg->thread_notifier);
-	return 0;
-}
-module_init(fsg_init);
-
-
-static void __exit fsg_cleanup(void)
-{
-	struct fsg_dev	*fsg = the_fsg;
-
-	/* Unregister the driver iff the thread hasn't already done so */
-	if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags))
-		usb_gadget_unregister_driver(&fsg_driver);
-
-	/* Wait for the thread to finish up */
-	wait_for_completion(&fsg->thread_notifier);
-
-	close_all_backing_files(fsg);
-	fsg_free(fsg);
-}
-module_exit(fsg_cleanup);
diff -ruN linux-2.4.20-WRTup/drivers/usb/gadget/gadget_chips.h linux-2.4.20-WRTstp/drivers/usb/gadget/gadget_chips.h
--- linux-2.4.20-WRTup/drivers/usb/gadget/gadget_chips.h	2006-06-12 18:04:59.000000000 -0700
+++ linux-2.4.20-WRTstp/drivers/usb/gadget/gadget_chips.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,57 +0,0 @@
-/*
- * USB device controllers have lots of quirks.  Use these macros in
- * gadget drivers or other code that needs to deal with them, and which
- * autoconfigures instead of using early binding to the hardware.
- *
- * This could eventually work like the ARM mach_is_*() stuff, driven by
- * some config file that gets updated as new hardware is supported.
- *
- * NOTE:  some of these controller drivers may not be available yet.
- */
-#ifdef CONFIG_USB_GADGET_NET2280
-#define	gadget_is_net2280(g)	!strcmp("net2280", (g)->name)
-#else
-#define	gadget_is_net2280(g)	0
-#endif
-
-#ifdef CONFIG_USB_GADGET_PXA
-#define	gadget_is_pxa(g)	!strcmp("pxa2xx_udc", (g)->name)
-#else
-#define	gadget_is_pxa(g)	0
-#endif
-
-#ifdef CONFIG_USB_GADGET_GOKU
-#define	gadget_is_goku(g)	!strcmp("goku_udc", (g)->name)
-#else
-#define	gadget_is_goku(g)	0
-#endif
-
-#ifdef CONFIG_USB_GADGET_SUPERH
-#define	gadget_is_sh(g)		!strcmp("sh_udc", (g)->name)
-#else
-#define	gadget_is_sh(g)		0
-#endif
-
-#ifdef CONFIG_USB_GADGET_SA1100
-#define	gadget_is_sa1100(g)	!strcmp("sa1100_udc", (g)->name)
-#else
-#define	gadget_is_sa1100(g)	0
-#endif
-
-#ifdef CONFIG_USB_GADGET_MQ11XX
-#define	gadget_is_mq11xx(g)	!strcmp("mq11xx_udc", (g)->name)
-#else
-#define	gadget_is_mq11xx(g)	0
-#endif
-
-#ifdef CONFIG_USB_GADGET_OMAP
-#define	gadget_is_omap(g)	!strcmp("omap_udc", (g)->name)
-#else
-#define	gadget_is_omap(g)	0
-#endif
-
-// CONFIG_USB_GADGET_AT91RM9200
-// CONFIG_USB_GADGET_SX2
-// CONFIG_USB_GADGET_AU1X00
-// ...
-
diff -ruN linux-2.4.20-WRTup/drivers/usb/gadget/goku_udc.c linux-2.4.20-WRTstp/drivers/usb/gadget/goku_udc.c
--- linux-2.4.20-WRTup/drivers/usb/gadget/goku_udc.c	2006-06-12 18:04:59.000000000 -0700
+++ linux-2.4.20-WRTstp/drivers/usb/gadget/goku_udc.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,1975 +0,0 @@
-/*
- * Toshiba TC86C001 ("Goku-S") USB Device Controller driver
- *
- * Copyright (C) 2000-2002 Lineo
- *      by Stuart Lynne, Tom Rushworth, and Bruce Balden
- * Copyright (C) 2002 Toshiba Corporation
- * Copyright (C) 2003 MontaVista Software (source@mvista.com)
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-/*
- * This device has ep0 and three semi-configurable bulk/interrupt endpoints.
- *
- *  - Endpoint numbering is fixed: ep{1,2,3}-bulk
- *  - Gadget drivers can choose ep maxpacket (8/16/32/64)
- *  - Gadget drivers can choose direction (IN, OUT)
- *  - DMA works with ep1 (OUT transfers) and ep2 (IN transfers).
- */
-
-#undef DEBUG
-// #define	VERBOSE		/* extra debug messages (success too) */
-// #define	USB_TRACE	/* packet-level success messages */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/proc_fs.h>
-#include <linux/usb_ch9.h>
-#include <linux/usb_gadget.h>
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-#include <asm/unaligned.h>
-
-
-#include "goku_udc.h"
-
-#define	DRIVER_DESC		"TC86C001 USB Device Controller"
-#define	DRIVER_VERSION		"30-Oct 2003"
-
-#define	DMA_ADDR_INVALID	(~(dma_addr_t)0)
-
-static const char driver_name [] = "goku_udc";
-static const char driver_desc [] = DRIVER_DESC;
-
-MODULE_AUTHOR("source@mvista.com");
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-
-
-/*
- * IN dma behaves ok under testing, though the IN-dma abort paths don't
- * seem to behave quite as expected.  Used by default.
- *
- * OUT dma documents design problems handling the common "short packet"
- * transfer termination policy; it couldn't enabled by default, even
- * if the OUT-dma abort problems had a resolution.
- */
-static unsigned use_dma = 1;
-
-#if 0
-//#include <linux/moduleparam.h>
-/* "modprobe goku_udc use_dma=1" etc
- *	0 to disable dma
- *	1 to use IN dma only (normal operation)
- *	2 to use IN and OUT dma
- */
-module_param(use_dma, uint, S_IRUGO);
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-static void nuke(struct goku_ep *, int status);
-
-static inline void
-command(struct goku_udc_regs *regs, int command, unsigned epnum)
-{
-	writel(COMMAND_EP(epnum) | command, &regs->Command);
-	udelay(300);
-}
-
-static int
-goku_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
-{
-	struct goku_udc	*dev;
-	struct goku_ep	*ep;
-	u32		mode;
-	u16		max;
-	unsigned long	flags;
-
-	ep = container_of(_ep, struct goku_ep, ep);
-	if (!_ep || !desc || ep->desc
-			|| desc->bDescriptorType != USB_DT_ENDPOINT)
-		return -EINVAL;
-	dev = ep->dev;
-	if (ep == &dev->ep[0])
-		return -EINVAL;
-	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
-		return -ESHUTDOWN;
-	if (ep->num != (desc->bEndpointAddress & 0x0f))
-		return -EINVAL;
-
-	switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
-	case USB_ENDPOINT_XFER_BULK:
-	case USB_ENDPOINT_XFER_INT:
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if ((readl(ep->reg_status) & EPxSTATUS_EP_MASK)
-			!= EPxSTATUS_EP_INVALID)
-		return -EBUSY;
-
-	/* enabling the no-toggle interrupt mode would need an api hook */
-	mode = 0;
-	max = le16_to_cpu(get_unaligned(&desc->wMaxPacketSize));
-	switch (max) {
-	case 64:	mode++;
-	case 32:	mode++;
-	case 16:	mode++;
-	case 8:		mode <<= 3;
-			break;
-	default:
-		return -EINVAL;
-	}
-	mode |= 2 << 1;		/* bulk, or intr-with-toggle */
-
-	/* ep1/ep2 dma direction is chosen early; it works in the other
-	 * direction, with pio.  be cautious with out-dma.
-	 */
-	ep->is_in = (USB_DIR_IN & desc->bEndpointAddress) != 0;
-	if (ep->is_in) {
-		mode |= 1;
-		ep->dma = (use_dma != 0) && (ep->num == UDC_MSTRD_ENDPOINT);
-	} else {
-		ep->dma = (use_dma == 2) && (ep->num == UDC_MSTWR_ENDPOINT);
-		if (ep->dma)
-			DBG(dev, "%s out-dma hides short packets\n",
-				ep->ep.name);
-	}
-
-	spin_lock_irqsave(&ep->dev->lock, flags);
-
-	/* ep1 and ep2 can do double buffering and/or dma */
-	if (ep->num < 3) {
-		struct goku_udc_regs	*regs = ep->dev->regs;
-		u32			tmp;
-
-		/* double buffer except (for now) with pio in */
-		tmp = ((ep->dma || !ep->is_in)
-				? 0x10	/* double buffered */
-				: 0x11	/* single buffer */
-			) << ep->num;
-		tmp |= readl(&regs->EPxSingle);
-		writel(tmp, &regs->EPxSingle);
-
-		tmp = (ep->dma ? 0x10/*dma*/ : 0x11/*pio*/) << ep->num;
-		tmp |= readl(&regs->EPxBCS);
-		writel(tmp, &regs->EPxBCS);
-	}
-	writel(mode, ep->reg_mode);
-	command(ep->dev->regs, COMMAND_RESET, ep->num);
-	ep->ep.maxpacket = max;
-	ep->stopped = 0;
-	ep->desc = desc;
-	spin_unlock_irqrestore(&ep->dev->lock, flags);
-
-	DBG(dev, "enable %s %s %s maxpacket %u\n", ep->ep.name,
-		ep->is_in ? "IN" : "OUT",
-		ep->dma ? "dma" : "pio",
-		max);
-
-	return 0;
-}
-
-static void ep_reset(struct goku_udc_regs *regs, struct goku_ep *ep)
-{
-	struct goku_udc		*dev = ep->dev;
-
-	if (regs) {
-		command(regs, COMMAND_INVALID, ep->num);
-		if (ep->num) {
-			if (ep->num == UDC_MSTWR_ENDPOINT)
-				dev->int_enable &= ~(INT_MSTWREND
-							|INT_MSTWRTMOUT);
-			else if (ep->num == UDC_MSTRD_ENDPOINT)
-				dev->int_enable &= ~INT_MSTRDEND;
-			dev->int_enable &= ~INT_EPxDATASET (ep->num);
-		} else
-			dev->int_enable &= ~INT_EP0;
-		writel(dev->int_enable, &regs->int_enable);
-		readl(&regs->int_enable);
-		if (ep->num < 3) {
-			struct goku_udc_regs	*regs = ep->dev->regs;
-			u32			tmp;
-
-			tmp = readl(&regs->EPxSingle);
-			tmp &= ~(0x11 << ep->num);
-			writel(tmp, &regs->EPxSingle);
-
-			tmp = readl(&regs->EPxBCS);
-			tmp &= ~(0x11 << ep->num);
-			writel(tmp, &regs->EPxBCS);
-		}
-		/* reset dma in case we're still using it */
-		if (ep->dma) {
-			u32	master;
-
-			master = readl(&regs->dma_master) & MST_RW_BITS;
-			if (ep->num == UDC_MSTWR_ENDPOINT) {
-				master &= ~MST_W_BITS;
-				master |= MST_WR_RESET;
-			} else {
-				master &= ~MST_R_BITS;
-				master |= MST_RD_RESET;
-			}
-			writel(master, &regs->dma_master);
-		}
-	}
-
-	ep->ep.maxpacket = MAX_FIFO_SIZE;
-	ep->desc = 0;
-	ep->stopped = 1;
-	ep->irqs = 0;
-	ep->dma = 0;
-}
-
-static int goku_ep_disable(struct usb_ep *_ep)
-{
-	struct goku_ep	*ep;
-	struct goku_udc	*dev;
-	unsigned long	flags;
-
-	ep = container_of(_ep, struct goku_ep, ep);
-	if (!_ep || !ep->desc)
-		return -ENODEV;
-	dev = ep->dev;
-	if (dev->ep0state == EP0_SUSPEND)
-		return -EBUSY;
-
-	VDBG(dev, "disable %s\n", _ep->name);
-
-	spin_lock_irqsave(&dev->lock, flags);
-	nuke(ep, -ESHUTDOWN);
-	ep_reset(dev->regs, ep);
-	spin_unlock_irqrestore(&dev->lock, flags);
-
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static struct usb_request *
-goku_alloc_request(struct usb_ep *_ep, int gfp_flags)
-{
-	struct goku_request	*req;
-
-	if (!_ep)
-		return 0;
-	req = kmalloc(sizeof *req, gfp_flags);
-	if (!req)
-		return 0;
-
-	memset(req, 0, sizeof *req);
-	req->req.dma = DMA_ADDR_INVALID;
-	INIT_LIST_HEAD(&req->queue);
-	return &req->req;
-}
-
-static void
-goku_free_request(struct usb_ep *_ep, struct usb_request *_req)
-{
-	struct goku_request	*req;
-
-	if (!_ep || !_req)
-		return;
-
-	req = container_of(_req, struct goku_request, req);
-	WARN_ON(!list_empty(&req->queue));
-	kfree(req);
-}
-
-/*-------------------------------------------------------------------------*/
-
-#undef USE_KMALLOC
-
-/* many common platforms have dma-coherent caches, which means that it's
- * safe to use kmalloc() memory for all i/o buffers without using any
- * cache flushing calls.  (unless you're trying to share cache lines
- * between dma and non-dma activities, which is a slow idea in any case.)
- *
- * other platforms need more care, with 2.6 having a moderately general
- * solution except for the common "buffer is smaller than a page" case.
- */
-#if	defined(CONFIG_X86)
-#define USE_KMALLOC
-
-#elif	defined(CONFIG_MIPS) && !defined(CONFIG_NONCOHERENT_IO)
-#define USE_KMALLOC
-
-#elif	defined(CONFIG_PPC) && !defined(CONFIG_NOT_COHERENT_CACHE)
-#define USE_KMALLOC
-
-#endif
-
-/* allocating buffers this way eliminates dma mapping overhead, which
- * on some platforms will mean eliminating a per-io buffer copy.  with
- * some kinds of system caches, further tweaks may still be needed.
- */
-static void *
-goku_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
-			dma_addr_t *dma, int  gfp_flags)
-{
-	void		*retval;
-	struct goku_ep	*ep;
-
-	ep = container_of(_ep, struct goku_ep, ep);
-	if (!_ep)
-		return 0;
-	*dma = DMA_ADDR_INVALID;
-
-#if	defined(USE_KMALLOC)
-	retval = kmalloc(bytes, gfp_flags);
-	if (retval)
-		*dma = virt_to_phys(retval);
-#else
-	if (ep->dma) {
-		/* one problem with this call is that it wastes memory on
-		 * typical 1/N page allocations: it allocates 1-N pages.
-		 * another is that it always uses GFP_ATOMIC.
-		 */
-#warning Using pci_alloc_consistent even with buffers smaller than a page.
-		retval = pci_alloc_consistent(ep->dev->pdev, bytes, dma);
-	} else
-		retval = kmalloc(bytes, gfp_flags);
-#endif
-	return retval;
-}
-
-static void
-goku_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma, unsigned bytes)
-{
-	/* free memory into the right allocator */
-#ifndef	USE_KMALLOC
-	if (dma != DMA_ADDR_INVALID) {
-		struct goku_ep	*ep;
-
-		ep = container_of(_ep, struct goku_ep, ep);
-		if (!_ep)
-			return;
-		/* one problem with this call is that some platforms
-		 * don't allow it to be used in_irq().
-		 */
-		pci_free_consistent(ep->dev->pdev, bytes, buf, dma);
-	} else
-#endif
-		kfree (buf);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void
-done(struct goku_ep *ep, struct goku_request *req, int status)
-{
-	struct goku_udc		*dev;
-	unsigned		stopped = ep->stopped;
-
-	list_del_init(&req->queue);
-
-	if (likely(req->req.status == -EINPROGRESS))
-		req->req.status = status;
-	else
-		status = req->req.status;
-
-	dev = ep->dev;
-	if (req->mapped) {
-		pci_unmap_single(dev->pdev, req->req.dma, req->req.length,
-			ep->is_in ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
-		req->req.dma = DMA_ADDR_INVALID;
-		req->mapped = 0;
-	}
-
-#ifndef USB_TRACE
-	if (status && status != -ESHUTDOWN)
-#endif
-		VDBG(dev, "complete %s req %p stat %d len %u/%u\n",
-			ep->ep.name, &req->req, status,
-			req->req.actual, req->req.length);
-
-	/* don't modify queue heads during completion callback */
-	ep->stopped = 1;
-	spin_unlock(&dev->lock);
-	req->req.complete(&ep->ep, &req->req);
-	spin_lock(&dev->lock);
-	ep->stopped = stopped;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static inline int
-write_packet(u32 *fifo, u8 *buf, struct goku_request *req, unsigned max)
-{
-	unsigned	length, count;
-
-	length = min(req->req.length - req->req.actual, max);
-	req->req.actual += length;
-
-	count = length;
-	while (likely(count--))
-		writel(*buf++, fifo);
-	return length;
-}
-
-// return:  0 = still running, 1 = completed, negative = errno
-static int write_fifo(struct goku_ep *ep, struct goku_request *req)
-{
-	struct goku_udc	*dev = ep->dev;
-	u32		tmp;
-	u8		*buf;
-	unsigned	count;
-	int		is_last;
-
-	tmp = readl(&dev->regs->DataSet);
-	buf = req->req.buf + req->req.actual;
-	prefetch(buf);
-
-	dev = ep->dev;
-	if (unlikely(ep->num == 0 && dev->ep0state != EP0_IN))
-		return -EL2HLT;
-
-	/* NOTE:  just single-buffered PIO-IN for now.  */
-	if (unlikely((tmp & DATASET_A(ep->num)) != 0))
-		return 0;
-
-	/* clear our "packet available" irq */
-	if (ep->num != 0)
-		writel(~INT_EPxDATASET(ep->num), &dev->regs->int_status);
-
-	count = write_packet(ep->reg_fifo, buf, req, ep->ep.maxpacket);
-
-	/* last packet often short (sometimes a zlp, especially on ep0) */
-	if (unlikely(count != ep->ep.maxpacket)) {
-		writel(~(1<<ep->num), &dev->regs->EOP);
-		if (ep->num == 0) {
-			dev->ep[0].stopped = 1;
-			dev->ep0state = EP0_STATUS;
-		}
-		is_last = 1;
-	} else {
-		if (likely(req->req.length != req->req.actual)
-				|| req->req.zero)
-			is_last = 0;
-		else
-			is_last = 1;
-	}
-#if 0		/* printk seemed to trash is_last...*/
-//#ifdef USB_TRACE
-	VDBG(dev, "wrote %s %u bytes%s IN %u left %p\n",
-		ep->ep.name, count, is_last ? "/last" : "",
-		req->req.length - req->req.actual, req);
-#endif
-
-	/* requests complete when all IN data is in the FIFO,
-	 * or sometimes later, if a zlp was needed.
-	 */
-	if (is_last) {
-		done(ep, req, 0);
-		return 1;
-	}
-
-	return 0;
-}
-
-static int read_fifo(struct goku_ep *ep, struct goku_request *req)
-{
-	struct goku_udc_regs	*regs;
-	u32			size, set;
-	u8			*buf;
-	unsigned		bufferspace, is_short, dbuff;
-
-	regs = ep->dev->regs;
-top:
-	buf = req->req.buf + req->req.actual;
-	prefetchw(buf);
-
-	if (unlikely(ep->num == 0 && ep->dev->ep0state != EP0_OUT))
-		return -EL2HLT;
-
-	dbuff = (ep->num == 1 || ep->num == 2);
-	do {
-		/* ack dataset irq matching the status we'll handle */
-		if (ep->num != 0)
-			writel(~INT_EPxDATASET(ep->num), &regs->int_status);
-
-		set = readl(&regs->DataSet) & DATASET_AB(ep->num);
-		size = readl(&regs->EPxSizeLA[ep->num]);
-		bufferspace = req->req.length - req->req.actual;
-
-		/* usually do nothing without an OUT packet */
-		if (likely(ep->num != 0 || bufferspace != 0)) {
-			if (unlikely(set == 0))
-				break;
-			/* use ep1/ep2 double-buffering for OUT */
-			if (!(size & PACKET_ACTIVE))
-				size = readl(&regs->EPxSizeLB[ep->num]);
-			if (!(size & PACKET_ACTIVE)) 	// "can't happen"
-				break;
-			size &= DATASIZE;	/* EPxSizeH == 0 */
-
-		/* ep0out no-out-data case for set_config, etc */
-		} else
-			size = 0;
-
-		/* read all bytes from this packet */
-		req->req.actual += size;
-		is_short = (size < ep->ep.maxpacket);
-#ifdef USB_TRACE
-		VDBG(ep->dev, "read %s %u bytes%s OUT req %p %u/%u\n",
-			ep->ep.name, size, is_short ? "/S" : "",
-			req, req->req.actual, req->req.length);
-#endif
-		while (likely(size-- != 0)) {
-			u8	byte = (u8) readl(ep->reg_fifo);
-
-			if (unlikely(bufferspace == 0)) {
-				/* this happens when the driver's buffer
-				 * is smaller than what the host sent.
-				 * discard the extra data in this packet.
-				 */
-				if (req->req.status != -EOVERFLOW)
-					DBG(ep->dev, "%s overflow %u\n",
-						ep->ep.name, size);
-				req->req.status = -EOVERFLOW;
-			} else {
-				*buf++ = byte;
-				bufferspace--;
-			}
-		}
-
-		/* completion */
-		if (unlikely(is_short || req->req.actual == req->req.length)) {
-			if (unlikely(ep->num == 0)) {
-				/* non-control endpoints now usable? */
-				if (ep->dev->req_config)
-					writel(ep->dev->configured
-							? USBSTATE_CONFIGURED
-							: 0,
-						&regs->UsbState);
-				/* ep0out status stage */
-				writel(~(1<<0), &regs->EOP);
-				ep->stopped = 1;
-				ep->dev->ep0state = EP0_STATUS;
-			}
-			done(ep, req, 0);
-
-			/* empty the second buffer asap */
-			if (dbuff && !list_empty(&ep->queue)) {
-				req = list_entry(ep->queue.next,
-						struct goku_request, queue);
-				goto top;
-			}
-			return 1;
-		}
-	} while (dbuff);
-	return 0;
-}
-
-static inline void
-pio_irq_enable(struct goku_udc *dev, struct goku_udc_regs *regs, int epnum)
-{
-	dev->int_enable |= INT_EPxDATASET (epnum);
-	writel(dev->int_enable, &regs->int_enable);
-	/* write may still be posted */
-}
-
-static inline void
-pio_irq_disable(struct goku_udc *dev, struct goku_udc_regs *regs, int epnum)
-{
-	dev->int_enable &= ~INT_EPxDATASET (epnum);
-	writel(dev->int_enable, &regs->int_enable);
-	/* write may still be posted */
-}
-
-static inline void
-pio_advance(struct goku_ep *ep)
-{
-	struct goku_request	*req;
-
-	if (unlikely(list_empty (&ep->queue)))
-		return;
-	req = list_entry(ep->queue.next, struct goku_request, queue);
-	(ep->is_in ? write_fifo : read_fifo)(ep, req);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-// return:  0 = q running, 1 = q stopped, negative = errno
-static int start_dma(struct goku_ep *ep, struct goku_request *req)
-{
-	struct goku_udc_regs	*regs = ep->dev->regs;
-	u32			master;
-	u32			start = req->req.dma;
-	u32			end = start + req->req.length - 1;
-
-	master = readl(&regs->dma_master) & MST_RW_BITS;
-
-	/* re-init the bits affecting IN dma; careful with zlps */
-	if (likely(ep->is_in)) {
-		if (unlikely(master & MST_RD_ENA)) {
-			DBG (ep->dev, "start, IN active dma %03x!!\n",
-				master);
-//			return -EL2HLT;
-		}
-		writel(end, &regs->in_dma_end);
-		writel(start, &regs->in_dma_start);
-
-		master &= ~MST_R_BITS;
-		if (unlikely(req->req.length == 0))
-			master = MST_RD_ENA | MST_RD_EOPB;
-		else if ((req->req.length % ep->ep.maxpacket) != 0
-					|| req->req.zero)
-			master = MST_RD_ENA | MST_EOPB_ENA;
-		else
-			master = MST_RD_ENA | MST_EOPB_DIS;
-
-		ep->dev->int_enable |= INT_MSTRDEND;
-
-	/* Goku DMA-OUT merges short packets, which plays poorly with
-	 * protocols where short packets mark the transfer boundaries.
-	 * The chip supports a nonstandard policy with INT_MSTWRTMOUT,
-	 * ending transfers after 3 SOFs; we don't turn it on.
-	 */
-	} else {
-		if (unlikely(master & MST_WR_ENA)) {
-			DBG (ep->dev, "start, OUT active dma %03x!!\n",
-				master);
-//			return -EL2HLT;
-		}
-		writel(end, &regs->out_dma_end);
-		writel(start, &regs->out_dma_start);
-
-		master &= ~MST_W_BITS;
-		master |= MST_WR_ENA | MST_TIMEOUT_DIS;
-
-		ep->dev->int_enable |= INT_MSTWREND|INT_MSTWRTMOUT;
-	}
-
-	writel(master, &regs->dma_master);
-	writel(ep->dev->int_enable, &regs->int_enable);
-	return 0;
-}
-
-static void dma_advance(struct goku_udc *dev, struct goku_ep *ep)
-{
-	struct goku_request	*req;
-	struct goku_udc_regs	*regs = ep->dev->regs;
-	u32			master;
-
-	master = readl(&regs->dma_master);
-
-	if (unlikely(list_empty(&ep->queue))) {
-stop:
-		if (ep->is_in)
-			dev->int_enable &= ~INT_MSTRDEND;
-		else
-			dev->int_enable &= ~(INT_MSTWREND|INT_MSTWRTMOUT);
-		writel(dev->int_enable, &regs->int_enable);
-		return;
-	}
-	req = list_entry(ep->queue.next, struct goku_request, queue);
-
-	/* normal hw dma completion (not abort) */
-	if (likely(ep->is_in)) {
-		if (unlikely(master & MST_RD_ENA))
-			return;
-		req->req.actual = readl(&regs->in_dma_current);
-	} else {
-		if (unlikely(master & MST_WR_ENA))
-			return;
-
-		/* hardware merges short packets, and also hides packet
-		 * overruns.  a partial packet MAY be in the fifo here.
-		 */
-		req->req.actual = readl(&regs->out_dma_current);
-	}
-	req->req.actual -= req->req.dma;
-	req->req.actual++;
-
-#ifdef USB_TRACE
-	VDBG(dev, "done %s %s dma, %u/%u bytes, req %p\n",
-		ep->ep.name, ep->is_in ? "IN" : "OUT",
-		req->req.actual, req->req.length, req);
-#endif
-	done(ep, req, 0);
-	if (list_empty(&ep->queue))
-		goto stop;
-	req = list_entry(ep->queue.next, struct goku_request, queue);
-	(void) start_dma(ep, req);
-}
-
-static void abort_dma(struct goku_ep *ep, int status)
-{
-	struct goku_udc_regs	*regs = ep->dev->regs;
-	struct goku_request	*req;
-	u32			curr, master;
-
-	/* NAK future host requests, hoping the implicit delay lets the
-	 * dma engine finish reading (or writing) its latest packet and
-	 * empty the dma buffer (up to 16 bytes).
-	 *
-	 * This avoids needing to clean up a partial packet in the fifo;
-	 * we can't do that for IN without side effects to HALT and TOGGLE.
-	 */
-	command(regs, COMMAND_FIFO_DISABLE, ep->num);
-	req = list_entry(ep->queue.next, struct goku_request, queue);
-	master = readl(&regs->dma_master) & MST_RW_BITS;
-
-	/* FIXME using these resets isn't usably documented. this may
-	 * not work unless it's followed by disabling the endpoint.
-	 *
-	 * FIXME the OUT reset path doesn't even behave consistently.
-	 */
-	if (ep->is_in) {
-		if (unlikely((readl(&regs->dma_master) & MST_RD_ENA) == 0))
-			goto finished;
-		curr = readl(&regs->in_dma_current);
-
-		writel(curr, &regs->in_dma_end);
-		writel(curr, &regs->in_dma_start);
-
-		master &= ~MST_R_BITS;
-		master |= MST_RD_RESET;
-		writel(master, &regs->dma_master);
-
-		if (readl(&regs->dma_master) & MST_RD_ENA)
-			DBG(ep->dev, "IN dma active after reset!\n");
-
-	} else {
-		if (unlikely((readl(&regs->dma_master) & MST_WR_ENA) == 0))
-			goto finished;
-		curr = readl(&regs->out_dma_current);
-
-		writel(curr, &regs->out_dma_end);
-		writel(curr, &regs->out_dma_start);
-
-		master &= ~MST_W_BITS;
-		master |= MST_WR_RESET;
-		writel(master, &regs->dma_master);
-
-		if (readl(&regs->dma_master) & MST_WR_ENA)
-			DBG(ep->dev, "OUT dma active after reset!\n");
-	}
-	req->req.actual = (curr - req->req.dma) + 1;
-	req->req.status = status;
-
-	VDBG(ep->dev, "%s %s %s %d/%d\n", __FUNCTION__, ep->ep.name,
-		ep->is_in ? "IN" : "OUT",
-		req->req.actual, req->req.length);
-
-	command(regs, COMMAND_FIFO_ENABLE, ep->num);
-
-	return;
-
-finished:
-	/* dma already completed; no abort needed */
-	command(regs, COMMAND_FIFO_ENABLE, ep->num);
-	req->req.actual = req->req.length;
-	req->req.status = 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int
-goku_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
-{
-	struct goku_request	*req;
-	struct goku_ep		*ep;
-	struct goku_udc		*dev;
-	unsigned long		flags;
-	int			status;
-
-	/* always require a cpu-view buffer so pio works */
-	req = container_of(_req, struct goku_request, req);
-	if (unlikely(!_req || !_req->complete
-			|| !_req->buf || !list_empty(&req->queue)))
-		return -EINVAL;
-	ep = container_of(_ep, struct goku_ep, ep);
-	if (unlikely(!_ep || (!ep->desc && ep->num != 0)))
-		return -EINVAL;
-	dev = ep->dev;
-	if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN))
-		return -ESHUTDOWN;
-
-	/* can't touch registers when suspended */
-	if (dev->ep0state == EP0_SUSPEND)
-		return -EBUSY;
-
-	/* set up dma mapping in case the caller didn't */
-	if (ep->dma && _req->dma == DMA_ADDR_INVALID) {
-		_req->dma = pci_map_single(dev->pdev, _req->buf, _req->length,
-			ep->is_in ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
-		req->mapped = 1;
-	}
-
-#ifdef USB_TRACE
-	VDBG(dev, "%s queue req %p, len %u buf %p\n",
-			_ep->name, _req, _req->length, _req->buf);
-#endif
-
-	spin_lock_irqsave(&dev->lock, flags);
-
-	_req->status = -EINPROGRESS;
-	_req->actual = 0;
-
-	/* for ep0 IN without premature status, zlp is required and
-	 * writing EOP starts the status stage (OUT).
-	 */
-	if (unlikely(ep->num == 0 && ep->is_in))
-		_req->zero = 1;
-
-	/* kickstart this i/o queue? */
-	status = 0;
-	if (list_empty(&ep->queue) && likely(!ep->stopped)) {
-		/* dma:  done after dma completion IRQ (or error)
-		 * pio:  done after last fifo operation
-		 */
-		if (ep->dma)
-			status = start_dma(ep, req);
-		else
-			status = (ep->is_in ? write_fifo : read_fifo)(ep, req);
-
-		if (unlikely(status != 0)) {
-			if (status > 0)
-				status = 0;
-			req = 0;
-		}
-
-	} /* else pio or dma irq handler advances the queue. */
-
-	if (likely(req != 0))
-		list_add_tail(&req->queue, &ep->queue);
-
-	if (likely(!list_empty(&ep->queue))
-			&& likely(ep->num != 0)
-			&& !ep->dma
-			&& !(dev->int_enable & INT_EPxDATASET (ep->num)))
-		pio_irq_enable(dev, dev->regs, ep->num);
-
-	spin_unlock_irqrestore(&dev->lock, flags);
-
-	/* pci writes may still be posted */
-	return status;
-}
-
-/* dequeue ALL requests */
-static void nuke(struct goku_ep *ep, int status)
-{
-	struct goku_request	*req;
-
-	ep->stopped = 1;
-	if (list_empty(&ep->queue))
-		return;
-	if (ep->dma)
-		abort_dma(ep, status);
-	while (!list_empty(&ep->queue)) {
-		req = list_entry(ep->queue.next, struct goku_request, queue);
-		done(ep, req, status);
-	}
-}
-
-/* dequeue JUST ONE request */
-static int goku_dequeue(struct usb_ep *_ep, struct usb_request *_req)
-{
-	struct goku_request	*req;
-	struct goku_ep		*ep;
-	struct goku_udc		*dev;
-	unsigned long		flags;
-
-	ep = container_of(_ep, struct goku_ep, ep);
-	if (!_ep || !_req || (!ep->desc && ep->num != 0))
-		return -EINVAL;
-	dev = ep->dev;
-	if (!dev->driver)
-		return -ESHUTDOWN;
-
-	/* we can't touch (dma) registers when suspended */
-	if (dev->ep0state == EP0_SUSPEND)
-		return -EBUSY;
-
-	VDBG(dev, "%s %s %s %s %p\n", __FUNCTION__, _ep->name,
-		ep->is_in ? "IN" : "OUT",
-		ep->dma ? "dma" : "pio",
-		_req);
-
-	spin_lock_irqsave(&dev->lock, flags);
-
-	/* make sure it's actually queued on this endpoint */
-	list_for_each_entry (req, &ep->queue, queue) {
-		if (&req->req == _req)
-			break;
-	}
-	if (&req->req != _req) {
-		spin_unlock_irqrestore (&dev->lock, flags);
-		return -EINVAL;
-	}
-
-	if (ep->dma && ep->queue.next == &req->queue && !ep->stopped) {
-		abort_dma(ep, -ECONNRESET);
-		done(ep, req, -ECONNRESET);
-		dma_advance(dev, ep);
-	} else if (!list_empty(&req->queue))
-		done(ep, req, -ECONNRESET);
-	else
-		req = 0;
-	spin_unlock_irqrestore(&dev->lock, flags);
-
-	return req ? 0 : -EOPNOTSUPP;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void goku_clear_halt(struct goku_ep *ep)
-{
-	// assert (ep->num !=0)
-	VDBG(ep->dev, "%s clear halt\n", ep->ep.name);
-	command(ep->dev->regs, COMMAND_SETDATA0, ep->num);
-	command(ep->dev->regs, COMMAND_STALL_CLEAR, ep->num);
-	if (ep->stopped) {
-		ep->stopped = 0;
-		if (ep->dma) {
-			struct goku_request	*req;
-
-			if (list_empty(&ep->queue))
-				return;
-			req = list_entry(ep->queue.next, struct goku_request,
-						queue);
-			(void) start_dma(ep, req);
-		} else
-			pio_advance(ep);
-	}
-}
-
-static int goku_set_halt(struct usb_ep *_ep, int value)
-{
-	struct goku_ep	*ep;
-	unsigned long	flags;
-	int		retval = 0;
-
-	if (!_ep)
-		return -ENODEV;
-	ep = container_of (_ep, struct goku_ep, ep);
-
-	if (ep->num == 0) {
-		if (value) {
-			ep->dev->ep0state = EP0_STALL;
-			ep->dev->ep[0].stopped = 1;
-		} else
-			return -EINVAL;
-
-	/* don't change EPxSTATUS_EP_INVALID to READY */
-	} else if (!ep->desc) {
-		DBG(ep->dev, "%s %s inactive?\n", __FUNCTION__, ep->ep.name);
-		return -EINVAL;
-	}
-
-	spin_lock_irqsave(&ep->dev->lock, flags);
-	if (!list_empty(&ep->queue))
-		retval = -EAGAIN;
-	else if (ep->is_in && value
-			/* data in (either) packet buffer? */
-			&& (ep->dev->regs->DataSet & DATASET_AB(ep->num)))
-		retval = -EAGAIN;
-	else if (!value)
-		goku_clear_halt(ep);
-	else {
-		ep->stopped = 1;
-		VDBG(ep->dev, "%s set halt\n", ep->ep.name);
-		command(ep->dev->regs, COMMAND_STALL, ep->num);
-		readl(ep->reg_status);
-	}
-	spin_unlock_irqrestore(&ep->dev->lock, flags);
-	return retval;
-}
-
-static int goku_fifo_status(struct usb_ep *_ep)
-{
-	struct goku_ep		*ep;
-	struct goku_udc_regs	*regs;
-	u32			size;
-
-	if (!_ep)
-		return -ENODEV;
-	ep = container_of(_ep, struct goku_ep, ep);
-
-	/* size is only reported sanely for OUT */
-	if (ep->is_in)
-		return -EOPNOTSUPP;
-
-	/* ignores 16-byte dma buffer; SizeH == 0 */
-	regs = ep->dev->regs;
-	size = readl(&regs->EPxSizeLA[ep->num]) & DATASIZE;
-	size += readl(&regs->EPxSizeLB[ep->num]) & DATASIZE;
-	VDBG(ep->dev, "%s %s %u\n", __FUNCTION__, ep->ep.name, size);
-	return size;
-}
-
-static void goku_fifo_flush(struct usb_ep *_ep)
-{
-	struct goku_ep		*ep;
-	struct goku_udc_regs	*regs;
-	u32			size;
-
-	if (!_ep)
-		return;
-	ep = container_of(_ep, struct goku_ep, ep);
-	VDBG(ep->dev, "%s %s\n", __FUNCTION__, ep->ep.name);
-
-	/* don't change EPxSTATUS_EP_INVALID to READY */
-	if (!ep->desc && ep->num != 0) {
-		DBG(ep->dev, "%s %s inactive?\n", __FUNCTION__, ep->ep.name);
-		return;
-	}
-
-	regs = ep->dev->regs;
-	size = readl(&regs->EPxSizeLA[ep->num]);
-	size &= DATASIZE;
-
-	/* Non-desirable behavior:  FIFO_CLEAR also clears the
-	 * endpoint halt feature.  For OUT, we _could_ just read
-	 * the bytes out (PIO, if !ep->dma); for in, no choice.
-	 */
-	if (size)
-		command(regs, COMMAND_FIFO_CLEAR, ep->num);
-}
-
-static struct usb_ep_ops goku_ep_ops = {
-	.enable		= goku_ep_enable,
-	.disable	= goku_ep_disable,
-
-	.alloc_request	= goku_alloc_request,
-	.free_request	= goku_free_request,
-
-	.alloc_buffer	= goku_alloc_buffer,
-	.free_buffer	= goku_free_buffer,
-
-	.queue		= goku_queue,
-	.dequeue	= goku_dequeue,
-
-	.set_halt	= goku_set_halt,
-	.fifo_status	= goku_fifo_status,
-	.fifo_flush	= goku_fifo_flush,
-};
-
-/*-------------------------------------------------------------------------*/
-
-static int goku_get_frame(struct usb_gadget *_gadget)
-{
-	return -EOPNOTSUPP;
-}
-
-static const struct usb_gadget_ops goku_ops = {
-	.get_frame	= goku_get_frame,
-	// no remote wakeup
-	// not selfpowered
-};
-
-/*-------------------------------------------------------------------------*/
-
-static inline char *dmastr(void)
-{
-	if (use_dma == 0)
-		return "(dma disabled)";
-	else if (use_dma == 2)
-		return "(dma IN and OUT)";
-	else
-		return "(dma IN)";
-}
-
-/* if we're trying to save space, don't bother with this proc file */
-
-#if defined(CONFIG_PROC_FS) && !defined(CONFIG_EMBEDDED)
-#  define	UDC_PROC_FILE
-#endif
-
-#ifdef UDC_PROC_FILE
-
-static const char proc_node_name [] = "driver/udc";
-
-#define FOURBITS "%s%s%s%s"
-#define EIGHTBITS FOURBITS FOURBITS
-
-static void
-dump_intmask(const char *label, u32 mask, char **next, unsigned *size)
-{
-	int t;
-
-	/* int_status is the same format ... */
-	t = snprintf(*next, *size,
-		"%s %05X =" FOURBITS EIGHTBITS EIGHTBITS "\n",
-		label, mask,
-		(mask & INT_PWRDETECT) ? " power" : "",
-		(mask & INT_SYSERROR) ? " sys" : "",
-		(mask & INT_MSTRDEND) ? " in-dma" : "",
-		(mask & INT_MSTWRTMOUT) ? " wrtmo" : "",
-
-		(mask & INT_MSTWREND) ? " out-dma" : "",
-		(mask & INT_MSTWRSET) ? " wrset" : "",
-		(mask & INT_ERR) ? " err" : "",
-		(mask & INT_SOF) ? " sof" : "",
-
-		(mask & INT_EP3NAK) ? " ep3nak" : "",
-		(mask & INT_EP2NAK) ? " ep2nak" : "",
-		(mask & INT_EP1NAK) ? " ep1nak" : "",
-		(mask & INT_EP3DATASET) ? " ep3" : "",
-
-		(mask & INT_EP2DATASET) ? " ep2" : "",
-		(mask & INT_EP1DATASET) ? " ep1" : "",
-		(mask & INT_STATUSNAK) ? " ep0snak" : "",
-		(mask & INT_STATUS) ? " ep0status" : "",
-
-		(mask & INT_SETUP) ? " setup" : "",
-		(mask & INT_ENDPOINT0) ? " ep0" : "",
-		(mask & INT_USBRESET) ? " reset" : "",
-		(mask & INT_SUSPEND) ? " suspend" : "");
-	*size -= t;
-	*next += t;
-}
-
-
-static int
-udc_proc_read(char *buffer, char **start, off_t off, int count,
-		int *eof, void *_dev)
-{
-	char			*buf = buffer;
-	struct goku_udc		*dev = _dev;
-	struct goku_udc_regs	*regs = dev->regs;
-	char			*next = buf;
-	unsigned		size = count;
-	unsigned long		flags;
-	int			i, t, is_usb_connected;
-	u32			tmp;
-
-	if (off != 0)
-		return 0;
-
-	local_irq_save(flags);
-
-	/* basic device status */
-	tmp = readl(&regs->power_detect);
-	is_usb_connected = tmp & PW_DETECT;
-	t = snprintf(next, size,
-		"%s - %s\n"
-		"%s version: %s %s\n"
-		"Gadget driver: %s\n"
-		"Host %s, %s\n"
-		"\n",
-		pci_name(dev->pdev), driver_desc,
-		driver_name, DRIVER_VERSION, dmastr(),
-		dev->driver ? dev->driver->driver.name : "(none)",
-		is_usb_connected
-			? ((tmp & PW_PULLUP) ? "full speed" : "powered")
-			: "disconnected",
-		({char *tmp;
-		switch(dev->ep0state){
-		case EP0_DISCONNECT:	tmp = "ep0_disconnect"; break;
-		case EP0_IDLE:		tmp = "ep0_idle"; break;
-		case EP0_IN:		tmp = "ep0_in"; break;
-		case EP0_OUT:		tmp = "ep0_out"; break;
-		case EP0_STATUS:	tmp = "ep0_status"; break;
-		case EP0_STALL:		tmp = "ep0_stall"; break;
-		case EP0_SUSPEND:	tmp = "ep0_suspend"; break;
-		default:		tmp = "ep0_?"; break;
-		} tmp; })
-		);
-	size -= t;
-	next += t;
-
-	dump_intmask("int_status", readl(&regs->int_status), &next, &size);
-	dump_intmask("int_enable", readl(&regs->int_enable), &next, &size);
-
-	if (!is_usb_connected || !dev->driver || (tmp & PW_PULLUP) == 0)
-		goto done;
-
-	/* registers for (active) device and ep0 */
-	t = snprintf(next, size, "\nirqs %lu\ndataset %02x "
-			"single.bcs %02x.%02x state %x addr %u\n",
-			dev->irqs, readl(&regs->DataSet),
-			readl(&regs->EPxSingle), readl(&regs->EPxBCS),
-			readl(&regs->UsbState),
-			readl(&regs->address));
-	size -= t;
-	next += t;
-
-	tmp = readl(&regs->dma_master);
-	t = snprintf(next, size,
-		"dma %03X =" EIGHTBITS "%s %s\n", tmp,
-		(tmp & MST_EOPB_DIS) ? " eopb-" : "",
-		(tmp & MST_EOPB_ENA) ? " eopb+" : "",
-		(tmp & MST_TIMEOUT_DIS) ? " tmo-" : "",
-		(tmp & MST_TIMEOUT_ENA) ? " tmo+" : "",
-
-		(tmp & MST_RD_EOPB) ? " eopb" : "",
-		(tmp & MST_RD_RESET) ? " in_reset" : "",
-		(tmp & MST_WR_RESET) ? " out_reset" : "",
-		(tmp & MST_RD_ENA) ? " IN" : "",
-
-		(tmp & MST_WR_ENA) ? " OUT" : "",
-		(tmp & MST_CONNECTION)
-			? "ep1in/ep2out"
-			: "ep1out/ep2in");
-	size -= t;
-	next += t;
-
-	/* dump endpoint queues */
-	for (i = 0; i < 4; i++) {
-		struct goku_ep		*ep = &dev->ep [i];
-		struct goku_request	*req;
-		int			t;
-
-		if (i && !ep->desc)
-			continue;
-
-		tmp = readl(ep->reg_status);
-		t = snprintf(next, size,
-			"%s %s max %u %s, irqs %lu, "
-			"status %02x (%s) " FOURBITS "\n",
-			ep->ep.name,
-			ep->is_in ? "in" : "out",
-			ep->ep.maxpacket,
-			ep->dma ? "dma" : "pio",
-			ep->irqs,
-			tmp, ({ char *s;
-			switch (tmp & EPxSTATUS_EP_MASK) {
-			case EPxSTATUS_EP_READY:
-				s = "ready"; break;
-			case EPxSTATUS_EP_DATAIN:
-				s = "packet"; break;
-			case EPxSTATUS_EP_FULL:
-				s = "full"; break;
-			case EPxSTATUS_EP_TX_ERR:	// host will retry
-				s = "tx_err"; break;
-			case EPxSTATUS_EP_RX_ERR:
-				s = "rx_err"; break;
-			case EPxSTATUS_EP_BUSY:		/* ep0 only */
-				s = "busy"; break;
-			case EPxSTATUS_EP_STALL:
-				s = "stall"; break;
-			case EPxSTATUS_EP_INVALID:	// these "can't happen"
-				s = "invalid"; break;
-			default:
-				s = "?"; break;
-			}; s; }),
-			(tmp & EPxSTATUS_TOGGLE) ? "data1" : "data0",
-			(tmp & EPxSTATUS_SUSPEND) ? " suspend" : "",
-			(tmp & EPxSTATUS_FIFO_DISABLE) ? " disable" : "",
-			(tmp & EPxSTATUS_STAGE_ERROR) ? " ep0stat" : ""
-			);
-		if (t <= 0 || t > size)
-			goto done;
-		size -= t;
-		next += t;
-
-		if (list_empty(&ep->queue)) {
-			t = snprintf(next, size, "\t(nothing queued)\n");
-			if (t <= 0 || t > size)
-				goto done;
-			size -= t;
-			next += t;
-			continue;
-		}
-		list_for_each_entry(req, &ep->queue, queue) {
-			if (ep->dma && req->queue.prev == &ep->queue) {
-				if (i == UDC_MSTRD_ENDPOINT)
-					tmp = readl(&regs->in_dma_current);
-				else
-					tmp = readl(&regs->out_dma_current);
-				tmp -= req->req.dma;
-				tmp++;
-			} else
-				tmp = req->req.actual;
-
-			t = snprintf(next, size,
-				"\treq %p len %u/%u buf %p\n",
-				&req->req, tmp, req->req.length,
-				req->req.buf);
-			if (t <= 0 || t > size)
-				goto done;
-			size -= t;
-			next += t;
-		}
-	}
-
-done:
-	local_irq_restore(flags);
-	*eof = 1;
-	return count - size;
-}
-
-#endif	/* UDC_PROC_FILE */
-
-/*-------------------------------------------------------------------------*/
-
-static void udc_reinit (struct goku_udc *dev)
-{
-	static char *names [] = { "ep0", "ep1-bulk", "ep2-bulk", "ep3-bulk" };
-	
-	unsigned i;
-
-	INIT_LIST_HEAD (&dev->gadget.ep_list);
-	dev->gadget.ep0 = &dev->ep [0].ep;
-	dev->gadget.speed = USB_SPEED_UNKNOWN;
-	dev->ep0state = EP0_DISCONNECT;
-	dev->irqs = 0;
-
-	for (i = 0; i < 4; i++) {
-		struct goku_ep	*ep = &dev->ep[i];
-
-		ep->num = i;
-		ep->ep.name = names[i];
-		ep->reg_fifo = &dev->regs->ep_fifo [i];
-		ep->reg_status = &dev->regs->ep_status [i];
-		ep->reg_mode = &dev->regs->ep_mode[i];
-
-		ep->ep.ops = &goku_ep_ops;
-		list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
-		ep->dev = dev;
-		INIT_LIST_HEAD (&ep->queue);
-
-		ep_reset(0, ep);
-	}
-
-	dev->ep[0].reg_mode = 0;
-	dev->ep[0].ep.maxpacket = MAX_EP0_SIZE;
-	list_del_init (&dev->ep[0].ep.ep_list);
-}
-
-static void udc_reset(struct goku_udc *dev)
-{
-	struct goku_udc_regs	*regs = dev->regs;
-
-	writel(0, &regs->power_detect);
-	writel(0, &regs->int_enable);
-	readl(&regs->int_enable);
-	dev->int_enable = 0;
-
-	/* deassert reset, leave USB D+ at hi-Z (no pullup)
-	 * don't let INT_PWRDETECT sequence begin
-	 */
-	udelay(250);
-	writel(PW_RESETB, &regs->power_detect);
-	readl(&regs->int_enable);
-}
-
-static void ep0_start(struct goku_udc *dev)
-{
-	struct goku_udc_regs	*regs = dev->regs;
-	unsigned		i;
-
-	VDBG(dev, "%s\n", __FUNCTION__);
-
-	udc_reset(dev);
-	udc_reinit (dev);
-	//writel(MST_EOPB_ENA | MST_TIMEOUT_ENA, &regs->dma_master);
-
-	/* hw handles set_address, set_feature, get_status; maybe more */
-	writel(   G_REQMODE_SET_INTF | G_REQMODE_GET_INTF
-		| G_REQMODE_SET_CONF | G_REQMODE_GET_CONF
-		| G_REQMODE_GET_DESC
-		| G_REQMODE_CLEAR_FEAT
-		, &regs->reqmode);
-
-	for (i = 0; i < 4; i++)
-		dev->ep[i].irqs = 0;
-
-	/* can't modify descriptors after writing UsbReady */
-	for (i = 0; i < DESC_LEN; i++)
-		writel(0, &regs->descriptors[i]);
-	writel(0, &regs->UsbReady);
-
-	/* expect ep0 requests when the host drops reset */
-	writel(PW_RESETB | PW_PULLUP, &regs->power_detect);
-	dev->int_enable = INT_DEVWIDE | INT_EP0;
-	writel(dev->int_enable, &dev->regs->int_enable);
-	readl(&regs->int_enable);
-	dev->gadget.speed = USB_SPEED_FULL;
-	dev->ep0state = EP0_IDLE;
-}
-
-static void udc_enable(struct goku_udc *dev)
-{
-	/* start enumeration now, or after power detect irq */
-	if (readl(&dev->regs->power_detect) & PW_DETECT)
-		ep0_start(dev);
-	else {
-		DBG(dev, "%s\n", __FUNCTION__);
-		dev->int_enable = INT_PWRDETECT;
-		writel(dev->int_enable, &dev->regs->int_enable);
-	}
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* keeping it simple:
- * - one bus driver, initted first;
- * - one function driver, initted second
- */
-
-static struct goku_udc	*the_controller;
-
-/* when a driver is successfully registered, it will receive
- * control requests including set_configuration(), which enables
- * non-control requests.  then usb traffic follows until a
- * disconnect is reported.  then a host may connect again, or
- * the driver might get unbound.
- */
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
-{
-	struct goku_udc	*dev = the_controller;
-	int			retval;
-
-	if (!driver
-			|| driver->speed != USB_SPEED_FULL
-			|| !driver->bind
-			|| !driver->unbind
-			|| !driver->disconnect
-			|| !driver->setup)
-		return -EINVAL;
-	if (!dev)
-		return -ENODEV;
-	if (dev->driver)
-		return -EBUSY;
-
-	/* hook up the driver */
-	dev->driver = driver;
-	retval = driver->bind(&dev->gadget);
-	if (retval) {
-		DBG(dev, "bind to driver %s --> error %d\n",
-				driver->driver.name, retval);
-		dev->driver = 0;
-		return retval;
-	}
-
-	/* then enable host detection and ep0; and we're ready
-	 * for set_configuration as well as eventual disconnect.
-	 */
-	udc_enable(dev);
-
-	DBG(dev, "registered gadget driver '%s'\n", driver->driver.name);
-	return 0;
-}
-EXPORT_SYMBOL(usb_gadget_register_driver);
-
-static void
-stop_activity(struct goku_udc *dev, struct usb_gadget_driver *driver)
-{
-	unsigned	i;
-
-	DBG (dev, "%s\n", __FUNCTION__);
-
-	if (dev->gadget.speed == USB_SPEED_UNKNOWN)
-		driver = 0;
-
-	/* disconnect gadget driver after quiesceing hw and the driver */
-	udc_reset (dev);
-	for (i = 0; i < 4; i++)
-		nuke(&dev->ep [i], -ESHUTDOWN);
-	if (driver) {
-		spin_unlock(&dev->lock);
-		driver->disconnect(&dev->gadget);
-		spin_lock(&dev->lock);
-	}
-
-	if (dev->driver)
-		udc_enable(dev);
-}
-
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
-{
-	struct goku_udc	*dev = the_controller;
-	unsigned long	flags;
-
-	if (!dev)
-		return -ENODEV;
-	if (!driver || driver != dev->driver)
-		return -EINVAL;
-
-	spin_lock_irqsave(&dev->lock, flags);
-	dev->driver = 0;
-	stop_activity(dev, driver);
-	spin_unlock_irqrestore(&dev->lock, flags);
-
-	driver->unbind(&dev->gadget);
-
-	DBG(dev, "unregistered driver '%s'\n", driver->driver.name);
-	return 0;
-}
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
-
-
-/*-------------------------------------------------------------------------*/
-
-static void ep0_setup(struct goku_udc *dev)
-{
-	struct goku_udc_regs	*regs = dev->regs;
-	struct usb_ctrlrequest	ctrl;
-	int			tmp;
-
-	/* read SETUP packet and enter DATA stage */
-	ctrl.bRequestType = readl(&regs->bRequestType);
-	ctrl.bRequest = readl(&regs->bRequest);
-	ctrl.wValue  = (readl(&regs->wValueH)  << 8) | readl(&regs->wValueL);
-	ctrl.wIndex  = (readl(&regs->wIndexH)  << 8) | readl(&regs->wIndexL);
-	ctrl.wLength = (readl(&regs->wLengthH) << 8) | readl(&regs->wLengthL);
-	writel(0, &regs->SetupRecv);
-
-	nuke(&dev->ep[0], 0);
-	dev->ep[0].stopped = 0;
-	if (likely(ctrl.bRequestType & USB_DIR_IN)) {
-		dev->ep[0].is_in = 1;
-		dev->ep0state = EP0_IN;
-		/* detect early status stages */
-		writel(ICONTROL_STATUSNAK, &dev->regs->IntControl);
-	} else {
-		dev->ep[0].is_in = 0;
-		dev->ep0state = EP0_OUT;
-
-		/* NOTE:  CLEAR_FEATURE is done in software so that we can
-		 * synchronize transfer restarts after bulk IN stalls.  data
-		 * won't even enter the fifo until the halt is cleared.
-		 */
-		switch (ctrl.bRequest) {
-		case USB_REQ_CLEAR_FEATURE:
-			switch (ctrl.bRequestType) {
-			case USB_RECIP_ENDPOINT:
-				tmp = ctrl.wIndex & 0x0f;
-				/* active endpoint */
-				if (tmp > 3 || (!dev->ep[tmp].desc && tmp != 0))
-					goto stall;
-				if (ctrl.wIndex & USB_DIR_IN) {
-					if (!dev->ep[tmp].is_in)
-						goto stall;
-				} else {
-					if (dev->ep[tmp].is_in)
-						goto stall;
-				}
-				/* endpoint halt */
-				if (ctrl.wValue != 0)
-					goto stall;
-				if (tmp)
-					goku_clear_halt(&dev->ep[tmp]);
-succeed:
-				/* start ep0out status stage */
-				writel(~(1<<0), &regs->EOP);
-				dev->ep[0].stopped = 1;
-				dev->ep0state = EP0_STATUS;
-				return;
-			case USB_RECIP_DEVICE:
-				/* device remote wakeup: always clear */
-				if (ctrl.wValue != 1)
-					goto stall;
-				VDBG(dev, "clear dev remote wakeup\n");
-				goto succeed;
-			case USB_RECIP_INTERFACE:
-				goto stall;
-			default:		/* pass to gadget driver */
-				break;
-			}
-			break;
-		default:
-			break;
-		}
-	}
-
-#ifdef USB_TRACE
-	VDBG(dev, "SETUP %02x.%02x v%04x i%04x l%04x\n",
-		ctrl.bRequestType, ctrl.bRequest,
-		ctrl.wValue, ctrl.wIndex, ctrl.wLength);
-#endif
-
-	/* hw wants to know when we're configured (or not) */
-	dev->req_config = (ctrl.bRequest == USB_REQ_SET_CONFIGURATION
-				&& ctrl.bRequestType == USB_RECIP_DEVICE);
-	if (unlikely(dev->req_config))
-		dev->configured = (ctrl.wValue != 0);
-
-	/* delegate everything to the gadget driver.
-	 * it may respond after this irq handler returns.
-	 */
-	spin_unlock (&dev->lock);
-	tmp = dev->driver->setup(&dev->gadget, &ctrl);
-	spin_lock (&dev->lock);
-	if (unlikely(tmp < 0)) {
-stall:
-#ifdef USB_TRACE
-		VDBG(dev, "req %02x.%02x protocol STALL; err %d\n",
-				ctrl.bRequestType, ctrl.bRequest, tmp);
-#endif
-		command(regs, COMMAND_STALL, 0);
-		dev->ep[0].stopped = 1;
-		dev->ep0state = EP0_STALL;
-	}
-
-	/* expect at least one data or status stage irq */
-}
-
-#define ACK(irqbit) { \
-		stat &= ~irqbit; \
-		writel(~irqbit, &regs->int_status); \
-		handled = 1; \
-		}
-
-static irqreturn_t goku_irq(int irq, void *_dev, struct pt_regs *r)
-{
-	struct goku_udc		*dev = _dev;
-	struct goku_udc_regs	*regs = dev->regs;
-	struct goku_ep		*ep;
-	u32			stat, handled = 0;
-	unsigned		i, rescans = 5;
-
-	spin_lock(&dev->lock);
-
-rescan:
-	stat = readl(&regs->int_status) & dev->int_enable;
-        if (!stat)
-		goto done;
-	dev->irqs++;
-
-	/* device-wide irqs */
-	if (unlikely(stat & INT_DEVWIDE)) {
-		if (stat & INT_SYSERROR) {
-			ERROR(dev, "system error\n");
-			stop_activity(dev, dev->driver);
-			stat = 0;
-			handled = 1;
-			// FIXME have a neater way to prevent re-enumeration
-			dev->driver = 0;
-			goto done;
-		}
-		if (stat & INT_PWRDETECT) {
-			writel(~stat, &regs->int_status);
-			if (readl(&dev->regs->power_detect) & PW_DETECT) {
-				VDBG(dev, "connect\n");
-				ep0_start(dev);
-			} else {
-				DBG(dev, "disconnect\n");
-				if (dev->gadget.speed == USB_SPEED_FULL)
-					stop_activity(dev, dev->driver);
-				dev->ep0state = EP0_DISCONNECT;
-				dev->int_enable = INT_DEVWIDE;
-				writel(dev->int_enable, &dev->regs->int_enable);
-			}
-			stat = 0;
-			handled = 1;
-			goto done;
-		}
-		if (stat & INT_SUSPEND) {
-			ACK(INT_SUSPEND);
-			if (readl(&regs->ep_status[0]) & EPxSTATUS_SUSPEND) {
-				switch (dev->ep0state) {
-				case EP0_DISCONNECT:
-				case EP0_SUSPEND:
-					goto pm_next;
-				default:
-					break;
-				}
-				DBG(dev, "USB suspend\n");
-				dev->ep0state = EP0_SUSPEND;
-				if (dev->gadget.speed != USB_SPEED_UNKNOWN
-						&& dev->driver
-						&& dev->driver->suspend) {
-					spin_unlock(&dev->lock);
-					dev->driver->suspend(&dev->gadget);
-					spin_lock(&dev->lock);
-				}
-			} else {
-				if (dev->ep0state != EP0_SUSPEND) {
-					DBG(dev, "bogus USB resume %d\n",
-						dev->ep0state);
-					goto pm_next;
-				}
-				DBG(dev, "USB resume\n");
-				dev->ep0state = EP0_IDLE;
-				if (dev->gadget.speed != USB_SPEED_UNKNOWN
-						&& dev->driver
-						&& dev->driver->resume) {
-					spin_unlock(&dev->lock);
-					dev->driver->resume(&dev->gadget);
-					spin_lock(&dev->lock);
-				}
-			}
-		}
-pm_next:
-		if (stat & INT_USBRESET) {		/* hub reset done */
-			ACK(INT_USBRESET);
-			INFO(dev, "USB reset done, gadget %s\n",
-				dev->driver->driver.name);
-		}
-		// and INT_ERR on some endpoint's crc/bitstuff/... problem
-	}
-
-	/* progress ep0 setup, data, or status stages.
-	 * no transition {EP0_STATUS, EP0_STALL} --> EP0_IDLE; saves irqs
-	 */
-	if (stat & INT_SETUP) {
-		ACK(INT_SETUP);
-		dev->ep[0].irqs++;
-		ep0_setup(dev);
-	}
-        if (stat & INT_STATUSNAK) {
-		ACK(INT_STATUSNAK|INT_ENDPOINT0);
-		if (dev->ep0state == EP0_IN) {
-			ep = &dev->ep[0];
-			ep->irqs++;
-			nuke(ep, 0);
-			writel(~(1<<0), &regs->EOP);
-			dev->ep0state = EP0_STATUS;
-		}
-	}
-        if (stat & INT_ENDPOINT0) {
-		ACK(INT_ENDPOINT0);
-		ep = &dev->ep[0];
-		ep->irqs++;
-		pio_advance(ep);
-        }
-
-	/* dma completion */
-        if (stat & INT_MSTRDEND) {	/* IN */
-		ACK(INT_MSTRDEND);
-		ep = &dev->ep[UDC_MSTRD_ENDPOINT];
-		ep->irqs++;
-		dma_advance(dev, ep);
-        }
-        if (stat & INT_MSTWREND) {	/* OUT */
-		ACK(INT_MSTWREND);
-		ep = &dev->ep[UDC_MSTWR_ENDPOINT];
-		ep->irqs++;
-		dma_advance(dev, ep);
-        }
-        if (stat & INT_MSTWRTMOUT) {	/* OUT */
-		ACK(INT_MSTWRTMOUT);
-		ep = &dev->ep[UDC_MSTWR_ENDPOINT];
-		ep->irqs++;
-		ERROR(dev, "%s write timeout ?\n", ep->ep.name);
-		// reset dma? then dma_advance()
-        }
-
-	/* pio */
-	for (i = 1; i < 4; i++) {
-		u32		tmp = INT_EPxDATASET(i);
-
-		if (!(stat & tmp))
-			continue;
-		ep = &dev->ep[i];
-		pio_advance(ep);
-		if (list_empty (&ep->queue))
-			pio_irq_disable(dev, regs, i);
-		stat &= ~tmp;
-		handled = 1;
-		ep->irqs++;
-	}
-
-	if (rescans--)
-		goto rescan;
-
-done:
-	(void)readl(&regs->int_enable);
-	spin_unlock(&dev->lock);
-	if (stat)
-		DBG(dev, "unhandled irq status: %05x (%05x, %05x)\n", stat,
-				readl(&regs->int_status), dev->int_enable);
-	return IRQ_RETVAL(handled);
-}
-
-#undef ACK
-
-/*-------------------------------------------------------------------------*/
-
-/* tear down the binding between this driver and the pci device */
-
-static void goku_remove(struct pci_dev *pdev)
-{
-	struct goku_udc		*dev = pci_get_drvdata(pdev);
-
-	DBG(dev, "%s\n", __FUNCTION__);
-	/* start with the driver above us */
-	if (dev->driver) {
-		/* should have been done already by driver model core */
-		WARN(dev, "pci remove, driver '%s' is still registered\n",
-				dev->driver->driver.name);
-		usb_gadget_unregister_driver(dev->driver);
-	}
-
-#ifdef	UDC_PROC_FILE
-	remove_proc_entry(proc_node_name, NULL);
-#endif
-	if (dev->regs)
-		udc_reset(dev);
-	if (dev->got_irq)
-		free_irq(pdev->irq, dev);
-	if (dev->regs)
-		iounmap(dev->regs);
-	if (dev->got_region)
-		release_mem_region(pci_resource_start (pdev, 0),
-				pci_resource_len (pdev, 0));
-	if (dev->enabled)
-		pci_disable_device(pdev);
-
-	pci_set_drvdata(pdev, 0);
-	dev->regs = 0;
-	the_controller = 0;
-
-	INFO(dev, "unbind\n");
-}
-
-/* wrap this driver around the specified pci device, but
- * don't respond over USB until a gadget driver binds to us.
- */
-
-static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-	struct goku_udc		*dev = 0;
-	unsigned long		resource, len;
-	void			*base = 0;
-	int			retval;
-	char			buf [8], *bufp;
-
-	/* if you want to support more than one controller in a system,
-	 * usb_gadget_driver_{register,unregister}() must change.
-	 */
-	if (the_controller) {
-		WARN(dev, "ignoring %s\n", pci_name(pdev));
-		return -EBUSY;
-	}
-	if (!pdev->irq) {
-		printk(KERN_ERR "Check PCI %s IRQ setup!\n", pci_name(pdev));
-		retval = -ENODEV;
-		goto done;
-	}
-
-	/* alloc, and start init */
-	dev = kmalloc (sizeof *dev, SLAB_KERNEL);
-	if (dev == NULL){
-		pr_debug("enomem %s\n", pci_name(pdev));
-		retval = -ENOMEM;
-		goto done;
-	}
-
-	memset(dev, 0, sizeof *dev);
-	spin_lock_init(&dev->lock);
-	dev->pdev = pdev;
-	dev->gadget.ops = &goku_ops;
-
-	/* the "gadget" abstracts/virtualizes the controller */
-	dev->gadget.dev.bus_id = "gadget";
-	dev->gadget.name = driver_name;
-
-	/* now all the pci goodies ... */
-	retval = pci_enable_device(pdev);
-	if (retval < 0) {
-		DBG(dev, "can't enable, %d\n", retval);
-		goto done;
-	}
-	dev->enabled = 1;
-
-	resource = pci_resource_start(pdev, 0);
-	len = pci_resource_len(pdev, 0);
-	if (!request_mem_region(resource, len, driver_name)) {
-		DBG(dev, "controller already in use\n");
-		retval = -EBUSY;
-		goto done;
-	}
-	dev->got_region = 1;
-
-	base = ioremap_nocache(resource, len);
-	if (base == NULL) {
-		DBG(dev, "can't map memory\n");
-		retval = -EFAULT;
-		goto done;
-	}
-	dev->regs = (struct goku_udc_regs *) base;
-
-	pci_set_drvdata(pdev, dev);
-	INFO(dev, "%s\n", driver_desc);
-	INFO(dev, "version: " DRIVER_VERSION " %s\n", dmastr());
-#ifndef __sparc__
-	snprintf(buf, sizeof buf, "%d", pdev->irq);
-	bufp = buf;
-#else
-	bufp = __irq_itoa(pdev->irq);
-#endif
-	INFO(dev, "irq %s, pci mem %p\n", bufp, base);
-
-	/* init to known state, then setup irqs */
-	udc_reset(dev);
-	udc_reinit (dev);
-	if (request_irq(pdev->irq, goku_irq, SA_SHIRQ/*|SA_SAMPLE_RANDOM*/,
-			driver_name, dev) != 0) {
-		DBG(dev, "request interrupt %s failed\n", bufp);
-		retval = -EBUSY;
-		goto done;
-	}
-	dev->got_irq = 1;
-	if (use_dma)
-		pci_set_master(pdev);
-
-
-#ifdef	UDC_PROC_FILE
-	create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev);
-#endif
-
-	/* done */
-	the_controller = dev;
-
-	return 0;
-
-done:
-	if (dev)
-		goku_remove (pdev);
-	return retval;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static struct pci_device_id pci_ids [] = { {
-	.class = 	((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
-	.class_mask = 	~0,
-	.vendor =	0x102f,		/* Toshiba */
-	.device =	0x0107,		/* this UDC */
-	.subvendor =	PCI_ANY_ID,
-	.subdevice =	PCI_ANY_ID,
-
-}, { /* end: all zeroes */ }
-};
-MODULE_DEVICE_TABLE (pci, pci_ids);
-
-static struct pci_driver goku_pci_driver = {
-	.name =		(char *) driver_name,
-	.id_table =	pci_ids,
-
-	.probe =	goku_probe,
-	.remove =	goku_remove,
-
-	/* FIXME add power management support */
-};
-
-static int __init init (void)
-{
-	return pci_module_init (&goku_pci_driver);
-}
-module_init (init);
-
-static void __exit cleanup (void)
-{
-	pci_unregister_driver (&goku_pci_driver);
-}
-module_exit (cleanup);
diff -ruN linux-2.4.20-WRTup/drivers/usb/gadget/goku_udc.h linux-2.4.20-WRTstp/drivers/usb/gadget/goku_udc.h
--- linux-2.4.20-WRTup/drivers/usb/gadget/goku_udc.h	2006-06-12 18:04:59.000000000 -0700
+++ linux-2.4.20-WRTstp/drivers/usb/gadget/goku_udc.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,321 +0,0 @@
-/*
- * Toshiba TC86C001 ("Goku-S") USB Device Controller driver
- *
- * Copyright (C) 2000-2002 Lineo
- *      by Stuart Lynne, Tom Rushworth, and Bruce Balden
- * Copyright (C) 2002 Toshiba Corporation
- * Copyright (C) 2003 MontaVista Software (source@mvista.com)
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-/*
- * PCI BAR 0 points to these registers.
- */
-struct goku_udc_regs {
-	/* irq management */
-	u32	int_status;		/* 0x000 */
-	u32	int_enable;
-#define INT_SUSPEND		0x00001		/* or resume */
-#define INT_USBRESET		0x00002
-#define INT_ENDPOINT0		0x00004
-#define INT_SETUP		0x00008
-#define INT_STATUS		0x00010
-#define INT_STATUSNAK		0x00020
-#define INT_EPxDATASET(n)	(0x00020 << (n))	/* 0 < n < 4 */
-#	define INT_EP1DATASET		0x00040
-#	define INT_EP2DATASET		0x00080
-#	define INT_EP3DATASET		0x00100
-#define INT_EPnNAK(n)		(0x00100 < (n))		/* 0 < n < 4 */
-#	define INT_EP1NAK		0x00200
-#	define INT_EP2NAK		0x00400
-#	define INT_EP3NAK		0x00800
-#define INT_SOF			0x01000
-#define INT_ERR			0x02000
-#define INT_MSTWRSET		0x04000
-#define INT_MSTWREND		0x08000
-#define INT_MSTWRTMOUT		0x10000
-#define INT_MSTRDEND		0x20000
-#define INT_SYSERROR		0x40000
-#define INT_PWRDETECT		0x80000
-
-#define	INT_DEVWIDE		(INT_PWRDETECT|INT_SYSERROR/*|INT_ERR*/|INT_USBRESET|INT_SUSPEND)
-#define	INT_EP0 		(INT_SETUP|INT_ENDPOINT0/*|INT_STATUS*/|INT_STATUSNAK)
-
-	u32	dma_master;
-#define MST_EOPB_DIS		0x0800
-#define MST_EOPB_ENA		0x0400
-#define MST_TIMEOUT_DIS		0x0200
-#define MST_TIMEOUT_ENA		0x0100
-#define MST_RD_EOPB		0x0080		/* write-only */
-#define MST_RD_RESET		0x0040
-#define MST_WR_RESET		0x0020
-#define MST_RD_ENA		0x0004		/* 1:start, 0:ignore */
-#define MST_WR_ENA		0x0002		/* 1:start, 0:ignore */
-#define MST_CONNECTION		0x0001		/* 0 for ep1out/ep2in */
-
-#define MST_R_BITS		(MST_EOPB_DIS|MST_EOPB_ENA \
-					|MST_RD_ENA|MST_RD_RESET)
-#define MST_W_BITS		(MST_TIMEOUT_DIS|MST_TIMEOUT_ENA \
-					|MST_WR_ENA|MST_WR_RESET)
-#define MST_RW_BITS		(MST_R_BITS|MST_W_BITS \
-					|MST_CONNECTION)
-
-/* these values assume (dma_master & MST_CONNECTION) == 0 */
-#define UDC_MSTWR_ENDPOINT        1
-#define UDC_MSTRD_ENDPOINT        2
-
-	/* dma master write */
-	u32	out_dma_start;
-	u32	out_dma_end;
-	u32	out_dma_current;
-
-	/* dma master read */
-	u32	in_dma_start;
-	u32	in_dma_end;
-	u32	in_dma_current;
-
-	u32	power_detect;
-#define PW_DETECT		0x04
-#define PW_RESETB		0x02
-#define PW_PULLUP		0x01
-
-	u8	_reserved0 [0x1d8];
-
-	/* endpoint registers */
-	u32	ep_fifo [4];		/* 0x200 */
-	u8	_reserved1 [0x10];
-	u32	ep_mode [4];		/* only 1-3 valid */
-	u8	_reserved2 [0x10];
-
-	u32	ep_status [4];
-#define EPxSTATUS_TOGGLE	0x40
-#define EPxSTATUS_SUSPEND	0x20
-#define EPxSTATUS_EP_MASK	(0x07<<2)
-#	define EPxSTATUS_EP_READY	(0<<2)
-#	define EPxSTATUS_EP_DATAIN	(1<<2)
-#	define EPxSTATUS_EP_FULL	(2<<2)
-#	define EPxSTATUS_EP_TX_ERR	(3<<2)
-#	define EPxSTATUS_EP_RX_ERR	(4<<2)
-#	define EPxSTATUS_EP_BUSY	(5<<2)
-#	define EPxSTATUS_EP_STALL	(6<<2)
-#	define EPxSTATUS_EP_INVALID	(7<<2)
-#define EPxSTATUS_FIFO_DISABLE	0x02
-#define EPxSTATUS_STAGE_ERROR	0x01
-
-	u8	_reserved3 [0x10];
-	u32	EPxSizeLA[4];
-#define PACKET_ACTIVE		(1<<7)
-#define DATASIZE		0x7f
-	u8	_reserved3a [0x10];
-	u32	EPxSizeLB[4];		/* only 1,2 valid */
-	u8	_reserved3b [0x10];
-	u32	EPxSizeHA[4];		/* only 1-3 valid */
-	u8	_reserved3c [0x10];
-	u32	EPxSizeHB[4];		/* only 1,2 valid */
-	u8	_reserved4[0x30];
-
-	/* SETUP packet contents */
-	u32	bRequestType;		/* 0x300 */
-	u32	bRequest;
-	u32	wValueL;
-	u32	wValueH;
-	u32	wIndexL;
-	u32	wIndexH;
-	u32	wLengthL;
-	u32	wLengthH;
-
-	/* command interaction/handshaking */
-	u32	SetupRecv;		/* 0x320 */
-	u32	CurrConfig;
-	u32	StdRequest;
-	u32	Request;
-	u32	DataSet;
-#define DATASET_A(epnum)	(1<<(2*(epnum)))
-#define DATASET_B(epnum)	(2<<(2*(epnum)))
-#define DATASET_AB(epnum)	(3<<(2*(epnum)))
-	u8	_reserved5[4];
-
-	u32	UsbState;
-#define USBSTATE_CONFIGURED	0x04
-#define USBSTATE_ADDRESSED	0x02
-#define USBSTATE_DEFAULT	0x01
-
-	u32	EOP;
-
-	u32	Command;		/* 0x340 */
-#define COMMAND_SETDATA0	2
-#define COMMAND_RESET		3
-#define COMMAND_STALL		4
-#define COMMAND_INVALID		5
-#define COMMAND_FIFO_DISABLE	7
-#define COMMAND_FIFO_ENABLE	8
-#define COMMAND_INIT_DESCRIPTOR	9
-#define COMMAND_FIFO_CLEAR	10	/* also stall */
-#define COMMAND_STALL_CLEAR	11
-#define COMMAND_EP(n)		((n) << 4)
-
-	u32	EPxSingle;
-	u8	_reserved6[4];
-	u32	EPxBCS;
-	u8	_reserved7[8];
-	u32	IntControl;
-#define ICONTROL_STATUSNAK	1
-	u8	_reserved8[4];
-
-	u32	reqmode;	// 0x360 standard request mode, low 8 bits
-#define G_REQMODE_SET_INTF	(1<<7)
-#define G_REQMODE_GET_INTF	(1<<6)
-#define G_REQMODE_SET_CONF	(1<<5)
-#define G_REQMODE_GET_CONF	(1<<4)
-#define G_REQMODE_GET_DESC	(1<<3)
-#define G_REQMODE_SET_FEAT	(1<<2)
-#define G_REQMODE_CLEAR_FEAT	(1<<1)
-#define G_REQMODE_GET_STATUS	(1<<0)
-
-	u32	ReqMode;
-	u8	_reserved9[0x18];
-	u32	PortStatus;		/* 0x380 */
-	u8	_reserved10[8];
-	u32	address;
-	u32	buff_test;
-	u8	_reserved11[4];
-	u32	UsbReady;
-	u8	_reserved12[4];
-	u32	SetDescStall;		/* 0x3a0 */
-	u8	_reserved13[0x45c];
-
-	/* hardware could handle limited GET_DESCRIPTOR duties */
-#define	DESC_LEN	0x80
-	u32	descriptors[DESC_LEN];	/* 0x800 */
-	u8	_reserved14[0x600];
-
-} __attribute__ ((packed));
-
-#define	MAX_FIFO_SIZE	64
-#define	MAX_EP0_SIZE	8		/* ep0 fifo is bigger, though */
-
-
-/*-------------------------------------------------------------------------*/
-
-/* DRIVER DATA STRUCTURES and UTILITIES */
-
-struct goku_ep {
-	struct usb_ep				ep;
-	struct goku_udc				*dev;
-	unsigned long				irqs;
-
-	unsigned				num:8,
-						dma:1,
-						is_in:1,
-						stopped:1;
-
-	/* analogous to a host-side qh */
-	struct list_head			queue;
-	const struct usb_endpoint_descriptor	*desc;
-
-	u32					*reg_fifo;
-	u32					*reg_mode;
-	u32					*reg_status;
-};
-
-struct goku_request {
-	struct usb_request		req;
-	struct list_head		queue;
-
-	unsigned			mapped:1;
-};
-
-enum ep0state {
-	EP0_DISCONNECT,		/* no host */
-	EP0_IDLE,		/* between STATUS ack and SETUP report */
-	EP0_IN, EP0_OUT, 	/* data stage */
-	EP0_STATUS,		/* status stage */
-	EP0_STALL,		/* data or status stages */
-	EP0_SUSPEND,		/* usb suspend */
-};
-
-struct goku_udc {
-	/* each pci device provides one gadget, several endpoints */
-	struct usb_gadget		gadget;
-	spinlock_t			lock;
-	struct goku_ep			ep[4];
-	struct usb_gadget_driver 	*driver;
-
-	enum ep0state			ep0state;
-	unsigned			got_irq:1,
-					got_region:1,
-					req_config:1,
-					configured:1,
-					enabled:1;
-
-	/* pci state used to access those endpoints */
-	struct pci_dev			*pdev;
-	struct goku_udc_regs		*regs;
-	u32				int_enable;
-
-	/* statistics... */
-	unsigned long			irqs;
-};
-
-/*-------------------------------------------------------------------------*/
-
-#define xprintk(dev,level,fmt,args...) \
-	printk(level "%s %s: " fmt , driver_name , \
-			pci_name(dev->pdev) , ## args)
-
-#ifdef DEBUG
-#define DBG(dev,fmt,args...) \
-	xprintk(dev , KERN_DEBUG , fmt , ## args)
-#else
-#define DBG(dev,fmt,args...) \
-	do { } while (0)
-#endif /* DEBUG */
-
-#ifdef VERBOSE
-#define VDBG DBG
-#else
-#define VDBG(dev,fmt,args...) \
-	do { } while (0)
-#endif	/* VERBOSE */
-
-#define ERROR(dev,fmt,args...) \
-	xprintk(dev , KERN_ERR , fmt , ## args)
-#define WARN(dev,fmt,args...) \
-	xprintk(dev , KERN_WARNING , fmt , ## args)
-#define INFO(dev,fmt,args...) \
-	xprintk(dev , KERN_INFO , fmt , ## args)
-
-/*-------------------------------------------------------------------------*/
-
-/* 2.5 stuff that's sometimes missing in 2.4 */
-
-#ifndef container_of
-#define	container_of	list_entry
-#endif
-
-#ifndef likely
-#define likely(x)	(x)
-#define unlikely(x)	(x)
-#endif
-
-#ifndef BUG_ON
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-#endif
-
-#ifndef WARN_ON
-#define	WARN_ON(x)	do { } while (0)
-#endif
-
-#ifndef	IRQ_NONE
-typedef void irqreturn_t;
-#define IRQ_NONE
-#define IRQ_HANDLED
-#define IRQ_RETVAL(x)
-#endif
-
-#ifndef pci_name
-#define pci_name(pdev)	((pdev)->slot_name)
-#endif
diff -ruN linux-2.4.20-WRTup/drivers/usb/gadget/inode.c linux-2.4.20-WRTstp/drivers/usb/gadget/inode.c
--- linux-2.4.20-WRTup/drivers/usb/gadget/inode.c	2006-06-12 18:04:59.000000000 -0700
+++ linux-2.4.20-WRTstp/drivers/usb/gadget/inode.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,1970 +0,0 @@
-/*
- * inode.c -- user mode filesystem api for usb gadget controllers
- *
- * Copyright (C) 2003 David Brownell
- * Copyright (C) 2003 Agilent Technologies
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-
-#define	DEBUG 1			/* data to help fault diagnosis */
-// #define	VERBOSE		/* extra debug messages (success too) */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/pagemap.h>
-#include <linux/uts.h>
-#include <linux/version.h>
-#include <linux/wait.h>
-#include <linux/compiler.h>
-#include <asm/uaccess.h>
-#include <linux/slab.h>
-
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
-#define	lk25
-#include <linux/device.h>
-#include <linux/moduleparam.h>
-#else
-#ifndef BUG_ON
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-#endif
-#endif
-
-#include <linux/usb_gadgetfs.h>
-#include <linux/usb_gadget.h>
-
-
-/*
- * The gadgetfs API maps each endpoint to a file descriptor so that you
- * can use standard synchronous read/write calls for I/O.  There's some
- * O_NONBLOCK and O_ASYNC/FASYNC style i/o support.  Example usermode
- * drivers show how this works in practice.
- *
- * Key parts that must be USB-specific are protocols defining how the
- * read/write operations relate to the hardware state machines.  There
- * are two types of files.  One type is for the device, implementing ep0.
- * The other type is for each IN or OUT endpoint.  In both cases, the
- * user mode driver must configure the hardware before using it.
- *
- * - First, dev_config() is called when /dev/gadget/$CHIP is configured
- *   (by writing configuration and device descriptors).  Afterwards it
- *   may serve as a source of device events, used to handle all control
- *   requests other than basic enumeration.
- *
- * - Then either immediately, or after a SET_CONFIGURATION control request,
- *   ep_config() is called when each /dev/gadget/ep* file is configured
- *   (by writing endpoint descriptors).  Afterwards these files are used
- *   to write() IN data or to read() OUT data.  To halt the endpoint, a
- *   "wrong direction" request is issued (like reading an IN endpoint).
- *
- * Unlike "usbfs" the only ioctl()s are for things that are rare, and maybe
- * not possible on all hardware.  For example, precise fault handling with
- * respect to data left in endpoint fifos after aborted operations; or
- * selective clearing of endpoint halts, to implement SET_INTERFACE.
- */
-
-#define	DRIVER_DESC	"USB Gadget filesystem"
-#define	DRIVER_VERSION	"20 Aug 2003"
-
-static const char driver_desc [] = DRIVER_DESC;
-static const char shortname [] = "gadgetfs";
-
-MODULE_DESCRIPTION (DRIVER_DESC);
-MODULE_AUTHOR ("David Brownell");
-MODULE_LICENSE ("GPL");
-
-
-/*----------------------------------------------------------------------*/
-
-#define GADGETFS_MAGIC		0xaee71ee7
-#define DMA_ADDR_INVALID	(~(dma_addr_t)0)
-
-/* /dev/gadget/$CHIP represents ep0 and the whole device */
-enum ep0_state {
-	/* DISBLED is the initial state.
-	 */
-	STATE_DEV_DISABLED = 0,
-
-	/* Only one open() of /dev/gadget/$CHIP; only one file tracks
-	 * ep0/device i/o modes and binding to the controller.  Driver
-	 * must always write descriptors to initialize the device, then
-	 * the device becomes UNCONNECTED until enumeration.
-	 */
-	STATE_OPENED,
-
-	/* From then on, ep0 fd is in either of two basic modes:
-	 * - (UN)CONNECTED: read usb_gadgetfs_event(s) from it
-	 * - SETUP: read/write will transfer control data and succeed;
-	 *   or if "wrong direction", performs protocol stall
-	 */
-	STATE_UNCONNECTED,
-	STATE_CONNECTED,
-	STATE_SETUP,
-
-	/* UNBOUND means the driver closed ep0, so the device won't be
-	 * accessible again (DEV_DISABLED) until all fds are closed.
-	 */
-	STATE_DEV_UNBOUND,
-};
-
-/* enough for the whole queue: most events invalidate others */
-#define	N_EVENT			5
-
-struct dev_data {
-	spinlock_t			lock;
-	atomic_t			count;
-	enum ep0_state			state;
-	struct usb_gadgetfs_event	event [N_EVENT];
-	unsigned			ev_next;
-	struct fasync_struct		*fasync;
-	u8				current_config;
-
-	/* drivers reading ep0 MUST handle control requests (SETUP)
-	 * reported that way; else the host will time out.
-	 */
-	unsigned			usermode_setup : 1,
-					setup_in : 1,
-					setup_can_stall : 1,
-					setup_out_ready : 1,
-					setup_out_error : 1,
-					setup_abort : 1;
-
-	/* the rest is basically write-once */
-	struct usb_config_descriptor	*config, *hs_config;
-	struct usb_device_descriptor	*dev;
-	struct usb_request		*req;
-	struct usb_gadget		*gadget;
-	struct list_head		epfiles;
-	void				*buf;
-	wait_queue_head_t		wait;
-	struct super_block		*sb;
-	struct dentry			*dentry;
-
-	/* except this scratch i/o buffer for ep0 */
-	u8				rbuf [256];
-};
-
-static inline void get_dev (struct dev_data *data)
-{
-	atomic_inc (&data->count);
-}
-
-static void put_dev (struct dev_data *data)
-{
-	if (likely (!atomic_dec_and_test (&data->count)))
-		return;
-	/* needs no more cleanup */
-	BUG_ON (waitqueue_active (&data->wait));
-	kfree (data);
-}
-
-static struct dev_data *dev_new (void)
-{
-	struct dev_data		*dev;
-
-	dev = kmalloc (sizeof *dev, GFP_KERNEL);
-	if (!dev)
-		return 0;
-	memset (dev, 0, sizeof *dev);
-	dev->state = STATE_DEV_DISABLED;
-	atomic_set (&dev->count, 1);
-	spin_lock_init (&dev->lock);
-	INIT_LIST_HEAD (&dev->epfiles);
-	init_waitqueue_head (&dev->wait);
-	return dev;
-}
-
-/*----------------------------------------------------------------------*/
-
-/* other /dev/gadget/$ENDPOINT files represent endpoints */
-enum ep_state {
-	STATE_EP_DISABLED = 0,
-	STATE_EP_READY,
-	STATE_EP_DEFER_ENABLE,
-	STATE_EP_ENABLED,
-	STATE_EP_UNBOUND,
-};
-
-struct ep_data {
-	struct semaphore		lock;
-	enum ep_state			state;
-	atomic_t			count;
-	struct dev_data			*dev;
-	/* must hold dev->lock before accessing ep or req */
-	struct usb_ep			*ep;
-	struct usb_request		*req;
-	ssize_t				status;
-	char				name [16];
-	struct usb_endpoint_descriptor	desc, hs_desc;
-	struct list_head		epfiles;
-	wait_queue_head_t		wait;
-	struct dentry			*dentry;
-	struct inode			*inode;
-};
-
-static inline void get_ep (struct ep_data *data)
-{
-	atomic_inc (&data->count);
-}
-
-static void put_ep (struct ep_data *data)
-{
-	if (likely (!atomic_dec_and_test (&data->count)))
-		return;
-	put_dev (data->dev);
-	/* needs no more cleanup */
-	BUG_ON (!list_empty (&data->epfiles));
-	BUG_ON (waitqueue_active (&data->wait));
-	BUG_ON (down_trylock (&data->lock) != 0);
-	kfree (data);
-}
-
-/*----------------------------------------------------------------------*/
-
-/* most "how to use the hardware" policy choices are in userspace:
- * mapping endpoint roles the driver needs to the capabilities that
- * the usb controller exposes.
- */
-
-#ifdef	CONFIG_USB_GADGETFS_NET2280
-#define CHIP			"net2280"
-#define HIGHSPEED
-#endif
-
-#ifdef	CONFIG_USB_GADGETFS_PXA2XX
-#define CHIP			"pxa2xx_udc"
-/* earlier hardware doesn't have UDCCFR, races set_{config,interface} */
-#warning works best with pxa255 or newer
-#endif
-
-#ifdef	CONFIG_USB_GADGETFS_SA1100
-#define CHIP			"sa1100"
-#endif
-
-/*----------------------------------------------------------------------*/
-
-/* NOTE:  don't use dev_printk calls before binding to the gadget
- * at the end of ep0 configuration, or after unbind.
- */
-
-/* too wordy: dev_printk(level , &(d)->gadget->dev , fmt , ## args) */
-#define xprintk(d,level,fmt,args...) \
-	printk(level "%s: " fmt , shortname , ## args)
-
-#ifdef DEBUG
-#define DBG(dev,fmt,args...) \
-	xprintk(dev , KERN_DEBUG , fmt , ## args)
-#else
-#define DBG(dev,fmt,args...) \
-	do { } while (0)
-#endif /* DEBUG */
-
-#ifdef VERBOSE
-#define VDEBUG	DBG
-#else
-#define VDEBUG(dev,fmt,args...) \
-	do { } while (0)
-#endif /* DEBUG */
-
-#define ERROR(dev,fmt,args...) \
-	xprintk(dev , KERN_ERR , fmt , ## args)
-#define WARN(dev,fmt,args...) \
-	xprintk(dev , KERN_WARNING , fmt , ## args)
-#define INFO(dev,fmt,args...) \
-	xprintk(dev , KERN_INFO , fmt , ## args)
-
-
-/*----------------------------------------------------------------------*/
-
-/* SYNCHRONOUS ENDPOINT OPERATIONS (bulk/intr/iso)
- *
- * After opening, configure non-control endpoints.  Then use normal
- * stream read() and write() requests; and maybe ioctl() to get more
- * precise FIFO status when recovering from cancelation.
- */
-
-static void epio_complete (struct usb_ep *ep, struct usb_request *req)
-{
-	struct ep_data	*epdata = ep->driver_data;
-
-	if (!req->context)
-		return;
-	if (req->status)
-		epdata->status = req->status;
-	else
-		epdata->status = req->actual;
-	complete ((struct completion *)req->context);
-}
-
-/* tasklock endpoint, returning when it's connected.
- * still need dev->lock to use epdata->ep.
- */
-static int
-get_ready_ep (unsigned f_flags, struct ep_data *epdata)
-{
-	int	val;
-
-	if (f_flags & O_NONBLOCK) {
-		if (down_trylock (&epdata->lock) != 0)
-			goto nonblock;
-		if (epdata->state != STATE_EP_ENABLED) {
-			up (&epdata->lock);
-nonblock:
-			val = -EAGAIN;
-		} else
-			val = 0;
-		return val;
-	}
-
-	if ((val = down_interruptible (&epdata->lock)) < 0)
-		return val;
-newstate:
-	switch (epdata->state) {
-	case STATE_EP_ENABLED:
-		break;
-	case STATE_EP_DEFER_ENABLE:
-		DBG (epdata->dev, "%s wait for host\n", epdata->name);
-		if ((val = wait_event_interruptible (epdata->wait, 
-				epdata->state != STATE_EP_DEFER_ENABLE
-				|| epdata->dev->state == STATE_DEV_UNBOUND
-				)) < 0)
-			goto fail;
-		goto newstate;
-	// case STATE_EP_DISABLED:		/* "can't happen" */
-	// case STATE_EP_READY:			/* "can't happen" */
-	default:				/* error! */
-		pr_debug ("%s: ep %p not available, state %d\n",
-				shortname, epdata, epdata->state);
-		// FALLTHROUGH
-	case STATE_EP_UNBOUND:			/* clean disconnect */
-		val = -ENODEV;
-fail:
-		up (&epdata->lock);
-	}
-	return val;
-}
-
-static ssize_t
-ep_io (struct ep_data *epdata, void *buf, unsigned len)
-{
-	DECLARE_COMPLETION (done);
-
-	spin_lock_irq (&epdata->dev->lock);
-	if (likely (epdata->ep != NULL)) {
-		struct usb_request	*req = epdata->req;
-
-		req->context = &done;
-		req->complete = epio_complete;
-		req->buf = buf;
-		req->length = len;
-		epdata->status = usb_ep_queue (epdata->ep, req, GFP_ATOMIC);
-	} else
-		epdata->status = -ENODEV;
-	spin_unlock_irq (&epdata->dev->lock);
-
-	if (epdata->status == 0) {
-		int	value;
-
-		value = wait_event_interruptible (done.wait, done.done);
-		if (value != 0) {
-			spin_lock_irq (&epdata->dev->lock);
-			if (likely (epdata->ep != NULL)) {
-				DBG (epdata->dev, "%s i/o interrupted\n",
-						epdata->name);
-				usb_ep_dequeue (epdata->ep, epdata->req);
-				wait_event (done.wait, done.done);
-				if (epdata->status == 0)
-					epdata->status = value;
-			} else {
-				DBG (epdata->dev, "endpoint gone\n");
-				epdata->status = -ENODEV;
-			}
-			spin_unlock_irq (&epdata->dev->lock);
-		}
-	}
-	return epdata->status;
-}
-
-
-/* handle a synchronous OUT bulk/intr/iso transfer */
-static ssize_t
-ep_read (struct file *fd, char *buf, size_t len, loff_t *ptr)
-{
-	struct ep_data		*data = fd->private_data;
-	void			*kbuf;
-	ssize_t			value;
-
-	if ((value = get_ready_ep (fd->f_flags, data)) < 0)
-		return value;
-
-	/* halt any endpoint by doing a "wrong direction" i/o call */
-	if (data->desc.bEndpointAddress & USB_DIR_IN) {
-		if ((data->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-				== USB_ENDPOINT_XFER_ISOC)
-			return -EINVAL;
-		DBG (data->dev, "%s halt\n", data->name);
-		spin_lock_irq (&data->dev->lock);
-		if (likely (data->ep != NULL))
-			usb_ep_set_halt (data->ep);
-		spin_unlock_irq (&data->dev->lock);
-		up (&data->lock);
-		return -EBADMSG;
-	}
-
-
-	value = -ENOMEM;
-	kbuf = kmalloc (len, SLAB_KERNEL);
-	if (unlikely (!kbuf))
-		goto free1;
-
-	VDEBUG (data->dev, "%s read %d OUT\n", data->name, len);
-	value = ep_io (data, kbuf, len);
-	if (value >= 0 && copy_to_user (buf, kbuf, value))
-		value = -EFAULT;
-free1:
-	up (&data->lock);
-	kfree (kbuf);
-	return value;
-}
-
-/* handle a synchronous IN bulk/intr/iso transfer */
-static ssize_t
-ep_write (struct file *fd, const char *buf, size_t len, loff_t *ptr)
-{
-	struct ep_data		*data = fd->private_data;
-	void			*kbuf;
-	ssize_t			value;
-
-	if ((value = get_ready_ep (fd->f_flags, data)) < 0)
-		return value;
-
-	/* halt any endpoint by doing a "wrong direction" i/o call */
-	if (!(data->desc.bEndpointAddress & USB_DIR_IN)) {
-		if ((data->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-				== USB_ENDPOINT_XFER_ISOC)
-			return -EINVAL;
-		DBG (data->dev, "%s halt\n", data->name);
-		spin_lock_irq (&data->dev->lock);
-		if (likely (data->ep != NULL))
-			usb_ep_set_halt (data->ep);
-		spin_unlock_irq (&data->dev->lock);
-		up (&data->lock);
-		return -EBADMSG;
-	}
-
-
-	value = -ENOMEM;
-	kbuf = kmalloc (len, SLAB_KERNEL);
-	if (!kbuf)
-		goto free1;
-	if (copy_from_user (kbuf, buf, len)) {
-		value = -EFAULT;
-		goto free1;
-	}
-
-	VDEBUG (data->dev, "%s write %d IN\n", data->name, len);
-	value = ep_io (data, kbuf, len);
-free1:
-	up (&data->lock);
-	kfree (kbuf);
-	return value;
-}
-
-static int
-ep_release (struct inode *inode, struct file *fd)
-{
-	struct ep_data		*data = fd->private_data;
-
-	/* clean up if this can be reopened */
-	if (data->state != STATE_EP_UNBOUND) {
-		data->state = STATE_EP_DISABLED;
-		data->desc.bDescriptorType = 0;
-		data->hs_desc.bDescriptorType = 0;
-	}
-	put_ep (data);
-	return 0;
-}
-
-static int ep_ioctl (struct inode *inode, struct file *fd,
-		unsigned code, unsigned long value)
-{
-	struct ep_data		*data = fd->private_data;
-	int			status;
-
-	if ((status = get_ready_ep (fd->f_flags, data)) < 0)
-		return status;
-
-	spin_lock_irq (&data->dev->lock);
-	if (likely (data->ep != NULL)) {
-		switch (code) {
-		case GADGETFS_FIFO_STATUS:
-			status = usb_ep_fifo_status (data->ep);
-			break;
-		case GADGETFS_FIFO_FLUSH:
-			usb_ep_fifo_flush (data->ep);
-			break;
-		case GADGETFS_CLEAR_HALT:
-			status = usb_ep_clear_halt (data->ep);
-			break;
-		default:
-			status = -ENOTTY;
-		}
-	} else
-		status = -ENODEV;
-	spin_unlock_irq (&data->dev->lock);
-	up (&data->lock);
-	return status;
-}
-
-/* used after endpoint configuration */
-static struct file_operations ep_io_operations = {
-	.owner =	THIS_MODULE,
-	.read =		ep_read,
-	.write =	ep_write,
-	.ioctl =	ep_ioctl,
-	.release =	ep_release,
-
-	// .aio_read =	ep_aio_read,
-	// .aio_write =	ep_aio_write,
-};
-
-/* ENDPOINT INITIALIZATION
- *
- *     fd = open ("/dev/gadget/$ENDPOINT", O_RDWR)
- *     status = write (fd, descriptors, sizeof descriptors)
- *
- * That write establishes the endpoint configuration, configuring
- * the controller to process bulk, interrupt, or isochronous transfers
- * at the right maxpacket size, and so on.
- *
- * The descriptors are message type 1, identified by a host order u32
- * at the beginning of what's written.  Descriptor order is: full/low
- * speed descriptor, then optional high speed descriptor.
- */
-static ssize_t
-ep_config (struct file *fd, const char *buf, size_t len, loff_t *ptr)
-{
-	struct ep_data		*data = fd->private_data;
-	struct usb_ep		*ep;
-	u32			tag;
-	int			value;
-
-	if ((value = down_interruptible (&data->lock)) < 0)
-		return value;
-
-	if (data->state != STATE_EP_READY) {
-		value = -EL2HLT;
-		goto fail;
-	}
-
-	value = len;
-	if (len < USB_DT_ENDPOINT_SIZE + 4)
-		goto fail0;
-
-	/* we might need to change message format someday */
-	if (copy_from_user (&tag, buf, 4)) {
-		goto fail1;
-	}
-	if (tag != 1) {
-		DBG(data->dev, "config %s, bad tag %d\n", data->name, tag);
-		goto fail0;
-	}
-	buf += 4;
-	len -= 4;
-
-	/* NOTE:  audio endpoint extensions not accepted here;
-	 * just don't include the extra bytes.
-	 */
-
-	/* full/low speed descriptor, then high speed */
-	if (copy_from_user (&data->desc, buf, USB_DT_ENDPOINT_SIZE)) {
-		goto fail1;
-	}
-	if (data->desc.bLength != USB_DT_ENDPOINT_SIZE
-			|| data->desc.bDescriptorType != USB_DT_ENDPOINT)
-		goto fail0;
-	if (len != USB_DT_ENDPOINT_SIZE) {
-		if (len != 2 * USB_DT_ENDPOINT_SIZE)
-			goto fail0;
-		if (copy_from_user (&data->hs_desc, buf + USB_DT_ENDPOINT_SIZE,
-					USB_DT_ENDPOINT_SIZE)) {
-			goto fail1;
-		}
-		if (data->hs_desc.bLength != USB_DT_ENDPOINT_SIZE
-				|| data->hs_desc.bDescriptorType
-					!= USB_DT_ENDPOINT) {
-			DBG(data->dev, "config %s, bad hs length or type\n",
-					data->name);
-			goto fail0;
-		}
-	}
-	value = len;
-
-	spin_lock_irq (&data->dev->lock);
-	if (data->dev->state == STATE_DEV_UNBOUND) {
-		value = -ENOENT;
-		goto gone;
-	} else if ((ep = data->ep) == NULL) {
-		value = -ENODEV;
-		goto gone;
-	}
-	switch (data->dev->gadget->speed) {
-	case USB_SPEED_LOW:
-	case USB_SPEED_FULL:
-		value = usb_ep_enable (ep, &data->desc);
-		if (value == 0)
-			data->state = STATE_EP_ENABLED;
-		break;
-#ifdef	HIGHSPEED
-	case USB_SPEED_HIGH:
-		/* fails if caller didn't provide that descriptor... */
-		value = usb_ep_enable (ep, &data->hs_desc);
-		if (value == 0)
-			data->state = STATE_EP_ENABLED;
-		break;
-#endif
-	default:
-		DBG (data->dev, "unconnected, %s init deferred\n",
-				data->name);
-		data->state = STATE_EP_DEFER_ENABLE;
-	}
-	if (value == 0)
-		fd->f_op = &ep_io_operations;
-gone:
-	spin_unlock_irq (&data->dev->lock);
-	if (value < 0) {
-fail:
-		data->desc.bDescriptorType = 0;
-		data->hs_desc.bDescriptorType = 0;
-	}
-	up (&data->lock);
-	return value;
-fail0:
-	value = -EINVAL;
-	goto fail;
-fail1:
-	value = -EFAULT;
-	goto fail;
-}
-
-static int
-ep_open (struct inode *inode, struct file *fd)
-{
-	struct ep_data		*data = inode->u.generic_ip;
-	int			value = -EBUSY;
-
-	if (down_interruptible (&data->lock) != 0)
-		return -EINTR;
-	spin_lock_irq (&data->dev->lock);
-	if (data->dev->state == STATE_DEV_UNBOUND)
-		value = -ENOENT;
-	else if (data->state == STATE_EP_DISABLED) {
-		value = 0;
-		data->state = STATE_EP_READY;
-		get_ep (data);
-		fd->private_data = data;
-		VDEBUG (data->dev, "%s ready\n", data->name);
-	} else
-		DBG (data->dev, "%s state %d\n",
-			data->name, data->state);
-	spin_unlock_irq (&data->dev->lock);
-	up (&data->lock);
-	return value;
-}
-
-/* used before endpoint configuration */
-static struct file_operations ep_config_operations = {
-	.owner =	THIS_MODULE,
-	.open =		ep_open,
-	.write =	ep_config,
-	.release =	ep_release,
-};
-
-/*----------------------------------------------------------------------*/
-
-/* EP0 IMPLEMENTATION can be partly in userspace.
- *
- * Drivers that use this facility receive various events, including
- * control requests the kernel doesn't handle.  Drivers that don't
- * use this facility may be too simple-minded for real applications.
- */
-
-static inline void ep0_readable (struct dev_data *dev)
-{
-	wake_up (&dev->wait);
-	kill_fasync (&dev->fasync, SIGIO, POLL_IN);
-}
-
-static void clean_req (struct usb_ep *ep, struct usb_request *req)
-{
-	struct dev_data		*dev = ep->driver_data;
-
-	if (req->buf != dev->rbuf) {
-		usb_ep_free_buffer (ep, req->buf, req->dma, req->length);
-		req->buf = dev->rbuf;
-		req->dma = DMA_ADDR_INVALID;
-	}
-	req->complete = epio_complete;
-	dev->setup_out_ready = 0;
-}
-
-static void ep0_complete (struct usb_ep *ep, struct usb_request *req)
-{
-	struct dev_data		*dev = ep->driver_data;
-	int			free = 1;
-
-	/* for control OUT, data must still get to userspace */
-	if (!dev->setup_in) {
-		dev->setup_out_error = (req->status != 0);
-		if (!dev->setup_out_error)
-			free = 0;
-		dev->setup_out_ready = 1;
-		ep0_readable (dev);
-	} else if (dev->state == STATE_SETUP)
-		dev->state = STATE_CONNECTED;
-
-	/* clean up as appropriate */
-	if (free && req->buf != &dev->rbuf)
-		clean_req (ep, req);
-	req->complete = epio_complete;
-}
-
-static int setup_req (struct usb_ep *ep, struct usb_request *req, u16 len)
-{
-	struct dev_data	*dev = ep->driver_data;
-
-	if (dev->setup_out_ready) {
-		DBG (dev, "ep0 request busy!\n");
-		return -EBUSY;
-	}
-	if (len > sizeof (dev->rbuf))
-		req->buf = usb_ep_alloc_buffer (ep, len, &req->dma, GFP_ATOMIC);
-	if (req->buf == 0) {
-		req->buf = dev->rbuf;
-		return -ENOMEM;
-	}
-	req->complete = ep0_complete;
-	req->length = len;
-	return 0;
-}
-
-static ssize_t
-ep0_read (struct file *fd, char *buf, size_t len, loff_t *ptr)
-{
-	struct dev_data			*dev = fd->private_data;
-	ssize_t				retval;
-	enum ep0_state			state;
-
-	spin_lock_irq (&dev->lock);
-
-	/* report fd mode change before acting on it */
-	if (dev->setup_abort) {
-		dev->setup_abort = 0;
-		retval = -EIDRM;
-		goto done;
-	}
-
-	/* control DATA stage */
-	if ((state = dev->state) == STATE_SETUP) {
-
-		if (dev->setup_in) {		/* stall IN */
-			VDEBUG(dev, "ep0in stall\n");
-			(void) usb_ep_set_halt (dev->gadget->ep0);
-			retval = -EL2HLT;
-			dev->state = STATE_CONNECTED;
-
-		} else if (len == 0) {		/* ack SET_CONFIGURATION etc */
-			struct usb_ep		*ep = dev->gadget->ep0;
-			struct usb_request	*req = dev->req;
-
-			if ((retval = setup_req (ep, req, 0)) == 0)
-				retval = usb_ep_queue (ep, req, GFP_ATOMIC);
-			dev->state = STATE_CONNECTED;
-
-		} else {			/* collect OUT data */
-			if ((fd->f_flags & O_NONBLOCK) != 0
-					&& !dev->setup_out_ready) {
-				retval = -EAGAIN;
-				goto done;
-			}
-			spin_unlock_irq (&dev->lock);
-			retval = wait_event_interruptible (dev->wait,
-					dev->setup_out_ready != 0);
-
-			spin_lock_irq (&dev->lock);
-			if (retval)
-				goto done;
-			if (dev->setup_out_error)
-				retval = -EIO;
-			else {
-				len = min (len, dev->req->actual);
-// FIXME don't call this with the spinlock held ...
-				if (copy_to_user (buf, &dev->req->buf, len))
-					retval = -EFAULT;
-				clean_req (dev->gadget->ep0, dev->req);
-				/* NOTE userspace can't yet choose to stall */
-			}
-		}
-		goto done;
-	}
-
-	/* else normal: return event data */
-	if (len < sizeof dev->event [0]) {
-		retval = -EINVAL;
-		goto done;
-	}
-	len -= len % sizeof (struct usb_gadgetfs_event);
-	dev->usermode_setup = 1;
-
-scan:
-	/* return queued events right away */
-	if (dev->ev_next != 0) {
-		unsigned		i, n;
-		int			tmp = dev->ev_next;
-
-		len = min (len, tmp * sizeof (struct usb_gadgetfs_event));
-		n = len / sizeof (struct usb_gadgetfs_event);
-
-		/* ep0 can't deliver events when STATE_SETUP */
-		for (i = 0; i < n; i++) {
-			if (dev->event [i].type == GADGETFS_SETUP) {
-				len = n = i + 1;
-				len *= sizeof (struct usb_gadgetfs_event);
-				n = 0;
-				break;
-			}
-		}
-		spin_unlock_irq (&dev->lock);
-		if (copy_to_user (buf, &dev->event, len))
-			retval = -EFAULT;
-		else
-			retval = len;
-		if (len > 0) {
-			len /= sizeof (struct usb_gadgetfs_event);
-
-			/* NOTE this doesn't guard against broken drivers;
-			 * concurrent ep0 readers may lose events.
-			 */
-			spin_lock_irq (&dev->lock);
-			dev->ev_next -= len;
-			if (dev->ev_next != 0)
-				memmove (&dev->event, &dev->event [len],
-					sizeof (struct usb_gadgetfs_event)
-						* (tmp - len));
-			if (n == 0)
-				dev->state = STATE_SETUP;
-			spin_unlock_irq (&dev->lock);
-		}
-		return retval;
-	}
-	if (fd->f_flags & O_NONBLOCK) {
-		retval = -EAGAIN;
-		goto done;
-	}
-
-	switch (state) {
-	default:
-		DBG (dev, "fail %s, state %d\n", __FUNCTION__, state);
-		retval = -ESRCH;
-		break;
-	case STATE_UNCONNECTED:
-	case STATE_CONNECTED:
-		spin_unlock_irq (&dev->lock);
-		DBG (dev, "%s wait\n", __FUNCTION__);
-
-		/* wait for events */
-		retval = wait_event_interruptible (dev->wait,
-				dev->ev_next != 0);
-		if (retval < 0)
-			return retval;
-		spin_lock_irq (&dev->lock);
-		goto scan;
-	}
-
-done:
-	spin_unlock_irq (&dev->lock);
-	return retval;
-}
-
-static struct usb_gadgetfs_event *
-next_event (struct dev_data *dev, enum usb_gadgetfs_event_type type)
-{
-	struct usb_gadgetfs_event	*event;
-	unsigned			i;
-
-	switch (type) {
-	/* these events purge the queue */
-	case GADGETFS_DISCONNECT:
-		if (dev->state == STATE_SETUP)
-			dev->setup_abort = 1;
-		// FALL THROUGH
-	case GADGETFS_CONNECT:
-		dev->ev_next = 0;
-		break;
-	case GADGETFS_SETUP:		/* previous request timed out */
-	case GADGETFS_SUSPEND:		/* same effect */
-		/* these events can't be repeated */
-		for (i = 0; i != dev->ev_next; i++) {
-			if (dev->event [i].type != type)
-				continue;
-			DBG (dev, "discard old event %d\n", type);
-			dev->ev_next--;
-			if (i == dev->ev_next)
-				break;
-			/* indices start at zero, for simplicity */
-			memmove (&dev->event [i], &dev->event [i + 1],
-				sizeof (struct usb_gadgetfs_event)
-					* (dev->ev_next - i));
-		}
-		break;
-	default:
-		BUG ();
-	}
-	event = &dev->event [dev->ev_next++];
-	BUG_ON (dev->ev_next > N_EVENT);
-	VDEBUG (dev, "ev %d, next %d\n", type, dev->ev_next);
-	memset (event, 0, sizeof *event);
-	event->type = type;
-	return event;
-}
-
-static ssize_t
-ep0_write (struct file *fd, const char *buf, size_t len, loff_t *ptr)
-{
-	struct dev_data		*dev = fd->private_data;
-	ssize_t			retval = -ESRCH;
-
-	spin_lock_irq (&dev->lock);
-
-	/* report fd mode change before acting on it */
-	if (dev->setup_abort) {
-		dev->setup_abort = 0;
-		retval = -EIDRM;
-
-	/* data and/or status stage for control request */
-	} else if (dev->state == STATE_SETUP) {
-
-		/* IN DATA+STATUS caller makes len <= wLength */
-		if (dev->setup_in) {
-			retval = setup_req (dev->gadget->ep0, dev->req, len);
-			if (retval == 0) {
-				spin_unlock_irq (&dev->lock);
-				if (copy_from_user (dev->req->buf, buf, len))
-					retval = -EFAULT;
-				else
-					retval = usb_ep_queue (
-						dev->gadget->ep0, dev->req,
-						GFP_KERNEL);
-				if (retval < 0) {
-					spin_lock_irq (&dev->lock);
-					clean_req (dev->gadget->ep0, dev->req);
-					spin_unlock_irq (&dev->lock);
-				} else
-					retval = len;
-
-				return retval;
-			}
-
-		/* can stall some OUT transfers */
-		} else if (dev->setup_can_stall) {
-			VDEBUG(dev, "ep0out stall\n");
-			(void) usb_ep_set_halt (dev->gadget->ep0);
-			retval = -EL2HLT;
-			dev->state = STATE_CONNECTED;
-		} else {
-			DBG(dev, "bogus ep0out stall!\n");
-		}
-	} else
-		DBG (dev, "fail %s, state %d\n", __FUNCTION__, dev->state);
-
-	spin_unlock_irq (&dev->lock);
-	return retval;
-}
-
-static int
-ep0_fasync (int f, struct file *fd, int on)
-{
-	struct dev_data		*dev = fd->private_data;
-	// caller must F_SETOWN before signal delivery happens
-	VDEBUG (dev, "%s %s\n", __FUNCTION__, on ? "on" : "off");
-	return fasync_helper (f, fd, on, &dev->fasync);
-}
-
-static struct usb_gadget_driver gadgetfs_driver;
-
-static int
-dev_release (struct inode *inode, struct file *fd)
-{
-	struct dev_data		*dev = fd->private_data;
-
-	/* closing ep0 === shutdown all */
-
-	usb_gadget_unregister_driver (&gadgetfs_driver);
-
-	/* at this point "good" hardware has disconnected the
-	 * device from USB; the host won't see it any more.
-	 * alternatively, all host requests will time out.
-	 */
-
-	fasync_helper (-1, fd, 0, &dev->fasync);
-	kfree (dev->buf);
-	dev->buf = 0;
-	put_dev (dev);
-
-	/* other endpoints were all decoupled from this device */
-	dev->state = STATE_DEV_DISABLED;
-	return 0;
-}
-
-static int dev_ioctl (struct inode *inode, struct file *fd,
-		unsigned code, unsigned long value)
-{
-	struct dev_data		*dev = fd->private_data;
-	struct usb_gadget	*gadget = dev->gadget;
-
-	if (gadget->ops->ioctl)
-		return gadget->ops->ioctl (gadget, code, value);
-	return -ENOTTY;
-}
-
-/* used after device configuration */
-static struct file_operations ep0_io_operations = {
-	.owner =	THIS_MODULE,
-	.read =		ep0_read,
-	.write =	ep0_write,
-	.fasync =	ep0_fasync,
-	// .poll =	ep0_poll,
-	.ioctl =	dev_ioctl,
-	.release =	dev_release,
-};
-
-/*----------------------------------------------------------------------*/
-
-/* The in-kernel gadget driver handles most ep0 issues, in particular
- * enumerating the single configuration (as provided from user space).
- *
- * Unrecognized ep0 requests may be handled in user space.
- */
-
-#ifdef	HIGHSPEED
-static void make_qualifier (struct dev_data *dev)
-{
-	struct usb_qualifier_descriptor		qual;
-	struct usb_device_descriptor		*desc;
-
-	qual.bLength = sizeof qual;
-	qual.bDescriptorType = USB_DT_DEVICE_QUALIFIER;
-	qual.bcdUSB = __constant_cpu_to_le16 (0x0200);
-
-	desc = dev->dev;
-	qual.bDeviceClass = desc->bDeviceClass;
-	qual.bDeviceSubClass = desc->bDeviceSubClass;
-	qual.bDeviceProtocol = desc->bDeviceProtocol;
-
-	/* assumes ep0 uses the same value for both speeds ... */
-	qual.bMaxPacketSize0 = desc->bMaxPacketSize0;
-
-	qual.bNumConfigurations = 1;
-	qual.bRESERVED = 0;
-
-	memcpy (dev->rbuf, &qual, sizeof qual);
-}
-#endif
-
-static int
-config_buf (struct dev_data *dev, u8 type, unsigned index)
-{
-	int		len;
-#ifdef HIGHSPEED
-	int		hs;
-#endif
-
-	/* only one configuration */
-	if (index > 0)
-		return -EINVAL;
-
-#ifdef HIGHSPEED
-	hs = (dev->gadget->speed == USB_SPEED_HIGH);
-	if (type == USB_DT_OTHER_SPEED_CONFIG)
-		hs = !hs;
-	if (hs) {
-		dev->req->buf = dev->hs_config;
-		len = le16_to_cpup (&dev->hs_config->wTotalLength);
-	} else
-#endif
-	{
-		dev->req->buf = dev->config;
-		len = le16_to_cpup (&dev->config->wTotalLength);
-	}
-	((u8 *)dev->req->buf) [1] = type;
-	return len;
-}
-
-static int
-gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
-{
-	struct dev_data			*dev = get_gadget_data (gadget);
-	struct usb_request		*req = dev->req;
-	int				value = -EOPNOTSUPP;
-	struct usb_gadgetfs_event	*event;
-
-	spin_lock (&dev->lock);
-	dev->setup_abort = 0;
-	if (dev->state == STATE_UNCONNECTED) {
-		struct usb_ep	*ep;
-		struct ep_data	*data;
-
-		dev->state = STATE_CONNECTED;
-		dev->dev->bMaxPacketSize0 = gadget->ep0->maxpacket;
-
-#ifdef	HIGHSPEED
-		if (gadget->speed == USB_SPEED_HIGH && dev->hs_config == 0) {
-			ERROR (dev, "no high speed config??\n");
-			return -EINVAL;
-		}
-#endif	/* HIGHSPEED */
-
-		INFO (dev, "connected\n");
-		event = next_event (dev, GADGETFS_CONNECT);
-		event->u.speed = gadget->speed;
-		ep0_readable (dev);
-
-		list_for_each_entry (ep, &gadget->ep_list, ep_list) {
-			data = ep->driver_data;
-			/* ... down_trylock (&data->lock) ... */
-			if (data->state != STATE_EP_DEFER_ENABLE)
-				continue;
-#ifdef	HIGHSPEED
-			if (gadget->speed == USB_SPEED_HIGH)
-				value = usb_ep_enable (ep, &data->hs_desc);
-			else
-#endif	/* HIGHSPEED */
-				value = usb_ep_enable (ep, &data->desc);
-			if (value) {
-				ERROR (dev, "deferred %s enable --> %d\n",
-					data->name, value);
-				continue;
-			}
-			data->state = STATE_EP_ENABLED;
-			wake_up (&data->wait);
-			DBG (dev, "woke up %s waiters\n", data->name);
-		}
-
-	/* host may have given up waiting for response.  we can miss control
-	 * requests handled lower down (device/endpoint status and features);
-	 * then ep0_{read,write} will report the wrong status. controller
-	 * driver will have aborted pending i/o.
-	 */
-	} else if (dev->state == STATE_SETUP)
-		dev->setup_abort = 1;
-
-	req->buf = dev->rbuf;
-	req->dma = DMA_ADDR_INVALID;
-	req->context = 0;
-	value = -EOPNOTSUPP;
-	switch (ctrl->bRequest) {
-
-	case USB_REQ_GET_DESCRIPTOR:
-		if (ctrl->bRequestType != USB_DIR_IN)
-			goto unrecognized;
-		switch (ctrl->wValue >> 8) {
-
-		case USB_DT_DEVICE:
-			value = min (ctrl->wLength, (u16) sizeof *dev->dev);
-			req->buf = dev->dev;
-			break;
-#ifdef	HIGHSPEED
-		case USB_DT_DEVICE_QUALIFIER:
-			if (!dev->hs_config)
-				break;
-			value = min (ctrl->wLength, (u16)
-				sizeof (struct usb_qualifier_descriptor));
-			make_qualifier (dev);
-			break;
-		case USB_DT_OTHER_SPEED_CONFIG:
-			// FALLTHROUGH
-#endif
-		case USB_DT_CONFIG:
-			value = config_buf (dev,
-					ctrl->wValue >> 8,
-					ctrl->wValue & 0xff);
-			if (value >= 0)
-				value = min (ctrl->wLength, (u16) value);
-			break;
-
-		default:
-			goto unrecognized;
-		}
-		break;
-
-	/* currently one config, two speeds */
-	case USB_REQ_SET_CONFIGURATION:
-		if (ctrl->bRequestType != 0)
-			break;
-		if (0 == (u8) ctrl->wValue) {
-			value = 0;
-			dev->current_config = 0;
-			// user mode expected to disable endpoints
-		} else {
-			u8	config;
-#ifdef	HIGHSPEED
-			if (gadget->speed == USB_SPEED_HIGH)
-				config = dev->hs_config->bConfigurationValue;
-			else
-#endif
-				config = dev->config->bConfigurationValue;
-
-			if (config == (u8) ctrl->wValue) {
-				value = 0;
-				dev->current_config = config;
-			}
-		}
-
-		/* report SET_CONFIGURATION like any other control request,
-		 * except that usermode may not stall this.  the next
-		 * request mustn't be allowed start until this finishes:
-		 * endpoints and threads set up, etc.
-		 *
-		 * NOTE:  older PXA hardware (before PXA 255: without UDCCFR)
-		 * has bad/racey automagic that prevents synchronizing here.
-		 * even kernel mode drivers often miss them.
-		 */
-		if (value == 0) {
-			INFO (dev, "configuration #%d\n", dev->current_config);
-			if (dev->usermode_setup) {
-				dev->setup_can_stall = 0;
-				goto delegate;
-			}
-		}
-		break;
-
-#ifndef	CONFIG_USB_GADGETFS_PXA2XX
-	/* PXA automagically handles this request too */
-	case USB_REQ_GET_CONFIGURATION:
-		if (ctrl->bRequestType != 0x80)
-			break;
-		*(u8 *)req->buf = dev->current_config;
-		value = min (ctrl->wLength, (u16) 1);
-		break;
-#endif
-
-	default:
-unrecognized:
-		VDEBUG (dev, "%s req%02x.%02x v%04x i%04x l%d\n",
-			dev->usermode_setup ? "delegate" : "fail",
-			ctrl->bRequestType, ctrl->bRequest,
-			ctrl->wValue, ctrl->wIndex, ctrl->wLength);
-
-		/* if there's an ep0 reader, don't stall */
-		if (dev->usermode_setup) {
-			dev->setup_can_stall = 1;
-delegate:
-			dev->setup_in = (ctrl->bRequestType & USB_DIR_IN)
-						? 1 : 0;
-			dev->setup_out_ready = 0;
-			dev->setup_out_error = 0;
-			value = 0;
-
-			/* read DATA stage for OUT right away */
-			if (unlikely (!dev->setup_in && ctrl->wLength)) {
-				value = setup_req (gadget->ep0, dev->req,
-							ctrl->wLength);
-				if (value < 0)
-					break;
-				value = usb_ep_queue (gadget->ep0, dev->req,
-							GFP_ATOMIC);
-				if (value < 0) {
-					clean_req (gadget->ep0, dev->req);
-					break;
-				}
-
-				/* we can't currently stall these */
-				dev->setup_can_stall = 0;
-			}
-
-			/* state changes when reader collects event */
-			event = next_event (dev, GADGETFS_SETUP);
-			event->u.setup = *ctrl;
-			ep0_readable (dev);
-			spin_unlock (&dev->lock);
-			return 0;
-		}
-	}
-
-	/* proceed with data transfer and status phases? */
-	if (value >= 0 && dev->state != STATE_SETUP) {
-		req->length = value;
-		value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
-		if (value < 0) {
-			DBG (dev, "ep_queue --> %d\n", value);
-			req->status = 0;
-		}
-	}
-
-	/* device stalls when value < 0 */
-	spin_unlock (&dev->lock);
-	return value;
-}
-
-static void destroy_ep_files (struct dev_data *dev)
-{
-	struct list_head	*entry, *tmp;
-
-	DBG (dev, "%s %d\n", __FUNCTION__, dev->state);
-
-	/* dev->state must prevent interference */
-restart:
-	spin_lock_irq (&dev->lock);
-	list_for_each_safe (entry, tmp, &dev->epfiles) {
-		struct ep_data	*ep;
-#ifdef	lk25
-		struct inode	*parent;
-		struct dentry	*dentry;
-#endif
-
-		/* break link to FS */
-		ep = list_entry (entry, struct ep_data, epfiles);
-		list_del_init (&ep->epfiles);
-#ifdef	lk25
-		dentry = ep->dentry;
-		ep->dentry = 0;
-		parent = dentry->d_parent->d_inode;
-#endif
-
-		/* break link to controller */
-		if (ep->state == STATE_EP_ENABLED)
-			(void) usb_ep_disable (ep->ep);
-		ep->state = STATE_EP_UNBOUND;
-		usb_ep_free_request (ep->ep, ep->req);
-		ep->ep = 0;
-		wake_up (&ep->wait);
-		put_ep (ep);
-
-		spin_unlock_irq (&dev->lock);
-
-#ifdef	lk25
-		/* break link to dcache */
-		down (&parent->i_sem);
-		d_delete (dentry);
-		dput (dentry);
-		up (&parent->i_sem);
-#endif
-
-		/* fds may still be open */
-		goto restart;
-	}
-	spin_unlock_irq (&dev->lock);
-}
-
-
-#ifdef	lk25
-static struct inode *
-gadgetfs_create_file (struct super_block *sb, char const *name,
-		void *data, struct file_operations *fops,
-		struct dentry **dentry_p);
-#endif
-
-static int activate_ep_files (struct dev_data *dev)
-{
-	struct usb_ep	*ep;
-
-	gadget_for_each_ep (ep, dev->gadget) {
-		struct ep_data	*data;
-
-		data = kmalloc (sizeof *data, GFP_KERNEL);
-		if (!data)
-			goto enomem;
-		memset (data, 0, sizeof data);
-		data->state = STATE_EP_DISABLED;
-		init_MUTEX (&data->lock);
-		init_waitqueue_head (&data->wait);
-
-		strncpy (data->name, ep->name, sizeof (data->name) - 1);
-		atomic_set (&data->count, 1);
-		data->dev = dev;
-		get_dev (dev);
-
-		data->ep = ep;
-		ep->driver_data = data;
-
-		data->req = usb_ep_alloc_request (ep, GFP_KERNEL);
-		if (!data->req)
-			goto enomem;
-
-#ifdef	lk25
-		data->inode = gadgetfs_create_file (dev->sb, data->name,
-				data, &ep_config_operations,
-				&data->dentry);
-		if (!data->inode) {
-			kfree (data);
-			goto enomem;
-		}
-#endif
-		list_add_tail (&data->epfiles, &dev->epfiles);
-	}
-	return 0;
-
-enomem:
-	DBG (dev, "%s enomem\n", __FUNCTION__);
-	destroy_ep_files (dev);
-	return -ENOMEM;
-}
-
-static void
-gadgetfs_unbind (struct usb_gadget *gadget)
-{
-	struct dev_data		*dev = get_gadget_data (gadget);
-
-	DBG (dev, "%s\n", __FUNCTION__);
-
-	spin_lock_irq (&dev->lock);
-	dev->state = STATE_DEV_UNBOUND;
-	spin_unlock_irq (&dev->lock);
-
-	destroy_ep_files (dev);
-	gadget->ep0->driver_data = 0;
-	set_gadget_data (gadget, 0);
-
-	/* we've already been disconnected ... no i/o is active */
-	if (dev->req)
-		usb_ep_free_request (gadget->ep0, dev->req);
-	DBG (dev, "%s done\n", __FUNCTION__);
-	put_dev (dev);
-}
-
-static struct dev_data		*the_device;
-
-static int
-gadgetfs_bind (struct usb_gadget *gadget)
-{
-	struct dev_data		*dev = the_device;
-
-	if (!dev)
-		return -ESRCH;
-	if (0 != strcmp (CHIP, gadget->name)) {
-		printk (KERN_ERR "%s expected " CHIP " controller not %s\n",
-			shortname, gadget->name);
-		return -ENODEV;
-	}
-
-	set_gadget_data (gadget, dev);
-	dev->gadget = gadget;
-	gadget->ep0->driver_data = dev;
-	dev->dev->bMaxPacketSize0 = gadget->ep0->maxpacket;
-
-	/* preallocate control response and buffer */
-	dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);
-	if (!dev->req)
-		goto enomem;
-	dev->req->context = 0;
-	dev->req->complete = epio_complete;
-
-	if (activate_ep_files (dev) < 0)
-		goto enomem;
-
-	INFO (dev, "bound to %s driver\n", gadget->name);
-	dev->state = STATE_UNCONNECTED;
-	get_dev (dev);
-	return 0;
-
-enomem:
-	gadgetfs_unbind (gadget);
-	return -ENOMEM;
-}
-
-static void
-gadgetfs_disconnect (struct usb_gadget *gadget)
-{
-	struct dev_data		*dev = get_gadget_data (gadget);
-
-	if (dev->state == STATE_UNCONNECTED) {
-		DBG (dev, "already unconnected\n");
-		return;
-	}
-	dev->state = STATE_UNCONNECTED;
-
-	INFO (dev, "disconnected\n");
-	spin_lock (&dev->lock);
-	next_event (dev, GADGETFS_DISCONNECT);
-	ep0_readable (dev);
-	spin_unlock (&dev->lock);
-}
-
-static void
-gadgetfs_suspend (struct usb_gadget *gadget)
-{
-	struct dev_data		*dev = get_gadget_data (gadget);
-
-	INFO (dev, "suspended from state %d\n", dev->state);
-	spin_lock (&dev->lock);
-	switch (dev->state) {
-	case STATE_SETUP:		// VERY odd... host died??
-	case STATE_CONNECTED:
-	case STATE_UNCONNECTED:
-		next_event (dev, GADGETFS_SUSPEND);
-		ep0_readable (dev);
-		/* FALLTHROUGH */
-	default:
-		break;
-	}
-	spin_unlock (&dev->lock);
-}
-
-static struct usb_gadget_driver gadgetfs_driver = {
-#ifdef	HIGHSPEED
-	.speed		= USB_SPEED_HIGH,
-#else
-	.speed		= USB_SPEED_FULL,
-#endif
-	.function	= (char *) driver_desc,
-	.bind		= gadgetfs_bind,
-	.unbind		= gadgetfs_unbind,
-	.setup		= gadgetfs_setup,
-	.disconnect	= gadgetfs_disconnect,
-	.suspend	= gadgetfs_suspend,
-
-	.driver 	= {
-		.name		= (char *) shortname,
-		// .shutdown = ...
-		// .suspend = ...
-		// .resume = ...
-	},
-};
-
-/*----------------------------------------------------------------------*/
-
-/* DEVICE INITIALIZATION
- *
- *     fd = open ("/dev/gadget/$CHIP", O_RDWR)
- *     status = write (fd, descriptors, sizeof descriptors)
- *
- * That write establishes the device configuration, so the kernel can
- * bind to the controller ... guaranteeing it can handle enumeration
- * at all necessary speeds.  Descriptor order is:
- *
- * . message tag (u32, host order) ... for now, must be zero; it
- *	would change to support features like multi-config devices
- * . full/low speed config ... all wTotalLength bytes (with interface,
- *	class, altsetting, endpoint, and other descriptors)
- * . high speed config ... all descriptors, for high speed operation;
- * 	this one's optional except for high-speed hardware
- * . device descriptor
- *
- * Endpoints are not yet enabled. Drivers may want to immediately
- * initialize them, using the /dev/gadget/ep* files that are available
- * as soon as the kernel sees the configuration, or they can wait
- * until device configuration and interface altsetting changes create
- * the need to configure (or unconfigure) them.
- *
- * After initialization, the device stays active for as long as that
- * $CHIP file is open.  Events may then be read from that descriptor,
- * such configuration notifications.  More complex drivers will handle
- * some control requests in user space.
- */
-
-static int is_valid_config (struct usb_config_descriptor *config)
-{
-	return config->bDescriptorType == USB_DT_CONFIG
-		&& config->bLength == USB_DT_CONFIG_SIZE
-		&& config->bConfigurationValue != 0
-		&& (config->bmAttributes & USB_CONFIG_ATT_ONE) != 0
-		&& (config->bmAttributes & USB_CONFIG_ATT_WAKEUP) == 0;
-}
-
-static ssize_t
-dev_config (struct file *fd, const char *buf, size_t len, loff_t *ptr)
-{
-	struct dev_data		*dev = fd->private_data;
-	ssize_t			value = len, length = len;
-	unsigned		total;
-	u32			tag;
-	char			*kbuf;
-
-	if (dev->state != STATE_OPENED)
-		return -EEXIST;
-
-	if (len < (USB_DT_CONFIG_SIZE + USB_DT_DEVICE_SIZE + 4))
-		return -EINVAL;
-
-	/* we might need to change message format someday */
-	if (copy_from_user (&tag, buf, 4))
-		return -EFAULT;
-	if (tag != 0)
-		return -EINVAL;
-	buf += 4;
-	length -= 4;
-
-	kbuf = kmalloc (length, SLAB_KERNEL);
-	if (!kbuf)
-		return -ENOMEM;
-	if (copy_from_user (kbuf, buf, length)) {
-		kfree (kbuf);
-		return -EFAULT;
-	}
-
-	spin_lock_irq (&dev->lock);
-	value = -EINVAL;
-	if (dev->buf)
-		goto fail;
-	dev->buf = kbuf;
-
-	/* full or low speed config */
-	dev->config = (void *) kbuf;
-	total = le16_to_cpup (&dev->config->wTotalLength);
-	if (!is_valid_config (dev->config) || total >= length)
-		goto fail;
-	kbuf += total;
-	length -= total;
-
-	/* optional high speed config */
-	if (kbuf [1] == USB_DT_CONFIG) {
-		dev->hs_config = (void *) kbuf;
-		total = le16_to_cpup (&dev->hs_config->wTotalLength);
-		if (!is_valid_config (dev->hs_config) || total >= length)
-			goto fail;
-		kbuf += total;
-		length -= total;
-	}
-
-	/* could support multiple configs, using another encoding! */
-
-	/* device descriptor (tweaked for paranoia) */
-	if (length != USB_DT_DEVICE_SIZE)
-		goto fail;
-	dev->dev = (void *)kbuf;
-	if (dev->dev->bLength != USB_DT_DEVICE_SIZE
-			|| dev->dev->bDescriptorType != USB_DT_DEVICE
-			|| dev->dev->bNumConfigurations != 1)
-		goto fail;
-	dev->dev->bNumConfigurations = 1;
-	dev->dev->bcdUSB = __constant_cpu_to_le16 (0x0200);
-
-	/* triggers gadgetfs_bind(); then we can enumerate. */
-	spin_unlock_irq (&dev->lock);
-	value = usb_gadget_register_driver (&gadgetfs_driver);
-	if (value != 0) {
-		kfree (dev->buf);
-		dev->buf = 0;
-	} else {
-		/* at this point "good" hardware has for the first time
-		 * let the USB the host see us.  alternatively, if users
-		 * unplug/replug that will clear all the error state.
-		 *
-		 * note:  everything running before here was guaranteed
-		 * to choke driver model style diagnostics.  from here
-		 * on, they can work ... except in cleanup paths that
-		 * kick in after the ep0 descriptor is closed.
-		 */
-		fd->f_op = &ep0_io_operations;
-		value = len;
-	}
-	return value;
-
-fail:
-	spin_unlock_irq (&dev->lock);
-	pr_debug ("%s: %s fail %d, %p\n", shortname, __FUNCTION__, value, dev);
-	kfree (dev->buf);
-	dev->buf = 0;
-	return value;
-}
-
-static int
-dev_open (struct inode *inode, struct file *fd)
-{
-	struct dev_data		*dev = inode->u.generic_ip;
-	int			value = -EBUSY;
-
-	if (dev->state == STATE_DEV_DISABLED) {
-		dev->ev_next = 0;
-		dev->state = STATE_OPENED;
-		fd->private_data = dev;
-		get_dev (dev);
-		value = 0;
-	}
-	return value;
-}
-
-static struct file_operations dev_init_operations = {
-	.owner =	THIS_MODULE,
-	.open =		dev_open,
-	.write =	dev_config,
-	.fasync =	ep0_fasync,
-	.ioctl =	dev_ioctl,
-	.release =	dev_release,
-};
-
-/*----------------------------------------------------------------------*/
-
-#ifdef	lk25
-
-/* FILESYSTEM AND SUPERBLOCK OPERATIONS
- *
- * Mounting the filesystem creates a controller file, used first for
- * device configuration then later for event monitoring.
- */
-
-
-
-static unsigned default_uid;
-static unsigned default_gid;
-static unsigned default_perm = S_IRUSR | S_IWUSR;
-
-module_param (default_uid, uint, 0644);
-module_param (default_gid, uint, 0644);
-module_param (default_perm, uint, 0644);
-
-
-static struct inode *
-gadgetfs_make_inode (struct super_block *sb,
-		void *data, struct file_operations *fops,
-		int mode)
-{
-	struct inode *inode = new_inode (sb);
-
-	if (inode) {
-		inode->i_mode = mode;
-		inode->i_uid = default_uid;
-		inode->i_gid = default_gid;
-		inode->i_blksize = PAGE_CACHE_SIZE;
-		inode->i_blocks = 0;
-		inode->i_atime = inode->i_mtime = inode->i_ctime
-				= CURRENT_TIME;
-		inode->u.generic_ip = data;
-		inode->i_fop = fops;
-	}
-	return inode;
-}
-
-/* creates in fs root directory, so non-renamable and non-linkable.
- * so inode and dentry are paired, until device reconfig.
- */
-static struct inode *
-gadgetfs_create_file (struct super_block *sb, char const *name,
-		void *data, struct file_operations *fops,
-		struct dentry **dentry_p)
-{
-	struct dentry	*dentry;
-	struct inode	*inode;
-	struct qstr	qname;
-
-	qname.name = name;
-	qname.len = strlen (name);
-	qname.hash = full_name_hash (qname.name, qname.len);
-	dentry = d_alloc (sb->s_root, &qname);
-	if (!dentry)
-		return 0;
-
-	inode = gadgetfs_make_inode (sb, data, fops,
-			S_IFREG | (default_perm & S_IRWXUGO));
-	if (!inode) {
-		dput(dentry);
-		return 0;
-	}
-	d_add (dentry, inode);
-	*dentry_p = dentry;
-	return inode;
-}
-
-static struct super_operations gadget_fs_operations = {
-	.statfs =	simple_statfs,
-	.drop_inode =	generic_delete_inode,
-};
-
-static int
-gadgetfs_fill_super (struct super_block *sb, void *opts, int silent)
-{
-	struct inode	*inode;
-	struct dentry	*d;
-	struct dev_data	*dev;
-
-	if (the_device)
-		return -ESRCH;
-
-	/* superblock */
-	sb->s_blocksize = PAGE_CACHE_SIZE;
-	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
-	sb->s_magic = GADGETFS_MAGIC;
-	sb->s_op = &gadget_fs_operations;
-
-	/* root inode */
-	inode = gadgetfs_make_inode (sb,
-			0, &simple_dir_operations,
-			S_IFDIR | S_IRUGO | S_IXUGO);
-	if (!inode)
-		return -ENOMEM;
-	inode->i_op = &simple_dir_inode_operations;
-	if (!(d = d_alloc_root (inode))) {
-enomem:
-		iput (inode);
-		return -ENOMEM;
-	}
-	sb->s_root = d;
-
-	/* the ep0 file is named after the controller we expect;
-	 * user mode code can use it for sanity checks, like we do.
-	 */
-	dev = dev_new ();
-	if (!dev)
-		goto enomem;
-	dev->sb = sb;
-	if (!(inode = gadgetfs_create_file (sb, CHIP,
-				dev, &dev_init_operations,
-				&dev->dentry)))
-		goto enomem;
-
-	/* other endpoint files are available after hardware setup,
-	 * from binding to a controller.
-	 */
-	the_device = dev;
-	return 0;
-}
-
-/* "mount -t gadgetfs path /dev/gadget" ends up here */
-static struct super_block *
-gadgetfs_get_sb (struct file_system_type *t, int flags,
-		const char *path, void *opts)
-{
-	return get_sb_single (t, flags, opts, gadgetfs_fill_super);
-}
-
-static void
-gadgetfs_kill_sb (struct super_block *sb)
-{
-	kill_litter_super (sb);
-	put_dev (the_device);
-	the_device = 0;
-}
-
-/*----------------------------------------------------------------------*/
-
-static struct file_system_type gadgetfs_type = {
-	.owner		= THIS_MODULE,
-	.name		= shortname,
-	.get_sb		= gadgetfs_get_sb,
-	.kill_sb	= gadgetfs_kill_sb,
-};
-
-#else
-
-/*----------------------------------------------------------------------*/
-
-static int c_major = 240;	/* 240 is local/experimental */
-MODULE_PARM (c_major, "i");
-MODULE_PARM_DESC (c_major, "major number for char special files");
-
-static int gadget_open (struct inode *ino, struct file *fp)
-{
-	int			num = minor (ino->i_rdev);
-	struct dev_data		*dev;
-	struct file_operations	*ops;
-
-	/* ep0 file, "/dev/gadget/$CHIP" */
-	if (num == 0) {
-		int		status;
-
-		if (the_device != 0)
-			return -EBUSY;
-		the_device = dev_new ();
-		if (the_device == 0)
-			return -ENOMEM;
-
-		dev = the_device;
-		ino->u.generic_ip = dev;
-		ops = &dev_init_operations;
-		fp->f_op = ops;
-
-		status = ops->open (ino, fp);
-		if (status < 0) {
-			put_dev (dev);
-			the_device = 0;
-		}
-		return status;
-
-	/* ep files, "/dev/gadget/$ENDPOINT" */
-	} else {
-		struct list_head	*entry;
-		struct ep_data		*data;
-
-		/* unavailable till device is initted */
-		dev = the_device;
-		if (dev == 0)
-			return -ENODEV;
-
-		/* order in controller's name listing matters! */
-		list_for_each (entry, &dev->epfiles) {
-			if (--num == 0)
-				goto found;
-		}
-		return -ENODEV;
-found:
-		data = list_entry (entry, struct ep_data, epfiles);
-		ino->u.generic_ip = data;
-		ops = &ep_config_operations;
-		fp->f_op = ops;
-
-		return ops->open (ino, fp);
-	}
-}
-
-static struct file_operations gadget_fops = {
-	.owner =	THIS_MODULE,
-	.open =		gadget_open,
-};
-
-#endif
-
-/*----------------------------------------------------------------------*/
-
-static int __init init (void)
-{
-	int status;
-
-#ifdef	lk25
-	status = register_filesystem (&gadgetfs_type);
-#else
-	status = register_chrdev (c_major, shortname, &gadget_fops);
-	if (status < 0) {
-		printk (KERN_WARNING "%s: can't get major %d\n",
-			shortname, c_major);
-		return status;
-	}
-
-	/* dynamic assignment */
-	if (c_major == 0)
-		c_major = status;
-	status = 0;
-
-	pr_info ("%s: using char major %d\n", shortname, c_major);
-#endif
-	if (status == 0)
-		pr_info ("%s: %s, version " DRIVER_VERSION "\n",
-			shortname, driver_desc);
-	return status;
-}
-module_init (init);
-
-static void __exit cleanup (void)
-{
-	pr_debug ("unregister %s\n", shortname);
-#ifdef	lk25
-	unregister_filesystem (&gadgetfs_type);
-#else
-	unregister_chrdev (c_major, shortname);
-#endif
-}
-module_exit (cleanup);
-
diff -ruN linux-2.4.20-WRTup/drivers/usb/gadget/Makefile linux-2.4.20-WRTstp/drivers/usb/gadget/Makefile
--- linux-2.4.20-WRTup/drivers/usb/gadget/Makefile	2006-06-12 18:04:59.000000000 -0700
+++ linux-2.4.20-WRTstp/drivers/usb/gadget/Makefile	1969-12-31 16:00:00.000000000 -0800
@@ -1,83 +0,0 @@
-#
-# Makefile for USB peripheral controller and gadget drivers
-# for kbuild 2.4
-#
-
-# for static linking
-O_TARGET	:= built-in.o
-
-ifdef CONFIG_USB_GADGET_CONTROLLER
-
-list-multi			:= g_zero.o g_ether.o g_simple.o g_rndis.o gadgetfs.o
-
-obj-$(CONFIG_USB_NET2280)	+= net2280.o
-obj-$(CONFIG_USB_PXA2XX)	+= pxa2xx_udc.o
-
-# only one of these may be statically linked ...
-controller-$(CONFIG_USB_NET2280)	+= net2280.o
-controller-$(CONFIG_USB_PXA2XX)		+= pxa2xx_udc.o
-
-# ... and only one of these, too; kbuild/kconfig don't help though.
-g_zero-objs			:= zero.o usbstring.o
-obj-$(CONFIG_USB_ZERO)		+= g_zero.o
-
-g_ether-objs			:= ether.o usbstring.o
-obj-$(CONFIG_USB_ETH)		+= g_ether.o
-
-g_simple-objs			:= usbdev_gadget.o usbdev_simple.o
-obj-$(CONFIG_USB_SIMPLE)	+= g_simple.o
-
-g_rndis-objs			:= usbdev_gadget.o usbdev_rndis.o rndis.o rndis_linux.o
-obj-$(CONFIG_USB_RNDIS)		+= g_rndis.o
-
-gadgetfs-objs			:= inode.o usbstring.o
-obj-$(CONFIG_USB_GADGETFS)	+= gadgetfs.o
-
-export-objs :=			$(controller-y) $(controller-m)
-
-endif
-
-EXTRA_CFLAGS	+= -fshort-wchar
-
-ifdef CONFIG_USBDEV
-
-EXTRA_CFLAGS += -DCONFIG_USBRNDIS_RETAIL -DBCMWPA2
-
-list-multi			+= usbdev-simple.o usbdev-rndis.o
-
-# ... and only one of these, too; kbuild/kconfig don't help though.
-usbdev-simple-objs		:= usbdev_sb.o usbdev_linux.o usbdev_simple.o
-obj-$(CONFIG_USB_SIMPLE)	+= usbdev-simple.o
-
-usbdev-rndis-objs		:= usbdev_sb.o usbdev_linux.o usbdev_rndis.o rndis.o rndis_linux.o
-obj-$(CONFIG_USB_RNDIS)		+= usbdev-rndis.o
-
-endif
-
-# Search for sources or objects under src/usbdev
-ifneq ($(wildcard $(SRCBASE)/usbdev/*.c),)
-EXTRA_CFLAGS	+= -I$(SRCBASE)/usbdev
-vpath %.c $(SRCBASE)/usbdev $(SRCBASE)/shared
-else
-g_simple-objs		:= $(foreach obj,$(g_simple-objs),$(SRCBASE)/usbdev/linux/$(obj))
-g_rndis-objs		:= $(foreach obj,$(g_rndis-objs),$(SRCBASE)/usbdev/linux/$(obj))
-usbdev-simple-objs	:= $(foreach obj,$(usbdev-simple-objs),$(SRCBASE)/usbdev/linux/$(obj))
-usbdev-rndis-objs	:= $(foreach obj,$(usbdev-rndis-objs),$(SRCBASE)/usbdev/linux/$(obj))
-endif
-
-include $(TOPDIR)/Rules.make
-
-g_zero.o: $(g_zero-objs)
-	$(LD) -r -o $@ $(g_zero-objs)
-g_ether.o: $(g_ether-objs)
-	$(LD) -r -o $@ $(g_ether-objs)
-g_simple.o: $(g_simple-objs)
-	$(LD) -r -o $@ $(g_simple-objs)
-g_rndis.o: $(g_rndis-objs)
-	$(LD) -r -o $@ $(g_rndis-objs)
-gadgetfs.o: $(gadgetfs-objs)
-	$(LD) -r -o $@ $(gadgetfs-objs)
-usbdev-simple.o: $(usbdev-simple-objs)
-	$(LD) -r -o $@ $(usbdev-simple-objs)
-usbdev-rndis.o: $(usbdev-rndis-objs)
-	$(LD) -r -o $@ $(usbdev-rndis-objs)
diff -ruN linux-2.4.20-WRTup/drivers/usb/gadget/net2280.c linux-2.4.20-WRTstp/drivers/usb/gadget/net2280.c
--- linux-2.4.20-WRTup/drivers/usb/gadget/net2280.c	2006-06-12 18:04:59.000000000 -0700
+++ linux-2.4.20-WRTstp/drivers/usb/gadget/net2280.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,2701 +0,0 @@
-/*
- * Driver for the NetChip 2280 USB device controller.
- * Specs and errata are available from <http://www.netchip.com>.
- *
- * NetChip Technology Inc. supported the development of this driver.
- *
- *
- * CODE STATUS HIGHLIGHTS
- *
- * Used with a gadget driver like "zero.c" this enumerates fine to Windows
- * or Linux hosts; handles disconnect, reconnect, and reset, for full or
- * high speed operation; and passes USB-IF "chapter 9" tests.
- *
- * Handles standard stress loads from the Linux "usbtest" driver, with
- * either DMA (default) or PIO (use_dma=n) used for ep-{a,b,c,d}.  Testing
- * with "ttcp" (and the "ether.c" driver) behaves nicely too.
- *
- * DMA is enabled by default.  Drivers using transfer queues might use
- * DMA chaining to remove IRQ latencies between transfers.  (Except when
- * short OUT transfers happen.)  Drivers can use the req->no_interrupt
- * hint to completely eliminate some IRQs, if a later IRQ is guaranteed
- * and DMA chaining is enabled.
- *
- * Note that almost all the errata workarounds here are only needed for
- * rev1 chips.  Rev1a silicon (0110) fixes almost all of them.
- */
-
-#define USE_DMA_CHAINING
-
-
-/*
- * Copyright (C) 2003 David Brownell
- * Copyright (C) 2003 NetChip Technologies
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-// #define DEBUG	1
-// #define	VERBOSE		/* extra debug messages (success too) */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-
-#include <linux/usb_ch9.h>
-#include <linux/usb_gadget.h>
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-#include <asm/unaligned.h>
-
-
-#define	DRIVER_DESC		"NetChip 2280 USB Peripheral Controller"
-#define	DRIVER_VERSION		"Bastille Day 2003"
-
-#define	DMA_ADDR_INVALID	(~(dma_addr_t)0)
-#define	EP_DONTUSE		13	/* nonzero */
-
-#define USE_RDK_LEDS		/* GPIO pins control three LEDs */
-
-
-static const char driver_name [] = "net2280";
-static const char driver_desc [] = DRIVER_DESC;
-
-static const char ep0name [] = "ep0";
-static const char *ep_name [] = {
-	ep0name,
-	"ep-a", "ep-b", "ep-c", "ep-d",
-	"ep-e", "ep-f",
-};
-
-static int use_dma = 1;
-
-/* mode 0 == ep-{a,b,c,d} 1K fifo each
- * mode 1 == ep-{a,b} 2K fifo each, ep-{c,d} unavailable
- * mode 2 == ep-a 2K fifo, ep-{b,c} 1K each, ep-d unavailable
- */
-static ushort fifo_mode = 1;
-
-MODULE_PARM (use_dma, "i");
-MODULE_PARM_DESC (use_dma, "true to use dma controllers");
-
-MODULE_PARM (fifo_mode, "h");
-MODULE_PARM_DESC (fifo_mode, "net2280 fifo mode");
-
-
-#define	DIR_STRING(bAddress) (((bAddress) & USB_DIR_IN) ? "in" : "out")
-
-#if defined(USE_SYSFS_DEBUG_FILES) || defined(DEBUG)
-static char *type_string (u8 bmAttributes)
-{
-	switch ((bmAttributes) & USB_ENDPOINT_XFERTYPE_MASK) {
-	case USB_ENDPOINT_XFER_BULK:	return "bulk";
-	case USB_ENDPOINT_XFER_ISOC:	return "iso";
-	case USB_ENDPOINT_XFER_INT:	return "intr";
-	};
-	return "control";
-}
-#endif
-
-#include "net2280.h"
-
-#define valid_bit	__constant_cpu_to_le32 (1 << VALID_BIT)
-#define dma_done_ie	__constant_cpu_to_le32 (1 << DMA_DONE_INTERRUPT_ENABLE)
-
-/*-------------------------------------------------------------------------*/
-
-static int
-net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
-{
-	struct net2280		*dev;
-	struct net2280_ep	*ep;
-	u32			max, tmp;
-	unsigned long		flags;
-
-	ep = container_of (_ep, struct net2280_ep, ep);
-	if (!_ep || !desc || ep->desc || _ep->name == ep0name
-			|| desc->bDescriptorType != USB_DT_ENDPOINT)
-		return -EINVAL;
-	dev = ep->dev;
-	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
-		return -ESHUTDOWN;
-
-	if ((desc->bEndpointAddress & 0x0f) == EP_DONTUSE)
-		return -EDOM;
-
-	/* sanity check ep-e/ep-f since their fifos are small */
-	max = le16_to_cpu (desc->wMaxPacketSize) & 0x1fff;
-	if (ep->num > 4 && max > 64)
-		return -ERANGE;
-
-	spin_lock_irqsave (&dev->lock, flags);
-	_ep->maxpacket = max & 0x7ff;
-	ep->desc = desc;
-
-	/* ep_reset() has already been called */
-	ep->stopped = 0;
-
-	/* set speed-dependent max packet; may kick in high bandwidth */
-	set_idx_reg (dev->regs, REG_EP_MAXPKT (dev, ep->num), max);
-
-#ifdef USE_DMA_CHAINING
-	/* FIFO lines can't go to different packets.  PIO is ok, so
-	 * use it instead of troublesome (non-bulk) multi-packet DMA.
-	 */
-	if (ep->dma && (max % 4) != 0) {
-		DEBUG (ep->dev, "%s, no dma for maxpacket %d\n",
-			ep->ep.name, ep->ep.maxpacket);
-		ep->dma = 0;
-	}
-#endif
-
-	/* set type, direction, address; reset fifo counters */
-	writel ((1 << FIFO_FLUSH), &ep->regs->ep_stat);
-	tmp = (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
-	if (tmp == USB_ENDPOINT_XFER_INT) {
-		/* not just because of erratum 0105; avoid ever
-		 * kicking in the "toggle-irrelevant" mode.
-		 */
-		tmp = USB_ENDPOINT_XFER_BULK;
-	} else if (tmp == USB_ENDPOINT_XFER_BULK) {
-		/* catch some particularly blatant driver bugs */
-		if ((dev->gadget.speed == USB_SPEED_HIGH
-					&& max != 512)
-				|| (dev->gadget.speed == USB_SPEED_FULL
-					&& max > 64))
-			return -ERANGE;
-	}
-	ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC) ? 1 : 0;
-	tmp <<= ENDPOINT_TYPE;
-	tmp |= desc->bEndpointAddress;
-	tmp |= (4 << ENDPOINT_BYTE_COUNT);	/* default full fifo lines */
-	tmp |= 1 << ENDPOINT_ENABLE;
-	wmb ();
-
-	/* for OUT transfers, block the rx fifo until a read is posted */
-	ep->is_in = (tmp & USB_DIR_IN) != 0;
-	if (!ep->is_in)
-		writel ((1 << SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
-
-	writel (tmp, &ep->regs->ep_cfg);
-
-#ifdef NET2280_DMA_OUT_WORKAROUND
-	if (!ep->is_in)
-		ep->dma = 0;
-#endif
-
-	/* enable irqs */
-	if (!ep->dma) {				/* pio, per-packet */
-		tmp = (1 << ep->num) | readl (&dev->regs->pciirqenb0);
-		writel (tmp, &dev->regs->pciirqenb0);
-
-		tmp = (1 << DATA_PACKET_RECEIVED_INTERRUPT_ENABLE)
-			| (1 << DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE)
-			| readl (&ep->regs->ep_irqenb);
-		writel (tmp, &ep->regs->ep_irqenb);
-	} else {				/* dma, per-request */
-		tmp = (1 << (8 + ep->num));	/* completion */
-		tmp |= readl (&dev->regs->pciirqenb1);
-		writel (tmp, &dev->regs->pciirqenb1);
-
-		if ((desc->bEndpointAddress & USB_DIR_IN) == 0) {
-			tmp = (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE);
-			writel (tmp, &ep->regs->ep_irqenb);
-
-			tmp = (1 << ep->num) | readl (&dev->regs->pciirqenb0);
-			writel (tmp, &dev->regs->pciirqenb0);
-		}
-	}
-
-	tmp = desc->bEndpointAddress;
-	DEBUG (dev, "enabled %s (ep%d%s-%s) %s max %04x\n",
-		_ep->name, tmp & 0x0f, DIR_STRING (tmp),
-		type_string (desc->bmAttributes),
-		ep->dma ? "dma" : "pio", max);
-
-	/* pci writes may still be posted */
-	spin_unlock_irqrestore (&dev->lock, flags);
-	return 0;
-}
-
-static int handshake (u32 *ptr, u32 mask, u32 done, int usec)
-{
-	u32	result;
-
-	do {
-		result = readl (ptr);
-		if (result == ~(u32)0)		/* "device unplugged" */
-			return -ENODEV;
-		result &= mask;
-		if (result == done)
-			return 0;
-		udelay (1);
-		usec--;
-	} while (usec > 0);
-	return -ETIMEDOUT;
-}
-
-static struct usb_ep_ops net2280_ep_ops;
-
-static void ep_reset (struct net2280_regs *regs, struct net2280_ep *ep)
-{
-	u32		tmp;
-
-	ep->desc = 0;
-	INIT_LIST_HEAD (&ep->queue);
-
-	ep->ep.maxpacket = ~0;
-	ep->ep.ops = &net2280_ep_ops;
-
-	/* disable the dma, irqs, endpoint... */
-	if (ep->dma) {
-		writel (0, &ep->dma->dmactl);
-		writel (  (1 << DMA_SCATTER_GATHER_DONE_INTERRUPT)
-			| (1 << DMA_TRANSACTION_DONE_INTERRUPT)
-			| (1 << DMA_ABORT)
-			, &ep->dma->dmastat);
-
-		tmp = readl (&regs->pciirqenb0);
-		tmp &= ~(1 << ep->num);
-		writel (tmp, &regs->pciirqenb0);
-	} else {
-		tmp = readl (&regs->pciirqenb1);
-		tmp &= ~(1 << (8 + ep->num));	/* completion */
-		writel (tmp, &regs->pciirqenb1);
-	}
-	writel (0, &ep->regs->ep_irqenb);
-
-	/* init to our chosen defaults, notably so that we NAK OUT
-	 * packets until the driver queues a read (+note erratum 0112)
-	 */
-	writel (  (1 << SET_NAK_OUT_PACKETS_MODE)
-		| (1 << SET_NAK_OUT_PACKETS)
-		| (1 << CLEAR_EP_HIDE_STATUS_PHASE)
-		| (1 << CLEAR_INTERRUPT_MODE)
-		| (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE)
-		| (1 << CLEAR_ENDPOINT_TOGGLE)
-		| (1 << CLEAR_ENDPOINT_HALT)
-		, &ep->regs->ep_rsp);
-
-	/* scrub most status bits, and flush any fifo state */
-	writel (  (1 << TIMEOUT)
-		| (1 << USB_STALL_SENT)
-		| (1 << USB_IN_NAK_SENT)
-		| (1 << USB_IN_ACK_RCVD)
-		| (1 << USB_OUT_PING_NAK_SENT)
-		| (1 << USB_OUT_ACK_SENT)
-		| (1 << FIFO_OVERFLOW)
-		| (1 << FIFO_UNDERFLOW)
-		| (1 << FIFO_FLUSH)
-		| (1 << SHORT_PACKET_OUT_DONE_INTERRUPT)
-		| (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)
-		| (1 << DATA_PACKET_RECEIVED_INTERRUPT)
-		| (1 << DATA_PACKET_TRANSMITTED_INTERRUPT)
-		| (1 << DATA_OUT_PING_TOKEN_INTERRUPT)
-		| (1 << DATA_IN_TOKEN_INTERRUPT)
-		, &ep->regs->ep_stat);
-
-	/* fifo size is handled separately */
-}
-
-static void nuke (struct net2280_ep *);
-
-static int net2280_disable (struct usb_ep *_ep)
-{
-	struct net2280_ep	*ep;
-	unsigned long		flags;
-
-	ep = container_of (_ep, struct net2280_ep, ep);
-	if (!_ep || !ep->desc || _ep->name == ep0name)
-		return -EINVAL;
-
-	spin_lock_irqsave (&ep->dev->lock, flags);
-	nuke (ep);
-	ep_reset (ep->dev->regs, ep);
-
-	VDEBUG (ep->dev, "disabled %s %s\n",
-			ep->dma ? "dma" : "pio", _ep->name);
-
-	/* synch memory views with the device */
-	(void) readl (&ep->regs->ep_cfg);
-
-	if (use_dma && !ep->dma && ep->num >= 1 && ep->num <= 4)
-		ep->dma = &ep->dev->dma [ep->num - 1];
-
-	spin_unlock_irqrestore (&ep->dev->lock, flags);
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static struct usb_request *
-net2280_alloc_request (struct usb_ep *_ep, int gfp_flags)
-{
-	struct net2280_ep	*ep;
-	struct net2280_request	*req;
-
-	if (!_ep)
-		return 0;
-	ep = container_of (_ep, struct net2280_ep, ep);
-
-	req = kmalloc (sizeof *req, gfp_flags);
-	if (!req)
-		return 0;
-
-	memset (req, 0, sizeof *req);
-	req->req.dma = DMA_ADDR_INVALID;
-	INIT_LIST_HEAD (&req->queue);
-
-	/* this dma descriptor may be swapped with the previous dummy */
-	if (ep->dma) {
-		struct net2280_dma	*td;
-
-		td = pci_pool_alloc (ep->dev->requests, gfp_flags,
-				&req->td_dma);
-		if (!td) {
-			kfree (req);
-			return 0;
-		}
-		td->dmacount = 0;	/* not VALID */
-		td->dmaaddr = __constant_cpu_to_le32 (DMA_ADDR_INVALID);
-		req->td = td;
-	}
-	return &req->req;
-}
-
-static void
-net2280_free_request (struct usb_ep *_ep, struct usb_request *_req)
-{
-	struct net2280_ep	*ep;
-	struct net2280_request	*req;
-
-	ep = container_of (_ep, struct net2280_ep, ep);
-	if (!_ep || !_req)
-		return;
-
-	req = container_of (_req, struct net2280_request, req);
-	WARN_ON (!list_empty (&req->queue));
-	if (req->td)
-		pci_pool_free (ep->dev->requests, req->td, req->td_dma);
-	kfree (req);
-}
-
-/*-------------------------------------------------------------------------*/
-
-#undef USE_KMALLOC
-
-/* many common platforms have dma-coherent caches, which means that it's
- * safe to use kmalloc() memory for all i/o buffers without using any
- * cache flushing calls.  (unless you're trying to share cache lines
- * between dma and non-dma activities, which is a slow idea in any case.)
- *
- * other platforms need more care, with 2.5 having a moderately general
- * solution (which falls down for allocations smaller than one page)
- * that improves significantly on the 2.4 PCI allocators by removing
- * the restriction that memory never be freed in_interrupt().
- */
-#if	defined(CONFIG_X86) || defined(CONFIG_MIPS)
-#define USE_KMALLOC
-
-#elif	defined(CONFIG_PPC) && !defined(CONFIG_NOT_COHERENT_CACHE)
-#define USE_KMALLOC
-
-#endif
-
-/* allocating buffers this way eliminates dma mapping overhead, which
- * on some platforms will mean eliminating a per-io buffer copy.  with
- * some kinds of system caches, further tweaks may still be needed.
- */
-static void *
-net2280_alloc_buffer (
-	struct usb_ep		*_ep,
-	unsigned		bytes,
-	dma_addr_t		*dma,
-	int			gfp_flags
-)
-{
-	void			*retval;
-	struct net2280_ep	*ep;
-
-	ep = container_of (_ep, struct net2280_ep, ep);
-	if (!_ep || (!ep->desc && ep->num != 0))
-		return 0;
-
-	*dma = DMA_ADDR_INVALID;
-	if (ep->dma) {
-#if	defined(USE_KMALLOC)
-		retval = kmalloc (bytes, gfp_flags);
-		if (retval)
-			*dma = virt_to_phys (retval);
-
-#elif	LINUX_VERSION_CODE > KERNEL_VERSION(2,5,58)
-#warning Using dma_alloc_consistent even with sub-page allocations
-		/* the main problem with this call is that it wastes memory
-		 * on typical 1/N page allocations: it allocates 1-N pages.
-		 */
-		retval = dma_alloc_coherent (&ep->dev->pdev->dev,
-				bytes, dma, gfp_flags);
-#else
-#error No dma-coherent memory allocator is available
-		/* pci_alloc_consistent works, but pci_free_consistent()
-		 * isn't safe in_interrupt().  plus, in addition to the
-		 * 1/Nth page weakness, it doesn't understand gfp_flags.
-		 */
-#endif
-	} else
-		retval = kmalloc (bytes, gfp_flags);
-
-	return retval;
-}
-
-static void
-net2280_free_buffer (
-	struct usb_ep *_ep,
-	void *buf,
-	dma_addr_t dma,
-	unsigned bytes
-) {
-	/* free memory into the right allocator */
-#ifndef	USE_KMALLOC
-	if (dma != DMA_ADDR_INVALID)
-		dma_free_coherent (ep->dev->pdev, bytes, dma);
-	else
-#endif
-		kfree (buf);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* load a packet into the fifo we use for usb IN transfers.
- * works for all endpoints.
- *
- * NOTE: pio with ep-a..ep-d could stuff multiple packets into the fifo
- * at a time, but this code is simpler because it knows it only writes
- * one packet.  ep-a..ep-d should use dma instead.
- */
-static void
-write_fifo (struct net2280_ep *ep, struct usb_request *req)
-{
-	struct net2280_ep_regs	*regs = ep->regs;
-	u8			*buf;
-	u32			tmp;
-	unsigned		count, total;
-
-	/* INVARIANT:  fifo is currently empty. (testable) */
-
-	if (req) {
-		total = req->length - req->actual;
-		buf = req->buf + req->actual;
-	} else {
-		total = 0;
-		buf = 0;
-	}
-
-	/* write just one packet at a time */
-	count = min (ep->ep.maxpacket, total);
-	VDEBUG (ep->dev, "write %s fifo (IN) %d bytes%s req %p\n",
-			ep->ep.name, count,
-			(count != ep->ep.maxpacket) ? " (short)" : "",
-			req);
-	while (count >= 4) {
-		/* NOTE be careful if you try to align these. fifo lines
-		 * should normally be full (4 bytes) and successive partial
-		 * lines are ok only in certain cases.
-		 */
-		tmp = get_unaligned ((u32 *)buf);
-		cpu_to_le32s (&tmp);
-		writel (tmp, &regs->ep_data);
-		buf += 4;
-		count -= 4;
-	}
-
-	/* last fifo entry is "short" unless we wrote a full
-	 * packet. must also explicitly "validate" max length
-	 * isochronous packets if maxpacket is not a multiple of 4
-	 * bytes.
-	 */
-	if (total < ep->ep.maxpacket
-		|| (ep->is_iso
-			&& total == ep->ep.maxpacket
-			&& (ep->ep.maxpacket % 4))) {
-		tmp = count ? get_unaligned ((u32 *)buf) : count;
-		cpu_to_le32s (&tmp);
-		set_fifo_bytecount (ep, count & 0x03);
-		writel (tmp, &regs->ep_data);
-	}
-
-	/* pci writes may still be posted */
-}
-
-/* work around erratum 0106: PCI and USB race over the OUT fifo.
- * caller guarantees chiprev 0100, out endpoint is NAKing, and
- * there's no real data in the fifo.
- */
-static void out_flush (struct net2280_ep *ep)
-{
-	u32	*statp, tmp;
-
-	ASSERT_OUT_NAKING (ep);
-
-	statp = &ep->regs->ep_stat;
-	writel (  (1 << DATA_OUT_PING_TOKEN_INTERRUPT)
-		| (1 << DATA_PACKET_RECEIVED_INTERRUPT)
-		, statp);
-	writel ((1 << FIFO_FLUSH), statp);
-	mb ();
-	tmp = readl (statp);
-	if (tmp & (1 << DATA_OUT_PING_TOKEN_INTERRUPT)
-			/* high speed did bulk NYET; fifo isn't filling */
-			&& ep->dev->gadget.speed == USB_SPEED_FULL) {
-		unsigned	usec;
-
-		usec = 50;		/* 64 byte bulk/interrupt */
-		handshake (statp, (1 << USB_OUT_PING_NAK_SENT),
-				(1 << USB_OUT_PING_NAK_SENT), usec);
-		/* NAK done; now CLEAR_NAK_OUT_PACKETS is safe */
-	}
-}
-
-/* unload packet(s) from the fifo we use for usb OUT transfers.
- * returns true iff the request completed, because of short packet
- * or the request buffer having filled with full packets.
- *
- * for ep-a..ep-d this will read multiple packets out when they
- * have been accepted.
- */
-static int
-read_fifo (struct net2280_ep *ep, struct net2280_request *req)
-{
-	struct net2280_ep_regs	*regs = ep->regs;
-	u8			*buf = req->req.buf + req->req.actual;
-	unsigned		count, tmp, is_short;
-	unsigned		cleanup = 0, prevent = 0;
-
-	/* erratum 0106 ... packets coming in during fifo reads might
-	 * be incompletely rejected.  not all cases have workarounds.
-	 */
-	if (ep->dev->chiprev == 0x0100) {
-		tmp = readl (&ep->regs->ep_stat);
-		if ((tmp & (1 << NAK_OUT_PACKETS)))
-			/* cleanup = 1 */;
-		else if ((tmp & (1 << FIFO_FULL))
-				/* don't break hs PING protocol ... */
-				|| ep->dev->gadget.speed == USB_SPEED_FULL) {
-			start_out_naking (ep);
-			prevent = 1;
-		}
-		/* else: hope we don't see the problem */
-	}
-
-	/* never overflow the rx buffer. the fifo reads packets until
-	 * it sees a short one; we might not be ready for them all.
-	 */
-	count = readl (&regs->ep_avail);
-	tmp = req->req.length - req->req.actual;
-	if (count > tmp) {
-		/* as with DMA, data overflow gets flushed */
-		if ((tmp % ep->ep.maxpacket) != 0) {
-			ERROR (ep->dev,
-				"%s out fifo %d bytes, expected %d\n",
-				ep->ep.name, count, tmp);
-			req->req.status = -EOVERFLOW;
-			cleanup = 1;
-		}
-		count = tmp;
-	}
-	req->req.actual += count;
-
-	is_short = (count == 0) || ((count % ep->ep.maxpacket) != 0);
-
-	VDEBUG (ep->dev, "read %s fifo (OUT) %d bytes%s%s%s req %p %d/%d\n",
-			ep->ep.name, count, is_short ? " (short)" : "",
-			cleanup ? " flush" : "", prevent ? " nak" : "",
-			req, req->req.actual, req->req.length);
-
-	while (count >= 4) {
-		tmp = readl (&regs->ep_data);
-		cpu_to_le32s (&tmp);
-		put_unaligned (tmp, (u32 *)buf);
-		buf += 4;
-		count -= 4;
-	}
-	if (count) {
-		tmp = readl (&regs->ep_data);
-		cpu_to_le32s (&tmp);
-		do {
-			*buf++ = (u8) tmp;
-			tmp >>= 8;
-		} while (--count);
-	}
-	if (cleanup)
-		out_flush (ep);
-	if (prevent) {
-		writel ((1 << CLEAR_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
-		(void) readl (&ep->regs->ep_rsp);
-	}
-
-	return is_short || ((req->req.actual == req->req.length)
-				&& !req->req.zero);
-}
-
-/* fill out dma descriptor to match a given request */
-static inline void
-fill_dma_desc (struct net2280_ep *ep, struct net2280_request *req, int valid)
-{
-	struct net2280_dma	*td = req->td;
-	u32			dmacount = req->req.length;
-
-	/* don't let DMA continue after a short OUT packet,
-	 * so overruns can't affect the next transfer.
-	 * in case of overruns on max-size packets, we can't
-	 * stop the fifo from filling but we can flush it.
-	 */
-	if (ep->is_in)
-		dmacount |= (1 << DMA_DIRECTION);
-	else
-		dmacount |= (1 << END_OF_CHAIN);
-
-	req->valid = valid;
-	if (valid)
-		dmacount |= (1 << VALID_BIT);
-#ifdef USE_DMA_CHAINING
-	if (!req->req.no_interrupt)
-#endif
-		dmacount |= (1 << DMA_DONE_INTERRUPT_ENABLE);
-
-	/* td->dmadesc = previously set by caller */
-	td->dmaaddr = cpu_to_le32p (&req->req.dma);
-
-	/* 2280 may be polling VALID_BIT through ep->dma->dmadesc */
-	wmb ();
-	td->dmacount = cpu_to_le32p (&dmacount);
-}
-
-static const u32 dmactl_default =
-		  (1 << DMA_CLEAR_COUNT_ENABLE)
-		| (POLL_100_USEC << DESCRIPTOR_POLLING_RATE)
-		| (1 << DMA_VALID_BIT_POLLING_ENABLE)
-		| (1 << DMA_VALID_BIT_ENABLE)
-		| (1 << DMA_SCATTER_GATHER_ENABLE)
-		| (1 << DMA_ENABLE);
-
-static inline void spin_stop_dma (struct net2280_dma_regs *dma)
-{
-	handshake (&dma->dmactl, (1 << DMA_ENABLE), 0, 50);
-}
-
-static inline void stop_dma (struct net2280_dma_regs *dma)
-{
-	writel (dmactl_default & ~(1 << DMA_ENABLE), &dma->dmactl);
-	spin_stop_dma (dma);
-}
-
-static void start_dma (struct net2280_ep *ep, struct net2280_request *req)
-{
-	u32			tmp;
-	int			clear_nak = 0;
-	struct net2280_dma_regs	*dma = ep->dma;
-
-
-	/* previous OUT packet might have been short */
-	if (!ep->is_in && ((tmp = readl (&ep->regs->ep_stat))
-		 		& (1 << NAK_OUT_PACKETS)) != 0) {
-		writel ((1 << SHORT_PACKET_TRANSFERRED_INTERRUPT),
-			&ep->regs->ep_stat);
-
-		tmp = readl (&ep->regs->ep_avail);
-		if (tmp == 0)
-			clear_nak = 1;
-		else {
-			/* transfer all/some fifo data */
-			writel (req->req.dma, &dma->dmaaddr);
-			tmp = min (tmp, req->req.length);
-
-			/* dma irq, faking scatterlist status */
-			req->td->dmacount = cpu_to_le32 (req->req.length - tmp);
-			writel ((1 << DMA_DONE_INTERRUPT_ENABLE)
-				| tmp, &dma->dmacount);
-
-			writel ((1 << DMA_ENABLE), &dma->dmactl);
-			writel ((1 << DMA_START), &dma->dmastat);
-			return;
-		}
-	}
-
-	/* on this path we know there's no dma queue (yet) */
-	WARN_ON (readl (&dma->dmactl) & (1 << DMA_ENABLE));
-	tmp = dmactl_default;
-
-	/* force packet boundaries between dma requests, but prevent the
-	 * controller from automagically writing a last "short" packet
-	 * (zero length) unless the driver explicitly said to do that.
-	 */
-	if (ep->is_in) {
-		if (likely ((req->req.length % ep->ep.maxpacket) != 0
-				|| req->req.zero)) {
-			tmp |= (1 << DMA_FIFO_VALIDATE);
-			ep->in_fifo_validate = 1;
-		} else
-			ep->in_fifo_validate = 0;
-	}
-
-	/* init req->td, pointing to the current dummy */
-	req->td->dmadesc = cpu_to_le32 (ep->td_dma);
-	fill_dma_desc (ep, req, 1);
-
-#ifdef USE_DMA_CHAINING
-	writel (  (1 << VALID_BIT)
-		| (ep->is_in << DMA_DIRECTION)
-		| 0, &dma->dmacount);
-#else
-	req->td->dmacount |= __constant_cpu_to_le32 (1 << END_OF_CHAIN);
-#endif
-
-	writel (req->td_dma, &dma->dmadesc);
-	writel (tmp, &dma->dmactl);
-
-	(void) readl (&ep->dev->pci->pcimstctl);
-
-	writel ((1 << DMA_START), &dma->dmastat);
-
-	if (clear_nak)
-		writel ((1 << CLEAR_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
-}
-
-static inline void
-queue_dma (struct net2280_ep *ep, struct net2280_request *req, int valid)
-{
-	struct net2280_dma	*end;
-	dma_addr_t		tmp;
-
-	/* swap new dummy for old, link; fill and maybe activate */
-	end = ep->dummy;
-	ep->dummy = req->td;
-	req->td = end;
-
-	tmp = ep->td_dma;
-	ep->td_dma = req->td_dma;
-	req->td_dma = tmp;
-
-	end->dmadesc = cpu_to_le32 (ep->td_dma);
-
-	fill_dma_desc (ep, req, valid);
-}
-
-static void
-done (struct net2280_ep *ep, struct net2280_request *req, int status)
-{
-	struct net2280		*dev;
-	unsigned		stopped = ep->stopped;
-
-	list_del_init (&req->queue);
-
-	if (req->req.status == -EINPROGRESS)
-		req->req.status = status;
-	else
-		status = req->req.status;
-
-	dev = ep->dev;
-	if (req->mapped) {
-		pci_unmap_single (dev->pdev, req->req.dma, req->req.length,
-			ep->is_in ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
-		req->req.dma = DMA_ADDR_INVALID;
-		req->mapped = 0;
-	}
-
-	if (status && status != -ESHUTDOWN)
-		VDEBUG (dev, "complete %s req %p stat %d len %u/%u\n",
-			ep->ep.name, &req->req, status,
-			req->req.actual, req->req.length);
-
-	/* don't modify queue heads during completion callback */
-	ep->stopped = 1;
-	spin_unlock (&dev->lock);
-	req->req.complete (&ep->ep, &req->req);
-	spin_lock (&dev->lock);
-	ep->stopped = stopped;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int
-net2280_queue (struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
-{
-	struct net2280_request	*req;
-	struct net2280_ep	*ep;
-	struct net2280		*dev;
-	unsigned long		flags;
-
-	/* we always require a cpu-view buffer, so that we can
-	 * always use pio (as fallback or whatever).
-	 */
-	req = container_of (_req, struct net2280_request, req);
-	if (!_req || !_req->complete || !_req->buf
-			|| !list_empty (&req->queue))
-		return -EINVAL;
-	if (_req->length > (~0 & DMA_BYTE_COUNT_MASK))
-		return -EDOM;
-	ep = container_of (_ep, struct net2280_ep, ep);
-	if (!_ep || (!ep->desc && ep->num != 0))
-		return -EINVAL;
-	dev = ep->dev;
-	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
-		return -ESHUTDOWN;
-
-	if (ep->dma && _req->length == 0)
-		return -EOPNOTSUPP;
-
-	/* set up dma mapping in case the caller didn't */
-	if (ep->dma && _req->dma == DMA_ADDR_INVALID) {
-		_req->dma = pci_map_single (dev->pdev, _req->buf, _req->length,
-			ep->is_in ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
-		req->mapped = 1;
-	}
-
-
-	spin_lock_irqsave (&dev->lock, flags);
-
-	_req->status = -EINPROGRESS;
-	_req->actual = 0;
-	req->dma_done = 0;
-
-	/* kickstart this i/o queue? */
-	if (list_empty (&ep->queue) && !ep->stopped) {
-		/* use DMA if the endpoint supports it, else pio */
-		if (ep->dma)
-			start_dma (ep, req);
-		else {
-			/* maybe there's no control data, just status ack */
-			if (ep->num == 0 && _req->length == 0) {
-				allow_status (ep);
-				done (ep, req, 0);
-				VDEBUG (dev, "%s status ack\n", ep->ep.name);
-				goto done;
-			}
-
-			/* PIO ... stuff the fifo, or unblock it.  */
-			if (ep->is_in)
-				write_fifo (ep, _req);
-			else if (list_empty (&ep->queue)) {
-				u32	s;
-
-				/* OUT FIFO might have packet(s) buffered */
-				s = readl (&ep->regs->ep_stat);
-				if ((s & (1 << FIFO_EMPTY)) == 0) {
-					/* note:  _req->short_not_ok is
-					 * ignored here since PIO _always_
-					 * stops queue advance here, and
-					 * _req->status doesn't change for
-					 * short reads (only _req->actual)
-					 */
-					if (read_fifo (ep, req)) {
-						done (ep, req, 0);
-						if (ep->num == 0)
-							allow_status (ep);
-						/* don't queue it */
-						req = 0;
-					} else
-						s = readl (&ep->regs->ep_stat);
-				}
-
-				/* don't NAK, let the fifo fill */
-				if (req && (s & (1 << NAK_OUT_PACKETS)))
-					writel ((1 << CLEAR_NAK_OUT_PACKETS),
-							&ep->regs->ep_rsp);
-			}
-		}
-
-	} else if (ep->dma) {
-		int	valid = 1;
-
-		if (ep->is_in) {
-			int	expect;
-
-			/* preventing magic zlps is per-engine state, not
-			 * per-transfer; irq logic must recover hiccups.
-			 */
-			expect = likely (req->req.zero
-				|| (req->req.length % ep->ep.maxpacket) != 0);
-			if (expect != ep->in_fifo_validate)
-				valid = 0;
-		}
-		queue_dma (ep, req, valid);
-
-	} /* else the irq handler advances the queue. */
-
-	if (req)
-		list_add_tail (&req->queue, &ep->queue);
-done:
-	spin_unlock_irqrestore (&dev->lock, flags);
-
-	/* pci writes may still be posted */
-	return 0;
-}
-
-static inline void
-dma_done (
-	struct net2280_ep *ep,
-	struct net2280_request *req,
-	u32 dmacount,
-	int status
-)
-{
-	req->req.actual = req->req.length - (DMA_BYTE_COUNT_MASK & dmacount);
-	VDEBUG (ep->dev, "%s %s dma (%s) %d bytes%s req %p\n",
-			ep->is_in ? "write" : "read",
-			ep->ep.name, ep->is_in ? "IN" : "OUT",
-			req->req.actual,
-			(req->req.actual < req->req.length) ? " (short)" : "",
-			req);
-	rmb ();
-	done (ep, req, status);
-}
-
-static void scan_dma_completions (struct net2280_ep *ep)
-{
-	/* only look at descriptors that were "naturally" retired,
-	 * so fifo and list head state won't matter
-	 */
-	while (!list_empty (&ep->queue)) {
-		struct net2280_request	*req;
-		u32			tmp;
-
-		req = list_entry (ep->queue.next,
-				struct net2280_request, queue);
-		if (!req->valid)
-			break;
-		rmb ();
-		tmp = le32_to_cpup (&req->td->dmacount);
-		if ((tmp & (1 << VALID_BIT)) != 0)
-			break;
-
-		if (!ep->is_in && (req->req.length % ep->ep.maxpacket) != 0) {
-			req->dma_done = 1;
-			break;
-		}
-		dma_done (ep, req, tmp, 0);
-	}
-}
-
-static void restart_dma (struct net2280_ep *ep)
-{
-	struct net2280_request	*req;
-
-	if (ep->stopped)
-		return;
-	req = list_entry (ep->queue.next, struct net2280_request, queue);
-
-#ifdef USE_DMA_CHAINING
-	/* the 2280 will be processing the queue unless queue hiccups after
-	 * the previous transfer:
-	 *  IN:   wanted automagic zlp, head doesn't (or vice versa)
-	 *  OUT:  was "usb-short", we must restart.
-	 */
-	if (!req->valid) {
-		struct net2280_request	*entry, *prev = 0;
-		int			qmode, reqmode, done = 0;
-
-		DEBUG (ep->dev, "%s dma hiccup td %p\n", ep->ep.name, req->td);
-		qmode = likely (req->req.zero
-			|| (req->req.length % ep->ep.maxpacket) != 0);
-		list_for_each_entry (entry, &ep->queue, queue) {
-			u32		dmacount;
-
-			if (entry != req)
-				continue;
-			dmacount = entry->td->dmacount;
-			if (!done) {
-				reqmode = likely (entry->req.zero
-					|| (entry->req.length
-						% ep->ep.maxpacket) != 0);
-				if (reqmode == qmode) {
-					entry->valid = 1;
-					dmacount |= valid_bit;
-					entry->td->dmacount = dmacount;
-					prev = entry;
-					continue;
-				} else {
-					prev->td->dmacount |= dma_done_ie;
-					done = 1;
-				}
-			}
-
-			/* walk the rest of the queue so unlinks behave */
-			entry->valid = 0;
-			dmacount &= ~valid_bit;
-			entry->td->dmacount = dmacount;
-			prev = entry;
-		}
-		start_dma (ep, req);
-	} else if (!ep->is_in
-			&& (readl (&ep->regs->ep_stat)
-				& (1 << NAK_OUT_PACKETS)) != 0)
-		start_dma (ep, req);
-#else
-	start_dma (ep, req);
-#endif
-}
-
-static inline void abort_dma (struct net2280_ep *ep)
-{
-	/* abort the current transfer */
-	writel ((1 << DMA_ABORT), &ep->dma->dmastat);
-
-	/* collect completed transfers (except the current one) */
-	scan_dma_completions (ep);
-}
-
-/* dequeue ALL requests */
-static void nuke (struct net2280_ep *ep)
-{
-	struct net2280_request	*req;
-
-	/* called with spinlock held */
-	ep->stopped = 1;
-	if (ep->dma)
-		abort_dma (ep);
-	while (!list_empty (&ep->queue)) {
-		req = list_entry (ep->queue.next,
-				struct net2280_request,
-				queue);
-		done (ep, req, -ESHUTDOWN);
-	}
-}
-
-/* dequeue JUST ONE request */
-static int net2280_dequeue (struct usb_ep *_ep, struct usb_request *_req)
-{
-	struct net2280_ep	*ep;
-	struct net2280_request	*req;
-	unsigned long		flags;
-	u32			dmactl;
-	int			stopped;
-
-	ep = container_of (_ep, struct net2280_ep, ep);
-	req = container_of (_req, struct net2280_request, req);
-	if (!_ep || (!ep->desc && ep->num != 0) || !_req)
-		return -EINVAL;
-
-	spin_lock_irqsave (&ep->dev->lock, flags);
-	stopped = ep->stopped;
-
-	/* pause dma while we scan the queue */
-	dmactl = 0;
-	ep->stopped = 1;
-	if (ep->dma) {
-		dmactl = readl (&ep->dma->dmactl);
-		writel (dmactl & ~(1 << DMA_ENABLE), &ep->dma->dmactl);
-		/* force synch, clean any completed requests */
-		spin_stop_dma (ep->dma);
-		scan_dma_completions (ep);
-	}
-
-	/* queue head may be partially complete. */
-	if (ep->queue.next == &req->queue) {
-		if (ep->dma) {
-			DEBUG (ep->dev, "unlink (%s) dma\n", _ep->name);
-			_req->status = -ECONNRESET;
-			abort_dma (ep);
-			if (likely (ep->queue.next == &req->queue))
-				dma_done (ep, req,
-					le32_to_cpup (&req->td->dmacount),
-					-ECONNRESET);
-		} else {
-			DEBUG (ep->dev, "unlink (%s) pio\n", _ep->name);
-			done (ep, req, -ECONNRESET);
-		}
-		req = 0;
-
-#ifdef USE_DMA_CHAINING
-	/* patch up hardware chaining data */
-	} else if (ep->dma) {
-		if (req->queue.prev == ep->queue.next) {
-			writel (le32_to_cpu (req->td->dmadesc),
-				&ep->dma->dmadesc);
-			if (req->td->dmacount & dma_done_ie)
-				writel (readl (&ep->dma->dmacount)
-						| dma_done_ie,
-					&ep->dma->dmacount);
-		} else {
-			struct net2280_request	*prev;
-
-			prev = list_entry (req->queue.prev,
-				struct net2280_request, queue);
-			prev->td->dmadesc = req->td->dmadesc;
-			if (req->td->dmacount & dma_done_ie)
-				prev->td->dmacount |= dma_done_ie;
-		}
-#endif
-	}
-
-	if (req)
-		done (ep, req, -ECONNRESET);
-	ep->stopped = stopped;
-
-	if (ep->dma) {
-		/* turn off dma on inactive queues */
-		if (list_empty (&ep->queue))
-			stop_dma (ep->dma);
-		else if (!ep->stopped) {
-			/* resume current request, or start new one */
-			if (req)
-				writel (dmactl, &ep->dma->dmactl);
-			else
-				start_dma (ep, list_entry (ep->queue.next,
-					struct net2280_request, queue));
-		}
-	}
-
-	spin_unlock_irqrestore (&ep->dev->lock, flags);
-	return req ? 0 : -EOPNOTSUPP;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int
-net2280_set_halt (struct usb_ep *_ep, int value)
-{
-	struct net2280_ep	*ep;
-
-	ep = container_of (_ep, struct net2280_ep, ep);
-	if (!_ep || (!ep->desc && ep->num != 0))
-		return -EINVAL;
-	if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
-		return -ESHUTDOWN;
-	if (ep->desc /* not ep0 */ && (ep->desc->bmAttributes & 0x03)
-						== USB_ENDPOINT_XFER_ISOC)
-		return -EINVAL;
-
-	VDEBUG (ep->dev, "%s %s halt\n", _ep->name, value ? "set" : "clear");
-
-	/* set/clear, then synch memory views with the device */
-	if (value) {
-		if (ep->num == 0)
-			ep->dev->protocol_stall = 1;
-		else
-			set_halt (ep);
-	} else
-		clear_halt (ep);
-	(void) readl (&ep->regs->ep_rsp);
-
-	return 0;
-}
-
-static int
-net2280_fifo_status (struct usb_ep *_ep)
-{
-	struct net2280_ep	*ep;
-	u32			avail;
-
-	ep = container_of (_ep, struct net2280_ep, ep);
-	if (!_ep || (!ep->desc && ep->num != 0))
-		return -ENODEV;
-	if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
-		return -ESHUTDOWN;
-
-	avail = readl (&ep->regs->ep_avail) & ((1 << 12) - 1);
-	if (avail > ep->fifo_size)
-		return -EOVERFLOW;
-	if (ep->is_in)
-		avail = ep->fifo_size - avail;
-	return avail;
-}
-
-static void
-net2280_fifo_flush (struct usb_ep *_ep)
-{
-	struct net2280_ep	*ep;
-
-	ep = container_of (_ep, struct net2280_ep, ep);
-	if (!_ep || (!ep->desc && ep->num != 0))
-		return;
-	if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
-		return;
-
-	writel ((1 << FIFO_FLUSH), &ep->regs->ep_stat);
-	(void) readl (&ep->regs->ep_rsp);
-}
-
-static struct usb_ep_ops net2280_ep_ops = {
-	.enable		= net2280_enable,
-	.disable	= net2280_disable,
-
-	.alloc_request	= net2280_alloc_request,
-	.free_request	= net2280_free_request,
-
-	.alloc_buffer	= net2280_alloc_buffer,
-	.free_buffer	= net2280_free_buffer,
-
-	.queue		= net2280_queue,
-	.dequeue	= net2280_dequeue,
-
-	.set_halt	= net2280_set_halt,
-	.fifo_status	= net2280_fifo_status,
-	.fifo_flush	= net2280_fifo_flush,
-};
-
-/*-------------------------------------------------------------------------*/
-
-static int net2280_get_frame (struct usb_gadget *_gadget)
-{
-	struct net2280		*dev;
-	unsigned long		flags;
-	u16			retval;
-
-	if (!_gadget)
-		return -ENODEV;
-	dev = container_of (_gadget, struct net2280, gadget);
-	spin_lock_irqsave (&dev->lock, flags);
-	retval = get_idx_reg (dev->regs, REG_FRAME) & 0x03ff;
-	spin_unlock_irqrestore (&dev->lock, flags);
-	return retval;
-}
-
-static int net2280_wakeup (struct usb_gadget *_gadget)
-{
-	struct net2280		*dev;
-
-	if (!_gadget)
-		return 0;
-	dev = container_of (_gadget, struct net2280, gadget);
-	writel (1 << GENERATE_RESUME, &dev->usb->usbstat);
-
-	/* pci writes may still be posted */
-	return 0;
-}
-
-static const struct usb_gadget_ops net2280_ops = {
-	.get_frame	= net2280_get_frame,
-	.wakeup		= net2280_wakeup,
-
-	// .set_selfpowered = net2280_set_selfpowered,
-};
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef	USE_SYSFS_DEBUG_FILES
-
-/* "function" sysfs attribute */
-static ssize_t
-show_function (struct class_device *_dev, char *buf)
-{
-	struct net2280	*dev;
-
-	dev = container_of (_dev, struct net2280, classdev);
-	if (!dev->driver
-			|| !dev->driver->function
-			|| strlen (dev->driver->function) > PAGE_SIZE)
-		return 0;
-	return snprintf (buf, PAGE_SIZE, "%s\n", dev->driver->function);
-}
-static CLASS_DEVICE_ATTR (function, S_IRUGO, show_function, NULL);
-
-static ssize_t
-show_registers (struct class_device *_dev, char *buf)
-{
-	struct net2280		*dev;
-	char			*next;
-	unsigned		size, t;
-	unsigned long		flags;
-	int			i;
-	u32			t1, t2;
-	char			*s;
-
-	dev = container_of (_dev, struct net2280, classdev);
-	next = buf;
-	size = PAGE_SIZE;
-	spin_lock_irqsave (&dev->lock, flags);
-
-	if (dev->driver)
-		s = dev->driver->driver.name;
-	else
-		s = "(none)";
-
-	/* Main Control Registers */
-	t = snprintf (next, size, "%s version " DRIVER_VERSION
-			", chiprev %04x\n"
-			"devinit %03x fifoctl %08x gadget '%s'\n"
-			"pci irqenb0 %02x irqenb1 %08x "
-			"irqstat0 %04x irqstat1 %08x\n",
-			driver_name, dev->chiprev,
-			readl (&dev->regs->devinit),
-			readl (&dev->regs->fifoctl),
-			s,
-			readl (&dev->regs->pciirqenb0),
-			readl (&dev->regs->pciirqenb1),
-			readl (&dev->regs->irqstat0),
-			readl (&dev->regs->irqstat1));
-	size -= t;
-	next += t;
-
-	/* USB Control Registers */
-	t1 = readl (&dev->usb->usbctl);
-	t2 = readl (&dev->usb->usbstat);
-	if (t1 & (1 << VBUS_PIN)) {
-		if (t2 & (1 << HIGH_SPEED))
-			s = "high speed";
-		else if (dev->gadget.speed == USB_SPEED_UNKNOWN)
-			s = "powered";
-		else
-			s = "full speed";
-		/* full speed bit (6) not working?? */
-	} else
-			s = "not attached";
-	t = snprintf (next, size,
-			"stdrsp %08x usbctl %08x usbstat %08x "
-				"addr 0x%02x (%s)\n",
-			readl (&dev->usb->stdrsp), t1, t2,
-			readl (&dev->usb->ouraddr), s);
-	size -= t;
-	next += t;
-
-	/* PCI Master Control Registers */
-
-	/* DMA Control Registers */
-
-	/* Configurable EP Control Registers */
-	for (i = 0; i < 7; i++) {
-		struct net2280_ep	*ep;
-
-		ep = &dev->ep [i];
-		if (i && !ep->desc)
-			continue;
-
-		t1 = readl (&ep->regs->ep_cfg);
-		t = snprintf (next, size,
-				"%s\tcfg %05x rsp %02x enb %02x ",
-				ep->ep.name, t1,
-				readl (&ep->regs->ep_rsp) & 0xff,
-				readl (&ep->regs->ep_irqenb));
-		size -= t;
-		next += t;
-
-		t = snprintf (next, size,
-				"stat %08x avail %04x "
-				"(ep%d%s-%s)%s\n",
-				readl (&ep->regs->ep_stat),
-				readl (&ep->regs->ep_avail),
-				t1 & 0x0f, DIR_STRING (t1),
-				type_string (t1 >> 8),
-				ep->stopped ? "*" : "");
-		size -= t;
-		next += t;
-
-		if (!ep->dma)
-			continue;
-
-		t = snprintf (next, size,
-				"  dma\tctl %08x stat %08x count %08x\n"
-				"\taddr %08x desc %08x\n",
-				readl (&ep->dma->dmactl),
-				readl (&ep->dma->dmastat),
-				readl (&ep->dma->dmacount),
-				readl (&ep->dma->dmaaddr),
-				readl (&ep->dma->dmadesc));
-		size -= t;
-		next += t;
-
-	}
-
-	/* Indexed Registers */
-		// none yet 
-
-	/* Statistics */
-	t = snprintf (next, size, "irqs:  ");
-	size -= t;
-	next += t;
-	for (i = 0; i < 7; i++) {
-		struct net2280_ep	*ep;
-
-		ep = &dev->ep [i];
-		if (i && !ep->irqs)
-			continue;
-		t = snprintf (next, size, " %s/%ld", ep->ep.name, ep->irqs);
-		size -= t;
-		next += t;
-
-	}
-	t = snprintf (next, size, "\n");
-	size -= t;
-	next += t;
-
-	spin_unlock_irqrestore (&dev->lock, flags);
-
-	return PAGE_SIZE - size;
-}
-static CLASS_DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);
-
-static ssize_t
-show_queues (struct class_device *_dev, char *buf)
-{
-	struct net2280		*dev;
-	char			*next;
-	unsigned		size;
-	unsigned long		flags;
-	int			i;
-
-	dev = container_of (_dev, struct net2280, classdev);
-	next = buf;
-	size = PAGE_SIZE;
-	spin_lock_irqsave (&dev->lock, flags);
-
-	for (i = 0; i < 7; i++) {
-		struct net2280_ep		*ep = &dev->ep [i];
-		struct net2280_request		*req;
-		int				t;
-
-		if (i != 0) {
-			const struct usb_endpoint_descriptor	*d;
-
-			d = ep->desc;
-			if (!d)
-				continue;
-			t = d->bEndpointAddress;
-			t = snprintf (next, size,
-				"%s (ep%d%s-%s) max %04x %s\n",
-				ep->ep.name, t & USB_ENDPOINT_NUMBER_MASK,
-				(t & USB_DIR_IN) ? "in" : "out",
-				({ char *val;
-				 switch (d->bmAttributes & 0x03) {
-				 case USB_ENDPOINT_XFER_BULK:
-				 	val = "bulk"; break;
-				 case USB_ENDPOINT_XFER_INT:
-				 	val = "intr"; break;
-				 default:
-				 	val = "iso"; break;
-				 }; val; }),
-				le16_to_cpu (d->wMaxPacketSize) & 0x1fff,
-				ep->dma ? "dma" : "pio"
-				);
-		} else /* ep0 should only have one transfer queued */
-			t = snprintf (next, size, "ep0 max 64 pio %s\n",
-					ep->is_in ? "in" : "out");
-		if (t <= 0 || t > size)
-			goto done;
-		size -= t;
-		next += t;
-
-		if (list_empty (&ep->queue)) {
-			t = snprintf (next, size, "\t(nothing queued)\n");
-			if (t <= 0 || t > size)
-				goto done;
-			size -= t;
-			next += t;
-			continue;
-		}
-		list_for_each_entry (req, &ep->queue, queue) {
-			if (ep->dma && req->td_dma == readl (&ep->dma->dmadesc))
-				t = snprintf (next, size,
-					"\treq %p len %d/%d "
-					"buf %p (dmacount %08x)\n",
-					&req->req, req->req.actual,
-					req->req.length, req->req.buf,
-					readl (&ep->dma->dmacount));
-			else
-				t = snprintf (next, size,
-					"\treq %p len %d/%d buf %p\n",
-					&req->req, req->req.actual,
-					req->req.length, req->req.buf);
-			if (t <= 0 || t > size)
-				goto done;
-			size -= t;
-			next += t;
-		}
-	}
-
-done:
-	spin_unlock_irqrestore (&dev->lock, flags);
-	return PAGE_SIZE - size;
-}
-static CLASS_DEVICE_ATTR (queues, S_IRUGO, show_queues, NULL);
-
-
-#else
-
-#define class_device_create_file(a,b)	do {} while (0)
-#define class_device_remove_file	class_device_create_file
-
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-/* another driver-specific mode might be a request type doing dma
- * to/from another device fifo instead of to/from memory.
- */
-
-static void set_fifo_mode (struct net2280 *dev, int mode)
-{
-	/* keeping high bits preserves BAR2 */
-	writel ((0xffff << PCI_BASE2_RANGE) | mode, &dev->regs->fifoctl);
-
-	/* always ep-{a,b,e,f} ... maybe not ep-c or ep-d */
-	INIT_LIST_HEAD (&dev->gadget.ep_list);
-	list_add_tail (&dev->ep [1].ep.ep_list, &dev->gadget.ep_list);
-	list_add_tail (&dev->ep [2].ep.ep_list, &dev->gadget.ep_list);
-	switch (mode) {
-	case 0:
-		list_add_tail (&dev->ep [3].ep.ep_list, &dev->gadget.ep_list);
-		list_add_tail (&dev->ep [4].ep.ep_list, &dev->gadget.ep_list);
-		dev->ep [1].fifo_size = dev->ep [2].fifo_size = 1024;
-		break;
-	case 1:
-		dev->ep [1].fifo_size = dev->ep [2].fifo_size = 2048;
-		break;
-	case 2:
-		list_add_tail (&dev->ep [3].ep.ep_list, &dev->gadget.ep_list);
-		dev->ep [1].fifo_size = 2048;
-		dev->ep [2].fifo_size = 1024;
-		break;
-	}
-	/* fifo sizes for ep0, ep-c, ep-d, ep-e, and ep-f never change */
-	list_add_tail (&dev->ep [5].ep.ep_list, &dev->gadget.ep_list);
-	list_add_tail (&dev->ep [6].ep.ep_list, &dev->gadget.ep_list);
-}
-
-/**
- * net2280_set_fifo_mode - change allocation of fifo buffers
- * @gadget: access to the net2280 device that will be updated
- * @mode: 0 for default, four 1kB buffers (ep-a through ep-d);
- * 	1 for two 2kB buffers (ep-a and ep-b only);
- * 	2 for one 2kB buffer (ep-a) and two 1kB ones (ep-b, ep-c).
- *
- * returns zero on success, else negative errno.  when this succeeds,
- * the contents of gadget->ep_list may have changed.
- *
- * you may only call this function when endpoints a-d are all disabled.
- * use it whenever extra hardware buffering can help performance, such
- * as before enabling "high bandwidth" interrupt endpoints that use
- * maxpacket bigger than 512 (when double buffering would otherwise
- * be unavailable).
- */
-int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode)
-{
-	int			i;
-	struct net2280		*dev;
-	int			status = 0;
-	unsigned long		flags;
-
-	if (!gadget)
-		return -ENODEV;
-	dev = container_of (gadget, struct net2280, gadget);
-
-	spin_lock_irqsave (&dev->lock, flags);
-
-	for (i = 1; i <= 4; i++)
-		if (dev->ep [i].desc) {
-			status = -EINVAL;
-			break;
-		}
-	if (mode < 0 || mode > 2)
-		status = -EINVAL;
-	if (status == 0)
-		set_fifo_mode (dev, mode);
-	spin_unlock_irqrestore (&dev->lock, flags);
-
-	if (status == 0) {
-		if (mode == 1)
-			DEBUG (dev, "fifo:  ep-a 2K, ep-b 2K\n");
-		else if (mode == 2)
-			DEBUG (dev, "fifo:  ep-a 2K, ep-b 1K, ep-c 1K\n");
-		/* else all are 1K */
-	}
-	return status;
-}
-EXPORT_SYMBOL (net2280_set_fifo_mode);
-
-/*-------------------------------------------------------------------------*/
-
-/* keeping it simple:
- * - one bus driver, initted first;
- * - one function driver, initted second
- *
- * most of the work to support multiple net2280 controllers would
- * be to associate this gadget driver (yes?) with all of them, or
- * perhaps to bind specific drivers to specific devices.
- */
-
-static struct net2280	*the_controller;
-
-static void usb_reset (struct net2280 *dev)
-{
-	u32	tmp;
-
-	/* force immediate bus disconnect, and synch through pci */
-	writel (0, &dev->usb->usbctl);
-	dev->gadget.speed = USB_SPEED_UNKNOWN;
-	(void) readl (&dev->usb->usbctl);
-
-	net2280_led_init (dev);
-
-	/* disable automatic responses, and irqs */
-	writel (0, &dev->usb->stdrsp);
-	writel (0, &dev->regs->pciirqenb0);
-	writel (0, &dev->regs->pciirqenb1);
-
-	/* clear old dma and irq state */
-	for (tmp = 0; tmp < 4; tmp++) {
-		writel ((1 << DMA_ABORT), &dev->dma [tmp].dmastat);
-		stop_dma (&dev->dma [tmp]);
-	}
-	writel (~0, &dev->regs->irqstat0),
-	writel (~(1 << SUSPEND_REQUEST_INTERRUPT), &dev->regs->irqstat1),
-
-	/* reset, and enable pci */
-	tmp = readl (&dev->regs->devinit)
-		| (1 << PCI_ENABLE)
-		| (1 << FIFO_SOFT_RESET)
-		| (1 << USB_SOFT_RESET)
-		| (1 << M8051_RESET);
-	writel (tmp, &dev->regs->devinit);
-
-	/* standard fifo and endpoint allocations */
-	set_fifo_mode (dev, (fifo_mode <= 2) ? fifo_mode : 0);
-}
-
-static void usb_reinit (struct net2280 *dev)
-{
-	u32	tmp;
-	int	init_dma;
-
-	/* use_dma changes are ignored till next device re-init */
-	init_dma = use_dma;
-
-	/* basic endpoint init */
-	for (tmp = 0; tmp < 7; tmp++) {
-		struct net2280_ep	*ep = &dev->ep [tmp];
-
-		ep->ep.name = ep_name [tmp];
-		ep->dev = dev;
-		ep->num = tmp;
-
-		if (tmp > 0 && tmp <= 4) {
-			ep->fifo_size = 1024;
-			if (init_dma)
-				ep->dma = &dev->dma [tmp - 1];
-		} else
-			ep->fifo_size = 64;
-		ep->regs = &dev->epregs [tmp];
-		ep_reset (dev->regs, ep);
-	}
-	dev->ep [0].ep.maxpacket = 64;
-	dev->ep [5].ep.maxpacket = 64;
-	dev->ep [6].ep.maxpacket = 64;
-
-	dev->gadget.ep0 = &dev->ep [0].ep;
-	dev->ep [0].stopped = 0;
-	INIT_LIST_HEAD (&dev->gadget.ep0->ep_list);
-
-	/* we want to prevent lowlevel/insecure access from the USB host,
-	 * but erratum 0119 means this enable bit is ignored
-	 */
-	for (tmp = 0; tmp < 5; tmp++)
-		writel (EP_DONTUSE, &dev->dep [tmp].dep_cfg);
-}
-
-static void ep0_start (struct net2280 *dev)
-{
-	writel (  (1 << CLEAR_EP_HIDE_STATUS_PHASE)
-		| (1 << CLEAR_NAK_OUT_PACKETS)
-		| (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE)
-		, &dev->epregs [0].ep_rsp);
-
-	/*
-	 * hardware optionally handles a bunch of standard requests
-	 * that the API hides from drivers anyway.  have it do so.
-	 * endpoint status/features are handled in software, to
-	 * help pass tests for some dubious behavior.
-	 */
-	writel (  (1 << SET_TEST_MODE)
-		| (1 << SET_ADDRESS)
-		| (1 << DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP)
-		| (1 << GET_DEVICE_STATUS)
-		| (1 << GET_INTERFACE_STATUS)
-		, &dev->usb->stdrsp);
-	writel (  (1 << USB_ROOT_PORT_WAKEUP_ENABLE)
-		| (1 << SELF_POWERED_USB_DEVICE)
-		| (1 << REMOTE_WAKEUP_SUPPORT)
-		| (1 << USB_DETECT_ENABLE)
-		| (1 << DEVICE_REMOTE_WAKEUP_ENABLE)
-		, &dev->usb->usbctl);
-
-	/* enable irqs so we can see ep0 and general operation  */
-	writel (  (1 << SETUP_PACKET_INTERRUPT_ENABLE)
-		| (1 << ENDPOINT_0_INTERRUPT_ENABLE)
-		, &dev->regs->pciirqenb0);
-	writel (  (1 << PCI_INTERRUPT_ENABLE)
-		| (1 << PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE)
-		| (1 << PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE)
-		| (1 << PCI_RETRY_ABORT_INTERRUPT_ENABLE)
-		| (1 << VBUS_INTERRUPT_ENABLE)
-		| (1 << ROOT_PORT_RESET_INTERRUPT_ENABLE)
-		, &dev->regs->pciirqenb1);
-
-	/* don't leave any writes posted */
-	(void) readl (&dev->usb->usbctl);
-}
-
-/* when a driver is successfully registered, it will receive
- * control requests including set_configuration(), which enables
- * non-control requests.  then usb traffic follows until a
- * disconnect is reported.  then a host may connect again, or
- * the driver might get unbound.
- */
-int usb_gadget_register_driver (struct usb_gadget_driver *driver)
-{
-	struct net2280		*dev = the_controller;
-	int			retval;
-	unsigned		i;
-
-	/* insist on high speed support from the driver, since
-	 * (dev->usb->xcvrdiag & FORCE_FULL_SPEED_MODE)
-	 * "must not be used in normal operation"
-	 */
-	if (!driver
-			|| driver->speed != USB_SPEED_HIGH
-			|| !driver->bind
-			|| !driver->unbind
-			|| !driver->setup)
-		return -EINVAL;
-	if (!dev)
-		return -ENODEV;
-	if (dev->driver)
-		return -EBUSY;
-
-	for (i = 0; i < 7; i++)
-		dev->ep [i].irqs = 0;
-
-	/* hook up the driver ... */
-	dev->driver = driver;
-#ifdef HAVE_DRIVER_MODEL
-	dev->gadget.dev.driver = &driver->driver;
-#endif
-	retval = driver->bind (&dev->gadget);
-	if (retval) {
-		DEBUG (dev, "bind to driver %s --> %d\n",
-				driver->driver.name, retval);
-		dev->driver = 0;
-#ifdef HAVE_DRIVER_MODEL
-		dev->gadget.dev.driver = 0;
-#endif
-		return retval;
-	}
-
-	// device_create_file (&dev->pdev->dev, &dev_attr_function);
-	// device_create_file (&dev->pdev->dev, &dev_attr_queues);
-
-	/* ... then enable host detection and ep0; and we're ready
-	 * for set_configuration as well as eventual disconnect.
-	 */
-	net2280_led_active (dev, 1);
-	ep0_start (dev);
-
-	DEBUG (dev, "%s ready, usbctl %08x stdrsp %08x\n",
-			driver->driver.name,
-			readl (&dev->usb->usbctl),
-			readl (&dev->usb->stdrsp));
-
-	/* pci writes may still be posted */
-	return 0;
-}
-EXPORT_SYMBOL (usb_gadget_register_driver);
-
-static void
-stop_activity (struct net2280 *dev, struct usb_gadget_driver *driver)
-{
-	int			i;
-
-	/* don't disconnect if it's not connected */
-	if (dev->gadget.speed == USB_SPEED_UNKNOWN)
-		driver = 0;
-
-	/* stop hardware; prevent new request submissions;
-	 * and kill any outstanding requests.
-	 */
-	usb_reset (dev);
-	for (i = 0; i < 7; i++)
-		nuke (&dev->ep [i]);
-
-	/* report disconnect; the driver is already quiesced */
-	if (driver) {
-		spin_unlock (&dev->lock);
-		driver->disconnect (&dev->gadget);
-		spin_lock (&dev->lock);
-	}
-
-	usb_reinit (dev);
-}
-
-int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
-{
-	struct net2280	*dev = the_controller;
-	unsigned long	flags;
-
-	if (!dev)
-		return -ENODEV;
-	if (!driver || driver != dev->driver)
-		return -EINVAL;
-
-	spin_lock_irqsave (&dev->lock, flags);
-	stop_activity (dev, driver);
-	spin_unlock_irqrestore (&dev->lock, flags);
-
-	driver->unbind (&dev->gadget);
-	dev->driver = 0;
-
-	net2280_led_active (dev, 0);
-	// device_remove_file (&dev->pdev->dev, &dev_attr_function);
-	// device_remove_file (&dev->pdev->dev, &dev_attr_queues);
-
-	DEBUG (dev, "unregistered driver '%s'\n", driver->driver.name);
-	return 0;
-}
-EXPORT_SYMBOL (usb_gadget_unregister_driver);
-
-
-/*-------------------------------------------------------------------------*/
-
-/* handle ep0, ep-e, ep-f with 64 byte packets: packet per irq.
- * also works for dma-capable endpoints, in pio mode or just
- * to manually advance the queue after short OUT transfers.
- */
-static void handle_ep_small (struct net2280_ep *ep)
-{
-	struct net2280_request	*req;
-	u32			t;
-	/* 0 error, 1 mid-data, 2 done */
-	int			mode = 1;
-
-	if (!list_empty (&ep->queue))
-		req = list_entry (ep->queue.next,
-			struct net2280_request, queue);
-	else
-		req = 0;
-
-	/* ack all, and handle what we care about */
-	t = readl (&ep->regs->ep_stat);
-	ep->irqs++;
-	writel (t & ~(1 << NAK_OUT_PACKETS), &ep->regs->ep_stat);
-
-	/* for ep0, monitor token irqs to catch data stage length errors
-	 * and to synchronize on status.
-	 *
-	 * also, to defer reporting of protocol stalls ... here's where
-	 * data or status first appears, handling stalls here should never
-	 * cause trouble on the host side..
-	 *
-	 * control requests could be slightly faster without token synch for
-	 * status, but status can jam up that way.
-	 */
-	if (unlikely (ep->num == 0)) {
-		if (ep->is_in) {
-			/* status; stop NAKing */
-			if (t & (1 << DATA_OUT_PING_TOKEN_INTERRUPT)) {
-				if (ep->dev->protocol_stall) {
-					ep->stopped = 1;
-					set_halt (ep);
-				}
-				mode = 2;
-			/* reply to extra IN data tokens with a zlp */
-			} else if (t & (1 << DATA_IN_TOKEN_INTERRUPT)) {
-				if (ep->dev->protocol_stall) {
-					ep->stopped = 1;
-					set_halt (ep);
-					mode = 2;
-				} else if (!req && ep->stopped)
-					write_fifo (ep, 0);
-			}
-		} else {
-			/* status; stop NAKing */
-			if (t & (1 << DATA_IN_TOKEN_INTERRUPT)) {
-				if (ep->dev->protocol_stall) {
-					ep->stopped = 1;
-					set_halt (ep);
-				}
-				mode = 2;
-			}
-		}
-	}
-
-	if (unlikely (!req))
-		return;
-
-	/* manual DMA queue advance after short OUT */
-	if (likely (ep->dma != 0)) {
-		if (t & (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)) {
-			u32	count;
-
-			/* TRANSFERRED works around OUT_DONE erratum 0112.
-			 * we expect (N <= maxpacket) bytes; host wrote M.
-			 * iff (M < N) we won't ever see a DMA interrupt.
-			 */
-			count = readl (&ep->dma->dmacount);
-			count &= DMA_BYTE_COUNT_MASK;
-			if (!req->dma_done) {
-				/* dma can finish with the FIFO non-empty,
-				 * on (M > N) errors.
-				 */
-				while (count && (t & (1 << FIFO_EMPTY)) == 0) {
-					cpu_relax ();
-					t = readl (&ep->regs->ep_stat);
-					count = readl (&ep->dma->dmacount);
-					count &= DMA_BYTE_COUNT_MASK;
-				}
-			}
-
-			/* stop DMA, leave ep NAKing */
-			writel ((1 << DMA_ABORT), &ep->dma->dmastat);
-			spin_stop_dma (ep->dma);
-
-			/* buffer might have been too small */
-			t = readl (&ep->regs->ep_avail);
-			if (t != 0)
-				DEBUG (ep->dev, "%s dma, discard %d len %d\n",
-						ep->ep.name, t, count);
-			dma_done (ep, req, count, t ? -EOVERFLOW : 0);
-
-			/* also flush to prevent erratum 0106 trouble */
-			if (t || ep->dev->chiprev == 0x0100)
-				out_flush (ep);
-
-			/* restart dma (still NAKing OUT!) if needed */
-			if (!list_empty (&ep->queue))
-				restart_dma (ep);
-		} else
-			DEBUG (ep->dev, "%s dma ep_stat %08x ??\n",
-					ep->ep.name, t);
-		return;
-
-	/* data packet(s) received (in the fifo, OUT) */
-	} else if (t & (1 << DATA_PACKET_RECEIVED_INTERRUPT)) {
-		if (read_fifo (ep, req) && ep->num != 0)
-			mode = 2;
-
-	/* data packet(s) transmitted (IN) */
-	} else if (t & (1 << DATA_PACKET_TRANSMITTED_INTERRUPT)) {
-		unsigned	len;
-
-		len = req->req.length - req->req.actual;
-		len = min (ep->ep.maxpacket, len);
-		req->req.actual += len;
-
-		/* if we wrote it all, we're usually done */
-		if (req->req.actual == req->req.length) {
-			if (ep->num == 0) {
-				/* wait for control status */
-				if (mode != 2)
-					req = 0;
-			} else if (!req->req.zero || len != ep->ep.maxpacket)
-				mode = 2;
-		}
-
-	/* there was nothing to do ...  */
-	} else if (mode == 1)
-		return;
-
-	/* done */
-	if (mode == 2) {
-		/* stream endpoints often resubmit/unlink in completion */
-		done (ep, req, 0);
-
-		/* maybe advance queue to next request */
-		if (ep->num == 0) {
-			if (!ep->stopped)
-				allow_status (ep);
-			req = 0;
-		} else {
-			if (!list_empty (&ep->queue) && !ep->stopped)
-				req = list_entry (ep->queue.next,
-					struct net2280_request, queue);
-			else
-				req = 0;
-			if (req && !ep->is_in)
-				stop_out_naking (ep);
-		}
-	}
-
-	/* is there a buffer for the next packet?
-	 * for best streaming performance, make sure there is one.
-	 */
-	if (req && !ep->stopped) {
-
-		/* load IN fifo with next packet (may be zlp) */
-		if (t & (1 << DATA_PACKET_TRANSMITTED_INTERRUPT))
-			write_fifo (ep, &req->req);
-	}
-}
-
-static struct net2280_ep *
-get_ep_by_addr (struct net2280 *dev, u16 wIndex)
-{
-	struct net2280_ep	*ep;
-
-	if ((wIndex & USB_ENDPOINT_NUMBER_MASK) == 0)
-		return &dev->ep [0];
-	list_for_each_entry (ep, &dev->gadget.ep_list, ep.ep_list) {
-		u8	bEndpointAddress;
-
-		if (!ep->desc)
-			continue;
-		bEndpointAddress = ep->desc->bEndpointAddress;
-		if ((wIndex ^ bEndpointAddress) & USB_DIR_IN)
-			continue;
-		if ((wIndex & 0x0f) == (bEndpointAddress & 0x0f))
-			return ep;
-	}
-	return 0;
-}
-
-static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
-{
-	struct net2280_ep	*ep;
-	u32			num, scratch;
-
-	/* most of these don't need individual acks */
-	stat &= ~(1 << INTA_ASSERTED);
-	if (!stat)
-		return;
-	// DEBUG (dev, "irqstat0 %04x\n", stat);
-
-	/* starting a control request? */
-	if (unlikely (stat & (1 << SETUP_PACKET_INTERRUPT))) {
-		union {
-			u32			raw [2];
-			struct usb_ctrlrequest	r;
-		} u;
-		int				tmp = 0;
-		struct net2280_request		*req;
-
-		if (dev->gadget.speed == USB_SPEED_UNKNOWN) {
-			if (readl (&dev->usb->usbstat) & (1 << HIGH_SPEED))
-				dev->gadget.speed = USB_SPEED_HIGH;
-			else
-				dev->gadget.speed = USB_SPEED_FULL;
-			net2280_led_speed (dev, dev->gadget.speed);
-			DEBUG (dev, "%s speed\n",
-				(dev->gadget.speed == USB_SPEED_HIGH)
-					? "high" : "full");
-		}
-
-		ep = &dev->ep [0];
-		ep->irqs++;
-
-		/* make sure any leftover request state is cleared */
-		stat &= ~(1 << ENDPOINT_0_INTERRUPT);
-		while (!list_empty (&ep->queue)) {
-			req = list_entry (ep->queue.next,
-					struct net2280_request, queue);
-			done (ep, req, (req->req.actual == req->req.length)
-						? 0 : -EPROTO);
-		}
-		ep->stopped = 0;
-		dev->protocol_stall = 0;
-		writel (  (1 << TIMEOUT)
-			| (1 << USB_STALL_SENT)
-			| (1 << USB_IN_NAK_SENT)
-			| (1 << USB_IN_ACK_RCVD)
-			| (1 << USB_OUT_PING_NAK_SENT)
-			| (1 << USB_OUT_ACK_SENT)
-			| (1 << FIFO_OVERFLOW)
-			| (1 << FIFO_UNDERFLOW)
-			| (1 << SHORT_PACKET_OUT_DONE_INTERRUPT)
-			| (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)
-			| (1 << DATA_PACKET_RECEIVED_INTERRUPT)
-			| (1 << DATA_PACKET_TRANSMITTED_INTERRUPT)
-			| (1 << DATA_OUT_PING_TOKEN_INTERRUPT)
-			| (1 << DATA_IN_TOKEN_INTERRUPT)
-			, &ep->regs->ep_stat);
-		u.raw [0] = readl (&dev->usb->setup0123);
-		u.raw [1] = readl (&dev->usb->setup4567);
-		
-		cpu_to_le32s (&u.raw [0]);
-		cpu_to_le32s (&u.raw [1]);
-
-		le16_to_cpus (&u.r.wValue);
-		le16_to_cpus (&u.r.wIndex);
-		le16_to_cpus (&u.r.wLength);
-
-		/* ack the irq */
-		writel (1 << SETUP_PACKET_INTERRUPT, &dev->regs->irqstat0);
-		stat ^= (1 << SETUP_PACKET_INTERRUPT);
-
-		ep->is_in = (u.r.bRequestType & USB_DIR_IN) != 0;
-		if (ep->is_in)
-			scratch = (1 << DATA_PACKET_TRANSMITTED_INTERRUPT)
-				| (1 << DATA_OUT_PING_TOKEN_INTERRUPT)
-				| (1 << DATA_IN_TOKEN_INTERRUPT);
-		else
-			scratch = (1 << DATA_PACKET_RECEIVED_INTERRUPT)
-				| (1 << DATA_OUT_PING_TOKEN_INTERRUPT)
-				| (1 << DATA_IN_TOKEN_INTERRUPT);
-		writel (scratch, &dev->epregs [0].ep_irqenb);
-
-		/* we made the hardware handle most lowlevel requests;
-		 * everything else goes uplevel to the gadget code.
-		 */
-		switch (u.r.bRequest) {
-		case USB_REQ_GET_STATUS: {
-			struct net2280_ep	*e;
-			u16			status;
-
-			/* hw handles device and interface status */
-			if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT))
-				goto delegate;
-			if ((e = get_ep_by_addr (dev, u.r.wIndex)) == 0
-					|| u.r.wLength > 2)
-				goto do_stall;
-
-			if (readl (&e->regs->ep_rsp)
-					& (1 << SET_ENDPOINT_HALT))
-				status = __constant_cpu_to_le16 (1);
-			else
-				status = __constant_cpu_to_le16 (0);
-
-			/* don't bother with a request object! */
-			writel (0, &dev->epregs [0].ep_irqenb);
-			set_fifo_bytecount (ep, u.r.wLength);
-			writel (status, &dev->epregs [0].ep_data);
-			allow_status (ep);
-			VDEBUG (dev, "%s stat %02x\n", ep->ep.name, status);
-			goto next_endpoints;
-			}
-			break;
-		case USB_REQ_CLEAR_FEATURE: {
-			struct net2280_ep	*e;
-
-			/* hw handles device features */
-			if (u.r.bRequestType != USB_RECIP_ENDPOINT)
-				goto delegate;
-			if (u.r.wValue != 0 /* HALT feature */
-					|| u.r.wLength != 0)
-				goto do_stall;
-			if ((e = get_ep_by_addr (dev, u.r.wIndex)) == 0)
-				goto do_stall;
-			clear_halt (e);
-			allow_status (ep);
-			VDEBUG (dev, "%s clear halt\n", ep->ep.name);
-			goto next_endpoints;
-			}
-			break;
-		case USB_REQ_SET_FEATURE: {
-			struct net2280_ep	*e;
-
-			/* hw handles device features */
-			if (u.r.bRequestType != USB_RECIP_ENDPOINT)
-				goto delegate;
-			if (u.r.wValue != 0 /* HALT feature */
-					|| u.r.wLength != 0)
-				goto do_stall;
-			if ((e = get_ep_by_addr (dev, u.r.wIndex)) == 0)
-				goto do_stall;
-			set_halt (e);
-			allow_status (ep);
-			VDEBUG (dev, "%s set halt\n", ep->ep.name);
-			goto next_endpoints;
-			}
-			break;
-		default:
-delegate:
-			VDEBUG (dev, "setup %02x.%02x v%04x i%04x "
-				"ep_cfg %08x\n",
-				u.r.bRequestType, u.r.bRequest,
-				u.r.wValue, u.r.wIndex,
-				readl (&ep->regs->ep_cfg));
-			spin_unlock (&dev->lock);
-			tmp = dev->driver->setup (&dev->gadget, &u.r);
-			spin_lock (&dev->lock);
-		}
-
-		/* stall ep0 on error */
-		if (tmp < 0) {
-do_stall:
-			VDEBUG (dev, "req %02x.%02x protocol STALL; stat %d\n",
-					u.r.bRequestType, u.r.bRequest, tmp);
-			dev->protocol_stall = 1;
-		}
-
-		/* some in/out token irq should follow; maybe stall then.
-		 * driver must queue a request (even zlp) or halt ep0
-		 * before the host times out.
-		 */
-	}
-
-next_endpoints:
-	/* endpoint data irq ? */
-	scratch = stat & 0x7f;
-	stat &= ~0x7f;
-	for (num = 0; scratch; num++) {
-		u32		t;
-
-		/* do this endpoint's FIFO and queue need tending? */
-		t = 1 << num;
-		if ((scratch & t) == 0)
-			continue;
-		scratch ^= t;
-
-		ep = &dev->ep [num];
-		handle_ep_small (ep);
-	}
-
-	if (stat)
-		DEBUG (dev, "unhandled irqstat0 %08x\n", stat);
-}
-
-#define DMA_INTERRUPTS ( \
-		  (1 << DMA_D_INTERRUPT) \
-		| (1 << DMA_C_INTERRUPT) \
-		| (1 << DMA_B_INTERRUPT) \
-		| (1 << DMA_A_INTERRUPT))
-#define	PCI_ERROR_INTERRUPTS ( \
-		  (1 << PCI_MASTER_ABORT_RECEIVED_INTERRUPT) \
-		| (1 << PCI_TARGET_ABORT_RECEIVED_INTERRUPT) \
-		| (1 << PCI_RETRY_ABORT_INTERRUPT))
-
-static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
-{
-	struct net2280_ep	*ep;
-	u32			tmp, num, scratch;
-
-	/* after disconnect there's nothing else to do! */
-	tmp = (1 << VBUS_INTERRUPT) | (1 << ROOT_PORT_RESET_INTERRUPT);
-	if (stat & tmp) {
-		writel (tmp, &dev->regs->irqstat1);
-		if (((stat & (1 << ROOT_PORT_RESET_INTERRUPT)) != 0
-			|| (readl (&dev->usb->usbctl) & (1 << VBUS_PIN)) == 0
-			) && dev->gadget.speed != USB_SPEED_UNKNOWN) {
-			DEBUG (dev, "disconnect %s\n",
-					dev->driver->driver.name);
-			stop_activity (dev, dev->driver);
-			ep0_start (dev);
-			return;
-		}
-		stat &= ~tmp;
-
-		/* vBUS can bounce ... one of many reasons to ignore the
-		 * notion of hotplug events on bus connect/disconnect!
-		 */
-		if (!stat)
-			return;
-	}
-
-	/* NOTE: we don't actually suspend the hardware; that starts to
-	 * interact with PCI power management, and needs something like a
-	 * controller->suspend() call to clear SUSPEND_REQUEST_INTERRUPT.
-	 * we shouldn't see resume interrupts.
-	 * for rev 0100, this also avoids erratum 0102.
-	 */
-	tmp = (1 << SUSPEND_REQUEST_CHANGE_INTERRUPT);
-	if (stat & tmp) {
-		if (dev->driver->suspend)
-			dev->driver->suspend (&dev->gadget);
-		stat &= ~tmp;
-	}
-	stat &= ~(1 << SUSPEND_REQUEST_INTERRUPT);
-
-	/* clear any other status/irqs */
-	if (stat)
-		writel (stat, &dev->regs->irqstat1);
-
-	/* some status we can just ignore */
-	stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
-			| (1 << RESUME_INTERRUPT)
-			| (1 << SOF_INTERRUPT));
-	if (!stat)
-		return;
-	// DEBUG (dev, "irqstat1 %08x\n", stat);
-
-	/* DMA status, for ep-{a,b,c,d} */
-	scratch = stat & DMA_INTERRUPTS;
-	stat &= ~DMA_INTERRUPTS;
-	scratch >>= 9;
-	for (num = 0; scratch; num++) {
-		struct net2280_dma_regs	*dma;
-
-		tmp = 1 << num;
-		if ((tmp & scratch) == 0)
-			continue;
-		scratch ^= tmp;
-
-		ep = &dev->ep [num + 1];
-		dma = ep->dma;
-
-		if (!dma)
-			continue;
-
-		/* clear ep's dma status */
-		tmp = readl (&dma->dmastat);
-		writel (tmp, &dma->dmastat);
-
-#ifdef USE_DMA_CHAINING
-		/* chaining should stop only on error (which?)
-		 * or (stat0 codepath) short OUT transfer.
-		 */
-#else
-		if ((tmp & (1 << DMA_TRANSACTION_DONE_INTERRUPT)) == 0) {
-			DEBUG (ep->dev, "%s no xact done? %08x\n",
-				ep->ep.name, tmp);
-			continue;
-		}
-		stop_dma (ep->dma);
-#endif
-
-		/* OUT transfers terminate when the data from the
-		 * host is in our memory.  Process whatever's done.
-		 * On this path, we know transfer's last packet wasn't
-		 * less than req->length. NAK_OUT_PACKETS may be set,
-		 * or the FIFO may already be holding new packets.
-		 *
-		 * IN transfers can linger in the FIFO for a very
-		 * long time ... we ignore that for now, accounting
-		 * precisely (like PIO does) needs per-packet irqs
-		 */
-		scan_dma_completions (ep);
-
-		/* disable dma on inactive queues; else maybe restart */
-		if (list_empty (&ep->queue)) {
-#ifdef USE_DMA_CHAINING
-			stop_dma (ep->dma);
-#endif
-		} else {
-			tmp = readl (&dma->dmactl);
-			if ((tmp & (1 << DMA_SCATTER_GATHER_ENABLE)) == 0
-					|| (tmp & (1 << DMA_ENABLE)) == 0)
-				restart_dma (ep);
-#ifdef USE_DMA_CHAINING
-			else if (ep->desc->bEndpointAddress & USB_DIR_IN) {
-				struct net2280_request	*req;
-				u32			dmacount;
-
-				/* the descriptor at the head of the chain
-				 * may still have VALID_BIT clear; that's
-				 * used to trigger changing DMA_FIFO_VALIDATE
-				 * (affects automagic zlp writes).
-				 */
-				req = list_entry (ep->queue.next,
-						struct net2280_request, queue);
-				dmacount = req->td->dmacount;
-				dmacount &= __constant_cpu_to_le32 (
-						(1 << VALID_BIT)
-						| DMA_BYTE_COUNT_MASK);
-				if (dmacount && (dmacount & valid_bit) == 0) {
-					stop_dma (ep->dma);
-					restart_dma (ep);
-				}
-			}
-#endif
-		}
-		ep->irqs++;
-	}
-
-	/* NOTE:  there are other PCI errors we might usefully notice.
-	 * if they appear very often, here's where to try recovering.
-	 */
-	if (stat & PCI_ERROR_INTERRUPTS) {
-		ERROR (dev, "pci dma error; stat %08x\n", stat);
-		stat &= ~PCI_ERROR_INTERRUPTS;
-		/* these are fatal errors, but "maybe" they won't
-		 * happen again ...
-		 */
-		stop_activity (dev, dev->driver);
-		ep0_start (dev);
-		stat = 0;
-	}
-
-	if (stat)
-		DEBUG (dev, "unhandled irqstat1 %08x\n", stat);
-}
-
-static irqreturn_t net2280_irq (int irq, void *_dev, struct pt_regs * r)
-{
-	struct net2280		*dev = _dev;
-
-	spin_lock (&dev->lock);
-
-	/* handle disconnect, dma, and more */
-	handle_stat1_irqs (dev, readl (&dev->regs->irqstat1));
-
-	/* control requests and PIO */
-	handle_stat0_irqs (dev, readl (&dev->regs->irqstat0));
-
-	spin_unlock (&dev->lock);
-
-	return IRQ_HANDLED;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* tear down the binding between this driver and the pci device */
-
-static void net2280_remove (struct pci_dev *pdev)
-{
-	struct net2280		*dev = pci_get_drvdata (pdev);
-
-	/* start with the driver above us */
-	if (dev->driver) {
-		/* should have been done already by driver model core */
-		WARN (dev, "pci remove, driver '%s' is still registered\n",
-				dev->driver->driver.name);
-		usb_gadget_unregister_driver (dev->driver);
-	}
-
-	/* then clean up the resources we allocated during probe() */
-	net2280_led_shutdown (dev);
-	if (dev->requests) {
-		int		i;
-		for (i = 1; i < 5; i++) {
-			if (!dev->ep [i].dummy)
-				continue;
-			pci_pool_free (dev->requests, dev->ep [i].dummy,
-					dev->ep [i].td_dma);
-		}
-		pci_pool_destroy (dev->requests);
-	}
-	if (dev->got_irq)
-		free_irq (pdev->irq, dev);
-	if (dev->regs)
-		iounmap (dev->regs);
-	if (dev->region)
-		release_mem_region (pci_resource_start (pdev, 0),
-				pci_resource_len (pdev, 0));
-	if (dev->enabled)
-		pci_disable_device (pdev);
-	// device_remove_file (&pdev->dev, &dev_attr_registers);
-	pci_set_drvdata (pdev, 0);
-
-	INFO (dev, "unbind from pci %s\n", pdev->slot_name);
-
-	kfree (dev);
-	the_controller = 0;
-}
-
-/* wrap this driver around the specified device, but
- * don't respond over USB until a gadget driver binds to us.
- */
-
-static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
-{
-	struct net2280		*dev;
-	unsigned long		resource, len;
-	void			*base = 0;
-	int			retval, i;
-	char			buf [8], *bufp;
-
-	/* if you want to support more than one controller in a system,
-	 * usb_gadget_driver_{register,unregister}() must change.
-	 */
-	if (the_controller) {
-		WARN (the_controller, "ignoring %s\n", pdev->slot_name);
-		return -EBUSY;
-	}
-
-	/* alloc, and start init */
-	dev = kmalloc (sizeof *dev, SLAB_KERNEL);
-	if (dev == NULL){
-		retval = -ENOMEM;
-		goto done;
-	}
-
-	memset (dev, 0, sizeof *dev);
-	spin_lock_init (&dev->lock);
-	dev->pdev = pdev;
-	dev->gadget.ops = &net2280_ops;
-
-#ifdef HAVE_DRIVER_MODEL
-	strcpy (dev->gadget.dev.bus_id, pdev->slot_name);
-	strcpy (dev->gadget.dev.name, pdev->dev.name);
-	dev->gadget.dev.parent = &pdev->dev;
-	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
-#else
-	dev->gadget.dev.bus_id = pdev->slot_name;
-#endif
-	dev->gadget.name = driver_name;
-
-	/* now all the pci goodies ... */
-	if (pci_enable_device (pdev) < 0) {
-   	        retval = -ENODEV;
-		goto done;
-	}
-	dev->enabled = 1;
-
-	/* BAR 0 holds all the registers
-	 * BAR 1 is 8051 memory; unused here (note erratum 0103)
-	 * BAR 2 is fifo memory; unused here
-	 */
-	resource = pci_resource_start (pdev, 0);
-	len = pci_resource_len (pdev, 0);
-	if (!request_mem_region (resource, len, driver_name)) {
-		DEBUG (dev, "controller already in use\n");
-		retval = -EBUSY;
-		goto done;
-	}
-	dev->region = 1;
-
-	base = ioremap_nocache (resource, len);
-	if (base == NULL) {
-		DEBUG (dev, "can't map memory\n");
-		retval = -EFAULT;
-		goto done;
-	}
-	dev->regs = (struct net2280_regs *) base;
-	dev->usb = (struct net2280_usb_regs *) (base + 0x0080);
-	dev->pci = (struct net2280_pci_regs *) (base + 0x0100);
-	dev->dma = (struct net2280_dma_regs *) (base + 0x0180);
-	dev->dep = (struct net2280_dep_regs *) (base + 0x0200);
-	dev->epregs = (struct net2280_ep_regs *) (base + 0x0300);
-
-	/* put into initial config, link up all endpoints */
-	usb_reset (dev);
-	usb_reinit (dev);
-
-	/* irq setup after old hardware is cleaned up */
-	if (!pdev->irq) {
-		ERROR (dev, "No IRQ.  Check PCI setup!\n");
-		retval = -ENODEV;
-		goto done;
-	}
-#ifndef __sparc__
-	snprintf (buf, sizeof buf, "%d", pdev->irq);
-	bufp = buf;
-#else
-	bufp = __irq_itoa(pdev->irq);
-#endif
-	if (request_irq (pdev->irq, net2280_irq, SA_SHIRQ, driver_name, dev)
-			!= 0) {
-		ERROR (dev, "request interrupt %s failed\n", bufp);
-		retval = -EBUSY;
-		goto done;
-	}
-	dev->got_irq = 1;
-
-	/* DMA setup */
-	dev->requests = pci_pool_create ("requests", pdev,
-		sizeof (struct net2280_dma),
-		0 /* no alignment requirements */,
-		0 /* or page-crossing issues */,
-		SLAB_KERNEL /* 2.4 only */ );
-	if (!dev->requests) {
-		DEBUG (dev, "can't get request pool\n");
-		retval = -ENOMEM;
-		goto done;
-	}
-	for (i = 1; i < 5; i++) {
-		struct net2280_dma	*td;
-
-		td = pci_pool_alloc (dev->requests, GFP_KERNEL,
-				&dev->ep [i].td_dma);
-		if (!td) {
-			DEBUG (dev, "can't get dummy %d\n", i);
-			retval = -ENOMEM;
-			goto done;
-		}
-		td->dmacount = 0;	/* not VALID */
-		td->dmaaddr = __constant_cpu_to_le32 (DMA_ADDR_INVALID);
-		dev->ep [i].dummy = td;
-	}
-
-	/* enable lower-overhead pci memory bursts during DMA */
-	writel ((1 << PCI_RETRY_ABORT_ENABLE)
-			| (1 << DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE)
-			| (1 << DMA_READ_MULTIPLE_ENABLE)
-			| (1 << DMA_READ_LINE_ENABLE)
-			, &dev->pci->pcimstctl);
-	/* erratum 0115 shouldn't appear: Linux inits PCI_LATENCY_TIMER */
-	pci_set_master (pdev);
-#ifdef	HAVE_PCI_SET_MWI
-	pci_set_mwi (pdev);
-#endif
-
-	/* ... also flushes any posted pci writes */
-	dev->chiprev = get_idx_reg (dev->regs, REG_CHIPREV) & 0xffff;
-
-	/* done */
-	pci_set_drvdata (pdev, dev);
-	INFO (dev, "%s\n", driver_desc);
-	INFO (dev, "irq %s, pci mem %p, chip rev %04x\n",
-			bufp, base, dev->chiprev);
-	bufp = DRIVER_VERSION
-#ifndef USE_DMA_CHAINING
-		" (no dma chain)"
-#endif
-#ifdef NET2280_DMA_OUT_WORKAROUND
-		" (no dma out)"
-#endif
-		;
-	INFO (dev, "version: %s\n", bufp);
-	the_controller = dev;
-
-	// device_create_file (&pdev->dev, &dev_attr_registers);
-
-	return 0;
-
-done:
-	if (dev)
-		net2280_remove (pdev);
-	return retval;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static struct pci_device_id pci_ids [] = { {
-	.class = 	((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
-	.class_mask = 	~0,
-	.vendor =	0x17cc,
-	.device =	0x2280,
-	.subvendor =	PCI_ANY_ID,
-	.subdevice =	PCI_ANY_ID,
-
-}, { /* end: all zeroes */ }
-};
-MODULE_DEVICE_TABLE (pci, pci_ids);
-
-/* pci driver glue; this is a "new style" PCI driver module */
-static struct pci_driver net2280_pci_driver = {
-	.name =		(char *) driver_name,
-	.id_table =	pci_ids,
-
-	.probe =	net2280_probe,
-	.remove =	net2280_remove,
-
-};
-
-MODULE_DESCRIPTION (DRIVER_DESC);
-MODULE_AUTHOR ("David Brownell");
-MODULE_LICENSE ("GPL");
-
-static int __init init (void)
-{
-	return pci_module_init (&net2280_pci_driver);
-}
-module_init (init);
-
-static void __exit cleanup (void)
-{
-	pci_unregister_driver (&net2280_pci_driver);
-}
-module_exit (cleanup);
diff -ruN linux-2.4.20-WRTup/drivers/usb/gadget/net2280.h linux-2.4.20-WRTstp/drivers/usb/gadget/net2280.h
--- linux-2.4.20-WRTup/drivers/usb/gadget/net2280.h	2006-06-12 18:04:59.000000000 -0700
+++ linux-2.4.20-WRTstp/drivers/usb/gadget/net2280.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,752 +0,0 @@
-/*
- * NetChip 2280 high/full speed USB device controller.
- * Unlike many such controllers, this one talks PCI.
- */
-
-/*
- * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com)
- * Copyright (C) 2003 David Brownell
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*-------------------------------------------------------------------------*/
-
-/* NET2280 MEMORY MAPPED REGISTERS
- *
- * The register layout came from the chip documentation, and the bit
- * number definitions were extracted from chip specification.
- *
- * Use the shift operator ('<<') to build bit masks, with readl/writel
- * to access the registers through PCI.
- */
-
-/* main registers, BAR0 + 0x0000 */
-struct net2280_regs {
-	// offset 0x0000
-	u32		devinit;
-#define     LOCAL_CLOCK_FREQUENCY                               8
-#define     FORCE_PCI_RESET                                     7
-#define     PCI_ID                                              6
-#define     PCI_ENABLE                                          5
-#define     FIFO_SOFT_RESET                                     4
-#define     CFG_SOFT_RESET                                      3
-#define     PCI_SOFT_RESET                                      2
-#define     USB_SOFT_RESET                                      1
-#define     M8051_RESET                                         0
-	u32		eectl;
-#define     EEPROM_ADDRESS_WIDTH                                23
-#define     EEPROM_CHIP_SELECT_ACTIVE                           22
-#define     EEPROM_PRESENT                                      21
-#define     EEPROM_VALID                                        20
-#define     EEPROM_BUSY                                         19
-#define     EEPROM_CHIP_SELECT_ENABLE                           18
-#define     EEPROM_BYTE_READ_START                              17
-#define     EEPROM_BYTE_WRITE_START                             16
-#define     EEPROM_READ_DATA                                    8
-#define     EEPROM_WRITE_DATA                                   0
-	u32		eeclkfreq;
-	u32		_unused0;
-	// offset 0x0010
-
-	u32		pciirqenb0;		/* interrupt PCI master ... */
-#define     SETUP_PACKET_INTERRUPT_ENABLE                       7
-#define     ENDPOINT_F_INTERRUPT_ENABLE                         6
-#define     ENDPOINT_E_INTERRUPT_ENABLE                         5
-#define     ENDPOINT_D_INTERRUPT_ENABLE                         4
-#define     ENDPOINT_C_INTERRUPT_ENABLE                         3
-#define     ENDPOINT_B_INTERRUPT_ENABLE                         2
-#define     ENDPOINT_A_INTERRUPT_ENABLE                         1
-#define     ENDPOINT_0_INTERRUPT_ENABLE                         0
-	u32		pciirqenb1;
-#define     PCI_INTERRUPT_ENABLE                                31
-#define     POWER_STATE_CHANGE_INTERRUPT_ENABLE                 27
-#define     PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE                26
-#define     PCI_PARITY_ERROR_INTERRUPT_ENABLE                   25
-#define     PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE          20
-#define     PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE          19
-#define     PCI_TARGET_ABORT_ASSERTED_INTERRUPT_ENABLE          18
-#define     PCI_RETRY_ABORT_INTERRUPT_ENABLE                    17
-#define     PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE              16
-#define     GPIO_INTERRUPT_ENABLE                               13
-#define     DMA_D_INTERRUPT_ENABLE                              12
-#define     DMA_C_INTERRUPT_ENABLE                              11
-#define     DMA_B_INTERRUPT_ENABLE                              10
-#define     DMA_A_INTERRUPT_ENABLE                              9
-#define     EEPROM_DONE_INTERRUPT_ENABLE                        8
-#define     VBUS_INTERRUPT_ENABLE                               7
-#define     CONTROL_STATUS_INTERRUPT_ENABLE                     6
-#define     ROOT_PORT_RESET_INTERRUPT_ENABLE                    4
-#define     SUSPEND_REQUEST_INTERRUPT_ENABLE                    3
-#define     SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE             2
-#define     RESUME_INTERRUPT_ENABLE                             1
-#define     SOF_INTERRUPT_ENABLE                                0
-	u32		cpu_irqenb0;		/* ... or onboard 8051 */
-#define     SETUP_PACKET_INTERRUPT_ENABLE                       7
-#define     ENDPOINT_F_INTERRUPT_ENABLE                         6
-#define     ENDPOINT_E_INTERRUPT_ENABLE                         5
-#define     ENDPOINT_D_INTERRUPT_ENABLE                         4
-#define     ENDPOINT_C_INTERRUPT_ENABLE                         3
-#define     ENDPOINT_B_INTERRUPT_ENABLE                         2
-#define     ENDPOINT_A_INTERRUPT_ENABLE                         1
-#define     ENDPOINT_0_INTERRUPT_ENABLE                         0
-	u32		cpu_irqenb1;
-#define     CPU_INTERRUPT_ENABLE                                31
-#define     POWER_STATE_CHANGE_INTERRUPT_ENABLE                 27
-#define     PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE                26
-#define     PCI_PARITY_ERROR_INTERRUPT_ENABLE                   25
-#define     PCI_INTA_INTERRUPT_ENABLE                           24
-#define     PCI_PME_INTERRUPT_ENABLE                            23
-#define     PCI_SERR_INTERRUPT_ENABLE                           22
-#define     PCI_PERR_INTERRUPT_ENABLE                           21
-#define     PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE          20
-#define     PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE          19
-#define     PCI_RETRY_ABORT_INTERRUPT_ENABLE                    17
-#define     PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE              16
-#define     GPIO_INTERRUPT_ENABLE                               13
-#define     DMA_D_INTERRUPT_ENABLE                              12
-#define     DMA_C_INTERRUPT_ENABLE                              11
-#define     DMA_B_INTERRUPT_ENABLE                              10
-#define     DMA_A_INTERRUPT_ENABLE                              9
-#define     EEPROM_DONE_INTERRUPT_ENABLE                        8
-#define     VBUS_INTERRUPT_ENABLE                               7
-#define     CONTROL_STATUS_INTERRUPT_ENABLE                     6
-#define     ROOT_PORT_RESET_INTERRUPT_ENABLE                    4
-#define     SUSPEND_REQUEST_INTERRUPT_ENABLE                    3
-#define     SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE             2
-#define     RESUME_INTERRUPT_ENABLE                             1
-#define     SOF_INTERRUPT_ENABLE                                0
-
-	// offset 0x0020
-	u32		_unused1;
-	u32		usbirqenb1;
-#define     USB_INTERRUPT_ENABLE                                31
-#define     POWER_STATE_CHANGE_INTERRUPT_ENABLE                 27
-#define     PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE                26
-#define     PCI_PARITY_ERROR_INTERRUPT_ENABLE                   25
-#define     PCI_INTA_INTERRUPT_ENABLE                           24
-#define     PCI_PME_INTERRUPT_ENABLE                            23
-#define     PCI_SERR_INTERRUPT_ENABLE                           22
-#define     PCI_PERR_INTERRUPT_ENABLE                           21
-#define     PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE          20
-#define     PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE          19
-#define     PCI_RETRY_ABORT_INTERRUPT_ENABLE                    17
-#define     PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE              16
-#define     GPIO_INTERRUPT_ENABLE                               13
-#define     DMA_D_INTERRUPT_ENABLE                              12
-#define     DMA_C_INTERRUPT_ENABLE                              11
-#define     DMA_B_INTERRUPT_ENABLE                              10
-#define     DMA_A_INTERRUPT_ENABLE                              9
-#define     EEPROM_DONE_INTERRUPT_ENABLE                        8
-#define     VBUS_INTERRUPT_ENABLE                               7
-#define     CONTROL_STATUS_INTERRUPT_ENABLE                     6
-#define     ROOT_PORT_RESET_INTERRUPT_ENABLE                    4
-#define     SUSPEND_REQUEST_INTERRUPT_ENABLE                    3
-#define     SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE             2
-#define     RESUME_INTERRUPT_ENABLE                             1
-#define     SOF_INTERRUPT_ENABLE                                0
-	u32		irqstat0;
-#define     INTA_ASSERTED                                       12
-#define     SETUP_PACKET_INTERRUPT                              7
-#define     ENDPOINT_F_INTERRUPT                                6
-#define     ENDPOINT_E_INTERRUPT                                5
-#define     ENDPOINT_D_INTERRUPT                                4
-#define     ENDPOINT_C_INTERRUPT                                3
-#define     ENDPOINT_B_INTERRUPT                                2
-#define     ENDPOINT_A_INTERRUPT                                1
-#define     ENDPOINT_0_INTERRUPT                                0
-	u32		irqstat1;
-#define     POWER_STATE_CHANGE_INTERRUPT                        27
-#define     PCI_ARBITER_TIMEOUT_INTERRUPT                       26
-#define     PCI_PARITY_ERROR_INTERRUPT                          25
-#define     PCI_INTA_INTERRUPT                                  24
-#define     PCI_PME_INTERRUPT                                   23
-#define     PCI_SERR_INTERRUPT                                  22
-#define     PCI_PERR_INTERRUPT                                  21
-#define     PCI_MASTER_ABORT_RECEIVED_INTERRUPT                 20
-#define     PCI_TARGET_ABORT_RECEIVED_INTERRUPT                 19
-#define     PCI_RETRY_ABORT_INTERRUPT                           17
-#define     PCI_MASTER_CYCLE_DONE_INTERRUPT                     16
-#define     GPIO_INTERRUPT                                      13
-#define     DMA_D_INTERRUPT                                     12
-#define     DMA_C_INTERRUPT                                     11
-#define     DMA_B_INTERRUPT                                     10
-#define     DMA_A_INTERRUPT                                     9
-#define     EEPROM_DONE_INTERRUPT                               8
-#define     VBUS_INTERRUPT                                      7
-#define     CONTROL_STATUS_INTERRUPT                            6
-#define     ROOT_PORT_RESET_INTERRUPT                           4
-#define     SUSPEND_REQUEST_INTERRUPT                           3
-#define     SUSPEND_REQUEST_CHANGE_INTERRUPT                    2
-#define     RESUME_INTERRUPT                                    1
-#define     SOF_INTERRUPT                                       0
-	// offset 0x0030
-	u32		idxaddr;
-	u32		idxdata;
-	u32		fifoctl;
-#define     PCI_BASE2_RANGE                                     16
-#define     IGNORE_FIFO_AVAILABILITY                            3
-#define     PCI_BASE2_SELECT                                    2
-#define     FIFO_CONFIGURATION_SELECT                           0
-	u32		_unused2;
-	// offset 0x0040
-	u32		memaddr;
-#define     START                                               28
-#define     DIRECTION                                           27
-#define     FIFO_DIAGNOSTIC_SELECT                              24
-#define     MEMORY_ADDRESS                                      0
-	u32		memdata0;
-	u32		memdata1;
-	u32		_unused3;
-	// offset 0x0050
-	u32		gpioctl;
-#define     GPIO3_LED_SELECT                                    12
-#define     GPIO3_INTERRUPT_ENABLE                              11
-#define     GPIO2_INTERRUPT_ENABLE                              10
-#define     GPIO1_INTERRUPT_ENABLE                              9
-#define     GPIO0_INTERRUPT_ENABLE                              8
-#define     GPIO3_OUTPUT_ENABLE                                 7
-#define     GPIO2_OUTPUT_ENABLE                                 6
-#define     GPIO1_OUTPUT_ENABLE                                 5
-#define     GPIO0_OUTPUT_ENABLE                                 4
-#define     GPIO3_DATA                                          3
-#define     GPIO2_DATA                                          2
-#define     GPIO1_DATA                                          1
-#define     GPIO0_DATA                                          0
-	u32		gpiostat;
-#define     GPIO3_INTERRUPT                                     3
-#define     GPIO2_INTERRUPT                                     2
-#define     GPIO1_INTERRUPT                                     1
-#define     GPIO0_INTERRUPT                                     0
-} __attribute__ ((packed));
-
-/* usb control, BAR0 + 0x0080 */
-struct net2280_usb_regs {
-	// offset 0x0080
-	u32		stdrsp;
-#define     STALL_UNSUPPORTED_REQUESTS                          31
-#define     SET_TEST_MODE                                       16
-#define     GET_OTHER_SPEED_CONFIGURATION                       15
-#define     GET_DEVICE_QUALIFIER                                14
-#define     SET_ADDRESS                                         13
-#define     ENDPOINT_SET_CLEAR_HALT                             12
-#define     DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP               11
-#define     GET_STRING_DESCRIPTOR_2                             10
-#define     GET_STRING_DESCRIPTOR_1                             9
-#define     GET_STRING_DESCRIPTOR_0                             8
-#define     GET_SET_INTERFACE                                   6
-#define     GET_SET_CONFIGURATION                               5
-#define     GET_CONFIGURATION_DESCRIPTOR                        4
-#define     GET_DEVICE_DESCRIPTOR                               3
-#define     GET_ENDPOINT_STATUS                  