summaryrefslogtreecommitdiff
path: root/recipes/linux/files/linux-2.4-usb-gadget.patch
diff options
context:
space:
mode:
authorDenys Dmytriyenko <denis@denix.org>2009-03-17 14:32:59 -0400
committerDenys Dmytriyenko <denis@denix.org>2009-03-17 14:32:59 -0400
commit709c4d66e0b107ca606941b988bad717c0b45d9b (patch)
tree37ee08b1eb308f3b2b6426d5793545c38396b838 /recipes/linux/files/linux-2.4-usb-gadget.patch
parentfa6cd5a3b993f16c27de4ff82b42684516d433ba (diff)
rename packages/ to recipes/ per earlier agreement
See links below for more details: http://thread.gmane.org/gmane.comp.handhelds.openembedded/21326 http://thread.gmane.org/gmane.comp.handhelds.openembedded/21816 Signed-off-by: Denys Dmytriyenko <denis@denix.org> Acked-by: Mike Westerhof <mwester@dls.net> Acked-by: Philip Balister <philip@balister.org> Acked-by: Khem Raj <raj.khem@gmail.com> Acked-by: Marcin Juszkiewicz <hrw@openembedded.org> Acked-by: Koen Kooi <koen@openembedded.org> Acked-by: Frans Meulenbroeks <fransmeulenbroeks@gmail.com>
Diffstat (limited to 'recipes/linux/files/linux-2.4-usb-gadget.patch')
-rw-r--r--recipes/linux/files/linux-2.4-usb-gadget.patch29506
1 files changed, 29506 insertions, 0 deletions
diff --git a/recipes/linux/files/linux-2.4-usb-gadget.patch b/recipes/linux/files/linux-2.4-usb-gadget.patch
new file mode 100644
index 0000000000..0864ee98f5
--- /dev/null
+++ b/recipes/linux/files/linux-2.4-usb-gadget.patch
@@ -0,0 +1,29506 @@
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/Documentation/Configure.help kernel/Documentation/Configure.help
+--- /tmp/kernel/Documentation/Configure.help 2005-04-22 17:52:12.265476882 +0200
++++ kernel/Documentation/Configure.help 2005-04-22 17:57:15.940717930 +0200
+@@ -23701,6 +23701,163 @@
+ brave people. System crashes and other bad things are likely to occur if
+ you use this driver. If in doubt, select N.
+
++CONFIG_USB_GADGET
++ USB is a master/slave protocol, organized with one master
++ host (such as a PC) controlling up to 127 peripheral devices.
++ The USB hardware is asymmetric, which makes it easier to set up:
++ you can't connect two "to-the-host" connectors to each other.
++
++ Linux can run in the host, or in the peripheral. In both cases
++ you need a low level bus controller driver, and some software
++ talking to it. Peripheral controllers are often discrete silicon,
++ or are integrated with the CPU in a microcontroller. The more
++ familiar host side controllers have names like like "EHCI", "OHCI",
++ or "UHCI", and are usually integrated into southbridges on PC
++ motherboards.
++
++ Enable this configuration option if you want to run Linux inside
++ a USB peripheral device. Configure one hardware driver for your
++ peripheral/device side bus controller, and a "gadget driver" for
++ your peripheral protocol. (If you use modular gadget drivers,
++ you may configure more than one.)
++
++ If in doubt, say "N" and don't enable these drivers; most people
++ don't have this kind of hardware (except maybe inside Linux PDAs).
++
++CONFIG_USB_GADGET_NET2280
++ NetChip 2280 is a PCI based USB peripheral controller which
++ supports both full and high speed USB 2.0 data transfers.
++
++ It has six configurable endpoints, as well as endpoint zero
++ (for control transfers) and several endpoints with dedicated
++ functions.
++
++ Say "y" to link the driver statically, or "m" to build a
++ dynamically linked module called "net2280" and force all
++ gadget drivers to also be dynamically linked.
++
++CONFIG_USB_GADGET_GOKU
++ The Toshiba TC86C001 is a PCI device which includes controllers
++ for full speed USB devices, IDE, I2C, SIO, plus a USB host (OHCI).
++
++ The device controller has three configurable (bulk or interrupt)
++ endpoints, plus endpoint zero (for control transfers).
++
++ Say "y" to link the driver statically, or "m" to build a
++ dynamically linked module called "goku_udc" and force all
++ gadget drivers to also be dynamically linked.
++
++CONFIG_USB_GADGET_PXA2XX
++ Intel's PXA 2xx series XScale ARM-5TE processors include
++ an integrated full speed USB 1.1 device controller.
++
++ It has fifteen fixed-function endpoints, as well as endpoint
++ zero (for control transfers).
++
++ Say "y" to link the driver statically, or "m" to build a
++ dynamically linked module called "pxa2xx_udc" and force all
++ gadget drivers to also be dynamically linked.
++
++CONFIG_USB_GADGET_SUPERH
++ Some Renesas SuperH processors (SH7705, SH7727...) include an
++ integrated high speed USB 1.1 device controller.
++
++ It has three fixed-function endpoints, as well as endpoint zero (for
++ control transfers).
++
++ Say "y" to link the driver statically, or "m" to build a
++ dynamically linked module called "superh_udc" and force all
++ gadget drivers to also be dynamically linked.
++
++CONFIG_USB_ZERO
++ Gadget Zero is a two-configuration device. It either sinks and
++ sources bulk data; or it loops back a configurable number of
++ transfers. It also implements control requests, for "chapter 9"
++ conformance. The driver needs only two bulk-capable endpoints, so
++ it can work on top of most device-side usb controllers. It's
++ useful for testing, and is also a working example showing how
++ USB "gadget drivers" can be written.
++
++ Make this be the first driver you try using on top of any new
++ USB peripheral controller driver. Then you can use host-side
++ test software, like the "usbtest" driver, to put your hardware
++ and its driver through a basic set of functional tests.
++
++ Gadget Zero also works with the host-side "usb-skeleton" driver,
++ and with many kinds of host-side test software. You may need
++ to tweak product and vendor IDs before host software knows about
++ this device, and arrange to select an appropriate configuration.
++
++ Say "y" to link the driver statically, or "m" to build a
++ dynamically linked module called "g_zero".
++
++CONFIG_USB_ETH
++ This driver implements Ethernet style communication, in either
++ of two ways:
++
++ - The "Communication Device Class" (CDC) Ethernet Control Model.
++ That protocol is often avoided with pure Ethernet adapters, in
++ favor of simpler vendor-specific hardware, but is widely
++ supported by firmware for smart network devices.
++
++ - On hardware can't implement that protocol, a simpler approach
++ is used, placing fewer demands on USB.
++
++ Within the USB device, this gadget driver exposes a network device
++ "usbX", where X depends on what other networking devices you have.
++ Treat it like a two-node Ethernet link: host, and gadget.
++
++ The Linux-USB host-side "usbnet" driver interoperates with this
++ driver, so that deep I/O queues can be supported. On 2.4 kernels,
++ use "CDCEther" instead, if you're using the CDC option. That CDC
++ mode should also interoperate with standard CDC Ethernet class
++ drivers on other host operating systems.
++
++ Say "y" to link the driver statically, or "m" to build a
++ dynamically linked module called "g_ether".
++
++CONFIG_USB_ETH_RNDIS
++ Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol,
++ and Microsoft provides redistributable binary RNDIS drivers for
++ older versions of Windows.
++
++ If you say "y" here, the Ethernet gadget driver will try to provide
++ a second device configuration, supporting RNDIS to talk to such
++ Microsoft USB hosts.
++
++CONFIG_USB_FILE_STORAGE
++ The File-backed Storage Gadget acts as a USB Mass Storage
++ disk drive. As its storage repository it can use a regular
++ file or a block device (in much the same way as the "loop"
++ device driver), specified as a module parameter.
++
++CONFIG_USB_FILE_STORAGE_TEST
++ Say "y" to generate the larger testing version of the
++ File-backed Storage Gadget, useful for probing the
++ behavior of USB Mass Storage hosts. Not needed for
++ normal operation.
++
++CONFIG_USB_ETH_RNDIS
++ Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol,
++ and Microsoft provides redistributable binary RNDIS drivers for
++ older versions of Windows.
++
++ If you say "y" here, the Ethernet gadget driver will try to provide
++ a second device configuration, supporting RNDIS to talk to such
++ Microsoft USB hosts.
++
++CONFIG_USB_FILE_STORAGE
++ The File-backed Storage Gadget acts as a USB Mass Storage
++ disk drive. As its storage repository it can use a regular
++ file or a block device (in much the same way as the "loop"
++ device driver), specified as a module parameter.
++
++CONFIG_USB_FILE_STORAGE_TEST
++ Say "y" to generate the larger testing version of the
++ File-backed Storage Gadget, useful for probing the
++ behavior of USB Mass Storage hosts. Not needed for
++ normal operation.
++
+ Winbond W83977AF IrDA Device Driver
+ CONFIG_WINBOND_FIR
+ Say Y here if you want to build IrDA support for the Winbond
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/Makefile kernel/Makefile
+--- /tmp/kernel/Makefile 2005-04-22 17:52:12.362461090 +0200
++++ kernel/Makefile 2005-04-22 17:53:19.374549284 +0200
+@@ -196,6 +196,7 @@
+ DRIVERS-$(CONFIG_HAMRADIO) += drivers/net/hamradio/hamradio.o
+ DRIVERS-$(CONFIG_TC) += drivers/tc/tc.a
+ DRIVERS-$(CONFIG_USB) += drivers/usb/usbdrv.o
++DRIVERS-$(CONFIG_USB_GADGET) += drivers/usb/gadget/built-in.o
+ DRIVERS-$(CONFIG_LAB) += drivers/bootldr/labmod.o
+ DRIVERS-$(CONFIG_INPUT) += drivers/input/inputdrv.o
+ DRIVERS-$(CONFIG_I2O) += drivers/message/i2o/i2o.o
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/drivers/Makefile kernel/drivers/Makefile
+--- /tmp/kernel/drivers/Makefile 2005-04-22 17:52:12.728401503 +0200
++++ kernel/drivers/Makefile 2005-04-22 17:53:19.523525026 +0200
+@@ -27,6 +27,7 @@
+ subdir-$(CONFIG_MAC) += macintosh
+ subdir-$(CONFIG_PPC) += macintosh
+ subdir-$(CONFIG_USB) += usb
++subdir-$(CONFIG_USB_GADGET) += usb/gadget
+ subdir-$(CONFIG_INPUT) += input
+ subdir-$(CONFIG_PHONE) += telephony
+ subdir-$(CONFIG_SGI) += sgi
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/drivers/usb/Config.in kernel/drivers/usb/Config.in
+--- /tmp/kernel/drivers/usb/Config.in 2005-04-22 17:52:20.663109467 +0200
++++ kernel/drivers/usb/Config.in 2005-04-22 17:53:19.376548959 +0200
+@@ -120,4 +120,7 @@
+ dep_tristate ' USB Auerswald ISDN support (EXPERIMENTAL)' CONFIG_USB_AUERSWALD $CONFIG_USB $CONFIG_EXPERIMENTAL
+ dep_tristate ' Tieman Voyager USB Braille display support (EXPERIMENTAL)' CONFIG_USB_BRLVGER $CONFIG_USB $CONFIG_EXPERIMENTAL
+ fi
++
++source drivers/usb/gadget/Config.in
++
+ endmenu
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/drivers/usb/gadget/Config.in kernel/drivers/usb/gadget/Config.in
+--- /tmp/kernel/drivers/usb/gadget/Config.in 1970-01-01 01:00:00.000000000 +0100
++++ kernel/drivers/usb/gadget/Config.in 2005-04-22 17:53:19.403544563 +0200
+@@ -0,0 +1,128 @@
++#
++# 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'
++
++tristate 'Support for USB Gadgets' CONFIG_USB_GADGET
++if [ "$CONFIG_USB_GADGET" = "y" -o "$CONFIG_USB_GADGET" = "m" ]; then
++
++ #
++ # really want _exactly one_ device controller driver at a time,
++ # since they control compile options for gadget drivers.
++ #
++ choice 'USB Peripheral Controller Driver' "\
++ Intel-PXA2xx/IXP4xx CONFIG_USB_GADGET_PXA2XX \
++ National-N9603/N9604 CONFIG_USB_GADGET_N9604 \
++ NetChip-2280 CONFIG_USB_GADGET_NET2280 \
++ Renesas-SH7705/7727 CONFIG_USB_GADGET_SUPERH \
++ Toshiba-TC86C001(Goku-S) CONFIG_USB_GADGET_GOKU \
++ " NetChip-2280
++
++ define_tristate CONFIG_USB_GADGET_CONTROLLER n
++
++ if [ "$CONFIG_ARCH_PXA" = "y" -o "$CONFIG_ARCH_IXP425" = "y" ] ; then
++ if [ "$CONFIG_USB_GADGET_PXA2XX" = "y" ] ; then
++ define_tristate CONFIG_USB_PXA2XX $CONFIG_USB_GADGET
++ define_tristate CONFIG_USB_GADGET_CONTROLLER $CONFIG_USB_PXA2XX
++ fi
++ fi
++ if [ "$CONFIG_PCI" = "y" -a "$CONFIG_USB_GADGET_NET2280" = "y" ] ; then
++ define_tristate CONFIG_USB_NET2280 $CONFIG_USB_GADGET
++ define_tristate CONFIG_USB_GADGET_CONTROLLER $CONFIG_USB_NET2280
++ fi
++ if [ "$CONFIG_SUPERH" = "y" -a "$CONFIG_USB_GADGET_SUPERH" = "y" ] ; then
++ define_tristate CONFIG_USB_SUPERH $CONFIG_USB_GADGET
++ define_tristate CONFIG_USB_GADGET_CONTROLLER $CONFIG_USB_SUPERH
++ fi
++ if [ "$CONFIG_PCI" = "y" -a "$CONFIG_USB_GADGET_GOKU" = "y" ] ; then
++ define_tristate CONFIG_USB_GOKU $CONFIG_USB_GADGET
++ define_tristate CONFIG_USB_GADGET_CONTROLLER $CONFIG_USB_GOKU
++ fi
++ if [ "$CONFIG_USB_GADGET_N9604" = "y" ] ; then
++ define_tristate CONFIG_USB_N9604 $CONFIG_USB_GADGET
++ define_tristate CONFIG_USB_GADGET_CONTROLLER $CONFIG_USB_N9604
++ fi
++
++ # or any other controller that supports high speed transfers ...
++ define_bool CONFIG_USB_GADGET_DUALSPEED $CONFIG_USB_GADGET_NET2280
++
++ if [ "$CONFIG_USB_GADGET_CONTROLLER" = "y" -o "$CONFIG_USB_GADGET_CONTROLLER" = "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'
++
++ # FIXME when drivers all use #ifdef CONFIG_USB_GADGET_* tests,
++ # just remove all this driver-specific define_bool logic
++
++ dep_tristate ' Gadget Zero (DEVELOPMENT)' CONFIG_USB_ZERO $CONFIG_USB_GADGET_CONTROLLER
++ dep_tristate ' Ethernet Gadget (EXPERIMENTAL)' CONFIG_USB_ETH $CONFIG_USB_GADGET_CONTROLLER $CONFIG_NET
++ if [ "$CONFIG_USB_ETH" = "y" -o "$CONFIG_USB_ETH" = "m" ] ; then
++ bool ' RNDIS support (EXPERIMENTAL)' CONFIG_USB_ETH_RNDIS
++ fi
++ dep_tristate ' Gadget Filesystem API (EXPERIMENTAL)' CONFIG_USB_GADGETFS $CONFIG_USB_GADGET_CONTROLLER
++ dep_tristate ' File-backed Storage Gadget (DEVELOPMENT)' CONFIG_USB_FILE_STORAGE $CONFIG_USB_GADGET_CONTROLLER
++ dep_mbool ' File-backed Storage Gadget test mode' CONFIG_USB_FILE_STORAGE_TEST $CONFIG_USB_FILE_STORAGE
++ dep_tristate ' Serial Gadget (EXPERIMENTAL)' CONFIG_USB_G_SERIAL $CONFIG_USB_GADGET_CONTROLLER
++
++
++ # enforce the "only one statically linked gadget driver" rule
++
++ if [ "$CONFIG_USB_ZERO" = "y" ]; then
++ # zero = y
++ define_tristate CONFIG_USB_ETH n
++ define_tristate CONFIG_USB_GADGETFS n
++ define_tristate CONFIG_USB_FILE_STORAGE n
++ define_tristate CONFIG_USB_G_SERIAL n
++ fi
++
++ if [ "$CONFIG_USB_ETH" = "y" ]; then
++ define_tristate CONFIG_USB_ZERO n
++ # eth = y
++ define_tristate CONFIG_USB_GADGETFS n
++ define_tristate CONFIG_USB_FILE_STORAGE n
++ define_tristate CONFIG_USB_G_SERIAL n
++ fi
++
++ if [ "$CONFIG_USB_GADGETFS" = "y" ]; then
++ define_tristate CONFIG_USB_ZERO n
++ define_tristate CONFIG_USB_ETH n
++ # gadgetfs = y
++ define_tristate CONFIG_USB_FILE_STORAGE n
++ define_tristate CONFIG_USB_G_SERIAL n
++ fi
++
++ if [ "$CONFIG_USB_FILE_STORAGE" = "y" ]; then
++ define_tristate CONFIG_USB_ZERO n
++ define_tristate CONFIG_USB_ETH n
++ define_tristate CONFIG_USB_GADGETFS n
++ # file_storage = y
++ define_tristate CONFIG_USB_G_SERIAL n
++ fi
++
++ if [ "$CONFIG_USB_G_SERIAL" = "y" ]; then
++ define_tristate CONFIG_USB_ZERO n
++ define_tristate CONFIG_USB_ETH n
++ define_tristate CONFIG_USB_GADGETFS n
++ define_tristate CONFIG_USB_FILE_STORAGE n
++ # g_serial = y
++ fi
++ fi
++fi
++endmenu
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/drivers/usb/gadget/Makefile kernel/drivers/usb/gadget/Makefile
+--- /tmp/kernel/drivers/usb/gadget/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ kernel/drivers/usb/gadget/Makefile 2005-04-22 17:53:19.405544237 +0200
+@@ -0,0 +1,58 @@
++#
++# Makefile for USB peripheral controller and gadget drivers
++# for kbuild 2.4
++#
++
++# for static linking
++O_TARGET := built-in.o
++
++list-multi := g_zero.o g_ether.o gadgetfs.o g_file_storage.o g_serial.o
++
++obj-$(CONFIG_USB_NET2280) += net2280.o
++obj-$(CONFIG_USB_PXA2XX) += pxa2xx_udc.o
++obj-$(CONFIG_USB_GOKU) += goku_udc.o
++obj-$(CONFIG_USB_SUPERH) += superh_udc.o
++obj-$(CONFIG_USB_N9604) += n9604.o
++
++# only one of these may be statically linked ...
++controller-$(CONFIG_USB_NET2280) += net2280.o
++controller-$(CONFIG_USB_PXA2XX) += pxa2xx_udc.o
++controller-$(CONFIG_USB_GOKU) += goku_udc.o
++controller-$(CONFIG_USB_SUPERH) += superh_udc.o
++controller-$(CONFIG_USB_N9604) += n9604.o
++
++# ... and only one of these, too; kbuild/kconfig don't help though.
++g_zero-objs := zero.o usbstring.o config.o epautoconf.o
++obj-$(CONFIG_USB_ZERO) += g_zero.o
++
++g_ether-objs := ether.o usbstring.o config.o epautoconf.o
++obj-$(CONFIG_USB_ETH) += g_ether.o
++
++ifeq ($(CONFIG_USB_ETH_RNDIS),y)
++ g_ether-objs += rndis.o
++endif
++
++gadgetfs-objs := inode.o usbstring.o
++obj-$(CONFIG_USB_GADGETFS) += gadgetfs.o
++
++g_file_storage-objs := file_storage.o usbstring.o config.o \
++ epautoconf.o
++obj-$(CONFIG_USB_FILE_STORAGE) += g_file_storage.o
++
++g_serial-objs := gserial.o usbstring.o epautoconf.o
++obj-$(CONFIG_USB_G_SERIAL) += g_serial.o
++
++export-objs := $(controller-y) $(controller-m)
++
++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)
++gadgetfs.o: $(gadgetfs-objs)
++ $(LD) -r -o $@ $(gadgetfs-objs)
++g_file_storage.o: $(g_file_storage-objs)
++ $(LD) -r -o $@ $(g_file_storage-objs)
++g_serial.o: $(g_serial-objs)
++ $(LD) -r -o $@ $(g_serial-objs)
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/drivers/usb/gadget/config.c kernel/drivers/usb/gadget/config.c
+--- /tmp/kernel/drivers/usb/gadget/config.c 1970-01-01 01:00:00.000000000 +0100
++++ kernel/drivers/usb/gadget/config.c 2005-04-22 17:53:19.408543749 +0200
+@@ -0,0 +1,116 @@
++/*
++ * 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 <asm/byteorder.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 -x '*~' -x '.*' -r -N -u /tmp/kernel/drivers/usb/gadget/epautoconf.c kernel/drivers/usb/gadget/epautoconf.c
+--- /tmp/kernel/drivers/usb/gadget/epautoconf.c 1970-01-01 01:00:00.000000000 +0100
++++ kernel/drivers/usb/gadget/epautoconf.c 2005-04-22 17:53:19.410543423 +0200
+@@ -0,0 +1,311 @@
++/*
++ * epautoconf.c -- endpoint autoconfiguration for usb gadget drivers
++ *
++ * Copyright (C) 2004 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/kernel.h>
++#include <linux/init.h>
++#include <linux/types.h>
++#include <linux/list.h>
++#include <linux/errno.h>
++#include <linux/ctype.h>
++#include <linux/string.h>
++#include <linux/usb_ch9.h>
++#include <linux/usb_gadget.h>
++
++#include <asm/byteorder.h>
++
++#include "gadget_chips.h"
++
++
++/* we must assign addresses for configurable endpoints (like net2280) */
++static __initdata unsigned epnum;
++
++// #define MANY_ENDPOINTS
++#ifdef MANY_ENDPOINTS
++/* more than 15 configurable endpoints */
++static __initdata unsigned in_epnum;
++#endif
++
++
++/*
++ * This should work with endpoints from controller drivers sharing the
++ * same endpoint naming convention. By example:
++ *
++ * - ep1, ep2, ... address is fixed, not direction or type
++ * - ep1in, ep2out, ... address and direction are fixed, not type
++ * - ep1-bulk, ep2-bulk, ... address and type are fixed, not direction
++ * - ep1in-bulk, ep2out-iso, ... all three are fixed
++ * - ep-* ... no functionality restrictions
++ *
++ * Type suffixes are "-bulk", "-iso", or "-int". Numbers are decimal.
++ * Less common restrictions are implied by gadget_is_*().
++ *
++ * NOTE: each endpoint is unidirectional, as specified by its USB
++ * descriptor; and isn't specific to a configuration or altsetting.
++ */
++static int __init
++ep_matches (
++ struct usb_gadget *gadget,
++ struct usb_ep *ep,
++ struct usb_endpoint_descriptor *desc
++)
++{
++ u8 type;
++ const char *tmp;
++ u16 max;
++
++ /* endpoint already claimed? */
++ if (0 != ep->driver_data)
++ return 0;
++
++ /* only support ep0 for portable CONTROL traffic */
++ type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
++ if (USB_ENDPOINT_XFER_CONTROL == type)
++ return 0;
++
++ /* some other naming convention */
++ if ('e' != ep->name[0])
++ return 0;
++
++ /* type-restriction: "-iso", "-bulk", or "-int".
++ * direction-restriction: "in", "out".
++ */
++ if ('-' != ep->name[2]) {
++ tmp = strrchr (ep->name, '-');
++ if (tmp) {
++ switch (type) {
++ case USB_ENDPOINT_XFER_INT:
++ /* bulk endpoints handle interrupt transfers,
++ * except the toggle-quirky iso-synch kind
++ */
++ if ('s' == tmp[2]) // == "-iso"
++ return 0;
++ /* for now, avoid PXA "interrupt-in";
++ * it's documented as never using DATA1.
++ */
++ if (gadget_is_pxa (gadget)
++ && 'i' == tmp [1])
++ return 0;
++ break;
++ case USB_ENDPOINT_XFER_BULK:
++ if ('b' != tmp[1]) // != "-bulk"
++ return 0;
++ break;
++ case USB_ENDPOINT_XFER_ISOC:
++ if ('s' != tmp[2]) // != "-iso"
++ return 0;
++ }
++ } else {
++ tmp = ep->name + strlen (ep->name);
++ }
++
++ /* direction-restriction: "..in-..", "out-.." */
++ tmp--;
++ if (!isdigit (*tmp)) {
++ if (desc->bEndpointAddress & USB_DIR_IN) {
++ if ('n' != *tmp)
++ return 0;
++ } else {
++ if ('t' != *tmp)
++ return 0;
++ }
++ }
++ }
++
++ /* endpoint maxpacket size is an input parameter, except for bulk
++ * where it's an output parameter representing the full speed limit.
++ * the usb spec fixes high speed bulk maxpacket at 512 bytes.
++ */
++ max = 0x7ff & le16_to_cpup (&desc->wMaxPacketSize);
++ switch (type) {
++ case USB_ENDPOINT_XFER_INT:
++ /* INT: limit 64 bytes full speed, 1024 high speed */
++ if (!gadget->is_dualspeed && max > 64)
++ return 0;
++ /* FALLTHROUGH */
++
++ case USB_ENDPOINT_XFER_ISOC:
++ /* ISO: limit 1023 bytes full speed, 1024 high speed */
++ if (ep->maxpacket < max)
++ return 0;
++ if (!gadget->is_dualspeed && max > 1023)
++ return 0;
++
++ /* BOTH: "high bandwidth" works only at high speed */
++ if ((desc->wMaxPacketSize & __constant_cpu_to_le16(3<<11))) {
++ if (!gadget->is_dualspeed)
++ return 0;
++ /* configure your hardware with enough buffering!! */
++ }
++ break;
++ }
++
++ /* MATCH!! */
++
++ /* report address */
++ if (isdigit (ep->name [2])) {
++ u8 num = simple_strtol (&ep->name [2], NULL, 10);
++ desc->bEndpointAddress |= num;
++#ifdef MANY_ENDPOINTS
++ } else if (desc->bEndpointAddress & USB_DIR_IN) {
++ if (++in_epnum > 15)
++ return 0;
++ desc->bEndpointAddress = USB_DIR_IN | in_epnum;
++#endif
++ } else {
++ if (++epnum > 15)
++ return 0;
++ desc->bEndpointAddress |= epnum;
++ }
++
++ /* report (variable) full speed bulk maxpacket */
++ if (USB_ENDPOINT_XFER_BULK == type) {
++ int size = ep->maxpacket;
++
++ /* min() doesn't work on bitfields with gcc-3.5 */
++ if (size > 64)
++ size = 64;
++ desc->wMaxPacketSize = cpu_to_le16(size);
++ }
++ return 1;
++}
++
++static struct usb_ep * __init
++find_ep (struct usb_gadget *gadget, const char *name)
++{
++ struct usb_ep *ep;
++
++ list_for_each_entry (ep, &gadget->ep_list, ep_list) {
++ if (0 == strcmp (ep->name, name))
++ return ep;
++ }
++ return NULL;
++}
++
++/**
++ * usb_ep_autoconfig - choose an endpoint matching the descriptor
++ * @gadget: The device to which the endpoint must belong.
++ * @desc: Endpoint descriptor, with endpoint direction and transfer mode
++ * initialized. For periodic transfers, the maximum packet
++ * size must also be initialized. This is modified on success.
++ *
++ * By choosing an endpoint to use with the specified descriptor, this
++ * routine simplifies writing gadget drivers that work with multiple
++ * USB device controllers. The endpoint would be passed later to
++ * usb_ep_enable(), along with some descriptor.
++ *
++ * That second descriptor won't always be the same as the first one.
++ * For example, isochronous endpoints can be autoconfigured for high
++ * bandwidth, and then used in several lower bandwidth altsettings.
++ * Also, high and full speed descriptors will be different.
++ *
++ * Be sure to examine and test the results of autoconfiguration on your
++ * hardware. This code may not make the best choices about how to use the
++ * USB controller, and it can't know all the restrictions that may apply.
++ * Some combinations of driver and hardware won't be able to autoconfigure.
++ *
++ * On success, this returns an un-claimed usb_ep, and modifies the endpoint
++ * descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value
++ * is initialized as if the endpoint were used at full speed. To prevent
++ * the endpoint from being returned by a later autoconfig call, claim it
++ * by assigning ep->driver_data to some non-null value.
++ *
++ * On failure, this returns a null endpoint descriptor.
++ */
++struct usb_ep * __init usb_ep_autoconfig (
++ struct usb_gadget *gadget,
++ struct usb_endpoint_descriptor *desc
++)
++{
++ struct usb_ep *ep;
++ u8 type;
++
++ type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
++
++ /* First, apply chip-specific "best usage" knowledge.
++ * This might make a good usb_gadget_ops hook ...
++ */
++ if (gadget_is_net2280 (gadget) && type == USB_ENDPOINT_XFER_INT) {
++ /* ep-e, ep-f are PIO with only 64 byte fifos */
++ ep = find_ep (gadget, "ep-e");
++ if (ep && ep_matches (gadget, ep, desc))
++ return ep;
++ ep = find_ep (gadget, "ep-f");
++ if (ep && ep_matches (gadget, ep, desc))
++ return ep;
++
++ } else if (gadget_is_goku (gadget)) {
++ if (USB_ENDPOINT_XFER_INT == type) {
++ /* single buffering is enough */
++ ep = find_ep (gadget, "ep3-bulk");
++ if (ep && ep_matches (gadget, ep, desc))
++ return ep;
++ } else if (USB_ENDPOINT_XFER_BULK == type
++ && (USB_DIR_IN & desc->bEndpointAddress)) {
++ /* DMA may be available */
++ ep = find_ep (gadget, "ep2-bulk");
++ if (ep && ep_matches (gadget, ep, desc))
++ return ep;
++ }
++
++ } else if (gadget_is_sh (gadget) && USB_ENDPOINT_XFER_INT == type) {
++ /* single buffering is enough; maybe 8 byte fifo is too */
++ ep = find_ep (gadget, "ep3in-bulk");
++ if (ep && ep_matches (gadget, ep, desc))
++ return ep;
++
++ } else if (gadget_is_mq11xx (gadget) && USB_ENDPOINT_XFER_INT == type) {
++ ep = find_ep (gadget, "ep1-bulk");
++ if (ep && ep_matches (gadget, ep, desc))
++ return ep;
++ }
++
++ /* Second, look at endpoints until an unclaimed one looks usable */
++ list_for_each_entry (ep, &gadget->ep_list, ep_list) {
++ if (ep_matches (gadget, ep, desc))
++ return ep;
++ }
++
++ /* Fail */
++ return NULL;
++}
++
++/**
++ * usb_ep_autoconfig_reset - reset endpoint autoconfig state
++ * @gadget: device for which autoconfig state will be reset
++ *
++ * Use this for devices where one configuration may need to assign
++ * endpoint resources very differently from the next one. It clears
++ * state such as ep->driver_data and the record of assigned endpoints
++ * used by usb_ep_autoconfig().
++ */
++void __init usb_ep_autoconfig_reset (struct usb_gadget *gadget)
++{
++ struct usb_ep *ep;
++
++ list_for_each_entry (ep, &gadget->ep_list, ep_list) {
++ ep->driver_data = NULL;
++ }
++#ifdef MANY_ENDPOINTS
++ in_epnum = 0;
++#endif
++ epnum = 0;
++}
++
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/drivers/usb/gadget/ether.c kernel/drivers/usb/gadget/ether.c
+--- /tmp/kernel/drivers/usb/gadget/ether.c 1970-01-01 01:00:00.000000000 +0100
++++ kernel/drivers/usb/gadget/ether.c 2005-04-22 18:01:31.044861540 +0200
+@@ -0,0 +1,2734 @@
++/*
++ * ether.c -- Ethernet gadget driver, with CDC and non-CDC options
++ *
++ * Copyright (C) 2003-2005 David Brownell
++ * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
++ *
++ * 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 <linux/moduleparam.h>
++#include <linux/ctype.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_cdc.h>
++#include <linux/usb_gadget.h>
++
++#include <linux/random.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/ethtool.h>
++
++#include "gadget_chips.h"
++
++/*-------------------------------------------------------------------------*/
++
++/*
++ * Ethernet gadget driver -- with CDC and non-CDC options
++ * Builds on hardware support for a full duplex link.
++ *
++ * 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. This driver strongly prefers to use
++ * this USB-IF standard as its open-systems interoperability solution;
++ * most host side USB stacks (except from Microsoft) support it.
++ *
++ * 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.
++ * Linux supports it, but other host operating systems may not.
++ * (This is a subset of CDC Ethernet.)
++ *
++ * A third option is also in use. Rather than CDC Ethernet, or something
++ * simpler, Microsoft pushes their own approach: RNDIS. The published
++ * RNDIS specs are ambiguous and appear to be incomplete, and are also
++ * needlessly complex.
++ */
++
++#define DRIVER_DESC "Ethernet Gadget"
++#define DRIVER_VERSION "Equinox 2004"
++
++static const char shortname [] = "ether";
++static const char driver_desc [] = DRIVER_DESC;
++
++#define RX_EXTRA 20 /* guard against rx overflows */
++
++#ifdef CONFIG_USB_ETH_RNDIS
++#include "rndis.h"
++#else
++#define rndis_init() 0
++#define rndis_exit() do{}while(0)
++#endif
++
++/* 2.6-compat */
++#ifndef container_of
++#define container_of list_entry
++#endif
++
++/** PO: really needed? */
++#include <linux/tqueue.h>
++#define work_struct tq_struct
++#define INIT_WORK INIT_TQUEUE
++#define schedule_work schedule_task
++#define flush_scheduled_work flush_scheduled_tasks
++
++static void random_ether_addr (u8 *addr)
++{
++ get_random_bytes (addr, ETH_ALEN);
++ addr [0] &= 0xfe; // clear multicast bit
++ addr [0] |= 0x02; // set local assignment bit (IEEE802)
++}
++
++/* CDC and RNDIS support the same host-chosen outgoing packet filters. */
++#define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \
++ |USB_CDC_PACKET_TYPE_DIRECTED)
++
++
++/*-------------------------------------------------------------------------*/
++
++struct eth_dev {
++ spinlock_t lock;
++ struct usb_gadget *gadget;
++ struct usb_request *req; /* for control responses */
++ struct usb_request *stat_req; /* for cdc & rndis status */
++
++ 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 zlp:1;
++ unsigned cdc:1;
++ unsigned rndis:1;
++ unsigned suspended:1;
++ u16 cdc_filter;
++ unsigned long todo;
++#define WORK_RX_MEMORY 0
++ int rndis_config;
++ u8 host_mac [ETH_ALEN];
++};
++
++/* This version autoconfigures as much as possible at run-time.
++ *
++ * It also ASSUMES a self-powered device, without remote wakeup,
++ * although remote wakeup support would make sense.
++ */
++static const char *EP_IN_NAME;
++static const char *EP_OUT_NAME;
++static const char *EP_STATUS_NAME;
++
++/*-------------------------------------------------------------------------*/
++
++/* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!!
++ * Instead: allocate your own, using normal USB-IF procedures.
++ */
++
++/* Thanks to NetChip Technologies for donating this product ID.
++ * It's for devices with only CDC Ethernet configurations.
++ */
++#define CDC_VENDOR_NUM 0x0525 /* NetChip */
++#define CDC_PRODUCT_NUM 0xa4a1 /* Linux-USB Ethernet Gadget */
++
++/* 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. bcdDevice (version) is nonzero, so
++ * drivers that need to hard-wire endpoint numbers have a hook.
++ *
++ * The protocol is a minimal subset of CDC Ether, which works on any bulk
++ * hardware that's not deeply broken ... even on hardware that can't talk
++ * RNDIS (like SA-1100, with no interrupt endpoint, or anything that
++ * doesn't handle control-OUT).
++ */
++#define SIMPLE_VENDOR_NUM 0x049f
++#define SIMPLE_PRODUCT_NUM 0x505a
++
++/* For hardware that can talk RNDIS and either of the above protocols,
++ * use this ID ... the windows INF files will know it. Unless it's
++ * used with CDC Ethernet, Linux 2.4 hosts will need updates to choose
++ * the non-RNDIS configuration.
++ */
++#define RNDIS_VENDOR_NUM 0x0525 /* NetChip */
++#define RNDIS_PRODUCT_NUM 0xa4a2 /* Ethernet/RNDIS Gadget */
++
++
++/* Some systems will want different product identifers published in the
++ * device descriptor, either numbers or strings or both. These string
++ * parameters are in UTF-8 (superset of ASCII's 7 bit characters).
++ */
++
++static ushort __initdata idVendor;
++MODULE_PARM(idVendor, "h");
++MODULE_PARM_DESC(idVendor, "USB Vendor ID");
++
++static ushort __initdata idProduct;
++MODULE_PARM(idProduct, "h");
++MODULE_PARM_DESC(idProduct, "USB Product ID");
++
++static ushort __initdata bcdDevice;
++MODULE_PARM(bcdDevice, "h");
++MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)");
++
++static char *__initdata iManufacturer;
++MODULE_PARM(iManufacturer, "s");
++MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string");
++
++static char *__initdata iProduct;
++MODULE_PARM(iProduct, "s");
++MODULE_PARM_DESC(iProduct, "USB Product string");
++
++/* initial value, changed by "ifconfig usb0 hw ether xx:xx:xx:xx:xx:xx" */
++static char *__initdata dev_addr;
++MODULE_PARM(dev_addr, "s");
++MODULE_PARM_DESC(dev_addr, "Device Ethernet Address");
++
++/* this address is invisible to ifconfig */
++static char *__initdata host_addr;
++MODULE_PARM(host_addr, "s");
++MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
++
++
++/*-------------------------------------------------------------------------*/
++
++/* Include CDC support if we could run on CDC-capable hardware. */
++
++#ifdef CONFIG_USB_GADGET_NET2280
++#define DEV_CONFIG_CDC
++#endif
++
++#ifdef CONFIG_USB_GADGET_DUMMY_HCD
++#define DEV_CONFIG_CDC
++#endif
++
++#ifdef CONFIG_USB_GADGET_GOKU
++#define DEV_CONFIG_CDC
++#endif
++
++#ifdef CONFIG_USB_GADGET_LH7A40X
++#define DEV_CONFIG_CDC
++#endif
++
++#ifdef CONFIG_USB_GADGET_MQ11XX
++#define DEV_CONFIG_CDC
++#endif
++
++#ifdef CONFIG_USB_GADGET_OMAP
++#define DEV_CONFIG_CDC
++#endif
++
++#ifdef CONFIG_USB_GADGET_N9604
++#define DEV_CONFIG_CDC
++#endif
++
++#ifdef CONFIG_USB_GADGET_PXA27X
++#define DEV_CONFIG_CDC
++#endif
++
++#ifdef CONFIG_USB_GADGET_AT91
++#define DEV_CONFIG_CDC
++#endif
++
++
++/* For CDC-incapable hardware, choose the simple cdc subset.
++ * Anything that talks bulk (without notable bugs) can do this.
++ */
++#ifdef CONFIG_USB_GADGET_PXA2XX
++#define DEV_CONFIG_SUBSET
++#endif
++
++#ifdef CONFIG_USB_GADGET_SH
++#define DEV_CONFIG_SUBSET
++#endif
++
++#ifdef CONFIG_USB_GADGET_SA1100
++/* use non-CDC for backwards compatibility */
++#define DEV_CONFIG_SUBSET
++#endif
++
++#ifdef CONFIG_USB_GADGET_S3C2410
++#define DEV_CONFIG_CDC
++#endif
++
++/*-------------------------------------------------------------------------*/
++
++/* "main" config is either CDC, or its simple subset */
++static inline int is_cdc(struct eth_dev *dev)
++{
++#if !defined(DEV_CONFIG_SUBSET)
++ return 1; /* only cdc possible */
++#elif !defined (DEV_CONFIG_CDC)
++ return 0; /* only subset possible */
++#else
++ return dev->cdc; /* depends on what hardware we found */
++#endif
++}
++
++/* "secondary" RNDIS config may sometimes be activated */
++static inline int rndis_active(struct eth_dev *dev)
++{
++#ifdef CONFIG_USB_ETH_RNDIS
++ return dev->rndis;
++#else
++ return 0;
++#endif
++}
++
++#define subset_active(dev) (!is_cdc(dev) && !rndis_active(dev))
++#define cdc_active(dev) ( is_cdc(dev) && !rndis_active(dev))
++
++
++
++#define DEFAULT_QLEN 2 /* double buffering by default */
++
++/* peak bulk transfer bits-per-second */
++#define HS_BPS (13 * 512 * 8 * 1000 * 8)
++#define FS_BPS (19 * 64 * 1 * 1000 * 8)
++
++#ifdef CONFIG_USB_GADGET_DUALSPEED
++
++static unsigned qmult = 5;
++MODULE_PARM(qmult, "i");
++
++
++/* for dual-speed hardware, use deeper queues at highspeed */
++#define qlen(gadget) \
++ (DEFAULT_QLEN*((gadget->speed == USB_SPEED_HIGH) ? qmult : 1))
++
++/* also defer IRQs on highspeed TX */
++#define TX_DELAY qmult
++
++#define BITRATE(g) (((g)->speed == USB_SPEED_HIGH) ? HS_BPS : FS_BPS)
++
++#else /* full speed (low speed doesn't do bulk) */
++#define qlen(gadget) DEFAULT_QLEN
++
++#define BITRATE(g) FS_BPS
++#endif
++
++
++/*-------------------------------------------------------------------------*/
++
++#define xprintk(d,level,fmt,args...) \
++ printk(level "%s: " fmt , (d)->net->name , ## 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. For now we do either full CDC, or
++ * our simple subset, with RNDIS as an optional second configuration.
++ *
++ * RNDIS includes some CDC ACM descriptors ... like CDC Ethernet. But
++ * the class descriptors match a modem (they're ignored; it's really just
++ * Ethernet functionality), they don't need the NOP altsetting, and the
++ * status transfer endpoint isn't optional.
++ */
++
++#define STRING_MANUFACTURER 1
++#define STRING_PRODUCT 2
++#define STRING_ETHADDR 3
++#define STRING_DATA 4
++#define STRING_CONTROL 5
++#define STRING_RNDIS_CONTROL 6
++#define STRING_CDC 7
++#define STRING_SUBSET 8
++#define STRING_RNDIS 9
++
++#define USB_BUFSIZ 256 /* holds our biggest descriptor */
++
++/*
++ * This device advertises one configuration, eth_config, unless RNDIS
++ * is enabled (rndis_config) on hardware supporting at least two configs.
++ *
++ * NOTE: Controllers like superh_udc should probably be able to use
++ * an RNDIS-only configuration.
++ *
++ * FIXME define some higher-powered configurations to make it easier
++ * to recharge batteries ...
++ */
++
++#define DEV_CONFIG_VALUE 1 /* cdc or subset */
++#define DEV_RNDIS_CONFIG_VALUE 2 /* rndis; optional */
++
++static struct usb_device_descriptor
++device_desc = {
++ .bLength = sizeof device_desc,
++ .bDescriptorType = USB_DT_DEVICE,
++
++ .bcdUSB = __constant_cpu_to_le16 (0x0200),
++
++ .bDeviceClass = USB_CLASS_COMM,
++ .bDeviceSubClass = 0,
++ .bDeviceProtocol = 0,
++
++ .idVendor = __constant_cpu_to_le16 (CDC_VENDOR_NUM),
++ .idProduct = __constant_cpu_to_le16 (CDC_PRODUCT_NUM),
++ .iManufacturer = STRING_MANUFACTURER,
++ .iProduct = STRING_PRODUCT,
++ .bNumConfigurations = 1,
++};
++
++static struct usb_otg_descriptor
++otg_descriptor = {
++ .bLength = sizeof otg_descriptor,
++ .bDescriptorType = USB_DT_OTG,
++
++ .bmAttributes = USB_OTG_SRP,
++};
++
++static struct usb_config_descriptor
++eth_config = {
++ .bLength = sizeof eth_config,
++ .bDescriptorType = USB_DT_CONFIG,
++
++ /* compute wTotalLength on the fly */
++ .bNumInterfaces = 2,
++ .bConfigurationValue = DEV_CONFIG_VALUE,
++ .iConfiguration = STRING_CDC,
++ .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
++ .bMaxPower = 50,
++};
++
++#ifdef CONFIG_USB_ETH_RNDIS
++static struct usb_config_descriptor
++rndis_config = {
++ .bLength = sizeof rndis_config,
++ .bDescriptorType = USB_DT_CONFIG,
++
++ /* compute wTotalLength on the fly */
++ .bNumInterfaces = 2,
++ .bConfigurationValue = DEV_RNDIS_CONFIG_VALUE,
++ .iConfiguration = STRING_RNDIS,
++ .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
++ .bMaxPower = 50,
++};
++#endif
++
++/*
++ * Compared to the simple CDC subset, the full CDC Ethernet model adds
++ * three class descriptors, two interface descriptors, optional status
++ * endpoint. Both have a "data" interface and two bulk endpoints.
++ * There are also differences in how control requests are handled.
++ *
++ * RNDIS shares a lot with CDC-Ethernet, since it's a variant of
++ * the CDC-ACM (modem) spec.
++ */
++
++#ifdef DEV_CONFIG_CDC
++static struct usb_interface_descriptor
++control_intf = {
++ .bLength = sizeof control_intf,
++ .bDescriptorType = USB_DT_INTERFACE,
++
++ .bInterfaceNumber = 0,
++ /* status endpoint is optional; this may be patched later */
++ .bNumEndpoints = 1,
++ .bInterfaceClass = USB_CLASS_COMM,
++ .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET,
++ .bInterfaceProtocol = USB_CDC_PROTO_NONE,
++ .iInterface = STRING_CONTROL,
++};
++#endif
++
++#ifdef CONFIG_USB_ETH_RNDIS
++static const struct usb_interface_descriptor
++rndis_control_intf = {
++ .bLength = sizeof rndis_control_intf,
++ .bDescriptorType = USB_DT_INTERFACE,
++
++ .bInterfaceNumber = 0,
++ .bNumEndpoints = 1,
++ .bInterfaceClass = USB_CLASS_COMM,
++ .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
++ .bInterfaceProtocol = USB_CDC_ACM_PROTO_VENDOR,
++ .iInterface = STRING_RNDIS_CONTROL,
++};
++#endif
++
++#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
++
++static const struct usb_cdc_header_desc header_desc = {
++ .bLength = sizeof header_desc,
++ .bDescriptorType = USB_DT_CS_INTERFACE,
++ .bDescriptorSubType = USB_CDC_HEADER_TYPE,
++
++ .bcdCDC = __constant_cpu_to_le16 (0x0110),
++};
++
++static const struct usb_cdc_union_desc union_desc = {
++ .bLength = sizeof union_desc,
++ .bDescriptorType = USB_DT_CS_INTERFACE,
++ .bDescriptorSubType = USB_CDC_UNION_TYPE,
++
++ .bMasterInterface0 = 0, /* index of control interface */
++ .bSlaveInterface0 = 1, /* index of DATA interface */
++};
++
++#endif /* CDC || RNDIS */
++
++#ifdef CONFIG_USB_ETH_RNDIS
++
++static const struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor = {
++ .bLength = sizeof call_mgmt_descriptor,
++ .bDescriptorType = USB_DT_CS_INTERFACE,
++ .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE,
++
++ .bmCapabilities = 0x00,
++ .bDataInterface = 0x01,
++};
++
++static struct usb_cdc_acm_descriptor acm_descriptor = {
++ .bLength = sizeof acm_descriptor,
++ .bDescriptorType = USB_DT_CS_INTERFACE,
++ .bDescriptorSubType = USB_CDC_ACM_TYPE,
++
++ .bmCapabilities = 0x00,
++};
++
++#endif
++
++#ifdef DEV_CONFIG_CDC
++
++static const struct usb_cdc_ether_desc ether_desc = {
++ .bLength = sizeof ether_desc,
++ .bDescriptorType = USB_DT_CS_INTERFACE,
++ .bDescriptorSubType = USB_CDC_ETHERNET_TYPE,
++
++ /* this descriptor actually adds value, surprise! */
++ .iMACAddress = STRING_ETHADDR,
++ .bmEthernetStatistics = __constant_cpu_to_le32 (0), /* no statistics */
++ .wMaxSegmentSize = __constant_cpu_to_le16 (ETH_FRAME_LEN),
++ .wNumberMCFilters = __constant_cpu_to_le16 (0),
++ .bNumberPowerFilters = 0,
++};
++
++#endif
++
++#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
++
++/* include the status endpoint if we can, even where it's optional.
++ * use wMaxPacketSize big enough to fit CDC_NOTIFY_SPEED_CHANGE in one
++ * packet, to simplify cancelation; and a big transfer interval, to
++ * waste less bandwidth.
++ *
++ * some drivers (like Linux 2.4 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).
++ *
++ * RNDIS requires the status endpoint, since it uses that encapsulation
++ * mechanism for its funky RPC scheme.
++ */
++
++#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */
++#define STATUS_BYTECOUNT 16 /* 8 byte header + data */
++
++static struct usb_endpoint_descriptor
++fs_status_desc = {
++ .bLength = USB_DT_ENDPOINT_SIZE,
++ .bDescriptorType = USB_DT_ENDPOINT,
++
++ .bEndpointAddress = USB_DIR_IN,
++ .bmAttributes = USB_ENDPOINT_XFER_INT,
++ .wMaxPacketSize = __constant_cpu_to_le16 (STATUS_BYTECOUNT),
++ .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
++};
++#endif
++
++#ifdef DEV_CONFIG_CDC
++
++/* 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,
++};
++
++/* ... but the "real" data interface has two 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,
++};
++
++#endif
++
++#ifdef CONFIG_USB_ETH_RNDIS
++
++/* RNDIS doesn't activate by changing to the "real" altsetting */
++
++static const struct usb_interface_descriptor
++rndis_data_intf = {
++ .bLength = sizeof rndis_data_intf,
++ .bDescriptorType = USB_DT_INTERFACE,
++
++ .bInterfaceNumber = 1,
++ .bAlternateSetting = 0,
++ .bNumEndpoints = 2,
++ .bInterfaceClass = USB_CLASS_CDC_DATA,
++ .bInterfaceSubClass = 0,
++ .bInterfaceProtocol = 0,
++ .iInterface = STRING_DATA,
++};
++
++#endif
++
++#ifdef DEV_CONFIG_SUBSET
++
++/*
++ * "Simple" CDC-subset 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
++subset_data_intf = {
++ .bLength = sizeof subset_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 /* SUBSET */
++
++
++static struct usb_endpoint_descriptor
++fs_source_desc = {
++ .bLength = USB_DT_ENDPOINT_SIZE,
++ .bDescriptorType = USB_DT_ENDPOINT,
++
++ .bEndpointAddress = USB_DIR_IN,
++ .bmAttributes = USB_ENDPOINT_XFER_BULK,
++};
++
++static struct usb_endpoint_descriptor
++fs_sink_desc = {
++ .bLength = USB_DT_ENDPOINT_SIZE,
++ .bDescriptorType = USB_DT_ENDPOINT,
++
++ .bEndpointAddress = USB_DIR_OUT,
++ .bmAttributes = USB_ENDPOINT_XFER_BULK,
++};
++
++static const struct usb_descriptor_header *fs_eth_function [11] = {
++ (struct usb_descriptor_header *) &otg_descriptor,
++#ifdef DEV_CONFIG_CDC
++ /* "cdc" mode descriptors */
++ (struct usb_descriptor_header *) &control_intf,
++ (struct usb_descriptor_header *) &header_desc,
++ (struct usb_descriptor_header *) &union_desc,
++ (struct usb_descriptor_header *) &ether_desc,
++ /* NOTE: status endpoint may need to be removed */
++ (struct usb_descriptor_header *) &fs_status_desc,
++ /* data interface, with altsetting */
++ (struct usb_descriptor_header *) &data_nop_intf,
++ (struct usb_descriptor_header *) &data_intf,
++ (struct usb_descriptor_header *) &fs_source_desc,
++ (struct usb_descriptor_header *) &fs_sink_desc,
++ NULL,
++#endif /* DEV_CONFIG_CDC */
++};
++
++static inline void __init fs_subset_descriptors(void)
++{
++#ifdef DEV_CONFIG_SUBSET
++ fs_eth_function[1] = (struct usb_descriptor_header *) &subset_data_intf;
++ fs_eth_function[2] = (struct usb_descriptor_header *) &fs_source_desc;
++ fs_eth_function[3] = (struct usb_descriptor_header *) &fs_sink_desc;
++ fs_eth_function[4] = NULL;
++#else
++ fs_eth_function[1] = NULL;
++#endif
++}
++
++#ifdef CONFIG_USB_ETH_RNDIS
++static const struct usb_descriptor_header *fs_rndis_function [] = {
++ (struct usb_descriptor_header *) &otg_descriptor,
++ /* control interface matches ACM, not Ethernet */
++ (struct usb_descriptor_header *) &rndis_control_intf,
++ (struct usb_descriptor_header *) &header_desc,
++ (struct usb_descriptor_header *) &call_mgmt_descriptor,
++ (struct usb_descriptor_header *) &acm_descriptor,
++ (struct usb_descriptor_header *) &union_desc,
++ (struct usb_descriptor_header *) &fs_status_desc,
++ /* data interface has no altsetting */
++ (struct usb_descriptor_header *) &rndis_data_intf,
++ (struct usb_descriptor_header *) &fs_source_desc,
++ (struct usb_descriptor_header *) &fs_sink_desc,
++ NULL,
++};
++#endif
++
++#ifdef CONFIG_USB_GADGET_DUALSPEED
++
++/*
++ * usb 2.0 devices need to expose both high speed and full speed
++ * descriptors, unless they only run at full speed.
++ */
++
++#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
++static struct usb_endpoint_descriptor
++hs_status_desc = {
++ .bLength = USB_DT_ENDPOINT_SIZE,
++ .bDescriptorType = USB_DT_ENDPOINT,
++
++ .bmAttributes = USB_ENDPOINT_XFER_INT,
++ .wMaxPacketSize = __constant_cpu_to_le16 (STATUS_BYTECOUNT),
++ .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
++};
++#endif /* DEV_CONFIG_CDC */
++
++static struct usb_endpoint_descriptor
++hs_source_desc = {
++ .bLength = USB_DT_ENDPOINT_SIZE,
++ .bDescriptorType = USB_DT_ENDPOINT,
++
++ .bmAttributes = USB_ENDPOINT_XFER_BULK,
++ .wMaxPacketSize = __constant_cpu_to_le16 (512),
++};
++
++static struct usb_endpoint_descriptor
++hs_sink_desc = {
++ .bLength = USB_DT_ENDPOINT_SIZE,
++ .bDescriptorType = USB_DT_ENDPOINT,
++
++ .bmAttributes = USB_ENDPOINT_XFER_BULK,
++ .wMaxPacketSize = __constant_cpu_to_le16 (512),
++};
++
++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_COMM,
++
++ .bNumConfigurations = 1,
++};
++
++static const struct usb_descriptor_header *hs_eth_function [11] = {
++ (struct usb_descriptor_header *) &otg_descriptor,
++#ifdef DEV_CONFIG_CDC
++ /* "cdc" mode descriptors */
++ (struct usb_descriptor_header *) &control_intf,
++ (struct usb_descriptor_header *) &header_desc,
++ (struct usb_descriptor_header *) &union_desc,
++ (struct usb_descriptor_header *) &ether_desc,
++ /* NOTE: status endpoint may need to be removed */
++ (struct usb_descriptor_header *) &hs_status_desc,
++ /* data interface, with altsetting */
++ (struct usb_descriptor_header *) &data_nop_intf,
++ (struct usb_descriptor_header *) &data_intf,
++ (struct usb_descriptor_header *) &hs_source_desc,
++ (struct usb_descriptor_header *) &hs_sink_desc,
++ NULL,
++#endif /* DEV_CONFIG_CDC */
++};
++
++static inline void __init hs_subset_descriptors(void)
++{
++#ifdef DEV_CONFIG_SUBSET
++ hs_eth_function[1] = (struct usb_descriptor_header *) &subset_data_intf;
++ hs_eth_function[2] = (struct usb_descriptor_header *) &fs_source_desc;
++ hs_eth_function[3] = (struct usb_descriptor_header *) &fs_sink_desc;
++ hs_eth_function[4] = NULL;
++#else
++ hs_eth_function[1] = NULL;
++#endif
++}
++
++#ifdef CONFIG_USB_ETH_RNDIS
++static const struct usb_descriptor_header *hs_rndis_function [] = {
++ (struct usb_descriptor_header *) &otg_descriptor,
++ /* control interface matches ACM, not Ethernet */
++ (struct usb_descriptor_header *) &rndis_control_intf,
++ (struct usb_descriptor_header *) &header_desc,
++ (struct usb_descriptor_header *) &call_mgmt_descriptor,
++ (struct usb_descriptor_header *) &acm_descriptor,
++ (struct usb_descriptor_header *) &union_desc,
++ (struct usb_descriptor_header *) &hs_status_desc,
++ /* data interface has no altsetting */
++ (struct usb_descriptor_header *) &rndis_data_intf,
++ (struct usb_descriptor_header *) &hs_source_desc,
++ (struct usb_descriptor_header *) &hs_sink_desc,
++ NULL,
++};
++#endif
++
++
++/* 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
++
++static inline void __init hs_subset_descriptors(void)
++{
++}
++
++#endif /* !CONFIG_USB_GADGET_DUALSPEED */
++
++/*-------------------------------------------------------------------------*/
++
++/* descriptors that are built on-demand */
++
++static char manufacturer [50];
++static char product_desc [40] = DRIVER_DESC;
++
++#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 UTF-8 */
++static struct usb_string strings [] = {
++ { STRING_MANUFACTURER, manufacturer, },
++ { STRING_PRODUCT, product_desc, },
++ { STRING_DATA, "Ethernet Data", },
++#ifdef DEV_CONFIG_CDC
++ { STRING_CDC, "CDC Ethernet", },
++ { STRING_ETHADDR, ethaddr, },
++ { STRING_CONTROL, "CDC Communications Control", },
++#endif
++#ifdef DEV_CONFIG_SUBSET
++ { STRING_SUBSET, "CDC Ethernet Subset", },
++#endif
++#ifdef CONFIG_USB_ETH_RNDIS
++ { STRING_RNDIS, "RNDIS", },
++ { STRING_RNDIS_CONTROL, "RNDIS Communications Control", },
++#endif
++ { } /* 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, int is_otg)
++{
++ int len;
++ const struct usb_config_descriptor *config;
++ const struct usb_descriptor_header **function;
++#ifdef CONFIG_USB_GADGET_DUALSPEED
++ int hs = (speed == USB_SPEED_HIGH);
++
++ if (type == USB_DT_OTHER_SPEED_CONFIG)
++ hs = !hs;
++#define which_fn(t) (hs ? hs_ ## t ## _function : fs_ ## t ## _function)
++#else
++#define which_fn(t) (fs_ ## t ## _function)
++#endif
++
++ if (index >= device_desc.bNumConfigurations)
++ return -EINVAL;
++
++#ifdef CONFIG_USB_ETH_RNDIS
++ /* list the RNDIS config first, to make Microsoft's drivers
++ * happy. DOCSIS 1.0 needs this too.
++ */
++ if (device_desc.bNumConfigurations == 2 && index == 0) {
++ config = &rndis_config;
++ function = which_fn (rndis);
++ } else
++#endif
++ {
++ config = &eth_config;
++ function = which_fn (eth);
++ }
++
++ /* for now, don't advertise srp-only devices */
++ if (!is_otg)
++ function++;
++
++ len = usb_gadget_config_buf (config, buf, USB_BUFSIZ, function);
++ if (len < 0)
++ return len;
++ ((struct usb_config_descriptor *) buf)->bDescriptorType = type;
++ return 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);
++
++#ifdef DEV_CONFIG_CDC
++static inline int ether_alt_ep_setup (struct eth_dev *dev, struct usb_ep *ep)
++{
++ const struct usb_endpoint_descriptor *d;
++
++ /* 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. Reset from SET_INTERFACE.
++ *
++ * Strictly speaking RNDIS should work the same: activation is
++ * a side effect of setting a packet filter. Deactivation is
++ * from REMOTE_NDIS_HALT_MSG, reset from REMOTE_NDIS_RESET_MSG.
++ */
++
++ /* one endpoint writes data back IN to the host */
++ if (strcmp (ep->name, EP_IN_NAME) == 0) {
++ d = ep_desc (dev->gadget, &hs_source_desc, &fs_source_desc);
++ ep->driver_data = dev;
++ dev->in = d;
++
++ /* one endpoint just reads OUT packets */
++ } else if (strcmp (ep->name, EP_OUT_NAME) == 0) {
++ d = ep_desc (dev->gadget, &hs_sink_desc, &fs_sink_desc);
++ ep->driver_data = dev;
++ dev->out = d;
++
++ /* optional status/notification endpoint */
++ } else if (EP_STATUS_NAME &&
++ strcmp (ep->name, EP_STATUS_NAME) == 0) {
++ int result;
++
++ d = ep_desc (dev->gadget, &hs_status_desc, &fs_status_desc);
++ result = usb_ep_enable (ep, d);
++ if (result < 0)
++ return result;
++
++ ep->driver_data = dev;
++ dev->status = d;
++ }
++ return 0;
++}
++#endif
++
++#if defined(DEV_CONFIG_SUBSET) || defined(CONFIG_USB_ETH_RNDIS)
++static inline int ether_ep_setup (struct eth_dev *dev, struct usb_ep *ep)
++{
++ int result;
++ const struct usb_endpoint_descriptor *d;
++
++ /* CDC subset is simpler: if the device is there,
++ * it's live with rx and tx endpoints.
++ *
++ * Do this as a shortcut for RNDIS too.
++ */
++
++ /* one endpoint writes data back IN to the host */
++ if (strcmp (ep->name, EP_IN_NAME) == 0) {
++ d = ep_desc (dev->gadget, &hs_source_desc, &fs_source_desc);
++ result = usb_ep_enable (ep, d);
++ if (result < 0)
++ return result;
++
++ ep->driver_data = dev;
++ dev->in = d;
++
++ /* one endpoint just reads OUT packets */
++ } else if (strcmp (ep->name, EP_OUT_NAME) == 0) {
++ d = ep_desc (dev->gadget, &hs_sink_desc, &fs_sink_desc);
++ result = usb_ep_enable (ep, d);
++ if (result < 0)
++ return result;
++
++ ep->driver_data = dev;
++ dev->out = d;
++ }
++
++ return 0;
++}
++#endif
++
++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) {
++#ifdef DEV_CONFIG_CDC
++ if (!dev->rndis && dev->cdc) {
++ result = ether_alt_ep_setup (dev, ep);
++ if (result == 0)
++ continue;
++ }
++#endif
++
++#ifdef CONFIG_USB_ETH_RNDIS
++ if (dev->rndis && strcmp (ep->name, EP_STATUS_NAME) == 0) {
++ const struct usb_endpoint_descriptor *d;
++ 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 = d;
++ continue;
++ }
++ } else
++#endif
++
++ {
++#if defined(DEV_CONFIG_SUBSET) || defined(CONFIG_USB_ETH_RNDIS)
++ result = ether_ep_setup (dev, ep);
++ if (result == 0)
++ continue;
++#endif
++ }
++
++ /* 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);
++
++ /* on error, disable any endpoints */
++ if (result < 0) {
++#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
++ if (dev->status)
++ (void) usb_ep_disable (dev->status_ep);
++#endif
++ dev->status = NULL;
++#if defined(DEV_CONFIG_SUBSET) || defined(CONFIG_USB_ETH_RNDIS)
++ if (dev->rndis || !dev->cdc) {
++ if (dev->in)
++ (void) usb_ep_disable (dev->in_ep);
++ if (dev->out)
++ (void) usb_ep_disable (dev->out_ep);
++ }
++#endif
++ dev->in = NULL;
++ dev->out = NULL;
++ } else
++
++ /* activate non-CDC configs right away
++ * this isn't strictly according to the RNDIS spec
++ */
++#if defined(DEV_CONFIG_SUBSET) || defined(CONFIG_USB_ETH_RNDIS)
++ if (dev->rndis || !dev->cdc) {
++ netif_carrier_on (dev->net);
++ if (netif_running (dev->net)) {
++ spin_unlock (&dev->lock);
++ eth_start (dev, GFP_ATOMIC);
++ spin_lock (&dev->lock);
++ }
++ }
++#endif
++
++ 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)
++{
++ struct usb_request *req;
++
++ if (dev->config == 0)
++ return;
++
++ DEBUG (dev, "%s\n", __FUNCTION__);
++
++ netif_stop_queue (dev->net);
++ netif_carrier_off (dev->net);
++
++ /* disable endpoints, forcing (synchronous) completion of
++ * pending i/o. then free the requests.
++ */
++ if (dev->in) {
++ usb_ep_disable (dev->in_ep);
++ while (likely (!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);
++ }
++ }
++ if (dev->out) {
++ usb_ep_disable (dev->out_ep);
++ while (likely (!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);
++ }
++ }
++
++ if (dev->status) {
++ usb_ep_disable (dev->status_ep);
++ }
++ 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;
++
++ if (gadget_is_sa1100 (gadget)
++ && 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;
++ }
++ eth_reset_config (dev);
++
++ /* default: pass all packets, no multicast filtering */
++ dev->cdc_filter = 0x000f;
++
++ switch (number) {
++ case DEV_CONFIG_VALUE:
++ dev->rndis = 0;
++ result = set_ether_config (dev, gfp_flags);
++ break;
++#ifdef CONFIG_USB_ETH_RNDIS
++ case DEV_RNDIS_CONFIG_VALUE:
++ dev->rndis = 1;
++ result = set_ether_config (dev, gfp_flags);
++ break;
++#endif
++ default:
++ result = -EINVAL;
++ /* FALL THROUGH */
++ case 0:
++ break;
++ }
++
++ if (result) {
++ if (number)
++ eth_reset_config (dev);
++ usb_gadget_vbus_draw(dev->gadget,
++ dev->gadget->is_otg ? 8 : 100);
++ } else {
++ char *speed;
++ unsigned power;
++
++ power = 2 * eth_config.bMaxPower;
++ usb_gadget_vbus_draw(dev->gadget, power);
++
++ switch (gadget->speed) {
++ case USB_SPEED_FULL: speed = "full"; break;
++#ifdef CONFIG_USB_GADGET_DUALSPEED
++ case USB_SPEED_HIGH: speed = "high"; break;
++#endif
++ default: speed = "?"; break;
++ }
++
++ dev->config = number;
++ INFO (dev, "%s speed config #%d: %d mA, %s, using %s\n",
++ speed, number, power, driver_desc,
++ dev->rndis
++ ? "RNDIS"
++ : (dev->cdc
++ ? "CDC Ethernet"
++ : "CDC Ethernet Subset"));
++ }
++ return result;
++}
++
++/*-------------------------------------------------------------------------*/
++
++#ifdef DEV_CONFIG_CDC
++
++static void eth_status_complete (struct usb_ep *ep, struct usb_request *req)
++{
++ struct usb_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 == USB_CDC_NOTIFY_NETWORK_CONNECTION
++ && value == 0) {
++ __le32 *data = req->buf + sizeof *event;
++
++ event->bmRequestType = 0xA1;
++ event->bNotificationType = USB_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 */
++ data [0] = data [1] = cpu_to_le32 (BITRATE (dev->gadget));
++
++ req->length = STATUS_BYTECOUNT;
++ value = usb_ep_queue (ep, req, GFP_ATOMIC);
++ DEBUG (dev, "send SPEED_CHANGE --> %d\n", value);
++ if (value == 0)
++ return;
++ } else if (value != -ECONNRESET)
++ DEBUG (dev, "event %02x --> %d\n",
++ event->bNotificationType, value);
++ event->bmRequestType = 0xff;
++}
++
++static void issue_start_status (struct eth_dev *dev)
++{
++ struct usb_request *req = dev->stat_req;
++ struct usb_cdc_notification *event;
++ int value;
++
++ DEBUG (dev, "%s, flush old status first\n", __FUNCTION__);
++
++ /* flush old status
++ *
++ * FIXME ugly idiom, maybe we'd be better with just
++ * a "cancel the whole queue" primitive since any
++ * unlink-one primitive has way too many error modes.
++ * here, we "know" toggle is already clear...
++ */
++ usb_ep_disable (dev->status_ep);
++ usb_ep_enable (dev->status_ep, dev->status);
++
++ /* 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 = USB_CDC_NOTIFY_NETWORK_CONNECTION;
++ event->wValue = __constant_cpu_to_le16 (1); /* connected */
++ event->wIndex = __constant_cpu_to_le16 (1);
++ event->wLength = 0;
++
++ req->length = sizeof *event;
++ 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);
++}
++
++#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);
++}
++
++#ifdef CONFIG_USB_ETH_RNDIS
++
++static void rndis_response_complete (struct usb_ep *ep, struct usb_request *req)
++{
++ if (req->status || req->actual != req->length)
++ DEBUG ((struct eth_dev *) ep->driver_data,
++ "rndis response complete --> %d, %d/%d\n",
++ req->status, req->actual, req->length);
++
++ /* done sending after USB_CDC_GET_ENCAPSULATED_RESPONSE */
++}
++
++static void rndis_command_complete (struct usb_ep *ep, struct usb_request *req)
++{
++ struct eth_dev *dev = ep->driver_data;
++ int status;
++
++ /* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */
++ spin_lock(&dev->lock);
++ status = rndis_msg_parser (dev->rndis_config, (u8 *) req->buf);
++ if (status < 0)
++ ERROR(dev, "%s: rndis parse error %d\n", __FUNCTION__, status);
++ spin_unlock(&dev->lock);
++}
++
++#endif /* RNDIS */
++
++/*
++ * 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
++ * - Ethernet data interface has two altsettings: default, and active
++ * - class-specific descriptors for the control interface
++ * - class-specific control requests
++ */
++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;
++ u16 wIndex = ctrl->wIndex;
++ u16 wValue = ctrl->wValue;
++ u16 wLength = ctrl->wLength;
++
++ /* descriptors just go into the pre-allocated ep0 buffer,
++ * while config change events may enable network traffic.
++ */
++ req->complete = eth_setup_complete;
++ switch (ctrl->bRequest) {
++
++ case USB_REQ_GET_DESCRIPTOR:
++ if (ctrl->bRequestType != USB_DIR_IN)
++ break;
++ switch (wValue >> 8) {
++
++ case USB_DT_DEVICE:
++ value = min (wLength, (u16) sizeof device_desc);
++ memcpy (req->buf, &device_desc, value);
++ break;
++#ifdef CONFIG_USB_GADGET_DUALSPEED
++ case USB_DT_DEVICE_QUALIFIER:
++ if (!gadget->is_dualspeed)
++ break;
++ value = min (wLength, (u16) sizeof dev_qualifier);
++ memcpy (req->buf, &dev_qualifier, value);
++ break;
++
++ case USB_DT_OTHER_SPEED_CONFIG:
++ if (!gadget->is_dualspeed)
++ break;
++ // FALLTHROUGH
++#endif /* CONFIG_USB_GADGET_DUALSPEED */
++ case USB_DT_CONFIG:
++ value = config_buf (gadget->speed, req->buf,
++ wValue >> 8,
++ wValue & 0xff,
++ gadget->is_otg);
++ if (value >= 0)
++ value = min (wLength, (u16) value);
++ break;
++
++ case USB_DT_STRING:
++ value = usb_gadget_get_string (&stringtab,
++ wValue & 0xff, req->buf);
++ if (value >= 0)
++ value = min (wLength, (u16) value);
++ break;
++ }
++ break;
++
++ case USB_REQ_SET_CONFIGURATION:
++ if (ctrl->bRequestType != 0)
++ break;
++ if (gadget->a_hnp_support)
++ DEBUG (dev, "HNP available\n");
++ else if (gadget->a_alt_hnp_support)
++ DEBUG (dev, "HNP needs a different root port\n");
++ spin_lock (&dev->lock);
++ value = eth_set_config (dev, wValue, GFP_ATOMIC);
++ spin_unlock (&dev->lock);
++ break;
++ case USB_REQ_GET_CONFIGURATION:
++ if (ctrl->bRequestType != USB_DIR_IN)
++ break;
++ *(u8 *)req->buf = dev->config;
++ value = min (wLength, (u16) 1);
++ break;
++
++ case USB_REQ_SET_INTERFACE:
++ if (ctrl->bRequestType != USB_RECIP_INTERFACE
++ || !dev->config
++ || wIndex > 1)
++ break;
++ if (!dev->cdc && wIndex != 0)
++ break;
++ spin_lock (&dev->lock);
++
++ /* PXA hardware partially handles SET_INTERFACE;
++ * we need to kluge around that interference.
++ */
++ if (gadget_is_pxa (gadget)) {
++ value = eth_set_config (dev, DEV_CONFIG_VALUE,
++ GFP_ATOMIC);
++ goto done_set_intf;
++ }
++
++#ifdef DEV_CONFIG_CDC
++ switch (wIndex) {
++ case 0: /* control/master intf */
++ if (wValue != 0)
++ break;
++ if (dev->status) {
++ usb_ep_disable (dev->status_ep);
++ usb_ep_enable (dev->status_ep, dev->status);
++ }
++ value = 0;
++ break;
++ case 1: /* data intf */
++ if (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 (wValue == 1) {
++ usb_ep_enable (dev->in_ep, dev->in);
++ usb_ep_enable (dev->out_ep, dev->out);
++ dev->cdc_filter = DEFAULT_FILTER;
++ netif_carrier_on (dev->net);
++ if (dev->status)
++ issue_start_status (dev);
++ if (netif_running (dev->net)) {
++ spin_unlock (&dev->lock);
++ eth_start (dev, GFP_ATOMIC);
++ spin_lock (&dev->lock);
++ }
++ } else {
++ netif_stop_queue (dev->net);
++ netif_carrier_off (dev->net);
++ }
++ value = 0;
++ break;
++ }
++#else
++ /* FIXME this is wrong, as is the assumption that
++ * all non-PXA hardware talks real CDC ...
++ */
++ WARN(dev, "set_interface ignored!\n");
++#endif /* DEV_CONFIG_CDC */
++
++done_set_intf:
++ spin_unlock (&dev->lock);
++ break;
++ case USB_REQ_GET_INTERFACE:
++ if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)
++ || !dev->config
++ || wIndex > 1)
++ break;
++ if (!(dev->cdc || dev->rndis) && wIndex != 0)
++ break;
++
++ /* for CDC, iff carrier is on, data interface is active. */
++ if (dev->rndis || wIndex != 1)
++ *(u8 *)req->buf = 0;
++ else
++ *(u8 *)req->buf = netif_carrier_ok (dev->net) ? 1 : 0;
++ value = min (wLength, (u16) 1);
++ break;
++
++#ifdef DEV_CONFIG_CDC
++ case USB_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)
++ || !dev->cdc
++ || dev->rndis
++ || wLength != 0
++ || wIndex > 1)
++ break;
++ DEBUG (dev, "packet filter %02x\n", wValue);
++ dev->cdc_filter = wValue;
++ value = 0;
++ break;
++
++ /* and potentially:
++ * case USB_CDC_SET_ETHERNET_MULTICAST_FILTERS:
++ * case USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER:
++ * case USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER:
++ * case USB_CDC_GET_ETHERNET_STATISTIC:
++ */
++
++#endif /* DEV_CONFIG_CDC */
++
++#ifdef CONFIG_USB_ETH_RNDIS
++ /* RNDIS uses the CDC command encapsulation mechanism to implement
++ * an RPC scheme, with much getting/setting of attributes by OID.
++ */
++ case USB_CDC_SEND_ENCAPSULATED_COMMAND:
++ if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE)
++ || !dev->rndis
++ || wLength > USB_BUFSIZ
++ || wValue
++ || rndis_control_intf.bInterfaceNumber
++ != wIndex)
++ break;
++ /* read the request, then process it */
++ value = wLength;
++ req->complete = rndis_command_complete;
++ /* later, rndis_control_ack () sends a notification */
++ break;
++
++ case USB_CDC_GET_ENCAPSULATED_RESPONSE:
++ if ((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE)
++ == ctrl->bRequestType
++ && dev->rndis
++ // && wLength >= 0x0400
++ && !wValue
++ && rndis_control_intf.bInterfaceNumber
++ == wIndex) {
++ u8 *buf;
++
++ /* return the result */
++ buf = rndis_get_next_response (dev->rndis_config,
++ &value);
++ if (buf) {
++ memcpy (req->buf, buf, value);
++ req->complete = rndis_response_complete;
++ rndis_free_response(dev->rndis_config, buf);
++ }
++ /* else stalls ... spec says to avoid that */
++ }
++ break;
++#endif /* RNDIS */
++
++ default:
++ VDEBUG (dev,
++ "unknown control req%02x.%02x v%04x i%04x l%d\n",
++ ctrl->bRequestType, ctrl->bRequest,
++ wValue, wIndex, wLength);
++ }
++
++ /* respond with data transfer before status phase? */
++ if (value >= 0) {
++ req->length = value;
++ req->zero = value < wLength
++ && (value % gadget->ep0->maxpacket) == 0;
++ 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);
++
++ /* FIXME RNDIS should enter RNDIS_UNINITIALIZED */
++
++ /* 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) */
++
++/* glue code: in more recent 2.4 kernels these functions are contained in netdev.h */
++
++#ifndef HAVE_NETDEV_PRIV
++static inline void *netdev_priv(struct net_device *net)
++{
++ return net->priv;
++}
++#endif
++
++#ifndef HAVE_FREE_NETDEV
++static inline void free_netdev(struct net_device *dev)
++{
++ kfree(dev);
++}
++#endif
++
++static int eth_change_mtu (struct net_device *net, int new_mtu)
++{
++ struct eth_dev *dev = netdev_priv(net);
++
++ // FIXME if rndis, don't change while link's live
++
++ if (new_mtu <= ETH_HLEN || new_mtu > ETH_FRAME_LEN)
++ 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 *)netdev_priv(net))->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, dev->gadget->name, 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);
++
++#ifndef NET_IP_ALIGN
++/* this can be a cpu-specific value */
++#define NET_IP_ALIGN 2
++#endif
++
++static int
++rx_submit (struct eth_dev *dev, struct usb_request *req, int gfp_flags)
++{
++ struct sk_buff *skb;
++ int retval = -ENOMEM;
++ size_t size;
++
++ /* Padding up to RX_EXTRA handles minor disagreements with host.
++ * Normally we use the USB "terminate on short read" convention;
++ * so allow up to (N*maxpacket), since that memory is normally
++ * already allocated. Some hardware doesn't deal well with short
++ * reads (e.g. DMA must be N*maxpacket), so for now don't trim a
++ * byte off the end (to force hardware errors on overflow).
++ *
++ * RNDIS uses internal framing, and explicitly allows senders to
++ * pad to end-of-packet. That's potentially nice for speed,
++ * but means receivers can't recover synch on their own.
++ */
++ size = (sizeof (struct ethhdr) + dev->net->mtu + RX_EXTRA);
++ size += dev->out_ep->maxpacket - 1;
++#ifdef CONFIG_USB_ETH_RNDIS
++ if (dev->rndis)
++ size += sizeof (struct rndis_packet_msg_type);
++#endif
++ size -= size % dev->out_ep->maxpacket;
++
++ if ((skb = alloc_skb (size + NET_IP_ALIGN, gfp_flags)) == 0) {
++ DEBUG (dev, "no rx skb\n");
++ goto enomem;
++ }
++
++ /* Some platforms perform better when IP packets are aligned,
++ * but on at least one, checksumming fails otherwise. Note:
++ * this doesn't account for variable-sized RNDIS headers.
++ */
++ skb_reserve(skb, NET_IP_ALIGN);
++
++ 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)
++enomem:
++ defer_kevent (dev, WORK_RX_MEMORY);
++ if (retval) {
++ DEBUG (dev, "rx submit --> %d\n", retval);
++ dev_kfree_skb_any (skb);
++ spin_lock (&dev->lock);
++ list_add (&req->list, &dev->rx_reqs);
++ spin_unlock (&dev->lock);
++ }
++ 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);
++#ifdef CONFIG_USB_ETH_RNDIS
++ /* we know MaxPacketsPerTransfer == 1 here */
++ if (dev->rndis)
++ rndis_rm_hdr (req->buf, &(skb->len));
++#endif
++ if (ETH_HLEN > skb->len || skb->len > ETH_FRAME_LEN) {
++ 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 = NULL;
++ 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:
++ /* nobody reading rx_reqs, so no dev->lock */
++ list_add (&req->list, &dev->rx_reqs);
++ req = NULL;
++ }
++ 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;
++
++ if (!n)
++ return -ENOMEM;
++
++ /* queue/recycle up to 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 list_empty (list) ? -ENOMEM : 0;
++ 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;
++ unsigned long flags;
++
++ clear_bit (WORK_RX_MEMORY, &dev->todo);
++
++ /* fill unused rxq slots with some skb */
++ spin_lock_irqsave (&dev->lock, flags);
++ while (!list_empty (&dev->rx_reqs)) {
++ req = container_of (dev->rx_reqs.next,
++ struct usb_request, list);
++ list_del_init (&req->list);
++ spin_unlock_irqrestore (&dev->lock, flags);
++
++ if (rx_submit (dev, req, gfp_flags) < 0) {
++ defer_kevent (dev, WORK_RX_MEMORY);
++ return;
++ }
++
++ spin_lock_irqsave (&dev->lock, flags);
++ }
++ spin_unlock_irqrestore (&dev->lock, flags);
++}
++
++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++;
++
++ spin_lock (&dev->lock);
++ list_add (&req->list, &dev->tx_reqs);
++ spin_unlock (&dev->lock);
++ dev_kfree_skb_any (skb);
++
++ atomic_dec (&dev->tx_qlen);
++ if (netif_carrier_ok (dev->net))
++ netif_wake_queue (dev->net);
++}
++
++static inline int eth_is_promisc (struct eth_dev *dev)
++{
++ /* no filters for the CDC subset; always promisc */
++ if (subset_active (dev))
++ return 1;
++ return dev->cdc_filter & USB_CDC_PACKET_TYPE_PROMISCUOUS;
++}
++
++static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
++{
++ struct eth_dev *dev = netdev_priv(net);
++ int length = skb->len;
++ int retval;
++ struct usb_request *req = NULL;
++ unsigned long flags;
++
++ /* apply outgoing CDC or RNDIS filters */
++ if (!eth_is_promisc (dev)) {
++ u8 *dest = skb->data;
++
++ if (dest [0] & 0x01) {
++ u16 type;
++
++ /* ignores USB_CDC_PACKET_TYPE_MULTICAST and host
++ * SET_ETHERNET_MULTICAST_FILTERS requests
++ */
++ if (memcmp (dest, net->broadcast, ETH_ALEN) == 0)
++ type = USB_CDC_PACKET_TYPE_BROADCAST;
++ else
++ type = USB_CDC_PACKET_TYPE_ALL_MULTICAST;
++ if (!(dev->cdc_filter & type)) {
++ dev_kfree_skb_any (skb);
++ return 0;
++ }
++ }
++ /* ignores USB_CDC_PACKET_TYPE_DIRECTED */
++ }
++
++ spin_lock_irqsave (&dev->lock, flags);
++ 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);
++ spin_unlock_irqrestore (&dev->lock, flags);
++
++ /* no buffer copies needed, unless the network stack did it
++ * or the hardware can't use skb buffers.
++ * or there's not enough space for any RNDIS headers we need
++ */
++#ifdef CONFIG_USB_ETH_RNDIS
++ if (dev->rndis) {
++ struct sk_buff *skb_rndis;
++
++ skb_rndis = skb_realloc_headroom (skb,
++ sizeof (struct rndis_packet_msg_type));
++ if (!skb_rndis)
++ goto drop;
++
++ dev_kfree_skb_any (skb);
++ skb = skb_rndis;
++ rndis_add_hdr (skb);
++ length = skb->len;
++ }
++#endif
++ req->buf = skb->data;
++ req->context = skb;
++ req->complete = tx_complete;
++
++ /* use zlp framing on tx for strict CDC-Ether conformance,
++ * though any robust network rx path ignores extra padding.
++ * and some hardware doesn't like to write zlps.
++ */
++ req->zero = 1;
++ if (!dev->zlp && (length % dev->in_ep->maxpacket) == 0)
++ length++;
++
++ req->length = length;
++
++#ifdef CONFIG_USB_GADGET_DUALSPEED
++ /* 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) {
++#ifdef CONFIG_USB_ETH_RNDIS
++drop:
++#endif
++ dev->stats.tx_dropped++;
++ dev_kfree_skb_any (skb);
++ spin_lock_irqsave (&dev->lock, flags);
++ if (list_empty (&dev->tx_reqs))
++ netif_start_queue (net);
++ list_add (&req->list, &dev->tx_reqs);
++ spin_unlock_irqrestore (&dev->lock, flags);
++ }
++ return 0;
++}
++
++/*-------------------------------------------------------------------------*/
++
++#ifdef CONFIG_USB_ETH_RNDIS
++
++static void rndis_send_media_state (struct eth_dev *dev, int connect)
++{
++ if (!dev)
++ return;
++
++ if (connect) {
++ if (rndis_signal_connect (dev->rndis_config))
++ return;
++ } else {
++ if (rndis_signal_disconnect (dev->rndis_config))
++ return;
++ }
++}
++
++static void
++rndis_control_ack_complete (struct usb_ep *ep, struct usb_request *req)
++{
++ if (req->status || req->actual != req->length)
++ DEBUG ((struct eth_dev *) ep->driver_data,
++ "rndis control ack complete --> %d, %d/%d\n",
++ req->status, req->actual, req->length);
++
++ usb_ep_free_buffer(ep, req->buf, req->dma, 8);
++ usb_ep_free_request(ep, req);
++}
++
++static int rndis_control_ack (struct net_device *net)
++{
++ struct eth_dev *dev = netdev_priv(net);
++ u32 length;
++ struct usb_request *resp;
++
++ /* in case RNDIS calls this after disconnect */
++ if (!dev->status_ep) {
++ DEBUG (dev, "status ENODEV\n");
++ return -ENODEV;
++ }
++
++ /* Allocate memory for notification ie. ACK */
++ resp = usb_ep_alloc_request (dev->status_ep, GFP_ATOMIC);
++ if (!resp) {
++ DEBUG (dev, "status ENOMEM\n");
++ return -ENOMEM;
++ }
++
++ resp->buf = usb_ep_alloc_buffer (dev->status_ep, 8,
++ &resp->dma, GFP_ATOMIC);
++ if (!resp->buf) {
++ DEBUG (dev, "status buf ENOMEM\n");
++ usb_ep_free_request (dev->status_ep, resp);
++ return -ENOMEM;
++ }
++
++ /* Send RNDIS RESPONSE_AVAILABLE notification;
++ * USB_CDC_NOTIFY_RESPONSE_AVAILABLE should work too
++ */
++ resp->length = 8;
++ resp->complete = rndis_control_ack_complete;
++
++ *((__le32 *) resp->buf) = __constant_cpu_to_le32 (1);
++ *((__le32 *) resp->buf + 1) = __constant_cpu_to_le32 (0);
++
++ length = usb_ep_queue (dev->status_ep, resp, GFP_ATOMIC);
++ if (length < 0) {
++ resp->status = 0;
++ rndis_control_ack_complete (dev->status_ep, resp);
++ }
++
++ return 0;
++}
++
++#endif /* RNDIS */
++
++static void eth_start (struct eth_dev *dev, int gfp_flags)
++{
++ DEBUG (dev, "%s\n", __FUNCTION__);
++
++ /* fill the rx queue */
++ rx_fill (dev, gfp_flags);
++
++ /* and open the tx floodgates */
++ atomic_set (&dev->tx_qlen, 0);
++ netif_wake_queue (dev->net);
++#ifdef CONFIG_USB_ETH_RNDIS
++ if (dev->rndis) {
++ rndis_set_param_medium (dev->rndis_config,
++ NDIS_MEDIUM_802_3,
++ BITRATE(dev->gadget));
++ rndis_send_media_state (dev, 1);
++ }
++#endif
++}
++
++static int eth_open (struct net_device *net)
++{
++ struct eth_dev *dev = netdev_priv(net);
++
++ 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 = netdev_priv(net);
++
++ VDEBUG (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->config) {
++ 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");
++ // FIXME idiom may leave toggle wrong here
++ usb_ep_enable (dev->in_ep, dev->in);
++ usb_ep_enable (dev->out_ep, dev->out);
++ }
++ if (dev->status_ep) {
++ usb_ep_disable (dev->status_ep);
++ usb_ep_enable (dev->status_ep, dev->status);
++ }
++ }
++
++#ifdef CONFIG_USB_ETH_RNDIS
++ if (dev->rndis) {
++ rndis_set_param_medium (dev->rndis_config,
++ NDIS_MEDIUM_802_3, 0);
++ rndis_send_media_state (dev, 0);
++ }
++#endif
++
++ return 0;
++}
++
++/*-------------------------------------------------------------------------*/
++
++static struct usb_request *eth_req_alloc (struct usb_ep *ep, unsigned size)
++{
++ struct usb_request *req;
++
++ req = usb_ep_alloc_request (ep, GFP_KERNEL);
++ if (!req)
++ return NULL;
++
++ req->buf = kmalloc (size, GFP_KERNEL);
++ if (!req->buf) {
++ usb_ep_free_request (ep, req);
++ req = NULL;
++ }
++ return req;
++}
++
++static void
++eth_req_free (struct usb_ep *ep, struct usb_request *req)
++{
++ kfree (req->buf);
++ usb_ep_free_request (ep, req);
++}
++
++
++static void
++eth_unbind (struct usb_gadget *gadget)
++{
++ struct eth_dev *dev = get_gadget_data (gadget);
++
++ DEBUG (dev, "unbind\n");
++#ifdef CONFIG_USB_ETH_RNDIS
++ rndis_deregister (dev->rndis_config);
++ rndis_exit ();
++#endif
++
++ /* we've already been disconnected ... no i/o is active */
++ if (dev->req) {
++ eth_req_free (gadget->ep0, dev->req);
++ dev->req = NULL;
++ }
++ if (dev->stat_req) {
++ eth_req_free (dev->status_ep, dev->stat_req);
++ dev->stat_req = NULL;
++ }
++
++ unregister_netdev (dev->net);
++ free_netdev(dev->net);
++
++ /* assuming we used keventd, it must quiesce too */
++ flush_scheduled_work ();
++ set_gadget_data (gadget, NULL);
++}
++
++static u8 __init nibble (unsigned char c)
++{
++ if (likely (isdigit (c)))
++ return c - '0';
++ c = toupper (c);
++ if (likely (isxdigit (c)))
++ return 10 + c - 'A';
++ return 0;
++}
++
++static void __init get_ether_addr (const char *str, u8 *dev_addr)
++{
++ if (str) {
++ unsigned i;
++
++ for (i = 0; i < 6; i++) {
++ unsigned char num;
++
++ if((*str == '.') || (*str == ':'))
++ str++;
++ num = nibble(*str++) << 4;
++ num |= (nibble(*str++));
++ dev_addr [i] = num;
++ }
++ if (is_valid_ether_addr (dev_addr))
++ return;
++ }
++ random_ether_addr(dev_addr);
++}
++
++static int __init
++eth_bind (struct usb_gadget *gadget)
++{
++ struct eth_dev *dev;
++ struct net_device *net;
++ u8 cdc = 1, zlp = 1, rndis = 1;
++ struct usb_ep *in_ep, *out_ep, *status_ep = NULL;
++ int status = -ENOMEM;
++
++ /* these flags are only ever cleared; compiler take note */
++#ifndef DEV_CONFIG_CDC
++ cdc = 0;
++#endif
++#ifndef CONFIG_USB_ETH_RNDIS
++ rndis = 0;
++#endif
++
++ /* Because most host side USB stacks handle CDC Ethernet, that
++ * standard protocol is _strongly_ preferred for interop purposes.
++ * (By everyone except Microsoft.)
++ */
++ if (gadget_is_net2280 (gadget)) {
++ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0201);
++ } else if (gadget_is_dummy (gadget)) {
++ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0202);
++ } else if (gadget_is_pxa (gadget)) {
++ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0203);
++ /* pxa doesn't support altsettings */
++ cdc = 0;
++ } else if (gadget_is_sh(gadget)) {
++ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0204);
++ /* sh doesn't support multiple interfaces or configs */
++ cdc = 0;
++ rndis = 0;
++ } else if (gadget_is_sa1100 (gadget)) {
++ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0205);
++ /* hardware can't write zlps */
++ zlp = 0;
++ /* sa1100 CAN do CDC, without status endpoint ... we use
++ * non-CDC to be compatible with ARM Linux-2.4 "usb-eth".
++ */
++ cdc = 0;
++ } else if (gadget_is_goku (gadget)) {
++ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0206);
++ } else if (gadget_is_mq11xx (gadget)) {
++ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0207);
++ } else if (gadget_is_omap (gadget)) {
++ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0208);
++ } else if (gadget_is_lh7a40x(gadget)) {
++ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0209);
++ } else if (gadget_is_n9604(gadget)) {
++ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0210);
++ } else if (gadget_is_pxa27x(gadget)) {
++ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0211);
++ } else if (gadget_is_s3c2410(gadget)) {
++ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0212);
++ } else if (gadget_is_at91(gadget)) {
++ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0213);
++ } else {
++ /* can't assume CDC works. don't want to default to
++ * anything less functional on CDC-capable hardware,
++ * so we fail in this case.
++ */
++ printk (KERN_ERR "%s: "
++ "controller '%s' not recognized\n",
++ shortname, gadget->name);
++ return -ENODEV;
++ }
++ snprintf (manufacturer, sizeof manufacturer,
++ UTS_SYSNAME " " UTS_RELEASE "/%s",
++ gadget->name);
++
++ /* If there's an RNDIS configuration, that's what Windows wants to
++ * be using ... so use these product IDs here and in the "linux.inf"
++ * needed to install MSFT drivers. Current Linux kernels will use
++ * the second configuration if it's CDC Ethernet, and need some help
++ * to choose the right configuration otherwise.
++ */
++ if (rndis) {
++ device_desc.idVendor =
++ __constant_cpu_to_le16(RNDIS_VENDOR_NUM);
++ device_desc.idProduct =
++ __constant_cpu_to_le16(RNDIS_PRODUCT_NUM);
++ snprintf (product_desc, sizeof product_desc,
++ "RNDIS/%s", driver_desc);
++
++ /* CDC subset ... recognized by Linux since 2.4.10, but Windows
++ * drivers aren't widely available.
++ */
++ } else if (!cdc) {
++ device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
++ device_desc.idVendor =
++ __constant_cpu_to_le16(SIMPLE_VENDOR_NUM);
++ device_desc.idProduct =
++ __constant_cpu_to_le16(SIMPLE_PRODUCT_NUM);
++ }
++
++ /* support optional vendor/distro customization */
++ if (idVendor) {
++ if (!idProduct) {
++ printk (KERN_ERR "%s: idVendor needs idProduct!\n",
++ shortname);
++ return -ENODEV;
++ }
++ device_desc.idVendor = cpu_to_le16(idVendor);
++ device_desc.idProduct = cpu_to_le16(idProduct);
++ if (bcdDevice)
++ device_desc.bcdDevice = cpu_to_le16(bcdDevice);
++ }
++ if (iManufacturer)
++ strncpy (manufacturer, iManufacturer, sizeof manufacturer);
++ if (iProduct)
++ strncpy (product_desc, iProduct, sizeof product_desc);
++
++ /* all we really need is bulk IN/OUT */
++ usb_ep_autoconfig_reset (gadget);
++ in_ep = usb_ep_autoconfig (gadget, &fs_source_desc);
++ if (!in_ep) {
++autoconf_fail:
++ printk (KERN_ERR "%s: can't autoconfigure on %s\n",
++ shortname, gadget->name);
++ return -ENODEV;
++ }
++ EP_IN_NAME = in_ep->name;
++ in_ep->driver_data = in_ep; /* claim */
++
++ out_ep = usb_ep_autoconfig (gadget, &fs_sink_desc);
++ if (!out_ep)
++ goto autoconf_fail;
++ EP_OUT_NAME = out_ep->name;
++ out_ep->driver_data = out_ep; /* claim */
++
++#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
++ /* CDC Ethernet control interface doesn't require a status endpoint.
++ * Since some hosts expect one, try to allocate one anyway.
++ */
++ if (cdc || rndis) {
++ status_ep = usb_ep_autoconfig (gadget, &fs_status_desc);
++ if (status_ep) {
++ EP_STATUS_NAME = status_ep->name;
++ status_ep->driver_data = status_ep; /* claim */
++ } else if (rndis) {
++ printk (KERN_ERR "%s: "
++ "can't run RNDIS on %s\n",
++ shortname, gadget->name);
++ return -ENODEV;
++#ifdef DEV_CONFIG_CDC
++ /* pxa25x only does CDC subset; often used with RNDIS */
++ } else if (cdc) {
++ control_intf.bNumEndpoints = 0;
++ /* FIXME remove endpoint from descriptor list */
++#endif
++ }
++ }
++#endif
++
++ /* one config: cdc, else minimal subset */
++ if (!cdc) {
++ eth_config.bNumInterfaces = 1;
++ eth_config.iConfiguration = STRING_SUBSET;
++ fs_subset_descriptors();
++ hs_subset_descriptors();
++ }
++
++ /* For now RNDIS is always a second config */
++ if (rndis)
++ device_desc.bNumConfigurations = 2;
++
++#ifdef CONFIG_USB_GADGET_DUALSPEED
++ if (rndis)
++ dev_qualifier.bNumConfigurations = 2;
++ else if (!cdc)
++ dev_qualifier.bDeviceClass = USB_CLASS_VENDOR_SPEC;
++
++ /* assumes ep0 uses the same value for both speeds ... */
++ dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
++
++ /* and that all endpoints are dual-speed */
++ hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
++ hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
++#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
++ if (EP_STATUS_NAME)
++ hs_status_desc.bEndpointAddress =
++ fs_status_desc.bEndpointAddress;
++#endif
++#endif /* DUALSPEED */
++
++ device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
++ usb_gadget_set_selfpowered (gadget);
++
++ if (gadget->is_otg) {
++ otg_descriptor.bmAttributes |= USB_OTG_HNP,
++ eth_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
++ eth_config.bMaxPower = 4;
++#ifdef CONFIG_USB_ETH_RNDIS
++ rndis_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
++ rndis_config.bMaxPower = 4;
++#endif
++ }
++
++ net = alloc_etherdev (sizeof *dev);
++ if (!net)
++ return status;
++ dev = netdev_priv(net);
++ 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);
++ strcpy (net->name, "usb%d");
++ dev->cdc = cdc;
++ dev->zlp = zlp;
++
++ dev->in_ep = in_ep;
++ dev->out_ep = out_ep;
++ dev->status_ep = status_ep;
++
++ /* Module params for these addresses should come from ID proms.
++ * The host side address is used with CDC and RNDIS, and commonly
++ * ends up in a persistent config database.
++ */
++ get_ether_addr(dev_addr, net->dev_addr);
++ if (cdc || rndis) {
++ get_ether_addr(host_addr, dev->host_mac);
++#ifdef DEV_CONFIG_CDC
++ snprintf (ethaddr, sizeof ethaddr, "%02X%02X%02X%02X%02X%02X",
++ dev->host_mac [0], dev->host_mac [1],
++ dev->host_mac [2], dev->host_mac [3],
++ dev->host_mac [4], dev->host_mac [5]);
++#endif
++ }
++
++ if (rndis) {
++ status = rndis_init();
++ if (status < 0) {
++ printk (KERN_ERR "%s: can't init RNDIS, %d\n",
++ shortname, status);
++ goto fail;
++ }
++ }
++
++ 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 message data and buffer */
++ dev->req = eth_req_alloc (gadget->ep0, USB_BUFSIZ);
++ if (!dev->req)
++ goto fail;
++ dev->req->complete = eth_setup_complete;
++
++ /* PO: this code my be reached with STATUS_BYTECOUNT undefined
++ Don't allocate stat_req then?!
++ */
++#ifdef STATUS_BYTECOUNT
++ /* ... and maybe likewise for status transfer */
++ if (dev->status_ep) {
++ dev->stat_req = eth_req_alloc (dev->status_ep,
++ STATUS_BYTECOUNT);
++ if (!dev->stat_req) {
++ eth_req_free (gadget->ep0, dev->req);
++ goto fail;
++ }
++ }
++#endif
++
++ /* finish hookup to lower layer ... */
++ dev->gadget = gadget;
++ set_gadget_data (gadget, dev);
++ gadget->ep0->driver_data = dev;
++
++ /* 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)
++ goto fail1;
++
++ INFO (dev, "%s, version: " DRIVER_VERSION "\n", driver_desc);
++ INFO (dev, "using %s, OUT %s IN %s%s%s\n", gadget->name,
++ EP_OUT_NAME, EP_IN_NAME,
++ EP_STATUS_NAME ? " STATUS " : "",
++ EP_STATUS_NAME ? EP_STATUS_NAME : ""
++ );
++ INFO (dev, "MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
++ net->dev_addr [0], net->dev_addr [1],
++ net->dev_addr [2], net->dev_addr [3],
++ net->dev_addr [4], net->dev_addr [5]);
++
++ if (cdc || rndis)
++ INFO (dev, "HOST MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
++ dev->host_mac [0], dev->host_mac [1],
++ dev->host_mac [2], dev->host_mac [3],
++ dev->host_mac [4], dev->host_mac [5]);
++
++#ifdef CONFIG_USB_ETH_RNDIS
++ if (rndis) {
++ u32 vendorID = 0;
++
++ /* FIXME RNDIS vendor id == "vendor NIC code" == ? */
++
++ dev->rndis_config = rndis_register (rndis_control_ack);
++ if (dev->rndis_config < 0) {
++fail0:
++ unregister_netdev (dev->net);
++ status = -ENODEV;
++ goto fail;
++ }
++
++ /* these set up a lot of the OIDs that RNDIS needs */
++ rndis_set_host_mac (dev->rndis_config, dev->host_mac);
++ if (rndis_set_param_dev (dev->rndis_config, dev->net,
++ &dev->stats))
++ goto fail0;
++ if (rndis_set_param_vendor (dev->rndis_config, vendorID,
++ manufacturer))
++ goto fail0;
++ if (rndis_set_param_medium (dev->rndis_config,
++ NDIS_MEDIUM_802_3,
++ 0))
++ goto fail0;
++ INFO (dev, "RNDIS ready\n");
++ }
++#endif
++
++ return status;
++
++fail1:
++ DEBUG (dev, "register_netdev failed, %d\n", status);
++fail:
++ eth_unbind (gadget);
++ return status;
++}
++
++/*-------------------------------------------------------------------------*/
++
++static void
++eth_suspend (struct usb_gadget *gadget)
++{
++ struct eth_dev *dev = get_gadget_data (gadget);
++
++ DEBUG (dev, "suspend\n");
++ dev->suspended = 1;
++}
++
++static void
++eth_resume (struct usb_gadget *gadget)
++{
++ struct eth_dev *dev = get_gadget_data (gadget);
++
++ DEBUG (dev, "resume\n");
++ dev->suspended = 0;
++}
++
++/*-------------------------------------------------------------------------*/
++
++static struct usb_gadget_driver eth_driver = {
++#ifdef CONFIG_USB_GADGET_DUALSPEED
++ .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,
++
++ /* PO: is this available? */
++ .suspend = eth_suspend,
++ .resume = eth_resume,
++
++ .driver = {
++ .name = (char *) shortname,
++ // .shutdown = ...
++ // .suspend = ...
++ // .resume = ...
++ },
++};
++
++MODULE_DESCRIPTION (DRIVER_DESC);
++MODULE_AUTHOR ("David Brownell, Benedikt Spanger");
++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 -x '*~' -x '.*' -r -N -u /tmp/kernel/drivers/usb/gadget/file_storage.c kernel/drivers/usb/gadget/file_storage.c
+--- /tmp/kernel/drivers/usb/gadget/file_storage.c 1970-01-01 01:00:00.000000000 +0100
++++ kernel/drivers/usb/gadget/file_storage.c 2005-04-22 17:53:19.431540004 +0200
+@@ -0,0 +1,3939 @@
++/*
++ * file_storage.c -- File-backed USB Storage Gadget, for USB development
++ *
++ * Copyright (C) 2003, 2004 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>
++
++#include "gadget_chips.h"
++
++
++/*-------------------------------------------------------------------------*/
++
++#define DRIVER_DESC "File-backed Storage Gadget"
++#define DRIVER_NAME "g_file_storage"
++#define DRIVER_VERSION "05 June 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
++
++
++/*
++ * This driver assumes self-powered hardware and has no way for users to
++ * trigger remote wakeup. It uses autoconfiguration to select endpoints
++ * and endpoint addresses.
++ */
++
++
++/*-------------------------------------------------------------------------*/
++
++#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;
++ // Default values
++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 = 0xffff; // Use controller chip type
++static unsigned int buflen = 16384;
++static int stall = 1;
++
++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(0xffff),
++
++ .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 computed by usb_gadget_config_buf() */
++ .bNumInterfaces = 1,
++ .bConfigurationValue = CONFIG_VALUE,
++ .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
++ .bMaxPower = 1, // self-powered
++};
++
++/* There is only one interface. */
++
++static struct usb_interface_descriptor
++intf_desc = {
++ .bLength = sizeof intf_desc,
++ .bDescriptorType = USB_DT_INTERFACE,
++
++ .bNumEndpoints = 2, // Adjusted during fsg_bind()
++ .bInterfaceClass = USB_CLASS_MASS_STORAGE,
++ .bInterfaceSubClass = USB_SC_SCSI, // Adjusted during fsg_bind()
++ .bInterfaceProtocol = USB_PR_BULK, // Adjusted during fsg_bind()
++};
++
++/* Three full-speed endpoint descriptors: bulk-in, bulk-out,
++ * and interrupt-in. */
++
++static struct usb_endpoint_descriptor
++fs_bulk_in_desc = {
++ .bLength = USB_DT_ENDPOINT_SIZE,
++ .bDescriptorType = USB_DT_ENDPOINT,
++
++ .bEndpointAddress = USB_DIR_IN,
++ .bmAttributes = USB_ENDPOINT_XFER_BULK,
++ /* wMaxPacketSize set by autoconfiguration */
++};
++
++static struct usb_endpoint_descriptor
++fs_bulk_out_desc = {
++ .bLength = USB_DT_ENDPOINT_SIZE,
++ .bDescriptorType = USB_DT_ENDPOINT,
++
++ .bEndpointAddress = USB_DIR_OUT,
++ .bmAttributes = USB_ENDPOINT_XFER_BULK,
++ /* wMaxPacketSize set by autoconfiguration */
++};
++
++static struct usb_endpoint_descriptor
++fs_intr_in_desc = {
++ .bLength = USB_DT_ENDPOINT_SIZE,
++ .bDescriptorType = USB_DT_ENDPOINT,
++
++ .bEndpointAddress = USB_DIR_IN,
++ .bmAttributes = USB_ENDPOINT_XFER_INT,
++ .wMaxPacketSize = __constant_cpu_to_le16(2),
++ .bInterval = 32, // frames -> 32 ms
++};
++
++static const struct usb_descriptor_header *fs_function[] = {
++ (struct usb_descriptor_header *) &intf_desc,
++ (struct usb_descriptor_header *) &fs_bulk_in_desc,
++ (struct usb_descriptor_header *) &fs_bulk_out_desc,
++ (struct usb_descriptor_header *) &fs_intr_in_desc,
++ NULL,
++};
++
++
++#ifdef CONFIG_USB_GADGET_DUALSPEED
++
++/*
++ * 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 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,
++};
++
++static struct usb_endpoint_descriptor
++hs_bulk_in_desc = {
++ .bLength = USB_DT_ENDPOINT_SIZE,
++ .bDescriptorType = USB_DT_ENDPOINT,
++
++ /* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */
++ .bmAttributes = USB_ENDPOINT_XFER_BULK,
++ .wMaxPacketSize = __constant_cpu_to_le16(512),
++};
++
++static struct usb_endpoint_descriptor
++hs_bulk_out_desc = {
++ .bLength = USB_DT_ENDPOINT_SIZE,
++ .bDescriptorType = USB_DT_ENDPOINT,
++
++ /* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */
++ .bmAttributes = USB_ENDPOINT_XFER_BULK,
++ .wMaxPacketSize = __constant_cpu_to_le16(512),
++ .bInterval = 1, // NAK every 1 uframe
++};
++
++static struct usb_endpoint_descriptor
++hs_intr_in_desc = {
++ .bLength = USB_DT_ENDPOINT_SIZE,
++ .bDescriptorType = USB_DT_ENDPOINT,
++
++ /* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */
++ .bmAttributes = USB_ENDPOINT_XFER_INT,
++ .wMaxPacketSize = __constant_cpu_to_le16(2),
++ .bInterval = 9, // 2**(9-1) = 256 uframes -> 32 ms
++};
++
++static const struct usb_descriptor_header *hs_function[] = {
++ (struct usb_descriptor_header *) &intf_desc,
++ (struct usb_descriptor_header *) &hs_bulk_in_desc,
++ (struct usb_descriptor_header *) &hs_bulk_out_desc,
++ (struct usb_descriptor_header *) &hs_intr_in_desc,
++ NULL,
++};
++
++/* 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, always use the full-speed descriptor. */
++#define ep_desc(g,fs,hs) fs
++
++#endif /* !CONFIG_USB_GADGET_DUALSPEED */
++
++
++/* The CBI specification limits the serial string to 12 uppercase hexadecimal
++ * characters. */
++static char manufacturer[40];
++static char serial[13];
++
++/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */
++static struct usb_string strings[] = {
++ {STRING_MANUFACTURER, manufacturer},
++ {STRING_PRODUCT, longname},
++ {STRING_SERIAL, serial},
++ {}
++};
++
++static struct usb_gadget_strings stringtab = {
++ .language = 0x0409, // en-us
++ .strings = strings,
++};
++
++
++/*
++ * Config descriptors 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 *buf, u8 type, unsigned index)
++{
++ int len;
++ const struct usb_descriptor_header **function;
++
++ if (index > 0)
++ return -EINVAL;
++
++#ifdef CONFIG_USB_GADGET_DUALSPEED
++ if (type == USB_DT_OTHER_SPEED_CONFIG)
++ speed = (USB_SPEED_FULL + USB_SPEED_HIGH) - speed;
++ if (speed == USB_SPEED_HIGH)
++ function = hs_function;
++ else
++#endif
++ function = fs_function;
++
++ len = usb_gadget_config_buf(&config_desc, buf, EP0_BUFSIZE, function);
++ if (len < 0)
++ return len;
++ ((struct usb_config_descriptor *) buf)->bDescriptorType = type;
++ return len;
++}
++
++
++/*-------------------------------------------------------------------------*/
++
++/* 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 CONFIG_USB_GADGET_DUALSPEED
++ case USB_DT_DEVICE_QUALIFIER:
++ VDBG(fsg, "get device qualifier\n");
++ if (!fsg->gadget->is_dualspeed)
++ break;
++ 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");
++ if (!fsg->gadget->is_dualspeed)
++ break;
++ goto get_config;
++#endif
++ case USB_DT_CONFIG:
++ VDBG(fsg, "get configuration descriptor\n");
++#ifdef CONFIG_USB_GADGET_DUALSPEED
++ get_config:
++#endif
++ 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,
++ mod_data.release);
++ 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 - 8; // 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 = cpu_to_le32(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 = le32_to_cpu(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;
++ fsg->bulk_out_maxpacket = d->wMaxPacketSize;
++
++ 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";
++
++ if (gadget_is_sh(fsg->gadget))
++ mod_data.can_stall = 0;
++
++ if (mod_data.release == 0xffff) { // Parameter wasn't set
++ if (gadget_is_net2280(fsg->gadget))
++ mod_data.release = __constant_cpu_to_le16(0x0221);
++ else if (gadget_is_dummy(fsg->gadget))
++ mod_data.release = __constant_cpu_to_le16(0x0222);
++ else if (gadget_is_pxa(fsg->gadget))
++ mod_data.release = __constant_cpu_to_le16(0x0223);
++ else if (gadget_is_sh(fsg->gadget))
++ mod_data.release = __constant_cpu_to_le16(0x0224);
++
++ /* The sa1100 controller is not supported */
++
++ else if (gadget_is_goku(fsg->gadget))
++ mod_data.release = __constant_cpu_to_le16(0x0226);
++ else if (gadget_is_mq11xx(fsg->gadget))
++ mod_data.release = __constant_cpu_to_le16(0x0227);
++ else if (gadget_is_omap(fsg->gadget))
++ mod_data.release = __constant_cpu_to_le16(0x0228);
++ else {
++ WARN(fsg, "controller '%s' not recognized\n",
++ fsg->gadget->name);
++ mod_data.release = __constant_cpu_to_le16(0x0299);
++ }
++ }
++
++ 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 {
++ ERROR(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 {
++ ERROR(fsg, "invalid protocol: %s\n", mod_data.protocol_parm);
++ return -EINVAL;
++ }
++
++ mod_data.buflen &= PAGE_CACHE_MASK;
++ if (mod_data.buflen <= 0) {
++ ERROR(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) {
++ ERROR(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) {
++ ERROR(fsg, "no file given for LUN%d\n", i);
++ rc = -EINVAL;
++ goto out;
++ }
++ }
++
++ /* Find all the endpoints we will use */
++ usb_ep_autoconfig_reset(gadget);
++ ep = usb_ep_autoconfig(gadget, &fs_bulk_in_desc);
++ if (!ep)
++ goto autoconf_fail;
++ ep->driver_data = fsg; // claim the endpoint
++ fsg->bulk_in = ep;
++
++ ep = usb_ep_autoconfig(gadget, &fs_bulk_out_desc);
++ if (!ep)
++ goto autoconf_fail;
++ ep->driver_data = fsg; // claim the endpoint
++ fsg->bulk_out = ep;
++
++ if (transport_is_cbi()) {
++ ep = usb_ep_autoconfig(gadget, &fs_intr_in_desc);
++ if (!ep)
++ goto autoconf_fail;
++ ep->driver_data = fsg; // claim the endpoint
++ fsg->intr_in = ep;
++ }
++
++ /* Fix up the descriptors */
++ device_desc.bMaxPacketSize0 = fsg->ep0->maxpacket;
++ 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
++ intf_desc.bNumEndpoints = i;
++ intf_desc.bInterfaceSubClass = mod_data.protocol_type;
++ intf_desc.bInterfaceProtocol = mod_data.transport_type;
++ fs_function[i+1] = NULL;
++
++#ifdef CONFIG_USB_GADGET_DUALSPEED
++ hs_function[i+1] = NULL;
++
++ /* Assume ep0 uses the same maxpacket value for both speeds */
++ dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket;
++
++ /* Assume that all endpoint addresses are the same for both speeds */
++ hs_bulk_in_desc.bEndpointAddress = fs_bulk_in_desc.bEndpointAddress;
++ hs_bulk_out_desc.bEndpointAddress = fs_bulk_out_desc.bEndpointAddress;
++ hs_intr_in_desc.bEndpointAddress = fs_intr_in_desc.bEndpointAddress;
++#endif
++
++ 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);
++
++ snprintf(manufacturer, sizeof manufacturer,
++ UTS_SYSNAME " " UTS_RELEASE " with %s",
++ gadget->name);
++
++ /* 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;
++
++autoconf_fail:
++ ERROR(fsg, "unable to autoconfigure all endpoints\n");
++ rc = -ENOTSUPP;
++
++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 CONFIG_USB_GADGET_DUALSPEED
++ .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 -x '*~' -x '.*' -r -N -u /tmp/kernel/drivers/usb/gadget/gadget_chips.h kernel/drivers/usb/gadget/gadget_chips.h
+--- /tmp/kernel/drivers/usb/gadget/gadget_chips.h 1970-01-01 01:00:00.000000000 +0100
++++ kernel/drivers/usb/gadget/gadget_chips.h 2005-04-22 17:53:19.434539516 +0200
+@@ -0,0 +1,92 @@
++/*
++ * 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_DUMMY_HCD
++#define gadget_is_dummy(g) !strcmp("dummy_udc", (g)->name)
++#else
++#define gadget_is_dummy(g) 0
++#endif
++
++#ifdef CONFIG_USB_GADGET_PXA2XX
++#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_LH7A40X
++#define gadget_is_lh7a40x(g) !strcmp("lh7a40x_udc", (g)->name)
++#else
++#define gadget_is_lh7a40x(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
++
++#ifdef CONFIG_USB_GADGET_N9604
++#define gadget_is_n9604(g) !strcmp("n9604_udc", (g)->name)
++#else
++#define gadget_is_n9604(g) 0
++#endif
++
++#ifdef CONFIG_USB_GADGET_PXA27X
++#define gadget_is_pxa27x(g) !strcmp("pxa27x_udc", (g)->name)
++#else
++#define gadget_is_pxa27x(g) 0
++#endif
++
++#ifdef CONFIG_USB_GADGET_S3C2410
++#define gadget_is_s3c2410(g) !strcmp("s3c2410_udc", (g)->name)
++#else
++#define gadget_is_s3c2410(g) 0
++#endif
++
++#ifdef CONFIG_USB_GADGET_AT91
++#define gadget_is_at91(g) !strcmp("at91_udc", (g)->name)
++#else
++#define gadget_is_at91(g) 0
++#endif
++
++// CONFIG_USB_GADGET_SX2
++// CONFIG_USB_GADGET_AU1X00
++// ...
++
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/drivers/usb/gadget/goku_udc.c kernel/drivers/usb/gadget/goku_udc.c
+--- /tmp/kernel/drivers/usb/gadget/goku_udc.c 1970-01-01 01:00:00.000000000 +0100
++++ kernel/drivers/usb/gadget/goku_udc.c 2005-04-22 17:53:19.440538539 +0200
+@@ -0,0 +1,1975 @@
++/*
++ * 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 -x '*~' -x '.*' -r -N -u /tmp/kernel/drivers/usb/gadget/goku_udc.h kernel/drivers/usb/gadget/goku_udc.h
+--- /tmp/kernel/drivers/usb/gadget/goku_udc.h 1970-01-01 01:00:00.000000000 +0100
++++ kernel/drivers/usb/gadget/goku_udc.h 2005-04-22 17:53:19.443538050 +0200
+@@ -0,0 +1,321 @@
++/*
++ * 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 -x '*~' -x '.*' -r -N -u /tmp/kernel/drivers/usb/gadget/gserial.c kernel/drivers/usb/gadget/gserial.c
+--- /tmp/kernel/drivers/usb/gadget/gserial.c 1970-01-01 01:00:00.000000000 +0100
++++ kernel/drivers/usb/gadget/gserial.c 2005-04-22 17:53:19.450536911 +0200
+@@ -0,0 +1,2301 @@
++/*
++ * g_serial.c -- USB gadget serial driver
++ *
++ * $Id: gserial.c,v 1.17 2003/10/01 06:31:57 borchers Exp $
++ *
++ * Copyright 2003 (c) Al Borchers (alborchers@steinerpoint.com)
++ *
++ * This code is based in part on the Gadget Zero driver, which
++ * is Copyright (C) 2003 by David Brownell, all rights reserved.
++ *
++ * This code also borrows from usbserial.c, which is
++ * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com)
++ * Copyright (c) 2000 Peter Berger (pberger@brimson.com)
++ * Copyright (c) 2000 Al Borchers (alborchers@steinerpoint.com)
++ *
++ * This software is 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.
++ *
++ */
++
++#ifndef __KERNEL__
++#define __KERNEL__
++#endif
++
++#ifndef MODULE
++#define MODULE
++#endif
++
++
++/* Includes */
++
++#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 <linux/wait.h>
++#include <linux/list.h>
++#include <linux/proc_fs.h>
++#include <linux/tty_flip.h>
++
++#include <asm/byteorder.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/system.h>
++#include <asm/unaligned.h>
++#include <asm/uaccess.h>
++
++#include <linux/usb_ch9.h>
++#include <linux/usb_gadget.h>
++
++#include "gadget_chips.h"
++
++
++/* Wait Cond */
++
++#define __wait_cond_interruptible(wq, condition, lock, flags, ret) \
++do { \
++ wait_queue_t __wait; \
++ init_waitqueue_entry(&__wait, current); \
++ \
++ add_wait_queue(&wq, &__wait); \
++ for (;;) { \
++ set_current_state(TASK_INTERRUPTIBLE); \
++ if (condition) \
++ break; \
++ if (!signal_pending(current)) { \
++ spin_unlock_irqrestore(lock, flags); \
++ schedule(); \
++ spin_lock_irqsave(lock, flags); \
++ continue; \
++ } \
++ ret = -ERESTARTSYS; \
++ break; \
++ } \
++ current->state = TASK_RUNNING; \
++ remove_wait_queue(&wq, &__wait); \
++} while (0)
++
++#define wait_cond_interruptible(wq, condition, lock, flags) \
++({ \
++ int __ret = 0; \
++ if (!(condition)) \
++ __wait_cond_interruptible(wq, condition, lock, flags, \
++ __ret); \
++ __ret; \
++})
++
++#define __wait_cond_interruptible_timeout(wq, condition, lock, flags, \
++ timeout, ret) \
++do { \
++ signed long __timeout = timeout; \
++ wait_queue_t __wait; \
++ init_waitqueue_entry(&__wait, current); \
++ \
++ add_wait_queue(&wq, &__wait); \
++ for (;;) { \
++ set_current_state(TASK_INTERRUPTIBLE); \
++ if (__timeout == 0) \
++ break; \
++ if (condition) \
++ break; \
++ if (!signal_pending(current)) { \
++ spin_unlock_irqrestore(lock, flags); \
++ __timeout = schedule_timeout(__timeout); \
++ spin_lock_irqsave(lock, flags); \
++ continue; \
++ } \
++ ret = -ERESTARTSYS; \
++ break; \
++ } \
++ current->state = TASK_RUNNING; \
++ remove_wait_queue(&wq, &__wait); \
++} while (0)
++
++#define wait_cond_interruptible_timeout(wq, condition, lock, flags, \
++ timeout) \
++({ \
++ int __ret = 0; \
++ if (!(condition)) \
++ __wait_cond_interruptible_timeout(wq, condition, lock, \
++ flags, timeout, __ret); \
++ __ret; \
++})
++
++
++/* Defines */
++
++#define GS_VERSION_STR "v1.0"
++#define GS_VERSION_NUM 0x0100
++
++#define GS_LONG_NAME "Gadget Serial"
++#define GS_SHORT_NAME "g_serial"
++
++#define GS_MAJOR 127
++#define GS_MINOR_START 0
++
++#define GS_NUM_PORTS 16
++
++#define GS_NUM_CONFIGS 1
++#define GS_NO_CONFIG_ID 0
++#define GS_BULK_CONFIG_ID 2
++
++#define GS_NUM_INTERFACES 1
++#define GS_INTERFACE_ID 0
++#define GS_ALT_INTERFACE_ID 0
++
++#define GS_NUM_ENDPOINTS 2
++
++#define GS_MAX_DESC_LEN 256
++
++#define GS_DEFAULT_READ_Q_SIZE 32
++#define GS_DEFAULT_WRITE_Q_SIZE 32
++
++#define GS_DEFAULT_WRITE_BUF_SIZE 8192
++#define GS_TMP_BUF_SIZE 8192
++
++#define GS_CLOSE_TIMEOUT 15
++
++/* debug macro */
++#if G_SERIAL_DEBUG
++
++static int debug = G_SERIAL_DEBUG;
++
++#define gs_debug(format, arg...) \
++ do { if(debug) printk( KERN_DEBUG format, ## arg ); } while(0)
++#define gs_debug_level(level, format, arg...) \
++ do { if(debug>=level) printk( KERN_DEBUG format, ## arg ); } while(0)
++
++#else
++
++#define gs_debug(format, arg...) \
++ do { } while(0)
++#define gs_debug_level(level, format, arg...) \
++ do { } while(0)
++
++#endif /* G_SERIAL_DEBUG */
++
++
++/* 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 GS_VENDOR_ID 0x0525 /* NetChip */
++#define GS_PRODUCT_ID 0xa4a6 /* Linux-USB Serial Gadget */
++
++
++/* Structures */
++
++struct gs_dev;
++
++/* circular buffer */
++struct gs_buf {
++ unsigned int buf_size;
++ char *buf_buf;
++ char *buf_get;
++ char *buf_put;
++};
++
++/* list of requests */
++struct gs_req_entry {
++ struct list_head re_entry;
++ struct usb_request *re_req;
++};
++
++/* the port structure holds info for each port, one for each minor number */
++struct gs_port {
++ struct gs_dev *port_dev; /* pointer to device struct */
++ struct tty_struct *port_tty; /* pointer to tty struct */
++ spinlock_t port_lock;
++ int port_num;
++ int port_open_count;
++ int port_in_use; /* open/close in progress */
++ wait_queue_head_t port_write_wait;/* waiting to write */
++ struct gs_buf *port_write_buf;
++};
++
++/* the device structure holds info for the USB device */
++struct gs_dev {
++ struct usb_gadget *dev_gadget; /* gadget device pointer */
++ spinlock_t dev_lock; /* lock for set/reset config */
++ int dev_config; /* configuration number */
++ struct usb_ep *dev_in_ep; /* address of in endpoint */
++ struct usb_ep *dev_out_ep; /* address of out endpoint */
++ struct usb_request *dev_ctrl_req; /* control request */
++ struct list_head dev_req_list; /* list of write requests */
++ int dev_sched_port; /* round robin port scheduled */
++ struct gs_port *dev_port[GS_NUM_PORTS]; /* the ports */
++};
++
++
++/* Functions */
++
++/* module */
++static int __init gs_module_init( void );
++static void __exit gs_module_exit( void );
++
++/* tty driver */
++static int gs_open( struct tty_struct *tty, struct file *file );
++static void gs_close( struct tty_struct *tty, struct file *file );
++static int gs_write( struct tty_struct *tty, int from_user,
++ const unsigned char *buf, int count );
++static void gs_put_char( struct tty_struct *tty, unsigned char ch );
++static void gs_flush_chars( struct tty_struct *tty );
++static int gs_write_room( struct tty_struct *tty );
++static int gs_chars_in_buffer( struct tty_struct *tty );
++static void gs_throttle( struct tty_struct * tty );
++static void gs_unthrottle( struct tty_struct * tty );
++static void gs_break( struct tty_struct *tty, int break_state );
++static int gs_ioctl( struct tty_struct *tty, struct file *file,
++ unsigned int cmd, unsigned long arg );
++static void gs_set_termios( struct tty_struct *tty, struct termios *old );
++static int gs_read_proc( char *page, char **start, off_t off, int count,
++ int *eof, void *data );
++
++static int gs_send( struct gs_dev *dev );
++static int gs_send_packet( struct gs_dev *dev, char *packet,
++ unsigned int size );
++static int gs_recv_packet( struct gs_dev *dev, char *packet,
++ unsigned int size );
++static void gs_read_complete( struct usb_ep *ep, struct usb_request *req );
++static void gs_write_complete( struct usb_ep *ep, struct usb_request *req );
++
++/* gadget driver */
++static int gs_bind( struct usb_gadget *gadget );
++static void gs_unbind( struct usb_gadget *gadget );
++static int gs_setup( struct usb_gadget *gadget,
++ const struct usb_ctrlrequest *ctrl );
++static void gs_setup_complete( struct usb_ep *ep, struct usb_request *req );
++static void gs_disconnect( struct usb_gadget *gadget );
++static int gs_set_config( struct gs_dev *dev, unsigned config );
++static void gs_reset_config( struct gs_dev *dev );
++static int gs_build_config_desc( u8 *buf, enum usb_device_speed speed,
++ u8 type, unsigned int index );
++
++static struct usb_request *gs_alloc_req( struct usb_ep *ep, unsigned int len,
++ int kmalloc_flags );
++static void gs_free_req( struct usb_ep *ep, struct usb_request *req );
++
++static struct gs_req_entry *gs_alloc_req_entry( struct usb_ep *ep, unsigned len,
++ int kmalloc_flags );
++static void gs_free_req_entry( struct usb_ep *ep, struct gs_req_entry *req );
++
++static int gs_alloc_ports( struct gs_dev *dev, int kmalloc_flags );
++static void gs_free_ports( struct gs_dev *dev );
++
++/* circular buffer */
++static struct gs_buf *gs_buf_alloc( unsigned int size, int kmalloc_flags );
++static void gs_buf_free( struct gs_buf *gb );
++static void gs_buf_clear( struct gs_buf *gb );
++static unsigned int gs_buf_data_avail( struct gs_buf *gb );
++static unsigned int gs_buf_space_avail( struct gs_buf *gb );
++static unsigned int gs_buf_put( struct gs_buf *gb, const char *buf,
++ unsigned int count );
++static unsigned int gs_buf_get( struct gs_buf *gb, char *buf,
++ unsigned int count );
++
++/* external functions */
++extern int net2280_set_fifo_mode(struct usb_gadget *gadget, int mode);
++
++
++/* Globals */
++
++static struct gs_dev *gs_device;
++
++static const char *EP_IN_NAME;
++static const char *EP_OUT_NAME;
++
++static struct semaphore gs_open_close_sem[GS_NUM_PORTS];
++
++static unsigned int read_q_size = GS_DEFAULT_READ_Q_SIZE;
++static unsigned int write_q_size = GS_DEFAULT_WRITE_Q_SIZE;
++
++static unsigned int write_buf_size = GS_DEFAULT_WRITE_BUF_SIZE;
++
++static unsigned char gs_tmp_buf[GS_TMP_BUF_SIZE];
++static struct semaphore gs_tmp_buf_sem;
++
++/* tty variables */
++static int gs_refcount;
++static struct tty_struct *gs_tty[GS_NUM_PORTS];
++static struct termios *gs_termios[GS_NUM_PORTS];
++static struct termios *gs_termios_locked[GS_NUM_PORTS];
++
++/* tty driver struct */
++static struct tty_driver gs_tty_driver = {
++ .magic = TTY_DRIVER_MAGIC,
++ .driver_name = GS_SHORT_NAME,
++ .name = "ttygs",
++ .major = GS_MAJOR,
++ .minor_start = GS_MINOR_START,
++ .num = GS_NUM_PORTS,
++ .type = TTY_DRIVER_TYPE_SERIAL,
++ .subtype = SERIAL_TYPE_NORMAL,
++ .flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS,
++ .refcount = &gs_refcount,
++ .table = gs_tty,
++ .termios = gs_termios,
++ .termios_locked = gs_termios_locked,
++
++ .open = gs_open,
++ .close = gs_close,
++ .write = gs_write,
++ .put_char = gs_put_char,
++ .flush_chars = gs_flush_chars,
++ .write_room = gs_write_room,
++ .ioctl = gs_ioctl,
++ .set_termios = gs_set_termios,
++ .throttle = gs_throttle,
++ .unthrottle = gs_unthrottle,
++ .break_ctl = gs_break,
++ .chars_in_buffer = gs_chars_in_buffer,
++ .read_proc = gs_read_proc,
++};
++
++/* gadget driver struct */
++static struct usb_gadget_driver gs_gadget_driver = {
++#ifdef CONFIG_USB_GADGET_DUALSPEED
++ .speed = USB_SPEED_HIGH,
++#else
++ .speed = USB_SPEED_FULL,
++#endif
++ .function = GS_LONG_NAME,
++ .bind = gs_bind,
++ .unbind = gs_unbind,
++ .setup = gs_setup,
++ .disconnect = gs_disconnect,
++ .driver = {
++ .name = GS_SHORT_NAME,
++ /* .shutdown = ... */
++ /* .suspend = ... */
++ /* .resume = ... */
++ },
++};
++
++
++/* USB descriptors */
++
++#define GS_MANUFACTURER_STR_ID 1
++#define GS_PRODUCT_STR_ID 2
++#define GS_SERIAL_STR_ID 3
++#define GS_CONFIG_STR_ID 4
++
++/* static strings, in iso 8859/1 */
++static char manufacturer[40];
++static struct usb_string gs_strings[] = {
++ { GS_MANUFACTURER_STR_ID, manufacturer },
++ { GS_PRODUCT_STR_ID, GS_LONG_NAME },
++ { GS_SERIAL_STR_ID, "0" },
++ { GS_CONFIG_STR_ID, "Bulk" },
++ { } /* end of list */
++};
++
++static struct usb_gadget_strings gs_string_table = {
++ .language = 0x0409, /* en-us */
++ .strings = gs_strings,
++};
++
++static struct usb_device_descriptor gs_device_desc = {
++ .bLength = USB_DT_DEVICE_SIZE,
++ .bDescriptorType = USB_DT_DEVICE,
++ .bcdUSB = __constant_cpu_to_le16(0x0200),
++ .bDeviceClass = USB_CLASS_VENDOR_SPEC,
++ .idVendor = __constant_cpu_to_le16(GS_VENDOR_ID),
++ .idProduct = __constant_cpu_to_le16(GS_PRODUCT_ID),
++ .iManufacturer = GS_MANUFACTURER_STR_ID,
++ .iProduct = GS_PRODUCT_STR_ID,
++ .iSerialNumber = GS_SERIAL_STR_ID,
++ .bNumConfigurations = GS_NUM_CONFIGS,
++};
++
++static const struct usb_config_descriptor gs_config_desc = {
++ .bLength = USB_DT_CONFIG_SIZE,
++ .bDescriptorType = USB_DT_CONFIG,
++ /* .wTotalLength set by gs_build_config_desc */
++ .bNumInterfaces = GS_NUM_INTERFACES,
++ .bConfigurationValue = GS_BULK_CONFIG_ID,
++ .iConfiguration = GS_CONFIG_STR_ID,
++ .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
++ .bMaxPower = 1,
++};
++
++static const struct usb_interface_descriptor gs_interface_desc = {
++ .bLength = USB_DT_INTERFACE_SIZE,
++ .bDescriptorType = USB_DT_INTERFACE,
++ .bNumEndpoints = GS_NUM_ENDPOINTS,
++ .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
++ .iInterface = GS_CONFIG_STR_ID,
++};
++
++static struct usb_endpoint_descriptor gs_fullspeed_in_desc = {
++ .bLength = USB_DT_ENDPOINT_SIZE,
++ .bDescriptorType = USB_DT_ENDPOINT,
++ .bEndpointAddress = USB_DIR_IN,
++ .bmAttributes = USB_ENDPOINT_XFER_BULK,
++};
++
++static struct usb_endpoint_descriptor gs_fullspeed_out_desc = {
++ .bLength = USB_DT_ENDPOINT_SIZE,
++ .bDescriptorType = USB_DT_ENDPOINT,
++ .bEndpointAddress = USB_DIR_OUT,
++ .bmAttributes = USB_ENDPOINT_XFER_BULK,
++};
++
++static struct usb_endpoint_descriptor gs_highspeed_in_desc = {
++ .bLength = USB_DT_ENDPOINT_SIZE,
++ .bDescriptorType = USB_DT_ENDPOINT,
++ .bmAttributes = USB_ENDPOINT_XFER_BULK,
++ .wMaxPacketSize = __constant_cpu_to_le16(512),
++};
++
++static struct usb_endpoint_descriptor gs_highspeed_out_desc = {
++ .bLength = USB_DT_ENDPOINT_SIZE,
++ .bDescriptorType = USB_DT_ENDPOINT,
++ .bmAttributes = USB_ENDPOINT_XFER_BULK,
++ .wMaxPacketSize = __constant_cpu_to_le16(512),
++};
++
++#ifdef CONFIG_USB_GADGET_DUALSPEED
++static struct usb_qualifier_descriptor gs_qualifier_desc = {
++ .bLength = sizeof(struct usb_qualifier_descriptor),
++ .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
++ .bcdUSB = __constant_cpu_to_le16 (0x0200),
++ .bDeviceClass = USB_CLASS_VENDOR_SPEC,
++ /* assumes ep0 uses the same value for both speeds ... */
++ .bNumConfigurations = GS_NUM_CONFIGS,
++};
++#endif
++
++
++/* Module */
++
++MODULE_DESCRIPTION( GS_LONG_NAME );
++MODULE_AUTHOR( "Al Borchers" );
++MODULE_LICENSE( "GPL" );
++
++#if G_SERIAL_DEBUG
++MODULE_PARM( debug, "i" );
++MODULE_PARM_DESC( debug, "Enable debugging, 0=off, 1=on" );
++#endif
++
++MODULE_PARM( read_q_size, "i" );
++MODULE_PARM_DESC( read_q_size, "Read request queue size, default=32" );
++
++MODULE_PARM( write_q_size, "i" );
++MODULE_PARM_DESC( write_q_size, "Write request queue size, default=32" );
++
++MODULE_PARM( write_buf_size, "i" );
++MODULE_PARM_DESC( write_buf_size, "Write buffer size, default=8192" );
++
++module_init( gs_module_init );
++module_exit( gs_module_exit );
++
++/*
++* gs_module_init
++*
++* Register as a USB gadget driver and a tty driver.
++*/
++
++static int __init gs_module_init( void )
++{
++
++ int i,ret;
++
++
++ if( (ret=usb_gadget_register_driver( &gs_gadget_driver )) ) {
++ printk( KERN_ERR
++ "gs_module_init: cannot register gadget driver, ret=%d\n",
++ ret );
++ return( ret );
++ }
++
++ /* initial stty settings */
++ gs_tty_driver.init_termios = tty_std_termios;
++ gs_tty_driver.init_termios.c_cflag
++ = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
++
++ for( i=0; i<GS_NUM_PORTS; i++ )
++ sema_init( &gs_open_close_sem[i], 1 );
++
++ sema_init( &gs_tmp_buf_sem, 1 );
++
++ if( (ret=tty_register_driver( &gs_tty_driver )) ) {
++ usb_gadget_unregister_driver( &gs_gadget_driver );
++ printk( KERN_ERR
++ "gs_module_init: cannot register tty driver, ret=%d\n",
++ ret );
++ return( ret );
++ }
++
++ printk( KERN_INFO "gs_module_init: %s %s loaded\n", GS_LONG_NAME,
++ GS_VERSION_STR );
++
++ return( 0 );
++
++}
++
++
++/*
++* gs_module_exit
++*
++* Unregister as a tty driver and a USB gadget driver.
++*/
++
++static void __exit gs_module_exit( void )
++{
++
++ tty_unregister_driver( &gs_tty_driver );
++ usb_gadget_unregister_driver( &gs_gadget_driver );
++
++ printk( KERN_INFO "gs_module_exit: %s %s unloaded\n",
++ GS_LONG_NAME, GS_VERSION_STR );
++
++}
++
++
++/* TTY Driver */
++
++/*
++ * gs_open
++ */
++
++static int gs_open( struct tty_struct *tty, struct file *file )
++{
++
++ int port_num;
++ unsigned long flags;
++ struct gs_port *port;
++ struct gs_dev *dev;
++ struct gs_buf *buf;
++ struct semaphore *sem;
++
++
++ port_num = MINOR( tty->device ) - GS_MINOR_START;
++
++ gs_debug( "gs_open: (%d,%p,%p)\n", port_num, tty, file );
++
++ tty->driver_data = NULL;
++
++ if( port_num < 0 || port_num >= GS_NUM_PORTS ) {
++ printk( KERN_ERR "gs_open: (%d,%p,%p) invalid port number\n",
++ port_num, tty, file );
++ return( -ENODEV );
++ }
++
++ dev = gs_device;
++
++ if( dev == NULL ) {
++ printk( KERN_ERR "gs_open: (%d,%p,%p) NULL device pointer\n",
++ port_num, tty, file );
++ return( -ENODEV );
++ }
++
++ sem = &gs_open_close_sem[port_num];
++ if( down_interruptible( sem ) ) {
++ printk( KERN_ERR
++ "gs_open: (%d,%p,%p) interrupted waiting for semaphore\n",
++ port_num, tty, file );
++ return( -ERESTARTSYS );
++ }
++
++ spin_lock_irqsave(&dev->dev_lock, flags );
++
++ if( dev->dev_config == GS_NO_CONFIG_ID ) {
++ printk( KERN_ERR
++ "gs_open: (%d,%p,%p) device is not connected\n",
++ port_num, tty, file );
++ spin_unlock_irqrestore(&dev->dev_lock, flags );
++ up( sem );
++ return( -ENODEV );
++ }
++
++ port = dev->dev_port[port_num];
++
++ if( port == NULL ) {
++ printk( KERN_ERR "gs_open: (%d,%p,%p) NULL port pointer\n",
++ port_num, tty, file );
++ spin_unlock_irqrestore(&dev->dev_lock, flags );
++ up( sem );
++ return( -ENODEV );
++ }
++
++ spin_lock(&port->port_lock );
++ spin_unlock(&dev->dev_lock );
++
++ if( port->port_dev == NULL ) {
++ printk( KERN_ERR "gs_open: (%d,%p,%p) port disconnected (1)\n",
++ port_num, tty, file );
++ spin_unlock_irqrestore(&port->port_lock, flags );
++ up( sem );
++ return( -EIO );
++ }
++
++ if( port->port_open_count > 0 ) {
++ ++port->port_open_count;
++ spin_unlock_irqrestore(&port->port_lock, flags );
++ gs_debug( "gs_open: (%d,%p,%p) already open\n",
++ port_num, tty, file );
++ up( sem );
++ return( 0 );
++ }
++
++ /* mark port as in use, we can drop port lock and sleep if necessary */
++ port->port_in_use = 1;
++
++ /* allocate write buffer on first open */
++ if( port->port_write_buf == NULL ) {
++
++ spin_unlock_irqrestore(&port->port_lock, flags );
++ buf = gs_buf_alloc( write_buf_size, GFP_KERNEL );
++ spin_lock_irqsave(&port->port_lock, flags );
++
++ /* might have been disconnected while asleep, check */
++ if( port->port_dev == NULL ) {
++ printk( KERN_ERR
++ "gs_open: (%d,%p,%p) port disconnected (2)\n",
++ port_num, tty, file );
++ port->port_in_use = 0;
++ spin_unlock_irqrestore(&port->port_lock, flags );
++ up( sem );
++ return( -EIO );
++ }
++
++ if( (port->port_write_buf=buf) == NULL ) {
++ printk( KERN_ERR "gs_open: (%d,%p,%p) cannot allocate port write buffer\n",
++ port_num, tty, file );
++ port->port_in_use = 0;
++ spin_unlock_irqrestore(&port->port_lock, flags );
++ up( sem );
++ return( -ENOMEM );
++ }
++
++ }
++
++ /* wait for carrier detect (not implemented) */
++
++ /* might have been disconnected while asleep, check */
++ if( port->port_dev == NULL ) {
++ printk( KERN_ERR "gs_open: (%d,%p,%p) port disconnected (3)\n",
++ port_num, tty, file );
++ port->port_in_use = 0;
++ spin_unlock_irqrestore(&port->port_lock, flags );
++ up( sem );
++ return( -EIO );
++ }
++
++ tty->driver_data = port;
++ port->port_tty = tty;
++ port->port_open_count = 1;
++ port->port_in_use = 0;
++
++ spin_unlock_irqrestore(&port->port_lock, flags );
++ up( sem );
++
++ gs_debug( "gs_open: (%d,%p,%p) completed\n", port_num, tty, file );
++
++ return( 0 );
++
++}
++
++
++/*
++ * gs_close
++ */
++
++static void gs_close( struct tty_struct *tty, struct file *file )
++{
++
++ unsigned long flags;
++ struct gs_port *port = tty->driver_data;
++ struct semaphore *sem;
++
++
++ if( port == NULL ) {
++ printk( KERN_ERR "gs_close: NULL port pointer\n" );
++ return;
++ }
++
++ gs_debug( "gs_close: (%d,%p,%p)\n", port->port_num, tty, file );
++
++ sem = &gs_open_close_sem[port->port_num];
++ down( sem );
++
++ spin_lock_irqsave(&port->port_lock, flags );
++
++ if( port->port_open_count == 0 ) {
++ printk( KERN_ERR
++ "gs_close: (%d,%p,%p) port is already closed\n",
++ port->port_num, tty, file );
++ spin_unlock_irqrestore(&port->port_lock, flags );
++ up( sem );
++ return;
++ }
++
++ if( port->port_open_count > 0 ) {
++ --port->port_open_count;
++ spin_unlock_irqrestore(&port->port_lock, flags );
++ up( sem );
++ return;
++ }
++
++ /* free disconnected port on final close */
++ if( port->port_dev == NULL ) {
++ kfree( port );
++ spin_unlock_irqrestore(&port->port_lock, flags );
++ up( sem );
++ return;
++ }
++
++ /* mark port as closed but in use, we can drop port lock */
++ /* and sleep if necessary */
++ port->port_in_use = 1;
++ port->port_open_count = 0;
++
++ /* wait for write buffer to drain, or */
++ /* at most GS_CLOSE_TIMEOUT seconds */
++ if( gs_buf_data_avail( port->port_write_buf ) > 0 ) {
++ wait_cond_interruptible_timeout( port->port_write_wait,
++ port->port_dev == NULL
++ || gs_buf_data_avail(port->port_write_buf) == 0,
++ &port->port_lock, flags, GS_CLOSE_TIMEOUT * HZ );
++ }
++
++ /* free disconnected port on final close */
++ /* (might have happened during the above sleep) */
++ if( port->port_dev == NULL ) {
++ kfree( port );
++ spin_unlock_irqrestore(&port->port_lock, flags );
++ up( sem );
++ return;
++ }
++
++ gs_buf_clear( port->port_write_buf );
++
++ tty->driver_data = NULL;
++ port->port_tty = NULL;
++ port->port_in_use = 0;
++
++ spin_unlock_irqrestore(&port->port_lock, flags );
++ up( sem );
++
++ gs_debug( "gs_close: (%d,%p,%p) completed\n",
++ port->port_num, tty, file );
++
++}
++
++
++/*
++ * gs_write
++ */
++
++static int gs_write( struct tty_struct *tty, int from_user,
++ const unsigned char *buf, int count )
++{
++
++ unsigned long flags;
++ struct gs_port *port = tty->driver_data;
++
++
++ if( port == NULL ) {
++ printk( KERN_ERR "gs_write: NULL port pointer\n" );
++ return( -EIO );
++ }
++
++ gs_debug( "gs_write: (%d,%p) writing %d bytes\n", port->port_num, tty,
++ count );
++
++ if( count == 0 )
++ return( 0 );
++
++ /* copy from user into tmp buffer, get tmp_buf semaphore */
++ if( from_user ) {
++ if( count > GS_TMP_BUF_SIZE )
++ count = GS_TMP_BUF_SIZE;
++ down( &gs_tmp_buf_sem );
++ if( copy_from_user( gs_tmp_buf, buf, count ) != 0 ) {
++ up( &gs_tmp_buf_sem );
++ printk( KERN_ERR
++ "gs_write: (%d,%p) cannot copy from user space\n",
++ port->port_num, tty );
++ return( -EFAULT );
++ }
++ buf = gs_tmp_buf;
++ }
++
++ spin_lock_irqsave(&port->port_lock, flags );
++
++ if( port->port_dev == NULL ) {
++ printk( KERN_ERR "gs_write: (%d,%p) port is not connected\n",
++ port->port_num, tty );
++ spin_unlock_irqrestore(&port->port_lock, flags );
++ if( from_user )
++ up( &gs_tmp_buf_sem );
++ return( -EIO );
++ }
++
++ if( port->port_open_count == 0 ) {
++ printk( KERN_ERR "gs_write: (%d,%p) port is closed\n",
++ port->port_num, tty );
++ spin_unlock_irqrestore(&port->port_lock, flags );
++ if( from_user )
++ up( &gs_tmp_buf_sem );
++ return( -EBADF );
++ }
++
++ count = gs_buf_put( port->port_write_buf, buf, count );
++
++ spin_unlock_irqrestore(&port->port_lock, flags );
++
++ if( from_user )
++ up( &gs_tmp_buf_sem );
++
++ gs_send( gs_device );
++
++ gs_debug( "gs_write: (%d,%p) wrote %d bytes\n", port->port_num, tty,
++ count );
++
++ return( count );
++
++}
++
++
++/*
++ * gs_put_char
++ */
++
++static void gs_put_char( struct tty_struct *tty, unsigned char ch )
++{
++
++ unsigned long flags;
++ struct gs_port *port = tty->driver_data;
++
++
++ if( port == NULL ) {
++ printk( KERN_ERR "gs_put_char: NULL port pointer\n" );
++ return;
++ }
++
++ gs_debug( "gs_put_char: (%d,%p) char=0x%x, called from %p, %p, %p\n", port->port_num, tty, ch, __builtin_return_address(0), __builtin_return_address(1), __builtin_return_address(2) );
++
++ spin_lock_irqsave(&port->port_lock, flags );
++
++ if( port->port_dev == NULL ) {
++ printk( KERN_ERR "gs_put_char: (%d,%p) port is not connected\n",
++ port->port_num, tty );
++ spin_unlock_irqrestore(&port->port_lock, flags );
++ return;
++ }
++
++ if( port->port_open_count == 0 ) {
++ printk( KERN_ERR "gs_put_char: (%d,%p) port is closed\n",
++ port->port_num, tty );
++ spin_unlock_irqrestore(&port->port_lock, flags );
++ return;
++ }
++
++ gs_buf_put( port->port_write_buf, &ch, 1 );
++
++ spin_unlock_irqrestore(&port->port_lock, flags );
++
++}
++
++
++/*
++ * gs_flush_chars
++ */
++
++static void gs_flush_chars( struct tty_struct *tty )
++{
++
++ unsigned long flags;
++ struct gs_port *port = tty->driver_data;
++
++
++ if( port == NULL ) {
++ printk( KERN_ERR "gs_flush_chars: NULL port pointer\n" );
++ return;
++ }
++
++ gs_debug( "gs_flush_chars: (%d,%p)\n", port->port_num, tty );
++
++ spin_lock_irqsave(&port->port_lock, flags );
++
++ if( port->port_dev == NULL ) {
++ printk( KERN_ERR
++ "gs_flush_chars: (%d,%p) port is not connected\n",
++ port->port_num, tty );
++ spin_unlock_irqrestore(&port->port_lock, flags );
++ return;
++ }
++
++ if( port->port_open_count == 0 ) {
++ printk( KERN_ERR "gs_flush_chars: (%d,%p) port is closed\n",
++ port->port_num, tty );
++ spin_unlock_irqrestore(&port->port_lock, flags );
++ return;
++ }
++
++ spin_unlock_irqrestore(&port->port_lock, flags );
++
++ gs_send( gs_device );
++
++}
++
++
++/*
++ * gs_write_room
++ */
++
++static int gs_write_room( struct tty_struct *tty )
++{
++
++ int room = 0;
++ unsigned long flags;
++ struct gs_port *port = tty->driver_data;
++
++
++ if( port == NULL )
++ return( 0 );
++
++ spin_lock_irqsave(&port->port_lock, flags );
++
++ if( port->port_dev != NULL && port->port_open_count > 0
++ && port->port_write_buf != NULL )
++ room = gs_buf_space_avail( port->port_write_buf );
++
++ spin_unlock_irqrestore(&port->port_lock, flags );
++
++ gs_debug( "gs_write_room: (%d,%p) room=%d\n",
++ port->port_num, tty, room );
++
++ return( room );
++
++}
++
++
++/*
++ * gs_chars_in_buffer
++ */
++
++static int gs_chars_in_buffer( struct tty_struct *tty )
++{
++
++ int chars = 0;
++ unsigned long flags;
++ struct gs_port *port = tty->driver_data;
++
++
++ if( port == NULL )
++ return( 0 );
++
++ spin_lock_irqsave(&port->port_lock, flags );
++
++ if( port->port_dev != NULL && port->port_open_count > 0
++ && port->port_write_buf != NULL )
++ chars = gs_buf_data_avail( port->port_write_buf );
++
++ spin_unlock_irqrestore(&port->port_lock, flags );
++
++ gs_debug( "gs_chars_in_buffer: (%d,%p) chars=%d\n",
++ port->port_num, tty, chars );
++
++ return( chars );
++
++}
++
++
++/*
++ * gs_throttle
++ */
++
++static void gs_throttle( struct tty_struct *tty )
++{
++
++}
++
++
++/*
++ * gs_unthrottle
++ */
++
++static void gs_unthrottle( struct tty_struct *tty )
++{
++
++}
++
++
++/*
++ * gs_break
++ */
++
++static void gs_break( struct tty_struct *tty, int break_state )
++{
++
++}
++
++
++/*
++ * gs_ioctl
++ */
++
++static int gs_ioctl( struct tty_struct *tty, struct file *file,
++ unsigned int cmd, unsigned long arg )
++{
++
++ struct gs_port *port = tty->driver_data;
++
++
++ if( port == NULL ) {
++ printk( KERN_ERR "gs_ioctl: NULL port pointer\n" );
++ return( -EIO );
++ }
++
++ gs_debug( "gs_ioctl: (%d,%p,%p) cmd=0x%4.4x, arg=%lu\n",
++ port->port_num, tty, file, cmd, arg );
++
++ /* handle ioctls */
++
++ /* could not handle ioctl */
++ return( -ENOIOCTLCMD );
++
++}
++
++
++/*
++ * gs_set_termios
++ */
++
++static void gs_set_termios( struct tty_struct *tty, struct termios *old )
++{
++
++}
++
++
++/*
++ * gs_read_proc
++ */
++
++static int gs_read_proc( char *page, char **start, off_t off, int count,
++ int *eof, void *data )
++{
++
++ return( 0 );
++
++}
++
++
++/*
++* gs_send
++*
++* This function finds available write requests, calls
++* gs_send_packet to fill these packets with data, and
++* continues until either there are no more write requests
++* available or no more data to send. This function is
++* run whenever data arrives or write requests are available.
++*/
++
++static int gs_send( struct gs_dev *dev )
++{
++
++ int ret,len;
++ unsigned long flags;
++ struct usb_ep *ep;
++ struct usb_request *req;
++ struct gs_req_entry *req_entry;
++
++
++ if( dev == NULL ) {
++ printk( KERN_ERR "gs_send: NULL device pointer\n" );
++ return( -ENODEV );
++ }
++
++ spin_lock_irqsave(&dev->dev_lock, flags );
++
++ ep = dev->dev_in_ep;
++
++ while( !list_empty( &dev->dev_req_list ) ) {
++
++ req_entry = list_entry( dev->dev_req_list.next,
++ struct gs_req_entry, re_entry );
++
++ req = req_entry->re_req;
++
++ len = gs_send_packet( dev, req->buf, ep->maxpacket );
++
++ if( len > 0 ) {
++gs_debug_level( 3, "gs_send: len=%d, 0x%2.2x 0x%2.2x 0x%2.2x ...\n", len, *((unsigned char *)req->buf), *((unsigned char *)req->buf+1), *((unsigned char *)req->buf+2) );
++ list_del( &req_entry->re_entry );
++ req->length = len;
++ if( (ret=usb_ep_queue( ep, req, GFP_ATOMIC )) ) {
++ printk( KERN_ERR
++ "gs_send: cannot queue read request, ret=%d\n",
++ ret );
++ break;
++ }
++ } else {
++ break;
++ }
++
++ }
++
++ spin_unlock_irqrestore(&dev->dev_lock, flags );
++
++ return( 0 );
++
++}
++
++
++/*
++ * gs_send_packet
++ *
++ * If there is data to send, a packet is built in the given
++ * buffer and the size is returned. If there is no data to
++ * send, 0 is returned. If there is any error a negative
++ * error number is returned.
++ *
++ * Called during USB completion routine, on interrupt time.
++ *
++ * We assume that disconnect will not happen until all completion
++ * routines have completed, so we can assume that the dev_port
++ * array does not change during the lifetime of this function.
++ */
++
++static int gs_send_packet( struct gs_dev *dev, char *packet, unsigned int size )
++{
++
++ unsigned int len;
++ struct gs_port *port;
++
++
++ /* TEMPORARY -- only port 0 is supported right now */
++ port = dev->dev_port[0];
++
++ if( port == NULL ) {
++ printk( KERN_ERR
++ "gs_send_packet: port=%d, NULL port pointer\n",
++ 0 );
++ return( -EIO );
++ }
++
++ spin_lock(&port->port_lock );
++
++ len = gs_buf_data_avail( port->port_write_buf );
++ if( len < size )
++ size = len;
++
++ if( size == 0 ) {
++ spin_unlock(&port->port_lock );
++ return( 0 );
++ }
++
++ size = gs_buf_get( port->port_write_buf, packet, size );
++
++ wake_up_interruptible( &port->port_tty->write_wait );
++
++ spin_unlock(&port->port_lock );
++
++ return( size );
++
++}
++
++
++/*
++ * gs_recv_packet
++ *
++ * Called for each USB packet received. Reads the packet
++ * header and stuffs the data in the appropriate tty buffer.
++ * Returns 0 if successful, or a negative error number.
++ *
++ * Called during USB completion routine, on interrupt time.
++ *
++ * We assume that disconnect will not happen until all completion
++ * routines have completed, so we can assume that the dev_port
++ * array does not change during the lifetime of this function.
++ */
++
++static int gs_recv_packet( struct gs_dev *dev, char *packet, unsigned int size )
++{
++
++ unsigned int len;
++ struct gs_port *port;
++
++
++ /* TEMPORARY -- only port 0 is supported right now */
++ port = dev->dev_port[0];
++
++ if( port == NULL ) {
++ printk( KERN_ERR "gs_recv_packet: port=%d, NULL port pointer\n",
++ port->port_num );
++ return( -EIO );
++ }
++
++ spin_lock(&port->port_lock );
++
++ if( port->port_tty == NULL ) {
++ printk( KERN_ERR "gs_recv_packet: port=%d, NULL tty pointer\n",
++ port->port_num );
++ spin_unlock(&port->port_lock );
++ return( -EIO );
++ }
++
++ if( port->port_tty->magic != TTY_MAGIC ) {
++ printk( KERN_ERR "gs_recv_packet: port=%d, bad tty magic\n",
++ port->port_num );
++ spin_unlock(&port->port_lock );
++ return( -EIO );
++ }
++
++ len = (unsigned int)(TTY_FLIPBUF_SIZE - port->port_tty->flip.count);
++ if( len < size )
++ size = len;
++
++ if( size > 0 ) {
++ memcpy( port->port_tty->flip.char_buf_ptr, packet, size );
++ port->port_tty->flip.char_buf_ptr += size;
++ port->port_tty->flip.count += size;
++ tty_flip_buffer_push( port->port_tty );
++ wake_up_interruptible( &port->port_tty->read_wait );
++ }
++
++ spin_unlock(&port->port_lock );
++
++ return( 0 );
++
++}
++
++
++/*
++* gs_read_complete
++*/
++
++static void gs_read_complete( struct usb_ep *ep, struct usb_request *req )
++{
++
++ int ret;
++ struct gs_dev *dev = ep->driver_data;
++
++
++ if( dev == NULL ) {
++ printk( KERN_ERR "gs_read_complete: NULL device pointer\n" );
++ return;
++ }
++
++ switch( req->status ) {
++
++ case 0:
++ /* normal completion */
++ gs_recv_packet( dev, req->buf, req->actual );
++requeue:
++ req->length = ep->maxpacket;
++ if( (ret=usb_ep_queue( ep, req, GFP_ATOMIC )) ) {
++ printk( KERN_ERR
++ "gs_read_complete: cannot queue read request, ret=%d\n",
++ ret );
++ }
++ break;
++
++ case -ESHUTDOWN:
++ /* disconnect */
++ gs_debug( "gs_read_complete: shutdown\n" );
++ gs_free_req( ep, req );
++ break;
++
++ default:
++ /* unexpected */
++ printk( KERN_ERR
++ "gs_read_complete: unexpected status error, status=%d\n",
++ req->status );
++ goto requeue;
++ break;
++
++ }
++
++}
++
++
++/*
++* gs_write_complete
++*/
++
++static void gs_write_complete( struct usb_ep *ep, struct usb_request *req )
++{
++
++ struct gs_dev *dev = ep->driver_data;
++ struct gs_req_entry *gs_req = req->context;
++
++
++ if( dev == NULL ) {
++ printk( KERN_ERR "gs_write_complete: NULL device pointer\n" );
++ return;
++ }
++
++ switch( req->status ) {
++
++ case 0:
++ /* normal completion */
++requeue:
++ if( gs_req == NULL ) {
++ printk( KERN_ERR
++ "gs_write_complete: NULL request pointer\n" );
++ return;
++ }
++
++ spin_lock(&dev->dev_lock );
++ list_add( &gs_req->re_entry, &dev->dev_req_list );
++ spin_unlock(&dev->dev_lock );
++
++ gs_send( dev );
++
++ break;
++
++ case -ESHUTDOWN:
++ /* disconnect */
++ gs_debug( "gs_write_complete: shutdown\n" );
++ gs_free_req( ep, req );
++ break;
++
++ default:
++ printk( KERN_ERR
++ "gs_write_complete: unexpected status error, status=%d\n",
++ req->status );
++ goto requeue;
++ break;
++
++ }
++
++}
++
++
++/* Gadget Driver */
++
++/*
++ * gs_bind
++ *
++ * Called on module load. Allocates and initializes the device
++ * structure and a control request.
++ */
++static int gs_bind(struct usb_gadget *gadget)
++{
++ int ret;
++ struct usb_ep *ep;
++ struct gs_dev *dev;
++
++ usb_ep_autoconfig_reset(gadget);
++
++ ep = usb_ep_autoconfig(gadget, &gs_fullspeed_in_desc);
++ if (!ep)
++ goto autoconf_fail;
++ EP_IN_NAME = ep->name;
++ ep->driver_data = ep; /* claim the endpoint */
++
++ ep = usb_ep_autoconfig(gadget, &gs_fullspeed_out_desc);
++ if (!ep)
++ goto autoconf_fail;
++ EP_OUT_NAME = ep->name;
++ ep->driver_data = ep; /* claim the endpoint */
++
++ /* device specific bcdDevice value in device descriptor */
++ if (gadget_is_net2280(gadget)) {
++ gs_device_desc.bcdDevice =
++ __constant_cpu_to_le16(GS_VERSION_NUM|0x0001);
++ } else if (gadget_is_pxa(gadget)) {
++ gs_device_desc.bcdDevice =
++ __constant_cpu_to_le16(GS_VERSION_NUM|0x0002);
++ } else if (gadget_is_sh(gadget)) {
++ gs_device_desc.bcdDevice =
++ __constant_cpu_to_le16(GS_VERSION_NUM|0x0003);
++ } else if (gadget_is_sa1100(gadget)) {
++ gs_device_desc.bcdDevice =
++ __constant_cpu_to_le16(GS_VERSION_NUM|0x0004);
++ } else if (gadget_is_goku(gadget)) {
++ gs_device_desc.bcdDevice =
++ __constant_cpu_to_le16(GS_VERSION_NUM|0x0005);
++ } else if (gadget_is_mq11xx(gadget)) {
++ gs_device_desc.bcdDevice =
++ __constant_cpu_to_le16(GS_VERSION_NUM|0x0006);
++ } else if (gadget_is_omap(gadget)) {
++ gs_device_desc.bcdDevice =
++ __constant_cpu_to_le16(GS_VERSION_NUM|0x0007);
++ } else {
++ printk(KERN_WARNING "gs_bind: controller '%s' not recognized\n",
++ gadget->name);
++ /* unrecognized, but safe unless bulk is REALLY quirky */
++ gs_device_desc.bcdDevice =
++ __constant_cpu_to_le16(GS_VERSION_NUM|0x0099);
++ }
++
++ gs_device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
++#ifdef CONFIG_USB_GADGET_DUALSPEED
++ /* assume ep0 uses the same packet size for both speeds */
++ gs_qualifier_desc.bMaxPacketSize0 = gs_device_desc.bMaxPacketSize0;
++ /* assume endpoints are dual-speed */
++ gs_highspeed_in_desc.bEndpointAddress =
++ gs_fullspeed_in_desc.bEndpointAddress;
++ gs_highspeed_out_desc.bEndpointAddress =
++ gs_fullspeed_out_desc.bEndpointAddress;
++#endif /* CONFIG_USB_GADGET_DUALSPEED */
++
++ usb_gadget_set_selfpowered(gadget);
++
++ gs_device = dev = kmalloc(sizeof(struct gs_dev), GFP_KERNEL);
++ if (dev == NULL)
++ return -ENOMEM;
++
++ snprintf (manufacturer, sizeof(manufacturer),
++ UTS_SYSNAME " " UTS_RELEASE " with %s", gadget->name);
++
++ memset(dev, 0, sizeof(struct gs_dev));
++ dev->dev_gadget = gadget;
++ spin_lock_init(&dev->dev_lock);
++ INIT_LIST_HEAD(&dev->dev_req_list);
++ set_gadget_data(gadget, dev);
++
++ if ((ret = gs_alloc_ports(dev, GFP_KERNEL)) != 0) {
++ printk(KERN_ERR "gs_bind: cannot allocate ports\n");
++ gs_unbind(gadget);
++ return ret;
++ }
++
++ /* preallocate control response and buffer */
++ dev->dev_ctrl_req = gs_alloc_req(gadget->ep0, GS_MAX_DESC_LEN,
++ GFP_KERNEL);
++ if (dev->dev_ctrl_req == NULL) {
++ gs_unbind(gadget);
++ return -ENOMEM;
++ }
++ dev->dev_ctrl_req->complete = gs_setup_complete;
++
++ gadget->ep0->driver_data = dev;
++
++ printk(KERN_INFO "gs_bind: %s %s bound\n",
++ GS_LONG_NAME, GS_VERSION_STR);
++
++ return 0;
++
++autoconf_fail:
++ printk(KERN_ERR "gs_bind: cannot autoconfigure on %s\n", gadget->name);
++ return -ENODEV;
++}
++
++
++/*
++ * gs_unbind
++ *
++ * Called on module unload. Frees the control request and device
++ * structure.
++ */
++
++static void gs_unbind( struct usb_gadget *gadget )
++{
++
++ struct gs_dev *dev = get_gadget_data( gadget );
++
++
++ gs_device = NULL;
++
++ /* read/write requests already freed, only control request remains */
++ if( dev != NULL ) {
++ if( dev->dev_ctrl_req != NULL )
++ gs_free_req( gadget->ep0, dev->dev_ctrl_req );
++ gs_free_ports( dev );
++ kfree( dev );
++ set_gadget_data( gadget, NULL );
++ }
++
++ printk( KERN_INFO "gs_unbind: %s %s unbound\n", GS_LONG_NAME,
++ GS_VERSION_STR );
++
++}
++
++
++/*
++ * gs_setup
++ *
++ * Implements all the control endpoint functionality that's not
++ * handled in hardware or the hardware driver.
++ *
++ * Returns the size of the data sent to the host, or a negative
++ * error number.
++ */
++
++static int gs_setup( struct usb_gadget *gadget,
++ const struct usb_ctrlrequest *ctrl )
++{
++
++ int ret = -EOPNOTSUPP;
++ unsigned int sv_config;
++ struct gs_dev *dev = get_gadget_data( gadget );
++ struct usb_request *req = dev->dev_ctrl_req;
++
++
++ switch (ctrl->bRequest) {
++
++ case USB_REQ_GET_DESCRIPTOR:
++
++ if( ctrl->bRequestType != USB_DIR_IN )
++ break;
++
++ switch (ctrl->wValue >> 8) {
++
++ case USB_DT_DEVICE:
++ ret = min( ctrl->wLength,
++ (u16)sizeof(struct usb_device_descriptor) );
++ memcpy( req->buf, &gs_device_desc, ret );
++ break;
++
++#ifdef CONFIG_USB_GADGET_DUALSPEED
++ case USB_DT_DEVICE_QUALIFIER:
++ if (!gadget->is_dualspeed)
++ break;
++ ret = min( ctrl->wLength,
++ (u16)sizeof(struct usb_qualifier_descriptor) );
++ memcpy( req->buf, &gs_qualifier_desc, ret );
++ break;
++
++ case USB_DT_OTHER_SPEED_CONFIG:
++#endif /* CONFIG_USB_GADGET_DUALSPEED */
++ case USB_DT_CONFIG:
++ ret = gs_build_config_desc( req->buf, gadget->speed,
++ ctrl->wValue >> 8, ctrl->wValue & 0xff );
++ if( ret >= 0 )
++ ret = min( ctrl->wLength, (u16)ret );
++ break;
++
++ case USB_DT_STRING:
++ /* wIndex == language code. */
++ ret = usb_gadget_get_string( &gs_string_table,
++ ctrl->wValue & 0xff, req->buf );
++ if( ret >= 0 )
++ ret = min( ctrl->wLength, (u16)ret );
++ break;
++ }
++ break;
++
++ case USB_REQ_SET_CONFIGURATION:
++ if( ctrl->bRequestType != 0 )
++ break;
++ spin_lock( &dev->dev_lock );
++ ret = gs_set_config( dev, ctrl->wValue );
++ spin_unlock( &dev->dev_lock );
++ break;
++
++ case USB_REQ_GET_CONFIGURATION:
++ if( ctrl->bRequestType != USB_DIR_IN )
++ break;
++ *(u8 *)req->buf = dev->dev_config;
++ ret = min( ctrl->wLength, (u16)1 );
++ break;
++
++ case USB_REQ_SET_INTERFACE:
++ if( ctrl->bRequestType != USB_RECIP_INTERFACE )
++ break;
++ spin_lock( &dev->dev_lock );
++ if( dev->dev_config == GS_BULK_CONFIG_ID
++ && ctrl->wIndex == GS_INTERFACE_ID
++ && ctrl->wValue == GS_ALT_INTERFACE_ID ) {
++ sv_config = dev->dev_config;
++ /* since there is only one interface, setting the */
++ /* interface is equivalent to setting the config */
++ gs_reset_config( dev );
++ gs_set_config( dev, sv_config );
++ ret = 0;
++ }
++ spin_unlock( &dev->dev_lock );
++ break;
++
++ case USB_REQ_GET_INTERFACE:
++ if( ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE) )
++ break;
++ if( dev->dev_config == GS_NO_CONFIG_ID )
++ break;
++ if( ctrl->wIndex != GS_INTERFACE_ID ) {
++ ret = -EDOM;
++ break;
++ }
++ *(u8 *)req->buf = GS_ALT_INTERFACE_ID;
++ ret = min( ctrl->wLength, (u16)1 );
++ break;
++
++ default:
++ printk( KERN_ERR "gs_setup: unknown request, type=%02x, request=%02x, value=%04x, index=%04x, length=%d\n",
++ ctrl->bRequestType, ctrl->bRequest, ctrl->wValue,
++ ctrl->wIndex, ctrl->wLength );
++ break;
++
++ }
++
++ /* respond with data transfer before status phase? */
++ if( ret >= 0 ) {
++ req->length = ret;
++ ret = usb_ep_queue( gadget->ep0, req, GFP_ATOMIC );
++ if( ret < 0 ) {
++ printk( KERN_ERR
++ "gs_setup: cannot queue response, ret=%d\n",
++ ret );
++ req->status = 0;
++ gs_setup_complete( gadget->ep0, req );
++ }
++ }
++
++ /* device either stalls (ret < 0) or reports success */
++ return( ret );
++
++}
++
++
++/*
++ * gs_setup_complete
++ */
++
++static void gs_setup_complete( struct usb_ep *ep, struct usb_request *req )
++{
++ if( req->status || req->actual != req->length ) {
++ printk( KERN_ERR "gs_setup_complete: status error, status=%d, actual=%d, length=%d\n",
++ req->status, req->actual, req->length );
++ }
++}
++
++
++/*
++ * gs_disconnect
++ *
++ * Called when the device is disconnected. Frees the closed
++ * ports and disconnects open ports. Open ports will be freed
++ * on close. Then reallocates the ports for the next connection.
++ */
++
++static void gs_disconnect( struct usb_gadget *gadget )
++{
++
++ unsigned long flags;
++ struct gs_dev *dev = get_gadget_data( gadget );
++
++
++ spin_lock_irqsave( &dev->dev_lock, flags );
++
++ gs_reset_config( dev );
++
++ /* free closed ports and disconnect open ports */
++ /* (open ports will be freed when closed) */
++ gs_free_ports( dev );
++
++ /* re-allocate ports for the next connection */
++ if( gs_alloc_ports( dev, GFP_ATOMIC ) != 0 )
++ printk( KERN_ERR "gs_disconnect: cannot re-allocate ports\n" );
++
++ spin_unlock_irqrestore( &dev->dev_lock, flags );
++
++ printk( KERN_INFO "gs_disconnect: %s disconnected\n", GS_LONG_NAME );
++
++}
++
++
++/*
++ * gs_set_config
++ *
++ * Configures the device by enabling device specific
++ * optimizations, setting up the endpoints, allocating
++ * read and write requests and queuing read requests.
++ *
++ * The device lock must be held when calling this function.
++ */
++
++static int gs_set_config( struct gs_dev *dev, unsigned config )
++{
++
++ int i;
++ int ret = 0;
++ struct usb_gadget *gadget = dev->dev_gadget;
++ struct usb_ep *ep;
++ struct usb_request *req;
++ struct gs_req_entry *req_entry;
++
++
++ if( dev == NULL ) {
++ printk( KERN_ERR "gs_set_config: NULL device pointer\n" );
++ return( 0 );
++ }
++
++ if( config == dev->dev_config )
++ return( 0 );
++
++ gs_reset_config( dev );
++
++ if( config == GS_NO_CONFIG_ID )
++ return( 0 );
++
++ if( config != GS_BULK_CONFIG_ID )
++ return( -EINVAL );
++
++ /* device specific optimizations */
++ if (gadget_is_net2280(gadget))
++ net2280_set_fifo_mode(gadget, 1);
++
++ gadget_for_each_ep( ep, gadget ) {
++
++ if( strcmp( ep->name, EP_IN_NAME ) == 0 ) {
++ ret = usb_ep_enable( ep,
++ gadget->speed == USB_SPEED_HIGH ?
++ &gs_highspeed_in_desc : &gs_fullspeed_in_desc );
++ if( ret == 0 ) {
++ ep->driver_data = dev;
++ dev->dev_in_ep = ep;
++ } else {
++ printk( KERN_ERR "gs_set_config: cannot enable in endpoint %s, ret=%d\n",
++ ep->name, ret );
++ gs_reset_config( dev );
++ return( ret );
++ }
++ }
++
++ else if( strcmp( ep->name, EP_OUT_NAME ) == 0 ) {
++ ret = usb_ep_enable( ep,
++ gadget->speed == USB_SPEED_HIGH ?
++ &gs_highspeed_out_desc :
++ &gs_fullspeed_out_desc );
++ if( ret == 0 ) {
++ ep->driver_data = dev;
++ dev->dev_out_ep = ep;
++ } else {
++ printk( KERN_ERR "gs_set_config: cannot enable out endpoint %s, ret=%d\n",
++ ep->name, ret );
++ gs_reset_config( dev );
++ return( ret );
++ }
++ }
++
++ }
++
++ if( dev->dev_in_ep == NULL || dev->dev_out_ep == NULL ) {
++ gs_reset_config( dev );
++ printk( KERN_ERR "gs_set_config: cannot find endpoints\n" );
++ return( -ENODEV );
++ }
++
++ /* allocate and queue read requests */
++ ep = dev->dev_out_ep;
++ for( i=0; i<read_q_size && ret == 0; i++ ) {
++ if( (req=gs_alloc_req( ep, ep->maxpacket, GFP_ATOMIC )) ) {
++ req->complete = gs_read_complete;
++ if( (ret=usb_ep_queue( ep, req, GFP_ATOMIC )) ) {
++ printk( KERN_ERR "gs_set_config: cannot queue read request, ret=%d\n",
++ ret );
++ }
++ } else {
++ gs_reset_config( dev );
++ printk( KERN_ERR
++ "gs_set_config: cannot allocate read requests\n" );
++ return( -ENOMEM );
++ }
++ }
++
++ /* allocate write requests, and put on free list */
++ ep = dev->dev_in_ep;
++ for( i=0; i<write_q_size; i++ ) {
++ if( (req_entry=gs_alloc_req_entry( ep, ep->maxpacket,
++ GFP_ATOMIC )) ) {
++ req_entry->re_req->complete = gs_write_complete;
++ list_add( &req_entry->re_entry, &dev->dev_req_list );
++ } else {
++ gs_reset_config( dev );
++ printk( KERN_ERR
++ "gs_set_config: cannot allocate write requests\n" );
++ return( -ENOMEM );
++ }
++ }
++
++ dev->dev_config = config;
++
++ printk( KERN_INFO "gs_set_config: %s configured for %s speed\n",
++ GS_LONG_NAME,
++ gadget->speed == USB_SPEED_HIGH ? "high" : "full" );
++
++ return( 0 );
++
++}
++
++
++/*
++ * gs_reset_config
++ *
++ * Mark the device as not configured, disable all endpoints,
++ * which forces completion of pending I/O and frees queued
++ * requests, and free the remaining write requests on the
++ * free list.
++ *
++ * The device lock must be held when calling this function.
++ */
++
++static void gs_reset_config( struct gs_dev *dev )
++{
++
++ struct gs_req_entry *req_entry;
++
++
++ if( dev == NULL ) {
++ printk( KERN_ERR "gs_reset_config: NULL device pointer\n" );
++ return;
++ }
++
++ if( dev->dev_config == GS_NO_CONFIG_ID )
++ return;
++
++ dev->dev_config = GS_NO_CONFIG_ID;
++
++ /* free write requests on the free list */
++ while( !list_empty( &dev->dev_req_list ) ) {
++ req_entry = list_entry( dev->dev_req_list.next,
++ struct gs_req_entry, re_entry );
++ list_del( &req_entry->re_entry );
++ gs_free_req_entry( dev->dev_in_ep, req_entry );
++ }
++
++ /* disable endpoints, forcing completion of pending i/o; */
++ /* completion handlers free their requests in this case */
++ if( dev->dev_in_ep ) {
++ usb_ep_disable( dev->dev_in_ep );
++ dev->dev_in_ep = NULL;
++ }
++ if( dev->dev_out_ep ) {
++ usb_ep_disable( dev->dev_out_ep );
++ dev->dev_out_ep = NULL;
++ }
++
++}
++
++
++/*
++ * gs_build_config_desc
++ *
++ * Builds a config descriptor in the given buffer and returns the
++ * length, or a negative error number.
++ */
++
++static int gs_build_config_desc( u8 *buf, enum usb_device_speed speed,
++ u8 type, unsigned int index )
++{
++
++ int high_speed;
++ int len = USB_DT_CONFIG_SIZE + USB_DT_INTERFACE_SIZE
++ + GS_NUM_ENDPOINTS * USB_DT_ENDPOINT_SIZE;
++
++
++ /* only one config */
++ if( index != 0 )
++ return( -EINVAL );
++
++ memcpy( buf, &gs_config_desc, USB_DT_CONFIG_SIZE );
++ ((struct usb_config_descriptor *)buf)->bDescriptorType = type;
++ ((struct usb_config_descriptor *)buf)->wTotalLength =
++ __constant_cpu_to_le16( len );
++ buf += USB_DT_CONFIG_SIZE;
++
++ memcpy( buf, &gs_interface_desc, USB_DT_INTERFACE_SIZE );
++ buf += USB_DT_INTERFACE_SIZE;
++
++ /* other speed switches high and full speed */
++ high_speed = (speed == USB_SPEED_HIGH);
++ if( type == USB_DT_OTHER_SPEED_CONFIG )
++ high_speed = !high_speed;
++
++ memcpy( buf,
++ high_speed ? &gs_highspeed_in_desc : &gs_fullspeed_in_desc,
++ USB_DT_ENDPOINT_SIZE );
++ buf += USB_DT_ENDPOINT_SIZE;
++ memcpy( buf,
++ high_speed ? &gs_highspeed_out_desc : &gs_fullspeed_out_desc,
++ USB_DT_ENDPOINT_SIZE );
++
++ return( len );
++
++}
++
++
++/*
++ * gs_alloc_req
++ *
++ * Allocate a usb_request and its buffer. Returns a pointer to the
++ * usb_request or NULL if there is an error.
++ */
++
++static struct usb_request *gs_alloc_req( struct usb_ep *ep, unsigned int len,
++ int kmalloc_flags )
++{
++
++ struct usb_request *req;
++
++
++ if( ep == NULL )
++ return( NULL );
++
++ req = usb_ep_alloc_request( ep, kmalloc_flags );
++
++ if( req != NULL ) {
++ req->length = len;
++ req->buf = usb_ep_alloc_buffer( ep, len, &req->dma,
++ kmalloc_flags );
++ if( req->buf == NULL ) {
++ usb_ep_free_request( ep, req );
++ return( NULL );
++ }
++ }
++
++ return( req );
++
++}
++
++
++/*
++ * gs_free_req
++ *
++ * Free a usb_request and its buffer.
++ */
++
++static void gs_free_req( struct usb_ep *ep, struct usb_request *req )
++{
++ if( ep != NULL && req != NULL ) {
++ if( req->buf != NULL )
++ usb_ep_free_buffer( ep, req->buf, req->dma,
++ req->length );
++ usb_ep_free_request( ep, req );
++ }
++}
++
++
++/*
++ * gs_alloc_req_entry
++ *
++ * Allocates a request and its buffer, using the given
++ * endpoint, buffer len, and kmalloc flags.
++ */
++
++static struct gs_req_entry *gs_alloc_req_entry( struct usb_ep *ep,
++ unsigned len, int kmalloc_flags )
++{
++
++ struct gs_req_entry *req;
++
++
++ req = kmalloc( sizeof(struct gs_req_entry), kmalloc_flags );
++ if( req == NULL )
++ return( NULL );
++
++ req->re_req = gs_alloc_req( ep, len, kmalloc_flags );
++ if( req->re_req == NULL ) {
++ kfree( req );
++ return( NULL );
++ }
++
++ req->re_req->context = req;
++
++ return( req );
++
++}
++
++
++/*
++ * gs_free_req_entry
++ *
++ * Frees a request and its buffer.
++ */
++
++static void gs_free_req_entry( struct usb_ep *ep, struct gs_req_entry *req )
++{
++ if( ep != NULL && req != NULL ) {
++ if( req->re_req != NULL )
++ gs_free_req( ep, req->re_req );
++ kfree( req );
++ }
++}
++
++
++/*
++ * gs_alloc_ports
++ *
++ * Allocate all ports and set the gs_dev struct to point to them.
++ * Return 0 if successful, or a negative error number.
++ *
++ * The device lock is normally held when calling this function.
++ */
++
++static int gs_alloc_ports( struct gs_dev *dev, int kmalloc_flags )
++{
++
++ int i;
++ struct gs_port *port;
++
++
++ if( dev == NULL )
++ return( -EIO );
++
++ for( i=0; i<GS_NUM_PORTS; i++ ) {
++
++ if( (port=(struct gs_port *)kmalloc( sizeof(struct gs_port),
++ kmalloc_flags )) == NULL )
++ return( -ENOMEM );
++
++ memset( port, 0, sizeof( struct gs_port ) );
++ port->port_dev = dev;
++ port->port_num = i;
++ spin_lock_init( &port->port_lock );
++ init_waitqueue_head( &port->port_write_wait );
++
++ dev->dev_port[i] = port;
++
++ }
++
++ return( 0 );
++
++}
++
++
++/*
++ * gs_free_ports
++ *
++ * Free all closed ports. Open ports are disconnected by
++ * freeing their write buffers, setting their device pointers
++ * and the pointers to them in the device to NULL. These
++ * ports will be freed when closed.
++ *
++ * The device lock is normally held when calling this function.
++ */
++
++static void gs_free_ports( struct gs_dev *dev )
++{
++
++ int i;
++ unsigned long flags;
++ struct gs_port *port;
++
++
++ if( dev == NULL )
++ return;
++
++ for( i=0; i<GS_NUM_PORTS; i++ ) {
++
++ if( (port=dev->dev_port[i]) != NULL ) {
++
++ dev->dev_port[i] = NULL;
++
++ spin_lock_irqsave(&port->port_lock, flags );
++
++ if( port->port_write_buf != NULL ) {
++ gs_buf_free( port->port_write_buf );
++ port->port_write_buf = NULL;
++ }
++
++ if( port->port_open_count > 0 || port->port_in_use ) {
++ port->port_dev = NULL;
++ wake_up_interruptible( &port->port_write_wait );
++ wake_up_interruptible( &port->port_tty->read_wait );
++ wake_up_interruptible( &port->port_tty->write_wait );
++ } else {
++ kfree( port );
++ }
++
++ spin_unlock_irqrestore(&port->port_lock, flags );
++
++ }
++
++ }
++
++}
++
++
++/* Circular Buffer */
++
++/*
++ * gs_buf_alloc
++ *
++ * Allocate a circular buffer and all associated memory.
++ */
++
++static struct gs_buf *gs_buf_alloc( unsigned int size, int kmalloc_flags )
++{
++
++ struct gs_buf *gb;
++
++
++ if( size == 0 )
++ return( NULL );
++
++ gb = (struct gs_buf *)kmalloc( sizeof(struct gs_buf), kmalloc_flags );
++ if( gb == NULL )
++ return( NULL );
++
++ gb->buf_buf = kmalloc( size, kmalloc_flags );
++ if( gb->buf_buf == NULL ) {
++ kfree( gb );
++ return( NULL );
++ }
++
++ gb->buf_size = size;
++ gb->buf_get = gb->buf_put = gb->buf_buf;
++
++ return( gb );
++
++}
++
++
++/*
++ * gs_buf_free
++ *
++ * Free the buffer and all associated memory.
++ */
++
++void gs_buf_free( struct gs_buf *gb )
++{
++ if( gb != NULL ) {
++ if( gb->buf_buf != NULL )
++ kfree( gb->buf_buf );
++ kfree( gb );
++ }
++}
++
++
++/*
++ * gs_buf_clear
++ *
++ * Clear out all data in the circular buffer.
++ */
++
++void gs_buf_clear( struct gs_buf *gb )
++{
++ if( gb != NULL )
++ gb->buf_get = gb->buf_put;
++ /* equivalent to a get of all data available */
++}
++
++
++/*
++ * gs_buf_data_avail
++ *
++ * Return the number of bytes of data available in the circular
++ * buffer.
++ */
++
++unsigned int gs_buf_data_avail( struct gs_buf *gb )
++{
++ if( gb != NULL )
++ return( (gb->buf_size + gb->buf_put - gb->buf_get)
++ % gb->buf_size );
++ else
++ return( 0 );
++}
++
++
++/*
++ * gs_buf_space_avail
++ *
++ * Return the number of bytes of space available in the circular
++ * buffer.
++ */
++
++unsigned int gs_buf_space_avail( struct gs_buf *gb )
++{
++ if( gb != NULL )
++ return( (gb->buf_size + gb->buf_get - gb->buf_put - 1)
++ % gb->buf_size );
++ else
++ return( 0 );
++}
++
++
++/*
++ * gs_buf_put
++ *
++ * Copy data data from a user buffer and put it into the circular buffer.
++ * Restrict to the amount of space available.
++ *
++ * Return the number of bytes copied.
++ */
++
++unsigned int gs_buf_put( struct gs_buf *gb, const char *buf,
++ unsigned int count )
++{
++
++ unsigned int len;
++
++
++ if( gb == NULL )
++ return( 0 );
++
++ len = gs_buf_space_avail( gb );
++ if( count > len )
++ count = len;
++
++ if( count == 0 )
++ return( 0 );
++
++ len = gb->buf_buf + gb->buf_size - gb->buf_put;
++ if( count > len ) {
++ memcpy( gb->buf_put, buf, len );
++ memcpy( gb->buf_buf, buf+len, count - len );
++ gb->buf_put = gb->buf_buf + count - len;
++ } else {
++ memcpy( gb->buf_put, buf, count );
++ if( count < len )
++ gb->buf_put += count;
++ else /* count == len */
++ gb->buf_put = gb->buf_buf;
++ }
++
++ return( count );
++
++}
++
++
++/*
++ * gs_buf_get
++ *
++ * Get data from the circular buffer and copy to the given buffer.
++ * Restrict to the amount of data available.
++ *
++ * Return the number of bytes copied.
++ */
++
++unsigned int gs_buf_get( struct gs_buf *gb, char *buf, unsigned int count )
++{
++
++ unsigned int len;
++
++
++ if( gb == NULL )
++ return( 0 );
++
++ len = gs_buf_data_avail( gb );
++ if( count > len )
++ count = len;
++
++ if( count == 0 )
++ return( 0 );
++
++ len = gb->buf_buf + gb->buf_size - gb->buf_get;
++ if( count > len ) {
++ memcpy( buf, gb->buf_get, len );
++ memcpy( buf+len, gb->buf_buf, count - len );
++ gb->buf_get = gb->buf_buf + count - len;
++ } else {
++ memcpy( buf, gb->buf_get, count );
++ if( count < len )
++ gb->buf_get += count;
++ else /* count == len */
++ gb->buf_get = gb->buf_buf;
++ }
++
++ return( count );
++
++}
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/drivers/usb/gadget/inode.c kernel/drivers/usb/gadget/inode.c
+--- /tmp/kernel/drivers/usb/gadget/inode.c 1970-01-01 01:00:00.000000000 +0100
++++ kernel/drivers/usb/gadget/inode.c 2005-04-22 17:53:19.456535934 +0200
+@@ -0,0 +1,1807 @@
++/*
++ * 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/kernel.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>
++
++#ifndef BUG_ON
++#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
++#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.
++ */
++
++ // FIXME the 2.6 version just probes the controller
++ // driver to find out the chip name; we should too.
++
++#ifdef CONFIG_USB_GADGET_NET2280
++#define CHIP "net2280"
++#define HIGHSPEED
++#endif
++
++#ifdef CONFIG_USB_GADGET_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_GADGET_GOKU
++#define CHIP "goku_udc"
++#endif
++
++#ifdef CONFIG_USB_GADGET_SA1100
++#define CHIP "sa1100"
++#endif
++
++#ifdef CONFIG_USB_GADGET_SUPERH
++#define CHIP "superh_udc"
++#endif
++
++#ifdef CONFIG_USB_GADGET_N9604
++#define CHIP "n9604_udc"
++#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);
++ int value;
++
++ 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;
++ value = usb_ep_queue (epdata->ep, req, GFP_ATOMIC);
++ } else
++ value = -ENODEV;
++ spin_unlock_irq (&epdata->dev->lock);
++
++ if (likely (value == 0)) {
++ 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);
++ spin_unlock_irq (&epdata->dev->lock);
++
++ wait_event (done.wait, done.done);
++ if (epdata->status == -ECONNRESET)
++ epdata->status = -EINTR;
++ } else {
++ spin_unlock_irq (&epdata->dev->lock);
++
++ DBG (epdata->dev, "endpoint gone\n");
++ epdata->status = -ENODEV;
++ }
++ }
++ return epdata->status;
++ }
++ return value;
++}
++
++
++/* 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;
++ }
++
++ /* FIXME readahead for O_NONBLOCK and poll(); careful with ZLPs */
++
++ value = -ENOMEM;
++ kbuf = kmalloc (len, SLAB_KERNEL);
++ if (unlikely (!kbuf))
++ goto free1;
++
++ value = ep_io (data, kbuf, len);
++ VDEBUG (data->dev, "%s read %d OUT, status %d\n",
++ data->name, len, value);
++ 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;
++ }
++
++ /* FIXME writebehind for O_NONBLOCK and poll(), qlen = 1 */
++
++ value = -ENOMEM;
++ kbuf = kmalloc (len, SLAB_KERNEL);
++ if (!kbuf)
++ goto free1;
++ if (copy_from_user (kbuf, buf, len)) {
++ value = -EFAULT;
++ goto free1;
++ }
++
++ value = ep_io (data, kbuf, len);
++ VDEBUG (data->dev, "%s write %d IN, status %d\n",
++ data->name, len, value);
++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);
++
++ /* FIXME state could change from under us */
++ 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;
++ case USB_DT_STRING:
++ goto unrecognized;
++
++ default: // all others are errors
++ break;
++ }
++ 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;
++
++ /* break link to FS */
++ ep = list_entry (entry, struct ep_data, epfiles);
++ list_del_init (&ep->epfiles);
++
++ /* 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);
++
++ /* fds may still be open */
++ goto restart;
++ }
++ spin_unlock_irq (&dev->lock);
++}
++
++
++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;
++
++ 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;
++ /* FIXME check lengths: walk to end */
++}
++
++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,
++};
++
++/*----------------------------------------------------------------------*/
++
++/*
++ * implementation for 2.4 uses character special files
++ * ep0/device file MKDEV (c_major, 0)
++ * first data ep MKDEV (c_major, 1)
++ * second data ep MKDEV (c_major, 2)
++ * ...
++ *
++ * FIXME can do it as a real filesystem on 2.4 too, without libfs
++ */
++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,
++};
++
++/*----------------------------------------------------------------------*/
++
++static int __init init (void)
++{
++ int status;
++
++ 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);
++
++ 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);
++ unregister_chrdev (c_major, shortname);
++}
++module_exit (cleanup);
++
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/drivers/usb/gadget/n9604.c kernel/drivers/usb/gadget/n9604.c
+--- /tmp/kernel/drivers/usb/gadget/n9604.c 1970-01-01 01:00:00.000000000 +0100
++++ kernel/drivers/usb/gadget/n9604.c 2005-04-22 17:53:19.461535120 +0200
+@@ -0,0 +1,1088 @@
++/*
++ * National 9603/4 USB Device Controller driver
++ * Copyright (C) 2004 Technical Solutions Inc. (support@techsol.ca)
++ * ported from : The Goku-S driver
++ * 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 six semi-configurable bulk/interrupt endpoints.
++ *
++ * - Endpoint numbering is fixed:
++ * Endpoint 0: ep0
++ * Endpoint 1: ep1in (tx)
++ * Endpoint 2: ep2out (rx)
++ * Endpoint 3: ep3in (tx)
++ * Endpoint 4: ep4out (rx)
++ * Endpoint 5: ep5in (tx)
++ * Endpoint 6: ep6out (rx)
++ */
++
++/*
++ * The ep->stage information refers to the state of a setup transaction
++ *
++ * state 0: no setup packet has been received
++ * state 1: setup packet has been received
++ * state 2: data has been sent/received
++ * state 3: ZLP has been received/sent
++ */
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/module.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>
++
++#include "n9604.h"
++#include "n9604regs.h"
++
++inline void Flush_and_enable(u8 control_reg) {
++ write_9604(RXC_FLUSH, control_reg);
++ while (read_9604(control_reg) & RXC_FLUSH);
++ write_9604(RXC_RX_EN, control_reg);
++}
++inline void Flush(u8 control_reg) {
++ write_9604(RXC_FLUSH, control_reg);
++ while (read_9604(control_reg) & RXC_FLUSH);
++}
++
++#define DRIVER_DESC "N9604 USB Device Controller"
++#define DRIVER_VERSION "29-Oct 2004"
++
++static const char driver_name [] = "n9604_udc";
++static const char driver_desc [] = DRIVER_DESC;
++
++MODULE_AUTHOR("support@techsol.ca");
++MODULE_DESCRIPTION(DRIVER_DESC);
++MODULE_LICENSE("GPL");
++
++static void nuke(struct n9604_ep *ep, int status);
++inline void send_zero_length(int endpoint, struct n9604_udc *dev);
++
++u8 * USBN9604_Offset; //device virtual address
++
++/* FIXME all the IRQ stuff is board-specific
++ */
++
++#define h7201_readl readl
++#define h7201_writel writel
++
++#define ETHER_IRQ_IP_OFFSET 0
++#define ETHER_IRQ_BIT_POS 0
++#define ETHER_IRQ_IM_OFFSET 0
++
++#define IRQ_GPIOC -1
++
++#define USBD_ENABLE_IRQ {h7201_writel( h7201_readl(ETHER_IRQ_IP_OFFSET) | (1 << ETHER_IRQ_BIT_POS), ETHER_IRQ_IP_OFFSET); h7201_writel( h7201_readl(ETHER_IRQ_IM_OFFSET) | (1 << ETHER_IRQ_BIT_POS), ETHER_IRQ_IM_OFFSET);}
++#define USBD_DISABLE_IRQ h7201_writel( h7201_readl(ETHER_IRQ_IM_OFFSET) & ~(1 << ETHER_IRQ_BIT_POS), ETHER_IRQ_IM_OFFSET);
++
++
++/*-------------------------------------------------------------------------*/
++
++//enable an end point, of description desc
++static int n9604_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) {
++ struct n9604_udc *dev;
++ struct n9604_ep *ep;
++ u16 max;
++
++ ep = container_of(_ep, struct n9604_ep, ep);
++
++ if (!_ep || !desc || ep->desc || desc->bDescriptorType != USB_DT_ENDPOINT)
++ return -EINVAL;
++
++ dev = ep->dev;
++ if (!ep->num)
++ 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;
++ }
++
++ write_9604((ep->numActual & EPC_EP_MASK) | EPC_EP_EN | (EPC_ISO * ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC)), ep->control);
++ if (ep->is_in)
++ Flush(ep->command);
++ else
++ Flush_and_enable(ep->command);
++
++ max = le16_to_cpu(get_unaligned(&desc->wMaxPacketSize));
++ ep->ep.maxpacket = min_t(u16, max, MAX_FIFO_SIZE);
++ ep->desc = desc;
++
++ return 0;
++}
++
++static int n9604_ep_disable(struct usb_ep *_ep)//ep > 0
++{
++ struct n9604_ep *ep;
++ struct n9604_udc *dev;
++ unsigned long flags;
++
++ ep = container_of(_ep, struct n9604_ep, ep);
++
++ if (!_ep || !ep->desc)
++ return -ENODEV;
++ dev = ep->dev;
++
++ spin_lock_irqsave(&dev->lock, flags);
++ nuke(ep, -ESHUTDOWN);
++ write_9604(0, ep->command);
++ ep->desc = NULL;
++ spin_unlock_irqrestore(&dev->lock, flags);
++
++ return 0;
++}
++
++/*-------------------------------------------------------------------------*/
++
++static struct usb_request *
++n9604_alloc_request(struct usb_ep *_ep, int gfp_flags)
++{
++ struct n9604_request *req;
++
++ if (!_ep)
++ return 0;
++ req = kmalloc(sizeof *req, gfp_flags);
++ if (!req)
++ return 0;
++
++ memset(req, 0, sizeof *req);
++ INIT_LIST_HEAD(&req->queue);
++ return &req->req;
++}
++
++static void
++n9604_free_request(struct usb_ep *_ep, struct usb_request *_req)
++{
++ struct n9604_request *req;
++
++ if (!_ep || !_req)
++ return;
++
++ req = container_of(_req, struct n9604_request, req);
++ WARN_ON(!list_empty(&req->queue));
++ kfree(req);
++}
++
++/*-------------------------------------------------------------------------*/
++
++static void done(struct n9604_ep *ep, struct n9604_request *req, int status);
++
++static inline int
++write_packet(struct n9604_ep *ep, u8 *buf, struct n9604_request *req)
++{
++ unsigned written_length, desired_length, available_length, maximum_length, flags, loop_length;
++
++ u8 fifo = ep->fifo;
++ u8 command = ep->command;
++ u8 status = ep->status;
++ if (!ep->num) {
++ fifo = TXD0;
++ command = TXC0;
++ status = TXS0;
++ }
++
++ if (read_9604(command) & TXC_TX_EN)
++ return -EBUSY;
++ ep->packets++;
++
++ desired_length = req->req.length - req->req.actual;
++ available_length = read_9604(status) & TXS_TCOUNT_MASK;//might be greater
++ written_length = 0;
++ if (ep->num)
++ maximum_length = MAX_FIFO_SIZE;
++ else
++ maximum_length = MAX_EP0_SIZE;
++
++ while ((loop_length = min(min(available_length, desired_length), maximum_length))) {
++ int i = loop_length;
++ while (i) { write_9604(*buf++,fifo); i--; }
++ written_length += loop_length;
++ desired_length -= loop_length;
++ maximum_length -= loop_length;
++ if (desired_length && maximum_length)//check if really need to read the chip again
++ available_length = (read_9604(status) & TXS_TCOUNT_MASK);
++ }
++
++ req->req.actual += written_length;
++
++ flags = TXC_TX_EN;
++ if (ep->num)
++ flags |= TXC_LAST;
++ if (ep->toggle)
++ flags |= TXC_TOGGLE;
++ write_9604(flags, command);
++ ep->toggle = !(ep->toggle);
++ if (!written_length) req->req.zero = 0;//just wrote zero bytes, there is no more need for req.zero
++ return written_length;
++}
++
++// return: 0 = still running, 1 = completed, negative = errno
++static int write_fifo(struct n9604_ep *ep, struct n9604_request *req)
++{
++ struct n9604_udc *dev = ep->dev;
++ u8 *buf;
++ unsigned count;
++ int is_last;
++
++ buf = req->req.buf + req->req.actual;
++ prefetch(buf);
++
++ dev = ep->dev;
++
++ count = write_packet(ep, buf, req);
++ if (count < 0)
++ return count;
++
++ /* last packet often short (sometimes a zlp, especially on ep0) */
++ if ((req->req.length != req->req.actual) || req->req.zero)
++ is_last = 0;
++ else
++ is_last = 1;
++
++ /* 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 inline void pio_irq_enable(struct n9604_ep *ep);
++
++static int read_fifo(struct n9604_ep *ep, struct n9604_request *req)
++{
++ u32 size;
++ u8 *buf;
++ int bufferspace_available, fifospace_left, num_bytes_read;
++ int fifo, status;
++ ep->packets++;
++ if (!ep->num) {
++ fifo = RXD0;
++ status = RXS0;
++ } else {
++ fifo = ep->fifo;
++ status = ep->status;
++ }
++ num_bytes_read = 0;
++ buf = req->req.buf + req->req.actual;
++ bufferspace_available = req->req.length - req->req.actual;
++ size = read_9604(status) & (RXS_RCOUNTMASK | RXS_RX_ERR);//number of bytes ready to be read (15 if greater than 15)
++ if (ep->num && (size & RXS_RX_ERR)) {
++ ERROR(ep->dev, "DATA ERROR!!!! on ep%d\nFlushing Fifo", ep->num);
++ Flush_and_enable(ep->command);
++ goto leave;
++ }
++ size = size & ~RXS_RX_ERR;//clear the bit
++ if (ep->num) fifospace_left = MAX_FIFO_SIZE;
++ else fifospace_left = MAX_EP0_SIZE;
++loop:
++ /* read all bytes from this packet */
++ while (size-- != 0) {
++ u8 byte = read_9604(fifo);
++ if (unlikely(bufferspace_available == 0)) {
++ /* this happens when the driver's buffer
++ * is smaller than what the host sent.
++ * discard the extra data in this packet.
++ */
++ done(ep, req, -EOVERFLOW);
++ return 1;
++ } else {
++ *buf++ = byte;
++ bufferspace_available--;
++ fifospace_left--;
++ num_bytes_read++;
++ }
++ }
++ if ((size = (read_9604(status) & RXS_RCOUNTMASK))) {
++ goto loop;//since there is more data
++ }
++ /* completion */
++ req->req.actual = req->req.actual + num_bytes_read;
++ if (fifospace_left || req->req.actual == req->req.length) {
++ done(ep, req, 0);
++ return 1;
++ }
++leave:
++ pio_irq_enable(ep);//turn the interrupt back on
++ return 0;
++}
++
++
++/*-------------------------------------------------------------------------*/
++
++static inline void
++pio_irq_enable(struct n9604_ep *ep)
++{
++ if (ep->is_in)
++ write_9604(read_9604(TXMSK) | 1 << ep->fifoNum | 0x10 << ep->fifoNum, TXMSK);
++ else {
++ u8 command = ep->command;
++ if (!ep->num) command = RXC0;
++ write_9604(read_9604(RXMSK) | 1 << ep->fifoNum | 0x10 << ep->fifoNum, RXMSK);
++ write_9604(RXC_RX_EN | RXC_RFWL0 | RXC_RFWL1, command);
++ }
++}
++
++static inline void
++pio_irq_disable(struct n9604_ep *ep)//epnum != 0
++{
++ if (ep->is_in)
++ write_9604(read_9604(TXMSK) & ~(1 << ep->fifoNum) & ~(0x10 << ep->fifoNum), TXMSK);
++ else
++ write_9604(read_9604(RXMSK) & ~(1 << ep->fifoNum) & ~(0x10 << ep->fifoNum), RXMSK);
++}
++
++static int request_voodoo = 0;//number of bytes the host requested
++
++static inline void
++pio_advance(struct n9604_ep *ep)
++{
++ struct n9604_request *req;
++
++ if (list_empty (&ep->queue)) {
++ if (!ep->num) {
++ if (ep->is_in && (ep->stage == 2)) {
++ ep->is_in = 0;//switch modes
++ Flush_and_enable(RXC0);//needed to receive a ZLP after tx
++ ep->stage++;//and bump the stage number
++ } else if (ep->stage == 3) {
++ ep->stage = 0;
++ }
++ }
++ return;
++ }
++ req = list_entry(ep->queue.next, struct n9604_request, queue);
++ (ep->is_in ? write_fifo : read_fifo)(ep, req);
++}
++
++/*-------------------------------------------------------------------------*/
++
++static void * n9604_alloc_buffer(struct usb_ep *_ep, unsigned bytes, dma_addr_t *dma, int gfp_flags)
++{
++ return kmalloc(bytes, gfp_flags);
++}
++
++static void n9604_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma, unsigned bytes)
++{
++ kfree (buf);
++}
++
++
++
++/*-------------------------------------------------------------------------*/
++
++static void
++done(struct n9604_ep *ep, struct n9604_request *req, int status)
++{
++ struct n9604_udc *dev;
++
++ list_del_init(&req->queue);
++ ep->queue_active--;
++
++ if (req->req.status == -EINPROGRESS)
++ req->req.status = status;
++ else
++ status = req->req.status;
++
++ dev = ep->dev;
++
++ /* don't modify queue heads during completion callback */
++ if (ep->num)
++ pio_irq_disable(ep);
++ else if (!ep->nuking) {
++ ep->stage++;
++ ep->toggle = 1;//other endpoints stay in their flipping mode between transactions
++ if (ep->stage == 2) {//we are in stage 2 now
++ if (!ep->is_in) {
++ ep->is_in = 1;//switch modes
++ request_voodoo = 1;//prevents n9604_queue from calling us again before doing anything
++ send_zero_length(0, dev);
++ } else {//we have to receive a ZLP
++ //this will happen when the tx is complete, the pio_advance fcn will activate it for us
++ }
++ }
++ }
++
++ req->req.complete(&ep->ep, &req->req);
++}
++
++
++/*-------------------------------------------------------------------------*/
++
++static int
++n9604_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
++{
++ struct n9604_request *req;
++ struct n9604_ep *ep;
++ struct n9604_udc *dev;
++ unsigned long flags;
++ int status;
++
++ req = container_of(_req, struct n9604_request, req);
++ if (unlikely(!_req || !_req->complete
++ || !_req->buf || !list_empty(&req->queue)))
++ return -EINVAL;
++ ep = container_of(_ep, struct n9604_ep, ep);
++ if (unlikely(!_ep || (!ep->desc && ep->num != 0)))
++ return -EINVAL;
++ dev = ep->dev;
++ if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) {
++ return -ESHUTDOWN;
++ }
++ if (ep->nuking)
++ return -ESHUTDOWN;
++
++ spin_lock_irqsave(&dev->lock, flags);
++
++ ep->queue_reqs++;
++ ep->queue_active++;
++
++ _req->status = -EINPROGRESS;
++ _req->actual = 0;
++
++ /* for ep0 IN without premature status, zlp is required and
++ * writing EOP starts the status stage (OUT).
++ */
++ if (ep->num == 0) {
++ if ((request_voodoo > _req->length) && !(_req->length % MAX_EP0_SIZE) && (_req->length != 0)) {
++ _req->zero = 1;
++ }
++ if (!request_voodoo && !ep->is_in) {//this is a zero length request
++ spin_unlock_irqrestore(&dev->lock, flags);//David
++ done(ep, req, 0);//this doesn't check if the list is empty (probably not an issue)
++ return 0; //shouldn't this be handled by the rx irq fcn, and passed to pio_advance
++ }//that may conflict with the voodoo stuff, maybe best to leave it
++ }
++
++ /* kickstart this i/o queue? */
++ status = 0;
++ if (list_empty(&ep->queue) && ep->is_in) {
++ status = write_fifo(ep, req);
++ if (status == -EBUSY)
++ ;//we should queue up the request then
++ else {
++ if (status != 0) {
++ if (status > 0)
++ status = 0;
++ req = 0;
++ }
++ }
++ } /* else pio or dma irq handler advances the queue. */
++
++ if (req != 0) {
++ list_add_tail(&req->queue, &ep->queue);
++ pio_irq_enable(ep);
++ }
++
++ spin_unlock_irqrestore(&dev->lock, flags);
++ return status;
++}
++
++/* dequeue ALL requests */
++static void nuke(struct n9604_ep *ep, int status)
++{
++ struct n9604_request *req;
++
++ if (list_empty(&ep->queue))
++ return;
++ ep->nuking = 1;
++ while (!list_empty(&ep->queue)) {
++ req = list_entry(ep->queue.next, struct n9604_request, queue);
++ done(ep, req, status);
++ }
++ ep->nuking = 0;
++}
++
++/* dequeue JUST ONE request */
++static int n9604_dequeue(struct usb_ep *_ep, struct usb_request *_req)
++{
++ struct n9604_request *req;
++ struct n9604_ep *ep;
++ struct n9604_udc *dev;
++ unsigned long flags;
++
++ ep = container_of(_ep, struct n9604_ep, ep);
++ if (!_ep || !_req || (!ep->desc && ep->num != 0))
++ return -EINVAL;
++ dev = ep->dev;
++
++ if (!dev->driver)
++ return -ESHUTDOWN;
++
++ 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;
++ }
++
++ spin_unlock_irqrestore(&dev->lock, flags);
++
++ return req ? 0 : -EOPNOTSUPP;
++}
++
++static int n9604_clear_halt(struct usb_ep *_ep) {
++ struct n9604_ep *ep;
++ ep = container_of (_ep, struct n9604_ep, ep);
++
++ write_9604(read_9604(ep->control) & ~EPC_STALL, ep->control);
++ pio_advance(ep);
++ return 0;
++}
++
++static int n9604_set_halt(struct usb_ep *_ep, int value) {
++ struct n9604_ep *ep;
++ unsigned long flags;
++ int retval = 0;
++
++ if (!_ep) {
++ retval = -ENODEV; goto exit;
++ }
++ ep = container_of (_ep, struct n9604_ep, ep);
++
++ if (ep->num == 0) {//is this valid?
++ if (!value) {
++ retval = -EINVAL; goto exit; }
++
++ /* don't change EPxSTATUS_EP_INVALID to READY */
++ } else if (!ep->desc) {
++ retval = -EINVAL; goto exit;
++ }
++
++ spin_lock_irqsave(&ep->dev->lock, flags);
++ if (!list_empty(&ep->queue))
++ retval = -EAGAIN;
++ else if (!value)
++ n9604_clear_halt(_ep);
++ else {
++ write_9604(read_9604(ep->control) | EPC_STALL, ep->control);
++ }
++ spin_unlock_irqrestore(&ep->dev->lock, flags);
++exit:
++ return retval;
++}
++
++static int n9604_fifo_status(struct usb_ep *_ep) {//not implemented
++ return -1;
++}
++
++static void n9604_fifo_flush(struct usb_ep *_ep) {//not implemented
++ struct n9604_ep *ep;
++ ep = container_of (_ep, struct n9604_ep, ep);
++}
++
++/*-------------------------------------------------------------------------*/
++
++static struct usb_ep_ops n9604_ep_ops = {
++ .enable = n9604_ep_enable,
++ .disable = n9604_ep_disable,
++
++ .alloc_request = n9604_alloc_request,//io request objects called struct usb_request
++ .free_request = n9604_free_request,
++
++ .alloc_buffer = n9604_alloc_buffer,
++ .free_buffer = n9604_free_buffer,
++
++ .queue = n9604_queue,//submit a struct usb_request object to an endpoint
++ .dequeue = n9604_dequeue,
++
++ .set_halt = n9604_set_halt,//halts an endpoint
++ .fifo_status = n9604_fifo_status,//bytes in FIFO + data ready to go in FIFO
++ .fifo_flush = n9604_fifo_flush,//flush all the data, endpoint is probably been reconfigured
++};
++
++/*-------------------------------------------------------------------------*/
++
++static int n9604_get_frame(struct usb_gadget *_gadget)
++{
++ return -EOPNOTSUPP;
++}
++
++static const struct usb_gadget_ops n9604_ops = {
++ .get_frame = n9604_get_frame,
++};
++
++/*-------------------------------------------------------------------------*/
++
++static void udc_reinit (struct n9604_udc *dev)
++{
++ static char *names [] = { "ep0", "ep1in", "ep2out", "ep3in", "ep4out", "ep5in", "ep6out" };
++ unsigned i;
++
++ INIT_LIST_HEAD (&dev->gadget.ep_list);
++ dev->gadget.ep0 = &dev->ep [0].ep;
++ dev->gadget.speed = USB_SPEED_UNKNOWN;
++ dev->irqs = 0;
++ dev->configured = 0;
++
++ //for (i = 0; i < 7; i++) {
++ for (i = 0; i < ARRAY_SIZE(names); i++) {
++ struct n9604_ep *ep = &dev->ep[i];
++ ep->num = i;
++ ep->numActual = i;
++ ep->ep.name = names[i];
++ ep->irqs = 0;
++ if (i) {
++ ep->fifo = (i * 4) + RXD0; //each FIFO address is 4 bytes away. TXD0 is the first
++ ep->control = ep->fifo - 1;
++ ep->status = ep->fifo + 1;
++ ep->command = ep->fifo + 2;
++ Flush(ep->command);//flush any data in the fifo//we don't care about the previous state
++ read_9604(ep->status);
++ ep->ep.maxpacket = MAX_FIFO_SIZE;
++ } else {//were are endpoint 0
++ ep->fifo = ep->control = ep->status = ep->command = 0xff;//this should force an error
++ //we need to do this since we don't know if
++ //this is tx or rx
++ read_9604(TXS0);
++ Flush(TXC0);
++ Flush(RXC0);//we could potentially (probably) overwriting a pending setup packet
++ if (ep->stage)//if we get a setup packet before we have a chance to finish the reset we have a problem
++ read_9604(RXS0);//fix this by sending stalls or something
++ ep->stage = 0;
++ ep->ep.maxpacket = MAX_EP0_SIZE;
++ }
++ ep->is_in = i % 2;
++ ep->fifoNum = (i + ep->is_in) / 2;//ignored for endpoint 0
++ ep->ep.ops = &n9604_ep_ops;
++ list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
++ ep->dev = dev;
++ INIT_LIST_HEAD (&ep->queue);
++ ep->nuking=0;
++ ep->queue_reqs = 0;
++ ep->queue_active = 0;
++ ep->packets = 0;
++ ep->desc = 0;
++ ep->irqs = 0;
++ }
++
++ list_del_init (&dev->ep[0].ep.ep_list);
++
++ write_9604(~WKUP_PNDUSB & ~WKUP_PNDUC & read_9604(WKUP), WKUP);//clear the bits, we've done a reset
++ write_9604(FAR_AD_EN, FAR);//enable the chip to answer requests//address 0
++ dev->address = 0;
++ write_9604(0, EPC0);//clear the control register
++ write_9604(NFSR_NodeOperational, NFSR);//we're going for gold
++}
++
++static void udc_reset(struct n9604_udc *dev)
++{
++ //USBD_DISABLE_IRQ; This disables all interrupts sharing that line
++ write_9604(MCNTRL_SRST,MCNTRL);//software reset -- this also prevents pullup
++ write_9604(0x00, MAMSK); //disable interrupts
++}
++
++
++
++static void udc_enable(struct n9604_udc *dev)
++{
++ udc_reset(dev); //this is to prevent a pullup resistor
++ udc_reinit (dev);
++
++ dev->gadget.speed = USB_SPEED_FULL;
++
++ // enable ep0 interrupts
++ dev->ep[0].is_in = 0;
++
++ write_9604(MAMSK_WARN | MAMSK_ALT | MAMSK_TX_EV | MAMSK_RX_EV | MAMSK_INTR, MAMSK);//for now we turn it all on, except frames & ULD & NAK
++ write_9604(ALTMSK_RESET, ALTMSK);//just turn on reset
++ write_9604(0x11, TXMSK);
++ write_9604(0x11, RXMSK);
++ write_9604(0x0, NAKMSK);
++ write_9604(0x0, FWMSK);
++ write_9604(MCNTRL_NAT | MCNTRL_INTOC_ActHigh, MCNTRL);//this activates the pull-up and turns on interrupts
++ USBD_ENABLE_IRQ;
++}
++
++/*-------------------------------------------------------------------------*/
++
++/* keeping it simple:
++ * - one bus driver, initted first;
++ * - one function driver, initted second
++ */
++
++static struct n9604_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 n9604_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) {
++ 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);
++
++ return 0;
++}
++EXPORT_SYMBOL(usb_gadget_register_driver);
++
++int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
++{
++ struct n9604_udc *dev = the_controller;
++ unsigned long flags;
++ int i;
++
++ if (!dev)
++ return -ENODEV;
++ if (!driver || driver != dev->driver)
++ return -EINVAL;
++
++ spin_lock_irqsave(&dev->lock, flags);
++ dev->driver = 0;
++
++ udc_reset(dev);//reset & diable irqs
++ for (i = 0; i < ARRAY_SIZE(dev->ep); i++)
++ nuke(&dev->ep [i], -ESHUTDOWN);
++ spin_unlock_irqrestore(&dev->lock, flags);
++
++ if (dev->gadget.speed != USB_SPEED_UNKNOWN)
++ driver->disconnect(&dev->gadget);
++ driver->unbind(&dev->gadget);
++
++ return 0;
++}
++EXPORT_SYMBOL(usb_gadget_unregister_driver);
++
++
++/*-------------------------------------------------------------------------*/
++
++inline u8 tx_ev_irq(struct n9604_udc *dev) {
++ u8 mask;
++
++ mask = read_9604(TXEV) & read_9604(TXMSK);
++
++ if (mask & TXEV_FIFO0) {
++ write_9604(0, EPC0);//make sure we are not stalled, & not using the default address
++ read_9604(TXS0);//should really check for error conditions
++ dev->ep[0].irqs++;
++ pio_advance(&dev->ep[0]);
++ }
++ if (mask & TXEV_FIFO1) {
++ read_9604(TXS1);
++ dev->ep[1].irqs++;
++ pio_advance(&dev->ep[1]);
++ }
++ if (mask & TXEV_FIFO2) {
++ read_9604(TXS2);
++ dev->ep[3].irqs++;
++ pio_advance(&dev->ep[3]);
++ }
++ if (mask & TXEV_FIFO3) {
++ read_9604(TXS3);
++ dev->ep[5].irqs++;
++ pio_advance(&dev->ep[5]);
++ }
++ return mask;
++}
++
++static void my_req_complete(struct usb_ep *_ep, struct usb_request *req) {//this was for the setup packet, but I guess I could use it for anything
++ n9604_free_buffer(_ep, req->buf, req->dma, req->length);
++ n9604_free_request(_ep, req);
++}
++
++inline void send_dummy_packet(int endpoint, struct n9604_udc *dev, int length) {
++ struct usb_request *my_req;
++ my_req = n9604_alloc_request(&dev->ep[endpoint].ep, GFP_ATOMIC);
++ my_req->length = length;
++ my_req->buf = n9604_alloc_buffer(&dev->ep[endpoint].ep, length, &my_req->dma, GFP_ATOMIC);
++ my_req->complete = my_req_complete;
++ n9604_queue(&dev->ep[endpoint].ep, my_req, GFP_ATOMIC);
++}
++
++inline void send_zero_length(int endpoint, struct n9604_udc *dev) {
++ send_dummy_packet(endpoint, dev, 0);
++}
++
++inline void rx_ev_irq(struct n9604_udc *dev) {
++ u8 mask;
++ struct n9604_ep *ep;
++
++ mask = read_9604(RXEV) & read_9604(RXMSK);
++
++ if (mask & RXEV_FIFO0) {
++ static int read_mode = 0;
++ u8 rxs_mask = read_9604(RXS0);
++ ep = &dev->ep[0];
++ ep->irqs++;
++ if (rxs_mask & RXS_SETUP) {
++ struct usb_ctrlrequest ctrl;
++ ep->packets++;
++ write_9604(0x40, ALTMSK);//someone is talking to us. Make sure we can be reset if we lose this communication
++ ep->stage = 1;
++ rxs_mask = read_9604(RXS0);//2nd read (1st one is for zero length packet)
++ ctrl.bRequestType = read_9604(RXD0);
++ ctrl.bRequest = read_9604(RXD0);
++ ctrl.wValue = read_9604(RXD0) + (read_9604(RXD0) << 8);
++ ctrl.wIndex = read_9604(RXD0) + (read_9604(RXD0) << 8);
++ ctrl.wLength = read_9604(RXD0) + (read_9604(RXD0) << 8);
++ ep->toggle = 1;
++ request_voodoo = ctrl.wLength;
++ if (ctrl.bRequestType & 0x80) {//This is an IN transaction
++ ep->is_in = 1;//David: is this correct for both cases//check with n9604_queue
++ read_mode = 0;
++ if (ctrl.wLength) {//should be followed by ZLP out packet
++ } else {//host expects ZLP out packet
++ ep->stage = 2;
++ }
++ } else {//This is an out transaction
++ if (ctrl.wLength) {
++ ep->is_in = 0;
++ read_mode = 1;
++ } else {//host expects ZLP in packet
++ read_mode = 0;
++ ep->stage = 2;
++ ep->is_in = 1;
++ }
++ }
++ switch (ctrl.bRequest) {
++ case USB_REQ_SET_ADDRESS:
++ write_9604(EPC_DEF, EPC0);//we still want to respond to the default address
++ write_9604(((dev->address = (ctrl.wValue & FAR_AD_MASK))) | FAR_AD_EN, FAR);
++ send_zero_length(0, dev);
++ dev->configured = 1;//we can send longer packets now :)
++ read_9604(ALTEV);
++ write_9604(ALTMSK_RESET, ALTMSK);//we also listen to reset requests too
++ break;
++ case USB_REQ_CLEAR_FEATURE:
++ if (ctrl.wValue == 0 && ctrl.bRequestType == 2) {//endpoint halt
++ int i;
++ for (i = 0; i < ARRAY_SIZE(dev->ep); i++)
++ if ((ctrl.wIndex & 0xF) == dev->ep[i].numActual)
++ n9604_clear_halt(&dev->ep[i].ep);
++ send_zero_length(0, dev);
++ break;
++ }
++ case USB_REQ_SET_DESCRIPTOR:
++ case USB_REQ_SYNCH_FRAME:
++ case USB_REQ_GET_STATUS:
++ case USB_REQ_SET_FEATURE:
++ case USB_REQ_SET_CONFIGURATION:
++ case USB_REQ_GET_DESCRIPTOR:
++ case USB_REQ_GET_CONFIGURATION:
++ case USB_REQ_SET_INTERFACE:
++ case USB_REQ_GET_INTERFACE:
++ default:
++ if (dev->driver->setup(&dev->gadget, &ctrl) < 0)//there was an error
++ if (((ctrl.bRequestType & 0x80) && ctrl.wLength) || (!(ctrl.bRequestType & 0x80) && !ctrl.wLength))
++ send_zero_length(0, dev);
++ }//crtl.bRequest
++ }//setup
++ else if (read_mode)
++ pio_advance(ep);
++ else {
++ ep->stage = 0;
++ ep->packets++;
++ }
++ }//fifo 0
++ if (mask & RXEV_FIFO1) {
++ ep = &dev->ep[2];
++ pio_advance(ep);
++ ep->irqs++;
++ }
++ if (mask & RXEV_FIFO2) {
++ ep = &dev->ep[4];
++ pio_advance(ep);
++ ep->irqs++;
++ }
++ if (mask & RXEV_FIFO3) {
++ ep = &dev->ep[6];
++ pio_advance(ep);
++ ep->irqs++;
++ }
++}
++
++inline void alt_ev_irq(struct n9604_udc *dev) {
++ u8 mask;
++
++ mask = read_9604(ALTEV) & read_9604(ALTMSK);
++
++ if (mask & ALTEV_EOP);
++ if (mask & ALTEV_SD3);
++ if (mask & ALTEV_SD5);
++ if (mask & ALTEV_RESET) {
++ int i;
++ udelay(1200);//no idea why this is needed, but it makes things work
++ write_9604(0x0, FAR);//lets not respond to any packets until we are ready
++ write_9604(NFSR_NodeReset, NFSR);
++ dev->driver->disconnect(&dev->gadget);
++ for (i = 0; i < ARRAY_SIZE(dev->ep); i++)
++ nuke(&dev->ep [i], -ESHUTDOWN);//this should be handled above by disconnect
++ write_9604(0x00, ALTMSK);//make sure reset is turned off, or we will constantly be interrupted
++ write_9604(0x11, TXMSK);
++ write_9604(0x11, RXMSK);
++ udc_reinit(dev);
++ dev->gadget.speed = USB_SPEED_FULL;
++ dev->ep[0].is_in = 0;
++ }
++ if (mask & ALTEV_RESUME); //write_9604(NFSR_NodeOperational, NFSR);
++ if (mask & ALTEV_WKUP);//we don't really sleep
++ if (mask & ALTEV_DMA);
++}
++
++static void n9604_irq(int irq, void *_dev, struct pt_regs *r) {
++ struct n9604_udc *dev = _dev;
++ u8 mask;
++
++ mask = read_9604(MAEV) & read_9604(MAMSK);
++ if (!mask)
++ return;
++
++ if (mask & MAEV_ALT) {
++ alt_ev_irq(dev);
++ mask = read_9604(MAEV) & read_9604(MAMSK);//force a re-read of the current pending interrupts
++ }
++ if (mask & MAEV_TX_EV)
++ tx_ev_irq(dev);
++ if (mask & MAEV_RX_EV)
++ rx_ev_irq(dev);
++ dev->irqs++;
++ return;
++}
++
++/*-------------------------------------------------------------------------*/
++
++static int __init init (void)
++{
++ struct n9604_udc *dev;
++ int ret;
++ u8 * addr;
++
++ if (the_controller)
++ return -EBUSY;
++
++ addr = ioremap(USBN9604_PHYS, 0x2);//ioremap will bump this to 1 page size
++ if (!addr) {
++ ERROR(dev, KERN_ERR "Unable to remap address\n");
++ return -EINVAL;
++ }
++
++ USBN9604_Offset = addr;
++
++ if ((read_9604(RID) & 0xF) != 0x2) { //0x2 is the identifier for 9603/4
++ iounmap(addr);
++ return -ENODEV;
++ }
++
++ /* alloc, and start init */
++ dev = kmalloc(sizeof *dev, SLAB_KERNEL);
++ if (dev == NULL){
++ WARN(dev, "No memory");
++ iounmap(addr);
++ return -ENOMEM;
++ }
++ memset(dev, 0, sizeof *dev);
++ spin_lock_init(&dev->lock);
++ dev->gadget.ops = &n9604_ops;
++ dev->gadget.is_dualspeed = 0;
++
++ /* the "gadget" abstracts/virtualizes the controller */
++ dev->gadget.dev.bus_id = "gadget";
++ dev->gadget.name = driver_name;
++
++ /* initialize the hardware */
++
++ udc_reset(dev);
++
++ write_9604(CCONF_CODIS | 11, CCONF);
++
++ udc_reinit(dev);//this is necessary as it sets up the epx functions
++
++ the_controller = dev;
++
++ if ((ret=request_irq(IRQ_GPIOC, n9604_irq, SA_SHIRQ, driver_name,dev))) {
++ WARN(dev, "Can't get IRQ\n");
++ iounmap(addr);
++ return ret;
++ }
++
++ return 0;
++}
++module_init (init);
++
++static void __exit cleanup (void)
++{
++ struct n9604_udc *dev = the_controller;
++
++ //first kill the interrupts
++ udc_reset(dev);
++ free_irq(IRQ_GPIOC, dev);
++
++ /* start with the driver above us */
++ if (dev->driver) {
++ /* should have been done already by driver model core */
++ WARN(dev, "Warning: Driver '%s' is still registered\n",
++ dev->driver->driver.name);
++ usb_gadget_unregister_driver(dev->driver);
++ }
++ kfree(dev);
++ iounmap(USBN9604_Offset);
++ the_controller = 0;
++
++}
++module_exit (cleanup);
++
++MODULE_PARM_DESC (delayTime, "Delays after reads and writes to the USB chip");
++MODULE_PARM (delayTime, "i");
++
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/drivers/usb/gadget/n9604.h kernel/drivers/usb/gadget/n9604.h
+--- /tmp/kernel/drivers/usb/gadget/n9604.h 1970-01-01 01:00:00.000000000 +0100
++++ kernel/drivers/usb/gadget/n9604.h 2005-04-22 17:53:19.463534794 +0200
+@@ -0,0 +1,112 @@
++/*
++ * National 9604 USB device controller driver
++ *
++ * Copyright 2003 Technical Solutions Inc.
++ *
++ * ported from:
++ *
++ * 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.
++ */
++
++#define MAX_FIFO_SIZE 64
++#define MAX_EP0_SIZE 8
++
++struct n9604_ep {
++ struct usb_ep ep;
++ struct n9604_udc *dev;
++ unsigned long irqs;
++ int acct_req_lengths[4];
++ int acct_req_dir[4];//direction
++ unsigned long queue_reqs;//how many times has n9604_queue been called
++ unsigned long queue_active;//how many current requests
++ unsigned long packets;//counter of raw packets
++ unsigned num:4,
++ numActual:4,
++ fifoNum:2,
++ is_in:1,
++ stage:2,//for ep0, 0 = unused, 1 = got setup, 2 = done transfer/ready to send/receive ZLP
++ toggle:1,
++ nuking:1;//are we killing on off this endpoint//only used for ep0 to help with stages
++ /* analogous to a host-side qh */
++ struct list_head queue;
++ const struct usb_endpoint_descriptor *desc;
++
++ u8 control;
++ u8 fifo;
++ u8 status;
++ u8 command;
++};
++
++struct n9604_request {
++ struct usb_request req;
++ struct list_head queue;
++ int complete;//this is added for tx requests
++ //if set the entire request has been written to the fifo, just waiting for confirmation
++ //from the interrupt that it has been sent
++
++ unsigned mapped:1;
++};
++
++struct n9604_udc {
++ struct usb_gadget gadget;
++ spinlock_t lock;
++ struct n9604_ep ep[7];
++ struct usb_gadget_driver *driver;
++ int configured;
++
++ u8 address;
++
++ /* statistics... */
++ unsigned long irqs;
++};
++
++
++/*-------------------------------------------------------------------------*/
++
++#define xprintk(dev,level,fmt,args...) \
++ printk(level "%s %s: " fmt , driver_name , \
++ "S2410 gadget" , ## args)
++
++#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
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/drivers/usb/gadget/n9604regs.h kernel/drivers/usb/gadget/n9604regs.h
+--- /tmp/kernel/drivers/usb/gadget/n9604regs.h 1970-01-01 01:00:00.000000000 +0100
++++ kernel/drivers/usb/gadget/n9604regs.h 2005-04-22 17:53:19.466534306 +0200
+@@ -0,0 +1,248 @@
++/* National 9604 registers */
++
++#define USBN9604_PHYS 0x08000000
++
++extern u8 * USBN9604_Offset;
++
++static u8 last_address = 255;//an invalid address
++
++inline u8 read_9604(u8 addr) {
++ u8 tmp;
++ if (addr != last_address) {
++ outb(addr, USBN9604_Offset + 1);
++ last_address = addr;
++ }
++ tmp = inb(USBN9604_Offset);
++ return tmp;
++}
++
++inline void write_9604(u8 value, u8 addr) {
++ if (addr != last_address) {
++ outb(addr, USBN9604_Offset + 1);
++ last_address = addr;
++ }
++ outb(value, USBN9604_Offset);
++}
++
++
++
++#define MCNTRL 0x00
++#define CCONF 0x01
++
++#define RID 0x03
++#define FAR 0x04
++#define NFSR 0x05
++#define MAEV 0x06
++#define MAMSK 0x07
++#define ALTEV 0x08
++#define ALTMSK 0x09
++#define TXEV 0x0A
++#define TXMSK 0x0B
++#define RXEV 0x0C
++#define RXMSK 0x0D
++#define NAKEV 0x0E
++#define NAKMSK 0x0F
++#define FWEV 0x10
++#define FWMSK 0x11
++#define FNH 0x12
++#define FNL 0x13
++#define DMACNTRL 0x14
++#define DMAEV 0x15
++#define DMAMSK 0x16
++#define MIR 0x17
++#define DMACNT 0x18
++#define DMAERR 0x19
++
++#define WKUP 0x1B
++
++
++
++
++#define EPC0 0x20
++#define TXD0 0x21
++#define TXS0 0x22
++#define TXC0 0x23
++
++#define RXD0 0x25
++#define RXS0 0x26
++#define RXC0 0x27
++#define EPC1 0x28
++#define TXD1 0x29
++#define TXS1 0x2A
++#define TXC1 0x2B
++#define EPC2 0x2C
++#define RXD1 0x2D
++#define RXS1 0x2E
++#define RXC1 0x2F
++#define EPC3 0x30
++#define TXD2 0x31
++#define TXS2 0x32
++#define TXC2 0x33
++#define EPC4 0x34
++#define RXD2 0x35
++#define RXS2 0x36
++#define RXC2 0x37
++#define EPC5 0x38
++#define TXD3 0x39
++#define TXS3 0x3A
++#define TXC3 0x3B
++#define EPC6 0x3C
++#define RXD3 0x3D
++#define RXS3 0x3E
++#define RXC3 0x3F
++
++
++/* MCNTRL values */
++#define MCNTRL_SRST (1 << 0)
++#define MCNTRL_VGE (1 << 2)
++#define MCNTRL_NAT (1 << 3)
++#define MCNTRL_INTOC_MASK (3 << 6)
++#define MCNTRL_INTOC_DISABLE 0
++#define MCNTRL_INTOC_ActLowOpen (1 << 6)
++#define MCNTRL_INTOC_ActHigh (2 << 6)
++#define MCNTRL_INTOC_ActLowPP (3 << 6)
++
++/* CCONF values */
++#define CCONF_CLKDIV_MASK 0x0F
++#define CCONF_CODIS (1 << 7)
++
++/* FAR values */
++#define FAR_AD_MASK 0x7F
++#define FAR_AD_EN 0x80
++
++/* NFSR values */
++#define NFSR_NodeReset 0x0
++#define NFSR_NodeResume 0x1
++#define NFSR_NodeOperational 0x2
++#define NFSR_NodeSuspend 0x3
++
++/* MAEV values */
++#define MAEV_WARN (1 << 0)
++#define MAEV_ALT (1 << 1)
++#define MAEV_TX_EV (1 << 2)
++#define MAEV_FRAME (1 << 3)
++#define MAEV_NAK (1 << 4)
++#define MAEV_ULD (1 << 5)
++#define MAEV_RX_EV (1 << 6)
++#define MAEV_INTR (1 << 7)
++
++/* MAMSK values */
++#define MAMSK_WARN (1 << 0)
++#define MAMSK_ALT (1 << 1)
++#define MAMSK_TX_EV (1 << 2)
++#define MAMSK_FRAME (1 << 3)
++#define MAMSK_NAK (1 << 4)
++#define MAMSK_ULD (1 << 5)
++#define MAMSK_RX_EV (1 << 6)
++#define MAMSK_INTR (1 << 7)
++
++/* ALTEV values */
++
++#define ALTEV_WKUP (1 << 1)
++#define ALTEV_DMA (1 << 2)
++#define ALTEV_EOP (1 << 3)
++#define ALTEV_SD3 (1 << 4)
++#define ALTEV_SD5 (1 << 5)
++#define ALTEV_RESET (1 << 6)
++#define ALTEV_RESUME (1 << 7)
++
++/* ALTMSK values */
++
++#define ALTMSK_WKUP (1 << 1)
++#define ALTMSK_DMA (1 << 2)
++#define ALTMSK_EOP (1 << 3)
++#define ALTMSK_SD3 (1 << 4)
++#define ALTMSK_SD5 (1 << 5)
++#define ALTMSK_RESET (1 << 6)
++#define ALTMSK_RESUME (1 << 7)
++
++/* NAKEV values */
++
++#define NAKEV_TXFIFO0 (1 << 0)
++#define NAKEV_TXFIFO1 (1 << 1)
++#define NAKEV_TXFIFO2 (1 << 2)
++#define NAKEV_TXFIFO3 (1 << 3)
++#define NAKEV_RXFIFO0 (1 << 4)
++#define NAKEV_RXFIFO1 (1 << 5)
++#define NAKEV_RXFIFO2 (1 << 6)
++#define NAKEV_RXFIFO3 (1 << 7)
++
++
++/* WKUP values */
++#define WKUP_PNDUSB (1 << 0)
++#define WKUP_PNDUC (1 << 1)
++#define WKUP_ENUSB (1 << 2)
++#define WKUP_ENUC (1 << 3)
++#define WKUP_WKMODE (1 << 5)
++#define WKUP_HOS (1 << 6)
++#define WKUP_FHT (1 << 7)
++
++/* EPC values */
++
++#define EPC_EP_MASK 0x0F //EP0 == 0
++#define EPC_EP_EN (1 << 4)//not EP0
++#define EPC_ISO (1 << 5)//not EP0
++#define EPC_DEF (1 << 6)//EP0 only
++#define EPC_STALL (1 << 7)
++
++/* TXS values */
++
++#define TXS_TCOUNT_MASK 0x1F
++#define TXS_TX_DONE (1 << 5)
++#define TXS_ACK_STAT (1 << 6)
++#define TXS_TX_URUN (1 << 7)
++
++/* TXC values */
++
++#define TXC_TX_EN (1 << 0)
++#define TXC_LAST (1 << 1)//not for endpoint 0
++#define TXC_TOGGLE (1 << 2)//sets DATA1 when set
++#define TXC_FLUSH (1 << 3)
++#define TXC_IGN_IN (1 << 4)//only endpoint 0
++#define TXC_RFF (1 << 4)//not for endpoint 0
++#define TXC_TFWL0 (1 << 5)//"
++#define TXC_TFWL1 (1 << 6)//"
++#define TXC_IGN_ISOMSK (1 << 7)//"
++
++/* TXEV values */
++
++#define TXEV_FIFO0 (1 << 0)
++#define TXEV_FIFO1 (1 << 1)
++#define TXEV_FIFO2 (1 << 2)
++#define TXEV_FIFO3 (1 << 3)
++#define TXEV_UDRRN0 (1 << 4)
++#define TXEV_UDRRN1 (1 << 5)
++#define TXEV_UDRRN2 (1 << 6)
++#define TXEV_UDRRN3 (1 << 7)
++
++
++/* RXEV values */
++
++#define RXEV_FIFO0 (1 << 0)
++#define RXEV_FIFO1 (1 << 1)
++#define RXEV_FIFO2 (1 << 2)
++#define RXEV_FIFO3 (1 << 3)
++#define RXEV_OVRRN0 (1 << 4)
++#define RXEV_OVRRN1 (1 << 5)
++#define RXEV_OVRRN2 (1 << 6)
++#define RXEV_OVRRN3 (1 << 7)
++
++/* RXC values */
++
++#define RXC_RX_EN (1 << 0)
++#define RXC_IGN_OUT (1 << 1)
++#define RXC_IGN_SETUP (1 << 2)
++#define RXC_FLUSH (1 << 3)
++#define RXC_RFWL0 (1 << 5)
++#define RXC_RFWL1 (1 << 6)
++
++/* RXS values */
++
++#define RXS_RCOUNTMASK 0xF
++#define RXS_RX_LAST (1 << 4)
++#define RXS_TOGGLE (1 << 5)
++#define RXS_SETUP (1 << 6)
++#define RXS_RX_ERR (1 << 7)
++
++
++
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/drivers/usb/gadget/ndis.h kernel/drivers/usb/gadget/ndis.h
+--- /tmp/kernel/drivers/usb/gadget/ndis.h 1970-01-01 01:00:00.000000000 +0100
++++ kernel/drivers/usb/gadget/ndis.h 2005-04-22 17:53:19.469533817 +0200
+@@ -0,0 +1,217 @@
++/*
++ * ndis.h
++ *
++ * ntddndis.h modified by Benedikt Spranger <b.spranger@pengutronix.de>
++ *
++ * Thanks to the cygwin development team,
++ * espacially to Casper S. Hornstrup <chorns@users.sourceforge.net>
++ *
++ * THIS SOFTWARE IS NOT COPYRIGHTED
++ *
++ * This source code is offered for use in the public domain. You may
++ * use, modify or distribute it freely.
++ *
++ * This code is distributed in the hope that it will be useful but
++ * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
++ * DISCLAIMED. This includes but is not limited to warranties of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
++ *
++ */
++
++#ifndef _LINUX_NDIS_H
++#define _LINUX_NDIS_H
++
++
++#define NDIS_STATUS_MULTICAST_FULL 0xC0010009
++#define NDIS_STATUS_MULTICAST_EXISTS 0xC001000A
++#define NDIS_STATUS_MULTICAST_NOT_FOUND 0xC001000B
++
++enum NDIS_DEVICE_POWER_STATE {
++ NdisDeviceStateUnspecified = 0,
++ NdisDeviceStateD0,
++ NdisDeviceStateD1,
++ NdisDeviceStateD2,
++ NdisDeviceStateD3,
++ NdisDeviceStateMaximum
++};
++
++struct NDIS_PM_WAKE_UP_CAPABILITIES {
++ enum NDIS_DEVICE_POWER_STATE MinMagicPacketWakeUp;
++ enum NDIS_DEVICE_POWER_STATE MinPatternWakeUp;
++ enum NDIS_DEVICE_POWER_STATE MinLinkChangeWakeUp;
++};
++
++/* NDIS_PNP_CAPABILITIES.Flags constants */
++#define NDIS_DEVICE_WAKE_UP_ENABLE 0x00000001
++#define NDIS_DEVICE_WAKE_ON_PATTERN_MATCH_ENABLE 0x00000002
++#define NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE 0x00000004
++
++struct NDIS_PNP_CAPABILITIES {
++ u32 Flags;
++ struct NDIS_PM_WAKE_UP_CAPABILITIES WakeUpCapabilities;
++};
++
++struct NDIS_PM_PACKET_PATTERN {
++ u32 Priority;
++ u32 Reserved;
++ u32 MaskSize;
++ u32 PatternOffset;
++ u32 PatternSize;
++ u32 PatternFlags;
++};
++
++
++/* Required Object IDs (OIDs) */
++#define OID_GEN_SUPPORTED_LIST 0x00010101
++#define OID_GEN_HARDWARE_STATUS 0x00010102
++#define OID_GEN_MEDIA_SUPPORTED 0x00010103
++#define OID_GEN_MEDIA_IN_USE 0x00010104
++#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105
++#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106
++#define OID_GEN_LINK_SPEED 0x00010107
++#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108
++#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109
++#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A
++#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B
++#define OID_GEN_VENDOR_ID 0x0001010C
++#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D
++#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E
++#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F
++#define OID_GEN_DRIVER_VERSION 0x00010110
++#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111
++#define OID_GEN_PROTOCOL_OPTIONS 0x00010112
++#define OID_GEN_MAC_OPTIONS 0x00010113
++#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114
++#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115
++#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116
++#define OID_GEN_SUPPORTED_GUIDS 0x00010117
++#define OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118
++#define OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119
++#define OID_GEN_MACHINE_NAME 0x0001021A
++#define OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B
++#define OID_GEN_VLAN_ID 0x0001021C
++
++/* Optional OIDs */
++#define OID_GEN_MEDIA_CAPABILITIES 0x00010201
++#define OID_GEN_PHYSICAL_MEDIUM 0x00010202
++
++/* Required statistics OIDs */
++#define OID_GEN_XMIT_OK 0x00020101
++#define OID_GEN_RCV_OK 0x00020102
++#define OID_GEN_XMIT_ERROR 0x00020103
++#define OID_GEN_RCV_ERROR 0x00020104
++#define OID_GEN_RCV_NO_BUFFER 0x00020105
++
++/* Optional statistics OIDs */
++#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201
++#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202
++#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203
++#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204
++#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205
++#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206
++#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207
++#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208
++#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209
++#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A
++#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B
++#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C
++#define OID_GEN_RCV_CRC_ERROR 0x0002020D
++#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E
++#define OID_GEN_GET_TIME_CAPS 0x0002020F
++#define OID_GEN_GET_NETCARD_TIME 0x00020210
++#define OID_GEN_NETCARD_LOAD 0x00020211
++#define OID_GEN_DEVICE_PROFILE 0x00020212
++#define OID_GEN_INIT_TIME_MS 0x00020213
++#define OID_GEN_RESET_COUNTS 0x00020214
++#define OID_GEN_MEDIA_SENSE_COUNTS 0x00020215
++#define OID_GEN_FRIENDLY_NAME 0x00020216
++#define OID_GEN_MINIPORT_INFO 0x00020217
++#define OID_GEN_RESET_VERIFY_PARAMETERS 0x00020218
++
++/* IEEE 802.3 (Ethernet) OIDs */
++#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001
++
++#define OID_802_3_PERMANENT_ADDRESS 0x01010101
++#define OID_802_3_CURRENT_ADDRESS 0x01010102
++#define OID_802_3_MULTICAST_LIST 0x01010103
++#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104
++#define OID_802_3_MAC_OPTIONS 0x01010105
++#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101
++#define OID_802_3_XMIT_ONE_COLLISION 0x01020102
++#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103
++#define OID_802_3_XMIT_DEFERRED 0x01020201
++#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202
++#define OID_802_3_RCV_OVERRUN 0x01020203
++#define OID_802_3_XMIT_UNDERRUN 0x01020204
++#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205
++#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206
++#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207
++
++/* OID_GEN_MINIPORT_INFO constants */
++#define NDIS_MINIPORT_BUS_MASTER 0x00000001
++#define NDIS_MINIPORT_WDM_DRIVER 0x00000002
++#define NDIS_MINIPORT_SG_LIST 0x00000004
++#define NDIS_MINIPORT_SUPPORTS_MEDIA_QUERY 0x00000008
++#define NDIS_MINIPORT_INDICATES_PACKETS 0x00000010
++#define NDIS_MINIPORT_IGNORE_PACKET_QUEUE 0x00000020
++#define NDIS_MINIPORT_IGNORE_REQUEST_QUEUE 0x00000040
++#define NDIS_MINIPORT_IGNORE_TOKEN_RING_ERRORS 0x00000080
++#define NDIS_MINIPORT_INTERMEDIATE_DRIVER 0x00000100
++#define NDIS_MINIPORT_IS_NDIS_5 0x00000200
++#define NDIS_MINIPORT_IS_CO 0x00000400
++#define NDIS_MINIPORT_DESERIALIZE 0x00000800
++#define NDIS_MINIPORT_REQUIRES_MEDIA_POLLING 0x00001000
++#define NDIS_MINIPORT_SUPPORTS_MEDIA_SENSE 0x00002000
++#define NDIS_MINIPORT_NETBOOT_CARD 0x00004000
++#define NDIS_MINIPORT_PM_SUPPORTED 0x00008000
++#define NDIS_MINIPORT_SUPPORTS_MAC_ADDRESS_OVERWRITE 0x00010000
++#define NDIS_MINIPORT_USES_SAFE_BUFFER_APIS 0x00020000
++#define NDIS_MINIPORT_HIDDEN 0x00040000
++#define NDIS_MINIPORT_SWENUM 0x00080000
++#define NDIS_MINIPORT_SURPRISE_REMOVE_OK 0x00100000
++#define NDIS_MINIPORT_NO_HALT_ON_SUSPEND 0x00200000
++#define NDIS_MINIPORT_HARDWARE_DEVICE 0x00400000
++#define NDIS_MINIPORT_SUPPORTS_CANCEL_SEND_PACKETS 0x00800000
++#define NDIS_MINIPORT_64BITS_DMA 0x01000000
++
++#define NDIS_MEDIUM_802_3 0x00000000
++#define NDIS_MEDIUM_802_5 0x00000001
++#define NDIS_MEDIUM_FDDI 0x00000002
++#define NDIS_MEDIUM_WAN 0x00000003
++#define NDIS_MEDIUM_LOCAL_TALK 0x00000004
++#define NDIS_MEDIUM_DIX 0x00000005
++#define NDIS_MEDIUM_ARCENT_RAW 0x00000006
++#define NDIS_MEDIUM_ARCENT_878_2 0x00000007
++#define NDIS_MEDIUM_ATM 0x00000008
++#define NDIS_MEDIUM_WIRELESS_LAN 0x00000009
++#define NDIS_MEDIUM_IRDA 0x0000000A
++#define NDIS_MEDIUM_BPC 0x0000000B
++#define NDIS_MEDIUM_CO_WAN 0x0000000C
++#define NDIS_MEDIUM_1394 0x0000000D
++
++#define NDIS_PACKET_TYPE_DIRECTED 0x00000001
++#define NDIS_PACKET_TYPE_MULTICAST 0x00000002
++#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004
++#define NDIS_PACKET_TYPE_BROADCAST 0x00000008
++#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010
++#define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020
++#define NDIS_PACKET_TYPE_SMT 0x00000040
++#define NDIS_PACKET_TYPE_ALL_LOCAL 0x00000080
++#define NDIS_PACKET_TYPE_GROUP 0x00000100
++#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00000200
++#define NDIS_PACKET_TYPE_FUNCTIONAL 0x00000400
++#define NDIS_PACKET_TYPE_MAC_FRAME 0x00000800
++
++#define NDIS_MEDIA_STATE_CONNECTED 0x00000000
++#define NDIS_MEDIA_STATE_DISCONNECTED 0x00000001
++
++#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA 0x00000001
++#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED 0x00000002
++#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND 0x00000004
++#define NDIS_MAC_OPTION_NO_LOOPBACK 0x00000008
++#define NDIS_MAC_OPTION_FULL_DUPLEX 0x00000010
++#define NDIS_MAC_OPTION_EOTX_INDICATION 0x00000020
++#define NDIS_MAC_OPTION_8021P_PRIORITY 0x00000040
++#define NDIS_MAC_OPTION_RESERVED 0x80000000
++
++#endif /* _LINUX_NDIS_H */
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/drivers/usb/gadget/net2280.c kernel/drivers/usb/gadget/net2280.c
+--- /tmp/kernel/drivers/usb/gadget/net2280.c 1970-01-01 01:00:00.000000000 +0100
++++ kernel/drivers/usb/gadget/net2280.c 2005-04-22 17:53:19.478532352 +0200
+@@ -0,0 +1,2918 @@
++/*
++ * 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
++ *
++ * This driver should work well with most "gadget" drivers, including
++ * the File Storage, Serial, and Ethernet/RNDIS gadget drivers
++ * as well as Gadget Zero and Gadgetfs.
++ *
++ * 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.
++ */
++
++/*
++ * 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
++ */
++
++#undef DEBUG /* messages on error and most fault paths */
++#undef 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 "2004 Jan 14"
++
++#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",
++};
++
++/* use_dma -- general goodness, fewer interrupts, less cpu load (vs PIO)
++ * use_dma_chaining -- dma descriptor queueing gives even more irq reduction
++ *
++ * The net2280 DMA engines are not tightly integrated with their FIFOs;
++ * not all cases are (yet) handled well in this driver or the silicon.
++ * Some gadget drivers work better with the dma support here than others.
++ * These two parameters let you use PIO or more aggressive DMA.
++ */
++static int use_dma = 1;
++static int use_dma_chaining = 0;
++
++MODULE_PARM (use_dma, "i");
++MODULE_PARM_DESC (use_dma, "true to use dma controllers");
++
++MODULE_PARM (use_dma_chaining, "i");
++MODULE_PARM_DESC (use_dma_chaining, "true to use dma descriptor queues");
++
++
++/* 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 = 0;
++
++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;
++
++ /* erratum 0119 workaround ties up an endpoint number */
++ 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;
++ ep->out_overflow = 0;
++
++ /* set speed-dependent max packet; may kick in high bandwidth */
++ set_idx_reg (dev->regs, REG_EP_MAXPKT (dev, ep->num), max);
++
++ /* 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 && use_dma_chaining) {
++ DEBUG (ep->dev, "%s, no dma for maxpacket %d\n",
++ ep->ep.name, ep->ep.maxpacket);
++ ep->dma = NULL;
++ }
++
++ /* 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) {
++ /* erratum 0105 workaround prevents hs NYET */
++ if (dev->chiprev == 0100
++ && dev->gadget.speed == USB_SPEED_HIGH
++ && !(desc->bEndpointAddress & USB_DIR_IN))
++ writel ((1 << CLEAR_NAK_OUT_PACKETS_MODE),
++ &ep->regs->ep_rsp);
++ } 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)) {
++ spin_unlock_irqrestore (&dev->lock, flags);
++ 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);
++
++ /* 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);
++
++ /* for short OUT transfers, dma completions can't
++ * advance the queue; do it pio-style, by hand.
++ * NOTE erratum 0112 workaround #2
++ */
++ 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 = NULL;
++ 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 NULL;
++ ep = container_of (_ep, struct net2280_ep, ep);
++
++ req = kmalloc (sizeof *req, gfp_flags);
++ if (!req)
++ return NULL;
++
++ 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 NULL;
++ }
++ td->dmacount = 0; /* not VALID */
++ td->dmaaddr = __constant_cpu_to_le32 (DMA_ADDR_INVALID);
++ td->dmadesc = td->dmaaddr;
++ 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)
++#define USE_KMALLOC
++
++#elif defined(CONFIG_PPC) && !defined(CONFIG_NOT_COHERENT_CACHE)
++#define USE_KMALLOC
++
++#elif defined(CONFIG_MIPS) && !defined(CONFIG_NONCOHERENT_IO)
++#define USE_KMALLOC
++
++/* FIXME there are other cases, including an x86-64 one ... */
++#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)
++ return NULL;
++ *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
++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) {
++ struct net2280_ep *ep;
++
++ ep = container_of(_ep, struct net2280_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);
++}
++
++/*-------------------------------------------------------------------------*/
++
++/* 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) {
++ buf = req->buf + req->actual;
++ prefetch (buf);
++ total = req->length - req->actual;
++ } else {
++ total = 0;
++ buf = NULL;
++ }
++
++ /* write just one packet at a time */
++ count = ep->ep.maxpacket;
++ if (count > total) /* min() cannot be used on a bitfield */
++ count = 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.
++ * also explicitly validate last word in (periodic) transfers
++ * when maxpacket is not a multiple of 4 bytes.
++ */
++ if (count || total < ep->ep.maxpacket) {
++ 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.
++ *
++ * NOTE: also used in cases where that erratum doesn't apply:
++ * where the host wrote "too much" data to us.
++ */
++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
++ && ep->dev->gadget.speed == USB_SPEED_FULL) {
++ udelay (1);
++ tmp = readl (&ep->regs->ep_stat);
++ if ((tmp & (1 << NAK_OUT_PACKETS)))
++ cleanup = 1;
++ else if ((tmp & (1 << FIFO_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.
++ */
++ prefetchw (buf);
++ count = readl (&regs->ep_avail);
++ if (unlikely (count == 0)) {
++ udelay (1);
++ tmp = readl (&ep->regs->ep_stat);
++ count = readl (&regs->ep_avail);
++ /* handled that data already? */
++ if (count == 0 && (tmp & (1 << NAK_OUT_PACKETS)) == 0)
++ return 0;
++ }
++
++ 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;
++ /* NAK_OUT_PACKETS will be set, so flushing is safe;
++ * the next read will start with the next packet
++ */
++ } /* else it's a ZLP, no worries */
++ 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);
++ /* LE conversion is implicit here: */
++ 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 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 if ((dmacount % ep->ep.maxpacket) != 0)
++ dmacount |= (1 << END_OF_CHAIN);
++
++ req->valid = valid;
++ if (valid)
++ dmacount |= (1 << VALID_BIT);
++ if (likely(!req->req.no_interrupt || !use_dma_chaining))
++ 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_SCATTER_GATHER_DONE_INTERRUPT)
++ | (1 << DMA_CLEAR_COUNT_ENABLE)
++ /* erratum 0116 workaround part 1 (use POLLING) */
++ | (POLL_100_USEC << DESCRIPTOR_POLLING_RATE)
++ | (1 << DMA_VALID_BIT_POLLING_ENABLE)
++ | (1 << DMA_VALID_BIT_ENABLE)
++ | (1 << DMA_SCATTER_GATHER_ENABLE)
++ /* erratum 0116 workaround part 2 (no AUTOSTART) */
++ | (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 (readl (&dma->dmactl) & ~(1 << DMA_ENABLE), &dma->dmactl);
++ spin_stop_dma (dma);
++}
++
++static void start_queue (struct net2280_ep *ep, u32 dmactl, u32 td_dma)
++{
++ struct net2280_dma_regs *dma = ep->dma;
++
++ writel ((1 << VALID_BIT) | (ep->is_in << DMA_DIRECTION),
++ &dma->dmacount);
++ writel (readl (&dma->dmastat), &dma->dmastat);
++
++ writel (td_dma, &dma->dmadesc);
++ writel (dmactl, &dma->dmactl);
++
++ /* erratum 0116 workaround part 3: pci arbiter away from net2280 */
++ (void) readl (&ep->dev->pci->pcimstctl);
++
++ writel ((1 << DMA_START), &dma->dmastat);
++
++ if (!ep->is_in)
++ stop_out_naking (ep);
++}
++
++static void start_dma (struct net2280_ep *ep, struct net2280_request *req)
++{
++ u32 tmp;
++ struct net2280_dma_regs *dma = ep->dma;
++
++ /* FIXME can't use DMA for ZLPs */
++
++ /* on this path we "know" there's no dma active (yet) */
++ WARN_ON (readl (&dma->dmactl) & (1 << DMA_ENABLE));
++ writel (0, &ep->dma->dmactl);
++
++ /* 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) {
++ writel (readl (&dma->dmastat), &dma->dmastat);
++
++ /* 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);
++ req->td->dmadesc = 0;
++ req->valid = 1;
++
++ writel ((1 << DMA_ENABLE), &dma->dmactl);
++ writel ((1 << DMA_START), &dma->dmastat);
++ return;
++ }
++ }
++
++ 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);
++
++ if (!use_dma_chaining)
++ req->td->dmacount |= __constant_cpu_to_le32 (1 << END_OF_CHAIN);
++
++ start_queue (ep, tmp, req->td_dma);
++}
++
++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;
++
++ /* FIXME implement PIO fallback for ZLPs with DMA */
++ 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;
++ }
++
++#if 0
++ VDEBUG (dev, "%s queue req %p, len %d buf %p\n",
++ _ep->name, _req, _req->length, _req->buf);
++#endif
++
++ spin_lock_irqsave (&dev->lock, flags);
++
++ _req->status = -EINPROGRESS;
++ _req->actual = 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 = NULL;
++ } 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);
++ done (ep, req, status);
++}
++
++static void restart_dma (struct net2280_ep *ep);
++
++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;
++
++ /* SHORT_PACKET_TRANSFERRED_INTERRUPT handles "usb-short"
++ * cases where DMA must be aborted; this code handles
++ * all non-abort DMA completions.
++ */
++ if (unlikely (req->td->dmadesc == 0)) {
++ /* paranoia */
++ tmp = readl (&ep->dma->dmacount);
++ if (tmp & DMA_BYTE_COUNT_MASK)
++ break;
++ /* single transfer mode */
++ dma_done (ep, req, tmp, 0);
++ break;
++ } else if (!ep->is_in
++ && (req->req.length % ep->ep.maxpacket) != 0) {
++ tmp = readl (&ep->regs->ep_stat);
++
++ /* AVOID TROUBLE HERE by not issuing short reads from
++ * your gadget driver. That helps avoids errata 0121,
++ * 0122, and 0124; not all cases trigger the warning.
++ */
++ if ((tmp & (1 << NAK_OUT_PACKETS)) == 0) {
++ WARN (ep->dev, "%s lost packet sync!\n",
++ ep->ep.name);
++ req->req.status = -EOVERFLOW;
++ } else if ((tmp = readl (&ep->regs->ep_avail)) != 0) {
++ /* fifo gets flushed later */
++ ep->out_overflow = 1;
++ DEBUG (ep->dev, "%s dma, discard %d len %d\n",
++ ep->ep.name, tmp,
++ req->req.length);
++ req->req.status = -EOVERFLOW;
++ }
++ }
++ dma_done (ep, req, tmp, 0);
++ }
++}
++
++static void restart_dma (struct net2280_ep *ep)
++{
++ struct net2280_request *req;
++ u32 dmactl = dmactl_default;
++
++ if (ep->stopped)
++ return;
++ req = list_entry (ep->queue.next, struct net2280_request, queue);
++
++ if (!use_dma_chaining) {
++ start_dma (ep, req);
++ return;
++ }
++
++ /* the 2280 will be processing the queue unless queue hiccups after
++ * the previous transfer:
++ * IN: wanted automagic zlp, head doesn't (or vice versa)
++ * DMA_FIFO_VALIDATE doesn't init from dma descriptors.
++ * OUT: was "usb-short", we must restart.
++ */
++ if (ep->is_in && !req->valid) {
++ struct net2280_request *entry, *prev = NULL;
++ int reqmode, done = 0;
++
++ DEBUG (ep->dev, "%s dma hiccup td %p\n", ep->ep.name, req->td);
++ ep->in_fifo_validate = likely (req->req.zero
++ || (req->req.length % ep->ep.maxpacket) != 0);
++ if (ep->in_fifo_validate)
++ dmactl |= (1 << DMA_FIFO_VALIDATE);
++ 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 == ep->in_fifo_validate) {
++ entry->valid = 1;
++ dmacount |= valid_bit;
++ entry->td->dmacount = dmacount;
++ prev = entry;
++ continue;
++ } else {
++ /* force a hiccup */
++ 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;
++ }
++ }
++
++ writel (0, &ep->dma->dmactl);
++ start_queue (ep, dmactl, req->td_dma);
++}
++
++static void abort_dma (struct net2280_ep *ep)
++{
++ /* abort the current transfer */
++ if (likely (!list_empty (&ep->queue))) {
++ /* FIXME work around errata 0121, 0122, 0124 */
++ writel ((1 << DMA_ABORT), &ep->dma->dmastat);
++ spin_stop_dma (ep->dma);
++ } else
++ stop_dma (ep->dma);
++ 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);
++ if (!_ep || (!ep->desc && ep->num != 0) || !_req)
++ return -EINVAL;
++
++ spin_lock_irqsave (&ep->dev->lock, flags);
++ stopped = ep->stopped;
++
++ /* quiesce dma while we patch the queue */
++ dmactl = 0;
++ ep->stopped = 1;
++ if (ep->dma) {
++ dmactl = readl (&ep->dma->dmactl);
++ /* WARNING erratum 0127 may kick in ... */
++ stop_dma (ep->dma);
++ scan_dma_completions (ep);
++ }
++
++ /* make sure it's still queued on this endpoint */
++ list_for_each_entry (req, &ep->queue, queue) {
++ if (&req->req == _req)
++ break;
++ }
++ if (&req->req != _req) {
++ spin_unlock_irqrestore (&ep->dev->lock, flags);
++ return -EINVAL;
++ }
++
++ /* 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)) {
++ // NOTE: misreports single-transfer mode
++ req->td->dmacount = 0; /* invalidate */
++ dma_done (ep, req,
++ readl (&ep->dma->dmacount),
++ -ECONNRESET);
++ }
++ } else {
++ DEBUG (ep->dev, "unlink (%s) pio\n", _ep->name);
++ done (ep, req, -ECONNRESET);
++ }
++ req = NULL;
++
++ /* patch up hardware chaining data */
++ } else if (ep->dma && use_dma_chaining) {
++ 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;
++ }
++ }
++
++ 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_fifo_status (struct usb_ep *_ep);
++
++static int
++net2280_set_halt (struct usb_ep *_ep, int value)
++{
++ struct net2280_ep *ep;
++ unsigned long flags;
++ int retval = 0;
++
++ 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;
++
++ spin_lock_irqsave (&ep->dev->lock, flags);
++ if (!list_empty (&ep->queue))
++ retval = -EAGAIN;
++ else if (ep->is_in && value && net2280_fifo_status (_ep) != 0)
++ retval = -EAGAIN;
++ else {
++ 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);
++ }
++ spin_unlock_irqrestore (&ep->dev->lock, flags);
++
++ return retval;
++}
++
++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;
++ u32 tmp;
++ unsigned long flags;
++
++ if (!_gadget)
++ return 0;
++ dev = container_of (_gadget, struct net2280, gadget);
++
++ spin_lock_irqsave (&dev->lock, flags);
++ tmp = readl (&dev->usb->usbctl);
++ if (tmp & (1 << DEVICE_REMOTE_WAKEUP_ENABLE))
++ writel (1 << GENERATE_RESUME, &dev->usb->usbstat);
++ spin_unlock_irqrestore (&dev->lock, flags);
++
++ /* pci writes may still be posted */
++ return 0;
++}
++
++static int net2280_set_selfpowered (struct usb_gadget *_gadget, int value)
++{
++ struct net2280 *dev;
++ u32 tmp;
++ unsigned long flags;
++
++ if (!_gadget)
++ return 0;
++ dev = container_of (_gadget, struct net2280, gadget);
++
++ spin_lock_irqsave (&dev->lock, flags);
++ tmp = readl (&dev->usb->usbctl);
++ if (value)
++ tmp |= (1 << SELF_POWERED_STATUS);
++ else
++ tmp &= ~(1 << SELF_POWERED_STATUS);
++ writel (tmp, &dev->usb->usbctl);
++ spin_unlock_irqrestore (&dev->lock, flags);
++
++ return 0;
++}
++
++static int net2280_pullup(struct usb_gadget *_gadget, int is_on)
++{
++ struct net2280 *dev;
++ u32 tmp;
++ unsigned long flags;
++
++ if (!_gadget)
++ return -ENODEV;
++ dev = container_of (_gadget, struct net2280, gadget);
++
++ spin_lock_irqsave (&dev->lock, flags);
++ tmp = readl (&dev->usb->usbctl);
++ dev->softconnect = (is_on != 0);
++ if (is_on)
++ tmp |= (1 << USB_DETECT_ENABLE);
++ else
++ tmp &= ~(1 << USB_DETECT_ENABLE);
++ writel (tmp, &dev->usb->usbctl);
++ spin_unlock_irqrestore (&dev->lock, flags);
++
++ return 0;
++}
++
++static const struct usb_gadget_ops net2280_ops = {
++ .get_frame = net2280_get_frame,
++ .wakeup = net2280_wakeup,
++ .set_selfpowered = net2280_set_selfpowered,
++ .pullup = net2280_pullup,
++};
++
++/*-------------------------------------------------------------------------*/
++
++#ifdef USE_SYSFS_DEBUG_FILES
++
++/* "function" sysfs attribute */
++static ssize_t
++show_function (struct device *_dev, char *buf)
++{
++ struct net2280 *dev = dev_get_drvdata (_dev);
++
++ 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 DEVICE_ATTR (function, S_IRUGO, show_function, NULL);
++
++static ssize_t
++show_registers (struct device *_dev, char *buf)
++{
++ struct net2280 *dev;
++ char *next;
++ unsigned size, t;
++ unsigned long flags;
++ int i;
++ u32 t1, t2;
++ char *s;
++
++ dev = dev_get_drvdata (_dev);
++ 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, dma %s\n\n"
++ "devinit %03x fifoctl %08x gadget '%s'\n"
++ "pci irqenb0 %02x irqenb1 %08x "
++ "irqstat0 %04x irqstat1 %08x\n",
++ driver_name, dev->chiprev,
++ use_dma
++ ? (use_dma_chaining ? "chaining" : "enabled")
++ : "disabled",
++ 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);
++ t2 = readl (&ep->regs->ep_rsp) & 0xff;
++ t = snprintf (next, size,
++ "\n%s\tcfg %05x rsp (%02x) %s%s%s%s%s%s%s%s"
++ "irqenb %02x\n",
++ ep->ep.name, t1, t2,
++ (t2 & (1 << CLEAR_NAK_OUT_PACKETS))
++ ? "NAK " : "",
++ (t2 & (1 << CLEAR_EP_HIDE_STATUS_PHASE))
++ ? "hide " : "",
++ (t2 & (1 << CLEAR_EP_FORCE_CRC_ERROR))
++ ? "CRC " : "",
++ (t2 & (1 << CLEAR_INTERRUPT_MODE))
++ ? "interrupt " : "",
++ (t2 & (1<<CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE))
++ ? "status " : "",
++ (t2 & (1 << CLEAR_NAK_OUT_PACKETS_MODE))
++ ? "NAKmode " : "",
++ (t2 & (1 << CLEAR_ENDPOINT_TOGGLE))
++ ? "DATA1 " : "DATA0 ",
++ (t2 & (1 << CLEAR_ENDPOINT_HALT))
++ ? "HALT " : "",
++ readl (&ep->regs->ep_irqenb));
++ size -= t;
++ next += t;
++
++ t = snprintf (next, size,
++ "\tstat %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, "\nirqs: ");
++ 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/%lu", 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 DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);
++
++static ssize_t
++show_queues (struct device *_dev, char *buf)
++{
++ struct net2280 *dev;
++ char *next;
++ unsigned size;
++ unsigned long flags;
++ int i;
++
++ dev = dev_get_drvdata (_dev);
++ 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,
++ "\n%s (ep%d%s-%s) max %04x %s fifo %d\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", ep->fifo_size
++ );
++ } 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;
++
++ if (ep->dma) {
++ struct net2280_dma *td;
++
++ td = req->td;
++ t = snprintf (next, size, "\t td %08x "
++ " count %08x buf %08x desc %08x\n",
++ req->td_dma, td->dmacount,
++ td->dmaaddr, td->dmadesc);
++ if (t <= 0 || t > size)
++ goto done;
++ size -= t;
++ next += t;
++ }
++ }
++ }
++
++done:
++ spin_unlock_irqrestore (&dev->lock, flags);
++ return PAGE_SIZE - size;
++}
++static DEVICE_ATTR (queues, S_IRUGO, show_queues, NULL);
++
++
++#else
++
++#define device_create_file(a,b) do {} while (0)
++#define device_remove_file 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;
++
++ 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++) {
++ struct net2280_ep *ep = &dev->ep [tmp + 1];
++
++ if (ep->dma)
++ abort_dma (ep);
++ }
++ 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)
++ /* erratum 0102 workaround */
++ | ((dev->chiprev == 0100) ? 0 : 1) << SUSPEND_IMMEDIATELY
++ | (1 << REMOTE_WAKEUP_SUPPORT)
++ | (dev->softconnect << USB_DETECT_ENABLE)
++ | (1 << SELF_POWERED_STATUS)
++ , &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)
++ | (1 << SUSPEND_REQUEST_CHANGE_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->softconnect = 1;
++ dev->driver = driver;
++ retval = driver->bind (&dev->gadget);
++ if (retval) {
++ DEBUG (dev, "bind to driver %s --> %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.
++ */
++ 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 = NULL;
++
++ /* 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);
++
++ 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 = NULL;
++
++ /* ack all, and handle what we care about */
++ t = readl (&ep->regs->ep_stat);
++ ep->irqs++;
++#if 0
++ VDEBUG (ep->dev, "%s ack ep_stat %08x, req %p\n",
++ ep->ep.name, t, req ? &req->req : 0);
++#endif
++ 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);
++ }
++ if (!req)
++ allow_status (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, NULL);
++ }
++ } else {
++ /* status; stop NAKing */
++ if (t & (1 << DATA_IN_TOKEN_INTERRUPT)) {
++ if (ep->dev->protocol_stall) {
++ ep->stopped = 1;
++ set_halt (ep);
++ }
++ mode = 2;
++ /* an extra OUT token is an error */
++ } else if (((t & (1 << DATA_OUT_PING_TOKEN_INTERRUPT))
++ && req
++ && req->req.actual == req->req.length)
++ || !req) {
++ ep->dev->protocol_stall = 1;
++ set_halt (ep);
++ ep->stopped = 1;
++ if (req)
++ done (ep, req, -EOVERFLOW);
++ req = NULL;
++ }
++ }
++ }
++
++ 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;
++ int stopped = ep->stopped;
++
++ /* 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.
++ */
++ ep->stopped = 1;
++ for (count = 0; ; t = readl (&ep->regs->ep_stat)) {
++
++ /* any preceding dma transfers must finish.
++ * dma handles (M >= N), may empty the queue
++ */
++ scan_dma_completions (ep);
++ if (unlikely (list_empty (&ep->queue)
++ || ep->out_overflow)) {
++ req = NULL;
++ break;
++ }
++ req = list_entry (ep->queue.next,
++ struct net2280_request, queue);
++
++ /* here either (M < N), a "real" short rx;
++ * or (M == N) and the queue didn't empty
++ */
++ if (likely (t & (1 << FIFO_EMPTY))) {
++ count = readl (&ep->dma->dmacount);
++ count &= DMA_BYTE_COUNT_MASK;
++ if (readl (&ep->dma->dmadesc)
++ != req->td_dma)
++ req = NULL;
++ break;
++ }
++ udelay(1);
++ }
++
++ /* stop DMA, leave ep NAKing */
++ writel ((1 << DMA_ABORT), &ep->dma->dmastat);
++ spin_stop_dma (ep->dma);
++
++ if (likely (req != 0)) {
++ req->td->dmacount = 0;
++ t = readl (&ep->regs->ep_avail);
++ dma_done (ep, req, count, t);
++ }
++
++ /* also flush to prevent erratum 0106 trouble */
++ if (unlikely (ep->out_overflow
++ || (ep->dev->chiprev == 0x0100
++ && ep->dev->gadget.speed
++ == USB_SPEED_FULL))) {
++ out_flush (ep);
++ ep->out_overflow = 0;
++ }
++
++ /* (re)start dma if needed, stop NAKing */
++ ep->stopped = stopped;
++ 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;
++ if (len > ep->ep.maxpacket)
++ len = ep->ep.maxpacket;
++ 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 = NULL;
++ } 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) {
++ /* NOTE: net2280 could let gadget driver start the
++ * status stage later. since not all controllers let
++ * them control that, the api doesn't (yet) allow it.
++ */
++ if (!ep->stopped)
++ allow_status (ep);
++ req = NULL;
++ } else {
++ if (!list_empty (&ep->queue) && !ep->stopped)
++ req = list_entry (ep->queue.next,
++ struct net2280_request, queue);
++ else
++ req = NULL;
++ 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 NULL;
++}
++
++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);
++
++ /* watch control traffic at the token level, and force
++ * synchronization before letting the status stage happen.
++ * FIXME ignore tokens we'll NAK, until driver responds.
++ * that'll mean a lot less irqs for some drivers.
++ */
++ 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);
++ stop_out_naking (ep);
++ } 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 != USB_ENDPOINT_HALT
++ || 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 != USB_ENDPOINT_HALT
++ || 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: chip stays in PCI D0 state for now, but it could
++ * enter D1 to save more power
++ */
++ tmp = (1 << SUSPEND_REQUEST_CHANGE_INTERRUPT);
++ if (stat & tmp) {
++ writel (tmp, &dev->regs->irqstat1);
++ if (stat & (1 << SUSPEND_REQUEST_INTERRUPT)) {
++ if (dev->driver->suspend)
++ dev->driver->suspend (&dev->gadget);
++ /* we use SUSPEND_IMMEDIATELY */
++ stat &= ~(1 << SUSPEND_REQUEST_INTERRUPT);
++ } else {
++ if (dev->driver->resume)
++ dev->driver->resume (&dev->gadget);
++ /* at high speed, note erratum 0133 */
++ }
++ stat &= ~tmp;
++ }
++
++ /* clear any other status/irqs */
++ if (stat)
++ writel (stat, &dev->regs->irqstat1);
++
++ /* some status we can just ignore */
++ stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
++ | (1 << SUSPEND_REQUEST_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);
++
++ /* chaining should stop on abort, short OUT from fifo,
++ * or (stat0 codepath) short OUT transfer.
++ */
++ if (!use_dma_chaining) {
++ 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);
++ }
++
++ /* 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)) {
++ if (use_dma_chaining)
++ stop_dma (ep->dma);
++ } else {
++ tmp = readl (&dma->dmactl);
++ if (!use_dma_chaining
++ || (tmp & (1 << DMA_ENABLE)) == 0)
++ restart_dma (ep);
++ else if (ep->is_in && use_dma_chaining) {
++ 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)
++ restart_dma (ep);
++ }
++ }
++ 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);
++ 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 = NULL;
++ 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;
++ dev->gadget.is_dualspeed = 1;
++
++ dev->gadget.dev.bus_id = pdev->slot_name;
++ 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 */
++ writel (0, &dev->usb->usbctl);
++ 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);
++ td->dmadesc = td->dmaaddr;
++ dev->ep [i].dummy = td;
++ }
++
++ /* enable lower-overhead pci memory bursts during DMA */
++ writel ( (1 << DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE)
++ // 256 write retries may not be enough...
++ // | (1 << PCI_RETRY_ABORT_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);
++ pci_set_mwi (pdev);
++
++ /* ... 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);
++ INFO (dev, "version: " DRIVER_VERSION "; dma %s\n",
++ use_dma
++ ? (use_dma_chaining ? "chaining" : "enabled")
++ : "disabled");
++ the_controller = dev;
++
++ 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,
++
++ /* FIXME add power management support */
++};
++
++MODULE_DESCRIPTION (DRIVER_DESC);
++MODULE_AUTHOR ("David Brownell");
++MODULE_LICENSE ("GPL");
++
++static int __init init (void)
++{
++ if (!use_dma)
++ use_dma_chaining = 0;
++ 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 -x '*~' -x '.*' -r -N -u /tmp/kernel/drivers/usb/gadget/net2280.h kernel/drivers/usb/gadget/net2280.h
+--- /tmp/kernel/drivers/usb/gadget/net2280.h 1970-01-01 01:00:00.000000000 +0100
++++ kernel/drivers/usb/gadget/net2280.h 2005-04-22 17:53:19.483531538 +0200
+@@ -0,0 +1,756 @@
++/*
++ * 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 2
++#define GET_INTERFACE_STATUS 1
++#define GET_DEVICE_STATUS 0
++ u32 prodvendid;
++#define PRODUCT_ID 16
++#define VENDOR_ID 0
++ u32 relnum;
++ u32 usbctl;
++#define SERIAL_NUMBER_INDEX 16
++#define PRODUCT_ID_STRING_ENABLE 13
++#define VENDOR_ID_STRING_ENABLE 12
++#define USB_ROOT_PORT_WAKEUP_ENABLE 11
++#define VBUS_PIN 10
++#define TIMED_DISCONNECT 9
++#define SUSPEND_IMMEDIATELY 7
++#define SELF_POWERED_USB_DEVICE 6
++#define REMOTE_WAKEUP_SUPPORT 5
++#define PME_POLARITY 4
++#define USB_DETECT_ENABLE 3
++#define PME_WAKEUP_ENABLE 2
++#define DEVICE_REMOTE_WAKEUP_ENABLE 1
++#define SELF_POWERED_STATUS 0
++ // offset 0x0090
++ u32 usbstat;
++#define HIGH_SPEED 7
++#define FULL_SPEED 6
++#define GENERATE_RESUME 5
++#define GENERATE_DEVICE_REMOTE_WAKEUP 4
++ u32 xcvrdiag;
++#define FORCE_HIGH_SPEED_MODE 31
++#define FORCE_FULL_SPEED_MODE 30
++#define USB_TEST_MODE 24
++#define LINE_STATE 16
++#define TRANSCEIVER_OPERATION_MODE 2
++#define TRANSCEIVER_SELECT 1
++#define TERMINATION_SELECT 0
++ u32 setup0123;
++ u32 setup4567;
++ // offset 0x0090
++ u32 _unused0;
++ u32 ouraddr;
++#define FORCE_IMMEDIATE 7
++#define OUR_USB_ADDRESS 0
++ u32 ourconfig;
++} __attribute__ ((packed));
++
++/* pci control, BAR0 + 0x0100 */
++struct net2280_pci_regs {
++ // offset 0x0100
++ u32 pcimstctl;
++#define PCI_ARBITER_PARK_SELECT 13
++#define PCI_MULTI LEVEL_ARBITER 12
++#define PCI_RETRY_ABORT_ENABLE 11
++#define DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE 10
++#define DMA_READ_MULTIPLE_ENABLE 9
++#define DMA_READ_LINE_ENABLE 8
++#define PCI_MASTER_COMMAND_SELECT 6
++#define MEM_READ_OR_WRITE 0
++#define IO_READ_OR_WRITE 1
++#define CFG_READ_OR_WRITE 2
++#define PCI_MASTER_START 5
++#define PCI_MASTER_READ_WRITE 4
++#define PCI_MASTER_WRITE 0
++#define PCI_MASTER_READ 1
++#define PCI_MASTER_BYTE_WRITE_ENABLES 0
++ u32 pcimstaddr;
++ u32 pcimstdata;
++ u32 pcimststat;
++#define PCI_ARBITER_CLEAR 2
++#define PCI_EXTERNAL_ARBITER 1
++#define PCI_HOST_MODE 0
++} __attribute__ ((packed));
++
++/* dma control, BAR0 + 0x0180 ... array of four structs like this,
++ * for channels 0..3. see also struct net2280_dma: descriptor
++ * that can be loaded into some of these registers.
++ */
++struct net2280_dma_regs { /* [11.7] */
++ // offset 0x0180, 0x01a0, 0x01c0, 0x01e0,
++ u32 dmactl;
++#define DMA_SCATTER_GATHER_DONE_INTERRUPT_ENABLE 25
++#define DMA_CLEAR_COUNT_ENABLE 21
++#define DESCRIPTOR_POLLING_RATE 19
++#define POLL_CONTINUOUS 0
++#define POLL_1_USEC 1
++#define POLL_100_USEC 2
++#define POLL_1_MSEC 3
++#define DMA_VALID_BIT_POLLING_ENABLE 18
++#define DMA_VALID_BIT_ENABLE 17
++#define DMA_SCATTER_GATHER_ENABLE 16
++#define DMA_OUT_AUTO_START_ENABLE 4
++#define DMA_PREEMPT_ENABLE 3
++#define DMA_FIFO_VALIDATE 2
++#define DMA_ENABLE 1
++#define DMA_ADDRESS_HOLD 0
++ u32 dmastat;
++#define DMA_SCATTER_GATHER_DONE_INTERRUPT 25
++#define DMA_TRANSACTION_DONE_INTERRUPT 24
++#define DMA_ABORT 1
++#define DMA_START 0
++ u32 _unused0 [2];
++ // offset 0x0190, 0x01b0, 0x01d0, 0x01f0,
++ u32 dmacount;
++#define VALID_BIT 31
++#define DMA_DIRECTION 30
++#define DMA_DONE_INTERRUPT_ENABLE 29
++#define END_OF_CHAIN 28
++#define DMA_BYTE_COUNT_MASK ((1<<24)-1)
++#define DMA_BYTE_COUNT 0
++ u32 dmaaddr;
++ u32 dmadesc;
++ u32 _unused1;
++} __attribute__ ((packed));
++
++/* dedicated endpoint registers, BAR0 + 0x0200 */
++
++struct net2280_dep_regs { /* [11.8] */
++ // offset 0x0200, 0x0210, 0x220, 0x230, 0x240
++ u32 dep_cfg;
++ // offset 0x0204, 0x0214, 0x224, 0x234, 0x244
++ u32 dep_rsp;
++ u32 _unused [2];
++} __attribute__ ((packed));
++
++/* configurable endpoint registers, BAR0 + 0x0300 ... array of seven structs
++ * like this, for ep0 then the configurable endpoints A..F
++ * ep0 reserved for control; E and F have only 64 bytes of fifo
++ */
++struct net2280_ep_regs { /* [11.9] */
++ // offset 0x0300, 0x0320, 0x0340, 0x0360, 0x0380, 0x03a0, 0x03c0
++ u32 ep_cfg;
++#define ENDPOINT_BYTE_COUNT 16
++#define ENDPOINT_ENABLE 10
++#define ENDPOINT_TYPE 8
++#define ENDPOINT_DIRECTION 7
++#define ENDPOINT_NUMBER 0
++ u32 ep_rsp;
++#define SET_NAK_OUT_PACKETS 15
++#define SET_EP_HIDE_STATUS_PHASE 14
++#define SET_EP_FORCE_CRC_ERROR 13
++#define SET_INTERRUPT_MODE 12
++#define SET_CONTROL_STATUS_PHASE_HANDSHAKE 11
++#define SET_NAK_OUT_PACKETS_MODE 10
++#define SET_ENDPOINT_TOGGLE 9
++#define SET_ENDPOINT_HALT 8
++#define CLEAR_NAK_OUT_PACKETS 7
++#define CLEAR_EP_HIDE_STATUS_PHASE 6
++#define CLEAR_EP_FORCE_CRC_ERROR 5
++#define CLEAR_INTERRUPT_MODE 4
++#define CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE 3
++#define CLEAR_NAK_OUT_PACKETS_MODE 2
++#define CLEAR_ENDPOINT_TOGGLE 1
++#define CLEAR_ENDPOINT_HALT 0
++ u32 ep_irqenb;
++#define SHORT_PACKET_OUT_DONE_INTERRUPT_ENABLE 6
++#define SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE 5
++#define DATA_PACKET_RECEIVED_INTERRUPT_ENABLE 3
++#define DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE 2
++#define DATA_OUT_PING_TOKEN_INTERRUPT_ENABLE 1
++#define DATA_IN_TOKEN_INTERRUPT_ENABLE 0
++ u32 ep_stat;
++#define FIFO_VALID_COUNT 24
++#define HIGH_BANDWIDTH_OUT_TRANSACTION_PID 22
++#define TIMEOUT 21
++#define USB_STALL_SENT 20
++#define USB_IN_NAK_SENT 19
++#define USB_IN_ACK_RCVD 18
++#define USB_OUT_PING_NAK_SENT 17
++#define USB_OUT_ACK_SENT 16
++#define FIFO_OVERFLOW 13
++#define FIFO_UNDERFLOW 12
++#define FIFO_FULL 11
++#define FIFO_EMPTY 10
++#define FIFO_FLUSH 9
++#define SHORT_PACKET_OUT_DONE_INTERRUPT 6
++#define SHORT_PACKET_TRANSFERRED_INTERRUPT 5
++#define NAK_OUT_PACKETS 4
++#define DATA_PACKET_RECEIVED_INTERRUPT 3
++#define DATA_PACKET_TRANSMITTED_INTERRUPT 2
++#define DATA_OUT_PING_TOKEN_INTERRUPT 1
++#define DATA_IN_TOKEN_INTERRUPT 0
++ // offset 0x0310, 0x0330, 0x0350, 0x0370, 0x0390, 0x03b0, 0x03d0
++ u32 ep_avail;
++ u32 ep_data;
++ u32 _unused0 [2];
++} __attribute__ ((packed));
++
++/*-------------------------------------------------------------------------*/
++
++#ifdef __KERNEL__
++
++/* indexed registers [11.10] are accessed indirectly
++ * caller must own the device lock.
++ */
++
++static inline u32
++get_idx_reg (struct net2280_regs *regs, u32 index)
++{
++ writel (index, &regs->idxaddr);
++ /* NOTE: synchs device/cpu memory views */
++ return readl (&regs->idxdata);
++}
++
++static inline void
++set_idx_reg (struct net2280_regs *regs, u32 index, u32 value)
++{
++ writel (index, &regs->idxaddr);
++ writel (value, &regs->idxdata);
++ /* posted, may not be visible yet */
++}
++
++#endif /* __KERNEL__ */
++
++
++#define REG_DIAG 0x0
++#define RETRY_COUNTER 16
++#define FORCE_PCI_SERR 11
++#define FORCE_PCI_INTERRUPT 10
++#define FORCE_USB_INTERRUPT 9
++#define FORCE_CPU_INTERRUPT 8
++#define ILLEGAL_BYTE_ENABLES 5
++#define FAST_TIMES 4
++#define FORCE_RECEIVE_ERROR 2
++#define FORCE_TRANSMIT_CRC_ERROR 0
++#define REG_FRAME 0x02 /* from last sof */
++#define REG_CHIPREV 0x03 /* in bcd */
++#define REG_HS_NAK_RATE 0x0a /* NAK per N uframes */
++
++#define CHIPREV_1 0x0100
++#define CHIPREV_1A 0x0110
++
++#ifdef __KERNEL__
++
++/* ep a-f highspeed and fullspeed maxpacket, addresses
++ * computed from ep->num
++ */
++#define REG_EP_MAXPKT(dev,num) (((num) + 1) * 0x10 + \
++ (((dev)->gadget.speed == USB_SPEED_HIGH) ? 0 : 1))
++
++/*-------------------------------------------------------------------------*/
++
++/* [8.3] for scatter/gather i/o
++ * use struct net2280_dma_regs bitfields
++ */
++struct net2280_dma {
++ u32 dmacount;
++ u32 dmaaddr; /* the buffer */
++ u32 dmadesc; /* next dma descriptor */
++ u32 _reserved;
++} __attribute__ ((aligned (16)));
++
++/*-------------------------------------------------------------------------*/
++
++/* DRIVER DATA STRUCTURES and UTILITIES */
++
++struct net2280_ep {
++ struct usb_ep ep;
++ struct net2280_ep_regs *regs;
++ struct net2280_dma_regs *dma;
++ struct net2280_dma *dummy;
++ dma_addr_t td_dma; /* of dummy */
++ struct net2280 *dev;
++ unsigned long irqs;
++
++ /* analogous to a host-side qh */
++ struct list_head queue;
++ const struct usb_endpoint_descriptor *desc;
++ unsigned num : 8,
++ fifo_size : 12,
++ in_fifo_validate : 1,
++ out_overflow : 1,
++ stopped : 1,
++ is_in : 1,
++ is_iso : 1;
++};
++
++static inline void allow_status (struct net2280_ep *ep)
++{
++ /* ep0 only */
++ writel ( (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE)
++ | (1 << CLEAR_NAK_OUT_PACKETS)
++ | (1 << CLEAR_NAK_OUT_PACKETS_MODE)
++ , &ep->regs->ep_rsp);
++ ep->stopped = 1;
++}
++
++/* count (<= 4) bytes in the next fifo write will be valid */
++static inline void set_fifo_bytecount (struct net2280_ep *ep, unsigned count)
++{
++ writeb (count, 2 + (u8 *) &ep->regs->ep_cfg);
++}
++
++struct net2280_request {
++ struct usb_request req;
++ struct net2280_dma *td;
++ dma_addr_t td_dma;
++ struct list_head queue;
++ unsigned mapped : 1,
++ valid : 1;
++};
++
++struct net2280 {
++ /* each pci device provides one gadget, several endpoints */
++ struct usb_gadget gadget;
++ spinlock_t lock;
++ struct net2280_ep ep [7];
++ struct usb_gadget_driver *driver;
++ unsigned enabled : 1,
++ protocol_stall : 1,
++ softconnect : 1,
++ got_irq : 1,
++ region : 1;
++ u16 chiprev;
++
++ /* pci state used to access those endpoints */
++ struct pci_dev *pdev;
++ struct net2280_regs *regs;
++ struct net2280_usb_regs *usb;
++ struct net2280_pci_regs *pci;
++ struct net2280_dma_regs *dma;
++ struct net2280_dep_regs *dep;
++ struct net2280_ep_regs *epregs;
++
++ struct pci_pool *requests;
++ // statistics...
++};
++
++static inline void set_halt (struct net2280_ep *ep)
++{
++ /* ep0 and bulk/intr endpoints */
++ writel ( (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE)
++ /* set NAK_OUT for erratum 0114 */
++ | ((ep->dev->chiprev == CHIPREV_1) << SET_NAK_OUT_PACKETS)
++ | (1 << SET_ENDPOINT_HALT)
++ , &ep->regs->ep_rsp);
++}
++
++static inline void clear_halt (struct net2280_ep *ep)
++{
++ /* ep0 and bulk/intr endpoints */
++ writel ( (1 << CLEAR_ENDPOINT_HALT)
++ | (1 << CLEAR_ENDPOINT_TOGGLE)
++ /* unless the gadget driver left a short packet in the
++ * fifo, this reverses the erratum 0114 workaround.
++ */
++ | ((ep->dev->chiprev == CHIPREV_1) << CLEAR_NAK_OUT_PACKETS)
++ , &ep->regs->ep_rsp);
++}
++
++#ifdef USE_RDK_LEDS
++
++static inline void net2280_led_init (struct net2280 *dev)
++{
++ /* LED3 (green) is on during USB activity. note erratum 0113. */
++ writel ((1 << GPIO3_LED_SELECT)
++ | (1 << GPIO3_OUTPUT_ENABLE)
++ | (1 << GPIO2_OUTPUT_ENABLE)
++ | (1 << GPIO1_OUTPUT_ENABLE)
++ | (1 << GPIO0_OUTPUT_ENABLE)
++ , &dev->regs->gpioctl);
++}
++
++/* indicate speed with bi-color LED 0/1 */
++static inline
++void net2280_led_speed (struct net2280 *dev, enum usb_device_speed speed)
++{
++ u32 val = readl (&dev->regs->gpioctl);
++ switch (speed) {
++ case USB_SPEED_HIGH: /* green */
++ val &= ~(1 << GPIO0_DATA);
++ val |= (1 << GPIO1_DATA);
++ break;
++ case USB_SPEED_FULL: /* red */
++ val &= ~(1 << GPIO1_DATA);
++ val |= (1 << GPIO0_DATA);
++ break;
++ default: /* (off/black) */
++ val &= ~((1 << GPIO1_DATA) | (1 << GPIO0_DATA));
++ break;
++ }
++ writel (val, &dev->regs->gpioctl);
++}
++
++/* indicate power with LED 2 */
++static inline void net2280_led_active (struct net2280 *dev, int is_active)
++{
++ u32 val = readl (&dev->regs->gpioctl);
++
++ // FIXME this LED never seems to turn on.
++ if (is_active)
++ val |= GPIO2_DATA;
++ else
++ val &= ~GPIO2_DATA;
++ writel (val, &dev->regs->gpioctl);
++}
++static inline void net2280_led_shutdown (struct net2280 *dev)
++{
++ /* turn off all four GPIO*_DATA bits */
++ writel (readl (&dev->regs->gpioctl) & ~0x0f,
++ &dev->regs->gpioctl);
++}
++
++#else
++
++#define net2280_led_init(dev) do { } while (0)
++#define net2280_led_speed(dev, speed) do { } while (0)
++#define net2280_led_shutdown(dev) do { } while (0)
++
++#endif
++
++/*-------------------------------------------------------------------------*/
++
++#define xprintk(dev,level,fmt,args...) \
++ printk(level "%s %s: " fmt , driver_name , \
++ dev->pdev->slot_name , ## 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 /* 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)
++
++/*-------------------------------------------------------------------------*/
++
++static inline void start_out_naking (struct net2280_ep *ep)
++{
++ /* NOTE: hardware races lurk here, and PING protocol issues */
++ writel ((1 << SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
++ /* synch with device */
++ readl (&ep->regs->ep_rsp);
++}
++
++#ifdef DEBUG
++static inline void assert_out_naking (struct net2280_ep *ep, const char *where)
++{
++ u32 tmp = readl (&ep->regs->ep_stat);
++
++ if ((tmp & (1 << NAK_OUT_PACKETS)) == 0) {
++ DEBUG (ep->dev, "%s %s %08x !NAK\n",
++ ep->ep.name, where, tmp);
++ writel ((1 << SET_NAK_OUT_PACKETS),
++ &ep->regs->ep_rsp);
++ }
++}
++#define ASSERT_OUT_NAKING(ep) assert_out_naking(ep,__FUNCTION__)
++#else
++#define ASSERT_OUT_NAKING(ep) do {} while (0)
++#endif
++
++static inline void stop_out_naking (struct net2280_ep *ep)
++{
++ u32 tmp;
++
++ tmp = readl (&ep->regs->ep_stat);
++ if ((tmp & (1 << NAK_OUT_PACKETS)) != 0)
++ writel ((1 << CLEAR_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
++}
++
++/*-------------------------------------------------------------------------*/
++
++/* 2.5 and 2.4.older portability changes ... */
++
++#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
++
++#endif /* __KERNEL__ */
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/drivers/usb/gadget/pxa2xx_udc.c kernel/drivers/usb/gadget/pxa2xx_udc.c
+--- /tmp/kernel/drivers/usb/gadget/pxa2xx_udc.c 1970-01-01 01:00:00.000000000 +0100
++++ kernel/drivers/usb/gadget/pxa2xx_udc.c 2005-04-22 17:53:19.492530073 +0200
+@@ -0,0 +1,2486 @@
++/*
++ * linux/drivers/usb/gadget/pxa2xx_udc.c
++ * Intel PXA2xx and IXP4xx on-chip full speed USB device controllers
++ *
++ * Copyright (C) 2002 Intrinsyc, Inc. (Frank Becker)
++ * Copyright (C) 2003 Robert Schwebel, Pengutronix
++ * Copyright (C) 2003 Benedikt Spranger, Pengutronix
++ * 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 DBG_VERBOSE
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/ioport.h>
++#include <linux/types.h>
++#include <linux/version.h>
++#include <linux/errno.h>
++#include <linux/delay.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/timer.h>
++#include <linux/list.h>
++#include <linux/interrupt.h>
++#include <linux/proc_fs.h>
++#include <linux/mm.h>
++// #include <linux/device.h>
++
++#include <asm/byteorder.h>
++#include <asm/dma.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/system.h>
++#include <asm/unaligned.h>
++#include <asm/proc/cache.h>
++
++#include <linux/usb_ch9.h>
++#include <linux/usb_gadget.h>
++
++
++/*
++ * This driver handles the USB Device Controller (UDC) in Intel's PXA 2xx
++ * series processors. The UDC for the IXP 4xx series is very similar.
++ * There are fifteen endpoints, in addition to ep0.
++ *
++ * Such controller drivers work with a gadget driver. The gadget driver
++ * returns descriptors, implements configuration and data protocols used
++ * by the host to interact with this device, and allocates endpoints to
++ * the different protocol interfaces. The controller driver virtualizes
++ * usb hardware so that the gadget drivers will be more portable.
++ *
++ * This UDC hardware wants to implement a bit too much USB protocol, so
++ * it constrains the sorts of USB configuration change events that work.
++ * The errata for these chips are misleading; some "fixed" bugs from
++ * pxa250 a0/a1 b0/b1/b2 sure act like they're still there.
++ */
++
++/* NOTE: the 2.6 driver is probably the most current version */
++#define DRIVER_VERSION "5-Jan-2004"
++#define DRIVER_DESC "PXA 2xx USB Device Controller driver"
++
++static const char driver_name [] = "pxa2xx_udc";
++
++static const char ep0name [] = "ep0";
++
++
++// #define USE_DMA
++// #define USE_OUT_DMA
++// #define DISABLE_TEST_MODE
++
++#ifdef CONFIG_PROC_FS
++#define UDC_PROC_FILE
++#endif
++
++#ifdef CONFIG_ARCH_IXP425
++#undef USE_DMA
++
++/* cpu-specific register addresses are compiled in to this code */
++#ifdef CONFIG_ARCH_PXA
++#error "Can't configure both IXP and PXA"
++#endif
++
++#endif
++
++#ifdef CONFIG_EMBEDDED
++/* few strings, and little code to use them */
++#undef DEBUG
++#undef UDC_PROC_FILE
++#endif
++
++
++#include "pxa2xx_udc.h"
++
++#ifdef USE_DMA
++static int use_dma = 1;
++MODULE_PARM (use_dma, "i");
++MODULE_PARM_DESC (use_dma, "true to use dma");
++
++static void dma_nodesc_handler (int dmach, void *_ep, struct pt_regs *r);
++static void kick_dma(struct pxa2xx_ep *ep, struct pxa2xx_request *req);
++
++#ifdef USE_OUT_DMA
++#define DMASTR " (dma support)"
++#else
++#define DMASTR " (dma in)"
++#endif
++
++#else /* !USE_DMA */
++#define DMASTR " (pio only)"
++#undef USE_OUT_DMA
++#endif
++
++#ifdef CONFIG_USB_PXA2XX_SMALL
++#define SIZE_STR " (small)"
++#else
++#define SIZE_STR ""
++#endif
++
++#ifdef DISABLE_TEST_MODE
++/* (mode == 0) == no undocumented chip tweaks
++ * (mode & 1) == double buffer bulk IN
++ * (mode & 2) == double buffer bulk OUT
++ * ... so mode = 3 (or 7, 15, etc) does it for both
++ */
++static ushort fifo_mode = 0;
++MODULE_PARM (fifo_mode, "h");
++MODULE_PARM_DESC (fifo_mode, "pxa2xx udc fifo mode");
++#endif
++
++/* ---------------------------------------------------------------------------
++ * endpoint related parts of the api to the usb controller hardware,
++ * used by gadget driver; and the inner talker-to-hardware core.
++ * ---------------------------------------------------------------------------
++ */
++
++static void pxa2xx_ep_fifo_flush (struct usb_ep *ep);
++static void nuke (struct pxa2xx_ep *, int status);
++
++static void pio_irq_enable(int bEndpointAddress)
++{
++ bEndpointAddress &= 0xf;
++ if (bEndpointAddress < 8)
++ UICR0 &= ~(1 << bEndpointAddress);
++ else {
++ bEndpointAddress -= 8;
++ UICR1 &= ~(1 << bEndpointAddress);
++ }
++}
++
++static void pio_irq_disable(int bEndpointAddress)
++{
++ bEndpointAddress &= 0xf;
++ if (bEndpointAddress < 8)
++ UICR0 |= 1 << bEndpointAddress;
++ else {
++ bEndpointAddress -= 8;
++ UICR1 |= 1 << bEndpointAddress;
++ }
++}
++
++/* The UDCCR reg contains mask and interrupt status bits,
++ * so using '|=' isn't safe as it may ack an interrupt.
++ */
++#define UDCCR_MASK_BITS (UDCCR_REM | UDCCR_SRM | UDCCR_UDE)
++
++static inline void udc_set_mask_UDCCR(int mask)
++{
++ UDCCR = (UDCCR & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS);
++}
++
++static inline void udc_clear_mask_UDCCR(int mask)
++{
++ UDCCR = (UDCCR & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS);
++}
++
++static inline void udc_ack_int_UDCCR(int mask)
++{
++ /* udccr contains the bits we dont want to change */
++ __u32 udccr = UDCCR & UDCCR_MASK_BITS;
++
++ UDCCR = udccr | (mask & ~UDCCR_MASK_BITS);
++}
++
++/*
++ * endpoint enable/disable
++ *
++ * we need to verify the descriptors used to enable endpoints. since pxa2xx
++ * endpoint configurations are fixed, and are pretty much always enabled,
++ * there's not a lot to manage here.
++ *
++ * because pxa2xx can't selectively initialize bulk (or interrupt) endpoints,
++ * (resetting endpoint halt and toggle), SET_INTERFACE is unusable except
++ * for a single interface (with only the default altsetting) and for gadget
++ * drivers that don't halt endpoints (not reset by set_interface). that also
++ * means that if you use ISO, you must violate the USB spec rule that all
++ * iso endpoints must be in non-default altsettings.
++ */
++static int pxa2xx_ep_enable (struct usb_ep *_ep,
++ const struct usb_endpoint_descriptor *desc)
++{
++ struct pxa2xx_ep *ep;
++ struct pxa2xx_udc *dev;
++
++ ep = container_of (_ep, struct pxa2xx_ep, ep);
++ if (!_ep || !desc || ep->desc || _ep->name == ep0name
++ || desc->bDescriptorType != USB_DT_ENDPOINT
++ || ep->bEndpointAddress != desc->bEndpointAddress
++ || ep->fifo_size < le16_to_cpu
++ (desc->wMaxPacketSize)) {
++ DMSG("%s, bad ep or descriptor\n", __FUNCTION__);
++ return -EINVAL;
++ }
++
++ /* xfer types must match, except that interrupt ~= bulk */
++ if (ep->bmAttributes != desc->bmAttributes
++ && ep->bmAttributes != USB_ENDPOINT_XFER_BULK
++ && desc->bmAttributes != USB_ENDPOINT_XFER_INT) {
++ DMSG("%s, %s type mismatch\n", __FUNCTION__, _ep->name);
++ return -EINVAL;
++ }
++
++ /* hardware _could_ do smaller, but driver doesn't */
++ if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK
++ && le16_to_cpu (desc->wMaxPacketSize)
++ != BULK_FIFO_SIZE)
++ || !desc->wMaxPacketSize) {
++ DMSG("%s, bad %s maxpacket\n", __FUNCTION__, _ep->name);
++ return -ERANGE;
++ }
++
++ dev = ep->dev;
++ if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) {
++ DMSG("%s, bogus device state\n", __FUNCTION__);
++ return -ESHUTDOWN;
++ }
++
++ ep->desc = desc;
++ ep->dma = -1;
++ ep->stopped = 0;
++ ep->pio_irqs = ep->dma_irqs = 0;
++ ep->ep.maxpacket = le16_to_cpu (desc->wMaxPacketSize);
++
++ /* flush fifo (mostly for OUT buffers) */
++ pxa2xx_ep_fifo_flush (_ep);
++
++ /* ... reset halt state too, if we could ... */
++
++#ifdef USE_DMA
++ /* for (some) bulk and ISO endpoints, try to get a DMA channel and
++ * bind it to the endpoint. otherwise use PIO.
++ */
++ switch (ep->bmAttributes) {
++ case USB_ENDPOINT_XFER_ISOC:
++ if (le16_to_cpu(desc->wMaxPacketSize) % 32)
++ break;
++ // fall through
++ case USB_ENDPOINT_XFER_BULK:
++ if (!use_dma || !ep->reg_drcmr)
++ break;
++ /* no bulk-out dma yet (pointless w/o descriptors) */
++ if ((ep->bmAttributes == USB_ENDPOINT_XFER_BULK)
++ && (ep->bEndpointAddress & USB_DIR_IN) == 0) {
++ DMSG("%s dma-out NYI\n", _ep->name);
++ break;
++ }
++ ep->dma = pxa_request_dma ((char *)_ep->name,
++ (le16_to_cpu(desc->wMaxPacketSize) > 64)
++ ? DMA_PRIO_MEDIUM /* some iso */
++ : DMA_PRIO_LOW,
++ // FIXME or ep_out_dma .. ..
++ dma_nodesc_handler, ep);
++ if (ep->dma >= 0) {
++ *ep->reg_drcmr = DRCMR_MAPVLD | ep->dma;
++ DMSG("%s using dma%d\n", _ep->name, ep->dma);
++ }
++ }
++#endif
++
++ DBG(DBG_VERBOSE, "enabled %s\n", _ep->name);
++ return 0;
++}
++
++static int pxa2xx_ep_disable (struct usb_ep *_ep)
++{
++ struct pxa2xx_ep *ep;
++
++ ep = container_of (_ep, struct pxa2xx_ep, ep);
++ if (!_ep || !ep->desc) {
++ DMSG("%s, %s not enabled\n", __FUNCTION__,
++ _ep ? ep->ep.name : NULL);
++ return -EINVAL;
++ }
++ nuke (ep, -ESHUTDOWN);
++
++#ifdef USE_DMA
++ if (ep->dma >= 0) {
++ *ep->reg_drcmr = 0;
++ pxa_free_dma (ep->dma);
++ ep->dma = -1;
++ }
++#endif
++
++ /* flush fifo (mostly for IN buffers) */
++ pxa2xx_ep_fifo_flush (_ep);
++
++ ep->desc = 0;
++ ep->stopped = 1;
++
++ DBG(DBG_VERBOSE, "%s disabled\n", _ep->name);
++ return 0;
++}
++
++/*-------------------------------------------------------------------------*/
++
++/* for the pxa2xx, these can just wrap kmalloc/kfree. gadget drivers
++ * must still pass correctly initialized endpoints, since other controller
++ * drivers may care about how it's currently set up (dma issues etc).
++ */
++
++/*
++ * pxa2xx_ep_alloc_request - allocate a request data structure
++ */
++static struct usb_request *
++pxa2xx_ep_alloc_request (struct usb_ep *_ep, int gfp_flags)
++{
++ struct pxa2xx_request *req;
++
++ /* FIXME for bulk out-dma endpoints, preallocate a frame's worth of
++ * (aligned) dma descriptors at the end of the request
++ */
++
++ req = kmalloc (sizeof *req, gfp_flags);
++ if (!req)
++ return 0;
++
++ memset (req, 0, sizeof *req);
++ INIT_LIST_HEAD (&req->queue);
++ return &req->req;
++}
++
++
++/*
++ * pxa2xx_ep_free_request - deallocate a request data structure
++ */
++static void
++pxa2xx_ep_free_request (struct usb_ep *_ep, struct usb_request *_req)
++{
++ struct pxa2xx_request *req;
++
++ req = container_of (_req, struct pxa2xx_request, req);
++ WARN_ON (!list_empty (&req->queue));
++ kfree(req);
++}
++
++
++/* PXA cache needs flushing with DMA I/O (it's dma-incoherent), but there's
++ * no device-affinity and the heap works perfectly well for i/o buffers.
++ */
++static void *
++pxa2xx_ep_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
++ dma_addr_t *dma, int gfp_flags)
++{
++ char *retval;
++
++ retval = kmalloc (bytes, gfp_flags & ~(__GFP_DMA|__GFP_HIGHMEM));
++ if (retval)
++ *dma = virt_to_bus (retval);
++ return retval;
++}
++
++static void
++pxa2xx_ep_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma,
++ unsigned bytes)
++{
++ kfree (buf);
++}
++
++/*-------------------------------------------------------------------------*/
++
++/*
++ * done - retire a request; caller blocked irqs
++ */
++static void done(struct pxa2xx_ep *ep, struct pxa2xx_request *req, int status)
++{
++ unsigned stopped = ep->stopped;
++
++ list_del_init(&req->queue);
++
++ if (likely (req->req.status == -EINPROGRESS))
++ req->req.status = status;
++ else
++ status = req->req.status;
++
++ if (status && status != -ESHUTDOWN)
++ DBG(DBG_VERBOSE, "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;
++ req->req.complete(&ep->ep, &req->req);
++ ep->stopped = stopped;
++}
++
++
++static inline void ep0_idle (struct pxa2xx_udc *dev)
++{
++ dev->ep0state = EP0_IDLE;
++ LED_EP0_OFF;
++}
++
++static int
++write_packet(volatile u32 *uddr, struct pxa2xx_request *req, unsigned max)
++{
++ u8 *buf;
++ unsigned length, count;
++
++ buf = req->req.buf + req->req.actual;
++ prefetch(buf);
++
++ /* how big will this packet be? */
++ length = min(req->req.length - req->req.actual, max);
++ req->req.actual += length;
++
++ count = length;
++ while (likely(count--))
++ *uddr = *buf++;
++
++ return length;
++}
++
++/*
++ * write to an IN endpoint fifo, as many packets as possible.
++ * irqs will use this to write the rest later.
++ * caller guarantees at least one packet buffer is ready (or a zlp).
++ */
++static int
++write_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req)
++{
++ unsigned max;
++
++ max = le16_to_cpu(ep->desc->wMaxPacketSize);
++ do {
++ unsigned count;
++ int is_last, is_short;
++
++ count = write_packet(ep->reg_uddr, req, max);
++
++ /* last packet is usually short (or a zlp) */
++ if (unlikely (count != max))
++ is_last = is_short = 1;
++ else {
++ if (likely(req->req.length != req->req.actual)
++ || req->req.zero)
++ is_last = 0;
++ else
++ is_last = 1;
++ /* interrupt/iso maxpacket may not fill the fifo */
++ is_short = unlikely (max < ep->fifo_size);
++ }
++
++ DBG(DBG_VERY_NOISY, "wrote %s %d bytes%s%s %d left %p\n",
++ ep->ep.name, count,
++ is_last ? "/L" : "", is_short ? "/S" : "",
++ req->req.length - req->req.actual, req);
++
++ /* let loose that packet. maybe try writing another one,
++ * double buffering might work. TSP, TPC, and TFS
++ * bit values are the same for all normal IN endpoints.
++ */
++ *ep->reg_udccs = UDCCS_BI_TPC;
++ if (is_short)
++ *ep->reg_udccs = UDCCS_BI_TSP;
++
++ /* requests complete when all IN data is in the FIFO */
++ if (is_last) {
++ done (ep, req, 0);
++ if (list_empty(&ep->queue) || unlikely(ep->dma >= 0))
++ pio_irq_disable (ep->bEndpointAddress);
++#ifdef USE_DMA
++ if (unlikely(ep->dma >= 0) && !list_empty(&ep->queue)) {
++DMSG("%s pio2dma\n", ep->ep.name);
++ req = list_entry(ep->queue.next,
++ struct pxa2xx_request, queue);
++ kick_dma(ep,req);
++ return 0;
++ }
++#endif
++ return 1;
++ }
++
++ // TODO experiment: how robust can fifo mode tweaking be?
++ // the double buffering could speed up I/O a bunch.
++
++ } while (*ep->reg_udccs & UDCCS_BI_TFS);
++ return 0;
++}
++
++/* caller asserts req->pending (ep0 irq status nyet cleared); starts
++ * ep0 data stage. these chips want very simple state transitions.
++ */
++static inline
++void ep0start(struct pxa2xx_udc *dev, u32 flags, const char *tag)
++{
++ UDCCS0 = flags|UDCCS0_SA|UDCCS0_OPR;
++ USIR0 = USIR0_IR0;
++ dev->req_pending = 0;
++ DBG(DBG_VERY_NOISY, "%s %s, %02x/%02x\n",
++ __FUNCTION__, tag, UDCCS0, flags);
++}
++
++static int
++write_ep0_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req)
++{
++ unsigned count;
++ int is_short;
++
++ count = write_packet(&UDDR0, req, EP0_FIFO_SIZE);
++ ep->dev->stats.write.bytes += count;
++
++ /* last packet "must be" short (or a zlp) */
++ is_short = (count != EP0_FIFO_SIZE);
++
++ DBG(DBG_VERY_NOISY, "ep0in %d bytes %d left %p\n", count,
++ req->req.length - req->req.actual, req);
++
++ if (unlikely (is_short)) {
++ if (ep->dev->req_pending)
++ ep0start(ep->dev, UDCCS0_IPR, "short IN");
++ else
++ UDCCS0 = UDCCS0_IPR;
++
++ count = req->req.length;
++ done (ep, req, 0);
++ ep0_idle(ep->dev);
++#if 1
++ /* This seems to get rid of lost status irqs in some cases:
++ * host responds quickly, or next request involves config
++ * change automagic, or should have been hidden, or ...
++ *
++ * FIXME get rid of all udelays possible...
++ */
++ if (count >= EP0_FIFO_SIZE) {
++ count = 100;
++ do {
++ if ((UDCCS0 & UDCCS0_OPR) != 0) {
++ /* clear OPR, generate ack */
++ UDCCS0 = UDCCS0_OPR;
++ break;
++ }
++ count--;
++ udelay(1);
++ } while (count);
++ }
++#endif
++ } else if (ep->dev->req_pending)
++ ep0start(ep->dev, 0, "IN");
++ return is_short;
++}
++
++
++/*
++ * read_fifo - unload packet(s) from the fifo we use for usb OUT
++ * transfers and put them into the request. caller should have made
++ * sure there's at least one packet ready.
++ *
++ * returns true if the request completed because of short packet or the
++ * request buffer having filled (and maybe overran till end-of-packet).
++ */
++static int
++read_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req)
++{
++ for (;;) {
++ u32 udccs;
++ u8 *buf;
++ unsigned bufferspace, count, is_short;
++
++ /* make sure there's a packet in the FIFO.
++ * UDCCS_{BO,IO}_RPC are all the same bit value.
++ * UDCCS_{BO,IO}_RNE are all the same bit value.
++ */
++ udccs = *ep->reg_udccs;
++ if (unlikely ((udccs & UDCCS_BO_RPC) == 0))
++ break;
++ buf = req->req.buf + req->req.actual;
++ prefetchw(buf);
++ bufferspace = req->req.length - req->req.actual;
++
++ /* read all bytes from this packet */
++ if (likely (udccs & UDCCS_BO_RNE)) {
++ count = 1 + (0x0ff & *ep->reg_ubcr);
++ req->req.actual += min (count, bufferspace);
++ } else /* zlp */
++ count = 0;
++ is_short = (count < ep->ep.maxpacket);
++ DBG(DBG_VERY_NOISY, "read %s %02x, %d bytes%s req %p %d/%d\n",
++ ep->ep.name, udccs, count,
++ is_short ? "/S" : "",
++ req, req->req.actual, req->req.length);
++ while (likely (count-- != 0)) {
++ u8 byte = (u8) *ep->reg_uddr;
++
++ if (unlikely (bufferspace == 0)) {
++ /* this happens when the driver's buffer
++ * is smaller than what the host sent.
++ * discard the extra data.
++ */
++ if (req->req.status != -EOVERFLOW)
++ DMSG("%s overflow %d\n",
++ ep->ep.name, count);
++ req->req.status = -EOVERFLOW;
++ } else {
++ *buf++ = byte;
++ bufferspace--;
++ }
++ }
++ *ep->reg_udccs = UDCCS_BO_RPC;
++ /* RPC/RSP/RNE could now reflect the other packet buffer */
++
++ /* iso is one request per packet */
++ if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
++ if (udccs & UDCCS_IO_ROF)
++ req->req.status = -EHOSTUNREACH;
++ /* more like "is_done" */
++ is_short = 1;
++ }
++
++ /* completion */
++ if (is_short || req->req.actual == req->req.length) {
++ done (ep, req, 0);
++ if (list_empty(&ep->queue))
++ pio_irq_disable (ep->bEndpointAddress);
++ return 1;
++ }
++
++ /* finished that packet. the next one may be waiting... */
++ }
++ return 0;
++}
++
++/*
++ * special ep0 version of the above. no UBCR0 or double buffering; status
++ * handshaking is magic. most device protocols don't need control-OUT.
++ * CDC vendor commands (and RNDIS), mass storage CB/CBI, and some other
++ * protocols do use them.
++ */
++static int
++read_ep0_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req)
++{
++ u8 *buf, byte;
++ unsigned bufferspace;
++
++ buf = req->req.buf + req->req.actual;
++ bufferspace = req->req.length - req->req.actual;
++
++ while (UDCCS0 & UDCCS0_RNE) {
++ byte = (u8) UDDR0;
++
++ if (unlikely (bufferspace == 0)) {
++ /* this happens when the driver's buffer
++ * is smaller than what the host sent.
++ * discard the extra data.
++ */
++ if (req->req.status != -EOVERFLOW)
++ DMSG("%s overflow\n", ep->ep.name);
++ req->req.status = -EOVERFLOW;
++ } else {
++ *buf++ = byte;
++ req->req.actual++;
++ bufferspace--;
++ }
++ }
++
++ UDCCS0 = UDCCS0_OPR | UDCCS0_IPR;
++
++ /* completion */
++ if (req->req.actual >= req->req.length)
++ return 1;
++
++ /* finished that packet. the next one may be waiting... */
++ return 0;
++}
++
++#ifdef USE_DMA
++
++static inline void
++start_dma_nodesc(struct pxa2xx_ep *ep, struct pxa2xx_request *req, int is_in)
++{
++ u32 dcmd = req->req.length;
++ u32 buf = virt_to_bus (req->req.buf);
++ u32 fifo = io_v2p ((u32)ep->reg_uddr);
++
++ /* no-descriptor mode can be simple for bulk-in, iso-in, iso-out */
++ DCSR(ep->dma) = DCSR_NODESC;
++ dcmd |= DCMD_BURST32 | DCMD_ENDIRQEN | DCMD_WIDTH1;
++ if (is_in) {
++ DSADR(ep->dma) = buf;
++ DTADR(ep->dma) = fifo;
++ dcmd |= DCMD_FLOWTRG | DCMD_INCSRCADDR;
++ } else {
++ DSADR(ep->dma) = fifo;
++ DTADR(ep->dma) = buf;
++ dcmd |= DCMD_FLOWSRC | DCMD_INCTRGADDR;
++ }
++ DCMD(ep->dma) = dcmd;
++ DCSR(ep->dma) = DCSR_RUN | DCSR_STOPIRQEN | DCSR_NODESC;
++ /* and later the dma handler gets called */
++}
++
++static void kick_dma(struct pxa2xx_ep *ep, struct pxa2xx_request *req)
++{
++ if (ep->bEndpointAddress & USB_DIR_IN) {
++ /* docs imply we can't preload with pio */
++ if ((((u32)req->req.buf) & 0x0f) != 0) {
++// VERBOSE
++ DMSG("%s bad DMA align %p\n",
++ ep->ep.name, req->req.buf);
++pio_in:
++// FIXME PIO fallback doesn't work right yet (recovery?)
++DMSG("%s dma2pio\n", ep->ep.name);
++ pio_irq_enable(ep->bEndpointAddress);
++ if ((*ep->reg_udccs & UDCCS_BI_TFS) != 0)
++ (void) write_fifo(ep, req);
++ return;
++ }
++ /* dmacount 0 means end-of-transfer */
++ if (unlikely((req->req.length - req->req.actual) == 0)) {
++// VERBOSE
++ DMSG("%s zlp dma write...\n", ep->ep.name);
++ goto pio_in;
++ }
++ start_dma_nodesc(ep, req, USB_DIR_IN);
++ } else {
++ // if ISO, use no-descriptor DMA
++ BUG();
++ }
++}
++
++static void cancel_dma(struct pxa2xx_ep *ep)
++{
++ struct pxa2xx_request *req;
++ u32 tmp;
++
++ if (DCSR(ep->dma) == 0 || list_empty(&ep->queue))
++ return;
++
++ DCSR(ep->dma) = 0;
++ while ((DCSR(ep->dma) & DCSR_STOPSTATE) == 0)
++ cpu_relax();
++
++ req = list_entry(ep->queue.next, struct pxa2xx_request, queue);
++ tmp = DCMD(ep->dma) & DCMD_LENGTH;
++ req->req.actual = req->req.length - (tmp & DCMD_LENGTH);
++
++ /* the last tx packet may be incomplete, so flush the fifo.
++ * FIXME correct req.actual if we can
++ */
++ if (ep->bEndpointAddress & USB_DIR_IN)
++ *ep->reg_udccs = UDCCS_BI_FTF;
++}
++
++static void dma_nodesc_handler(int dmach, void *_ep, struct pt_regs *r)
++{
++ struct pxa2xx_ep *ep = _ep;
++ struct pxa2xx_request *req;
++ u32 tmp;
++
++ req = list_entry(ep->queue.next, struct pxa2xx_request, queue);
++
++ ep->dev->stats.irqs++;
++ HEX_DISPLAY(ep->dev->stats.irqs);
++
++ /* ack/clear */
++ tmp = DCSR(ep->dma);
++ DCSR(ep->dma) = tmp;
++ if ((tmp & DCSR_STOPSTATE) == 0
++ || (DDADR(ep->dma) & DDADR_STOP) != 0) {
++ DBG(DBG_VERBOSE, "%s, dcsr %08x ddadr %08x\n",
++ ep->ep.name, DCSR(ep->dma), DDADR(ep->dma));
++ return;
++ }
++ DCSR(ep->dma) = 0; /* clear DCSR_STOPSTATE */
++
++ /* wrap up the transfer, and collect status */
++ if (unlikely(tmp & DCSR_BUSERR))
++ req->req.status = -EIO;
++ tmp = DCMD(ep->dma);
++ req->req.actual = req->req.length - (tmp & DCMD_LENGTH);
++ tmp = 1; /* normally this is the last packet */
++
++ if (ep->bEndpointAddress & USB_DIR_IN) {
++ /* maybe validate final short packet */
++ if ((ep->bmAttributes == USB_ENDPOINT_XFER_BULK
++ && req->req.actual % BULK_FIFO_SIZE)
++ || (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
++ && req->req.actual % ISO_FIFO_SIZE))
++ *ep->reg_udccs = UDCCS_BI_TSP /*|UDCCS_BI_TPC*/;
++
++ /* or force a zlp, with pio ... */
++ else if (ep->bmAttributes == USB_ENDPOINT_XFER_BULK
++ && req->req.zero) {
++ tmp = 0;
++ }
++ // if iso, maybe report underrun (TUR)
++ } else {
++ BUG();
++ }
++
++ if (likely(tmp != 0))
++ done(ep, req, 0);
++
++ /* maybe re-activate after completion */
++ if (ep->stopped || list_empty(&ep->queue))
++ return;
++ req = list_entry(ep->queue.next, struct pxa2xx_request, queue);
++ kick_dma(ep, req);
++}
++
++#endif
++
++/*-------------------------------------------------------------------------*/
++
++static int
++pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
++{
++ struct pxa2xx_request *req;
++ struct pxa2xx_ep *ep;
++ struct pxa2xx_udc *dev;
++ unsigned long flags;
++
++ req = container_of(_req, struct pxa2xx_request, req);
++ if (unlikely (!_req || !_req->complete || !_req->buf
++ || !list_empty(&req->queue))) {
++ DMSG("%s, bad params\n", __FUNCTION__);
++ return -EINVAL;
++ }
++
++ ep = container_of(_ep, struct pxa2xx_ep, ep);
++ if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) {
++ DMSG("%s, bad ep\n", __FUNCTION__);
++ return -EINVAL;
++ }
++
++ dev = ep->dev;
++ if (unlikely (!dev->driver
++ || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
++ DMSG("%s, bogus device state\n", __FUNCTION__);
++ return -ESHUTDOWN;
++ }
++
++ /* iso is always one packet per request, that's the only way
++ * we can report per-packet status. that also helps with dma.
++ */
++ if (unlikely (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
++ && req->req.length > le16_to_cpu
++ (ep->desc->wMaxPacketSize)))
++ return -EMSGSIZE;
++
++#ifdef USE_DMA
++ if (ep->dma >= 0) {
++ unsigned long start = (unsigned long) _req->buf;
++
++ clean_dcache_range(start, start + _req->length);
++ /* or for USB_DIR_OUT, invalidate_dcache_range (...) */
++ }
++#endif
++
++ DBG(DBG_NOISY, "%s queue req %p, len %d buf %p\n",
++ _ep->name, _req, _req->length, _req->buf);
++
++ local_irq_save(flags);
++
++ _req->status = -EINPROGRESS;
++ _req->actual = 0;
++
++ /* kickstart this i/o queue? */
++ if (list_empty(&ep->queue) && !ep->stopped) {
++ if (ep->desc == 0 /* ep0 */) {
++ unsigned length = _req->length;
++
++ switch (dev->ep0state) {
++ case EP0_IN_DATA_PHASE:
++ dev->stats.write.ops++;
++ if (write_ep0_fifo(ep, req))
++ req = 0;
++ break;
++
++ case EP0_OUT_DATA_PHASE:
++ dev->stats.read.ops++;
++ /* messy ... */
++ if (dev->req_config) {
++ DBG(DBG_VERBOSE, "ep0 config ack%s\n",
++ dev->has_cfr ? "" : " raced");
++ if (dev->has_cfr)
++ UDCCFR = UDCCFR_AREN|UDCCFR_ACM;
++ done(ep, req, 0);
++ dev->ep0state = EP0_END_XFER;
++ local_irq_restore (flags);
++ return 0;
++ }
++ if (dev->req_pending)
++ ep0start(dev, UDCCS0_IPR, "OUT");
++ if (length == 0 || ((UDCCS0 & UDCCS0_RNE) != 0
++ && read_ep0_fifo(ep, req))) {
++ ep0_idle(dev);
++ done(ep, req, 0);
++ req = 0;
++ }
++ break;
++
++ default:
++ DMSG("ep0 i/o, odd state %d\n", dev->ep0state);
++ local_irq_restore (flags);
++ return -EL2HLT;
++ }
++#ifdef USE_DMA
++ /* either start dma or prime pio pump */
++ } else if (ep->dma >= 0) {
++ kick_dma(ep, req);
++#endif
++ /* can the FIFO can satisfy the request immediately? */
++ } else if ((ep->bEndpointAddress & USB_DIR_IN) != 0
++ && (*ep->reg_udccs & UDCCS_BI_TFS) != 0
++ && write_fifo(ep, req)) {
++ req = 0;
++ } else if ((*ep->reg_udccs & UDCCS_BO_RFS) != 0
++ && read_fifo(ep, req)) {
++ req = 0;
++ }
++
++ if (likely (req && ep->desc) && ep->dma < 0)
++ pio_irq_enable(ep->bEndpointAddress);
++ }
++
++ /* pio or dma irq handler advances the queue. */
++ if (likely (req != 0))
++ list_add_tail(&req->queue, &ep->queue);
++ local_irq_restore(flags);
++
++ return 0;
++}
++
++
++/*
++ * nuke - dequeue ALL requests
++ */
++static void nuke(struct pxa2xx_ep *ep, int status)
++{
++ struct pxa2xx_request *req;
++
++ /* called with irqs blocked */
++#ifdef USE_DMA
++ if (ep->dma >= 0 && !ep->stopped)
++ cancel_dma(ep);
++#endif
++ while (!list_empty(&ep->queue)) {
++ req = list_entry(ep->queue.next,
++ struct pxa2xx_request,
++ queue);
++ done(ep, req, status);
++ }
++ if (ep->desc)
++ pio_irq_disable (ep->bEndpointAddress);
++}
++
++
++/* dequeue JUST ONE request */
++static int pxa2xx_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
++{
++ struct pxa2xx_ep *ep;
++ struct pxa2xx_request *req;
++ unsigned long flags;
++
++ ep = container_of(_ep, struct pxa2xx_ep, ep);
++ if (!_ep || ep->ep.name == ep0name)
++ return -EINVAL;
++
++ local_irq_save(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) {
++ local_irq_restore(flags);
++ return -EINVAL;
++ }
++
++#ifdef USE_DMA
++ if (ep->dma >= 0 && ep->queue.next == &req->queue && !ep->stopped) {
++ cancel_dma(ep);
++ done(ep, req, -ECONNRESET);
++ /* restart i/o */
++ if (!list_empty(&ep->queue)) {
++ req = list_entry(ep->queue.next,
++ struct pxa2xx_request, queue);
++ kick_dma(ep, req);
++ }
++ } else
++#endif
++ done(ep, req, -ECONNRESET);
++
++ local_irq_restore(flags);
++ return 0;
++}
++
++/*-------------------------------------------------------------------------*/
++
++static int pxa2xx_ep_set_halt(struct usb_ep *_ep, int value)
++{
++ struct pxa2xx_ep *ep;
++ unsigned long flags;
++
++ ep = container_of(_ep, struct pxa2xx_ep, ep);
++ if (unlikely (!_ep
++ || (!ep->desc && ep->ep.name != ep0name))
++ || ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
++ DMSG("%s, bad ep\n", __FUNCTION__);
++ return -EINVAL;
++ }
++ if (value == 0) {
++ /* this path (reset toggle+halt) is needed to implement
++ * SET_INTERFACE on normal hardware. but it can't be
++ * done from software on the PXA UDC, and the hardware
++ * forgets to do it as part of SET_INTERFACE automagic.
++ */
++ DMSG("only host can clear %s halt\n", _ep->name);
++ return -EROFS;
++ }
++
++ local_irq_save(flags);
++
++ if ((ep->bEndpointAddress & USB_DIR_IN) != 0
++ && ((*ep->reg_udccs & UDCCS_BI_TFS) == 0
++ || !list_empty(&ep->queue))) {
++ local_irq_restore(flags);
++ return -EAGAIN;
++ }
++
++ /* FST bit is the same for control, bulk in, bulk out, interrupt in */
++ *ep->reg_udccs = UDCCS_BI_FST|UDCCS_BI_FTF;
++
++ /* ep0 needs special care */
++ if (!ep->desc) {
++ start_watchdog(ep->dev);
++ ep->dev->req_pending = 0;
++ ep->dev->ep0state = EP0_STALL;
++ LED_EP0_OFF;
++
++ /* and bulk/intr endpoints like dropping stalls too */
++ } else {
++ unsigned i;
++ for (i = 0; i < 1000; i += 20) {
++ if (*ep->reg_udccs & UDCCS_BI_SST)
++ break;
++ udelay(20);
++ }
++ }
++ local_irq_restore(flags);
++
++ DBG(DBG_VERBOSE, "%s halt\n", _ep->name);
++ return 0;
++}
++
++static int pxa2xx_ep_fifo_status(struct usb_ep *_ep)
++{
++ struct pxa2xx_ep *ep;
++
++ ep = container_of(_ep, struct pxa2xx_ep, ep);
++ if (!_ep) {
++ DMSG("%s, bad ep\n", __FUNCTION__);
++ return -ENODEV;
++ }
++ /* pxa can't report unclaimed bytes from IN fifos */
++ if ((ep->bEndpointAddress & USB_DIR_IN) != 0)
++ return -EOPNOTSUPP;
++ if (ep->dev->gadget.speed == USB_SPEED_UNKNOWN
++ || (*ep->reg_udccs & UDCCS_BO_RFS) == 0)
++ return 0;
++ else
++ return (*ep->reg_ubcr & 0xfff) + 1;
++}
++
++static void pxa2xx_ep_fifo_flush(struct usb_ep *_ep)
++{
++ struct pxa2xx_ep *ep;
++
++ ep = container_of(_ep, struct pxa2xx_ep, ep);
++ if (!_ep || ep->ep.name == ep0name || !list_empty(&ep->queue)) {
++ DMSG("%s, bad ep\n", __FUNCTION__);
++ return;
++ }
++
++ /* toggle and halt bits stay unchanged */
++
++ /* for OUT, just read and discard the FIFO contents. */
++ if ((ep->bEndpointAddress & USB_DIR_IN) == 0) {
++ while (((*ep->reg_udccs) & UDCCS_BO_RNE) != 0)
++ (void) *ep->reg_uddr;
++ return;
++ }
++
++ /* most IN status is the same, but ISO can't stall */
++ *ep->reg_udccs = UDCCS_BI_TPC|UDCCS_BI_FTF|UDCCS_BI_TUR
++ | (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC)
++ ? 0 : UDCCS_BI_SST;
++}
++
++
++static struct usb_ep_ops pxa2xx_ep_ops = {
++ .enable = pxa2xx_ep_enable,
++ .disable = pxa2xx_ep_disable,
++
++ .alloc_request = pxa2xx_ep_alloc_request,
++ .free_request = pxa2xx_ep_free_request,
++
++ .alloc_buffer = pxa2xx_ep_alloc_buffer,
++ .free_buffer = pxa2xx_ep_free_buffer,
++
++ .queue = pxa2xx_ep_queue,
++ .dequeue = pxa2xx_ep_dequeue,
++
++ .set_halt = pxa2xx_ep_set_halt,
++ .fifo_status = pxa2xx_ep_fifo_status,
++ .fifo_flush = pxa2xx_ep_fifo_flush,
++};
++
++
++/* ---------------------------------------------------------------------------
++ * device-scoped parts of the api to the usb controller hardware
++ * ---------------------------------------------------------------------------
++ */
++
++static int pxa2xx_udc_get_frame(struct usb_gadget *_gadget)
++{
++ return ((UFNRH & 0x07) << 8) | (UFNRL & 0xff);
++}
++
++static int pxa2xx_udc_wakeup(struct usb_gadget *_gadget)
++{
++ /* host may not have enabled remote wakeup */
++ if ((UDCCS0 & UDCCS0_DRWF) == 0)
++ return -EHOSTUNREACH;
++ udc_set_mask_UDCCR(UDCCR_RSM);
++ return 0;
++}
++
++static const struct usb_gadget_ops pxa2xx_udc_ops = {
++ .get_frame = pxa2xx_udc_get_frame,
++ .wakeup = pxa2xx_udc_wakeup,
++ // current versions must always be self-powered
++};
++
++
++/*-------------------------------------------------------------------------*/
++
++#ifdef UDC_PROC_FILE
++
++static const char proc_node_name [] = "driver/udc";
++
++static int
++udc_proc_read(char *page, char **start, off_t off, int count,
++ int *eof, void *_dev)
++{
++ char *buf = page;
++ struct pxa2xx_udc *dev = _dev;
++ char *next = buf;
++ unsigned size = count;
++ unsigned long flags;
++ int i, t;
++ u32 tmp;
++
++ if (off != 0)
++ return 0;
++
++ local_irq_save(flags);
++
++ /* basic device status */
++ t = snprintf(next, size, DRIVER_DESC "\n"
++ "%s version: %s\nGadget driver: %s\nHost %s\n\n",
++ driver_name, DRIVER_VERSION SIZE_STR DMASTR,
++ dev->driver ? dev->driver->driver.name : "(none)",
++ is_usb_connected() ? "full speed" : "disconnected");
++ size -= t;
++ next += t;
++
++ /* registers for device and ep0 */
++ t = snprintf(next, size,
++ "uicr %02X.%02X, usir %02X.%02x, ufnr %02X.%02X\n",
++ UICR1, UICR0, USIR1, USIR0, UFNRH, UFNRL);
++ size -= t;
++ next += t;
++
++ tmp = UDCCR;
++ t = snprintf(next, size,
++ "udccr %02X =%s%s%s%s%s%s%s%s\n", tmp,
++ (tmp & UDCCR_REM) ? " rem" : "",
++ (tmp & UDCCR_RSTIR) ? " rstir" : "",
++ (tmp & UDCCR_SRM) ? " srm" : "",
++ (tmp & UDCCR_SUSIR) ? " susir" : "",
++ (tmp & UDCCR_RESIR) ? " resir" : "",
++ (tmp & UDCCR_RSM) ? " rsm" : "",
++ (tmp & UDCCR_UDA) ? " uda" : "",
++ (tmp & UDCCR_UDE) ? " ude" : "");
++ size -= t;
++ next += t;
++
++ tmp = UDCCS0;
++ t = snprintf(next, size,
++ "udccs0 %02X =%s%s%s%s%s%s%s%s\n", tmp,
++ (tmp & UDCCS0_SA) ? " sa" : "",
++ (tmp & UDCCS0_RNE) ? " rne" : "",
++ (tmp & UDCCS0_FST) ? " fst" : "",
++ (tmp & UDCCS0_SST) ? " sst" : "",
++ (tmp & UDCCS0_DRWF) ? " dwrf" : "",
++ (tmp & UDCCS0_FTF) ? " ftf" : "",
++ (tmp & UDCCS0_IPR) ? " ipr" : "",
++ (tmp & UDCCS0_OPR) ? " opr" : "");
++ size -= t;
++ next += t;
++
++ if (dev->has_cfr) {
++ tmp = UDCCFR;
++ t = snprintf(next, size,
++ "udccfr %02X =%s%s\n", tmp,
++ (tmp & UDCCFR_AREN) ? " aren" : "",
++ (tmp & UDCCFR_ACM) ? " acm" : "");
++ size -= t;
++ next += t;
++ }
++
++ if (!is_usb_connected() || !dev->driver)
++ goto done;
++
++ t = snprintf(next, size, "ep0 IN %lu/%lu, OUT %lu/%lu\nirqs %lu\n\n",
++ dev->stats.write.bytes, dev->stats.write.ops,
++ dev->stats.read.bytes, dev->stats.read.ops,
++ dev->stats.irqs);
++ size -= t;
++ next += t;
++
++ /* dump endpoint queues */
++ for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
++ struct pxa2xx_ep *ep = &dev->ep [i];
++ struct pxa2xx_request *req;
++ int t;
++
++ if (i != 0) {
++ const struct usb_endpoint_descriptor *d;
++
++ d = ep->desc;
++ if (!d)
++ continue;
++ tmp = *dev->ep [i].reg_udccs;
++ t = snprintf(next, size,
++ "%s max %d %s udccs %02x irqs %lu/%lu\n",
++ ep->ep.name, le16_to_cpu (d->wMaxPacketSize),
++ (ep->dma >= 0) ? "dma" : "pio", tmp,
++ ep->pio_irqs, ep->dma_irqs);
++ /* TODO translate all five groups of udccs bits! */
++
++ } else /* ep0 should only have one transfer queued */
++ t = snprintf(next, size, "ep0 max 16 pio irqs %lu\n",
++ ep->pio_irqs);
++ 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) {
++#ifdef USE_DMA
++ if (ep->dma >= 0 && req->queue.prev == &ep->queue)
++ t = snprintf(next, size,
++ "\treq %p len %d/%d "
++ "buf %p (dma%d dcmd %08x)\n",
++ &req->req, req->req.actual,
++ req->req.length, req->req.buf,
++ ep->dma, DCMD(ep->dma)
++ // low 13 bits == bytes-to-go
++ );
++ else
++#endif
++ 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:
++ local_irq_restore(flags);
++ *eof = 1;
++ return count - size;
++}
++
++#define create_proc_files() \
++ create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev)
++#define remove_proc_files() \
++ remove_proc_entry(proc_node_name, NULL)
++
++#else /* !UDC_PROC_FILE */
++#define create_proc_files() do {} while (0)
++#define remove_proc_files() do {} while (0)
++
++#endif /* UDC_PROC_FILE */
++
++/*-------------------------------------------------------------------------*/
++
++/*
++ * udc_disable - disable USB device controller
++ */
++static void udc_disable(struct pxa2xx_udc *dev)
++{
++ /* block all irqs */
++ udc_set_mask_UDCCR(UDCCR_SRM|UDCCR_REM);
++ UICR0 = UICR1 = 0xff;
++ UFNRH = UFNRH_SIM;
++
++ /* if hardware supports it, disconnect from usb */
++ make_usb_disappear();
++
++ udc_clear_mask_UDCCR(UDCCR_UDE);
++
++#ifdef CONFIG_ARCH_PXA
++ /* Disable clock for USB device */
++ CKEN &= ~CKEN11_USB;
++#endif
++
++ ep0_idle (dev);
++ dev->gadget.speed = USB_SPEED_UNKNOWN;
++ LED_CONNECTED_OFF;
++}
++
++
++/*
++ * udc_reinit - initialize software state
++ */
++static void udc_reinit(struct pxa2xx_udc *dev)
++{
++ u32 i;
++
++ /* device/ep0 records init */
++ INIT_LIST_HEAD (&dev->gadget.ep_list);
++ INIT_LIST_HEAD (&dev->gadget.ep0->ep_list);
++ dev->ep0state = EP0_IDLE;
++
++ /* basic endpoint records init */
++ for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
++ struct pxa2xx_ep *ep = &dev->ep[i];
++
++ if (i != 0)
++ list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
++
++ ep->desc = 0;
++ ep->stopped = 0;
++ INIT_LIST_HEAD (&ep->queue);
++ ep->pio_irqs = ep->dma_irqs = 0;
++ }
++
++ /* the rest was statically initialized, and is read-only */
++}
++
++/* until it's enabled, this UDC should be completely invisible
++ * to any USB host.
++ */
++static void udc_enable (struct pxa2xx_udc *dev)
++{
++ udc_clear_mask_UDCCR(UDCCR_UDE);
++
++#ifdef CONFIG_ARCH_PXA
++ /* Enable clock for USB device */
++ CKEN |= CKEN11_USB;
++#endif
++
++ /* try to clear these bits before we enable the udc */
++ udc_ack_int_UDCCR(UDCCR_SUSIR|/*UDCCR_RSTIR|*/UDCCR_RESIR);
++
++ ep0_idle(dev);
++ dev->gadget.speed = USB_SPEED_UNKNOWN;
++ dev->stats.irqs = 0;
++
++ /*
++ * sequence taken from chapter 12.5.10, PXA250 AppProcDevManual:
++ * - enable UDC
++ * - if RESET is already in progress, ack interrupt
++ * - unmask reset interrupt
++ */
++ udc_set_mask_UDCCR(UDCCR_UDE);
++ if (!(UDCCR & UDCCR_UDA))
++ udc_ack_int_UDCCR(UDCCR_RSTIR);
++
++ if (dev->has_cfr /* UDC_RES2 is defined */) {
++ /* pxa255 (a0+) can avoid a set_config race that could
++ * prevent gadget drivers from configuring correctly
++ */
++ UDCCFR = UDCCFR_ACM;
++ } else {
++ /* "USB test mode" for pxa250 errata 40-42 (stepping a0, a1)
++ * which could result in missing packets and interrupts.
++ * supposedly one bit per endpoint, controlling whether it
++ * double buffers or not; ACM/AREN bits fit into the holes.
++ * zero bits (like USIR0_IRx) disable double buffering.
++ */
++ UDC_RES1 = 0x00;
++ UDC_RES2 = 0x00;
++ }
++
++#ifdef DISABLE_TEST_MODE
++ /* "test mode" seems to have become the default in later chip
++ * revs, preventing double buffering (and invalidating docs).
++ * this EXPERIMENT enables it for bulk endpoints by tweaking
++ * undefined/reserved register bits (that other drivers clear).
++ * Belcarra code comments noted this usage.
++ */
++ if (fifo_mode & 1) { /* IN endpoints */
++ UDC_RES1 |= USIR0_IR1|USIR0_IR6;
++ UDC_RES2 |= USIR1_IR11;
++ }
++ if (fifo_mode & 2) { /* OUT endpoints */
++ UDC_RES1 |= USIR0_IR2|USIR0_IR7;
++ UDC_RES2 |= USIR1_IR12;
++ }
++#endif
++
++ /* caller must be able to sleep in order to cope
++ * with startup transients.
++ */
++ schedule_timeout(HZ/10);
++
++ /* enable suspend/resume and reset irqs */
++ udc_clear_mask_UDCCR(UDCCR_SRM | UDCCR_REM);
++
++ /* enable ep0 irqs */
++ UICR0 &= ~UICR0_IM0;
++
++ /* if hardware supports it, connect to usb and wait for host */
++ let_usb_appear();
++}
++
++
++/* 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 pxa2xx_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;
++
++ /* first hook up the driver ... */
++ dev->driver = driver;
++
++ retval = driver->bind(&dev->gadget);
++ if (retval) {
++ DMSG("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.
++ * NOTE: this shouldn't power up until later.
++ */
++ DMSG("registered gadget driver '%s'\n", driver->driver.name);
++ udc_enable(dev);
++ dump_state(dev);
++ return 0;
++}
++EXPORT_SYMBOL(usb_gadget_register_driver);
++
++static void
++stop_activity(struct pxa2xx_udc *dev, struct usb_gadget_driver *driver)
++{
++ int i;
++
++ /* don't disconnect drivers more than once */
++ if (dev->gadget.speed == USB_SPEED_UNKNOWN)
++ driver = 0;
++ dev->gadget.speed = USB_SPEED_UNKNOWN;
++
++ /* prevent new request submissions, kill any outstanding requests */
++ for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
++ struct pxa2xx_ep *ep = &dev->ep[i];
++
++ ep->stopped = 1;
++ nuke(ep, -ESHUTDOWN);
++ }
++ del_timer_sync(&dev->timer);
++
++ /* report disconnect; the driver is already quiesced */
++ LED_CONNECTED_OFF;
++ if (driver)
++ driver->disconnect(&dev->gadget);
++
++ /* re-init driver-visible data structures */
++ udc_reinit(dev);
++}
++
++int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
++{
++ struct pxa2xx_udc *dev = the_controller;
++
++ if (!dev)
++ return -ENODEV;
++ if (!driver || driver != dev->driver)
++ return -EINVAL;
++
++ local_irq_disable();
++ udc_disable(dev);
++ stop_activity(dev, driver);
++ local_irq_enable();
++
++ driver->unbind(&dev->gadget);
++ dev->driver = 0;
++
++ DMSG("unregistered gadget driver '%s'\n", driver->driver.name);
++ dump_state(dev);
++ return 0;
++}
++EXPORT_SYMBOL(usb_gadget_unregister_driver);
++
++
++/*-------------------------------------------------------------------------*/
++
++#ifdef CONFIG_ARCH_LUBBOCK
++#ifdef LUBBOCK_USB_DISC_IRQ
++
++/* Lubbock can report connect or disconnect irqs. Likely more hardware
++ * could support it as a timer callback.
++ *
++ * FIXME for better power management, keep the hardware powered down
++ * until a host is powering the link. means scheduling work later
++ * in some task that can udc_enable().
++ */
++
++#define enable_disconnect_irq() \
++ if (machine_is_lubbock()) { enable_irq(LUBBOCK_USB_DISC_IRQ); }
++#define disable_disconnect_irq() \
++ if (machine_is_lubbock()) { disable_irq(LUBBOCK_USB_DISC_IRQ); }
++
++static irqreturn_t
++usb_connection_irq(int irq, void *_dev, struct pt_regs *r)
++{
++ struct pxa2xx_udc *dev = _dev;
++
++ dev->stats.irqs++;
++ HEX_DISPLAY(dev->stats.irqs);
++
++ if (!is_usb_connected()) {
++ LED_CONNECTED_OFF;
++ disable_disconnect_irq();
++ /* report disconnect just once */
++ if (dev->gadget.speed != USB_SPEED_UNKNOWN) {
++ DMSG("disconnect %s\n",
++ dev->driver ? dev->driver->driver.name : 0);
++ stop_activity(dev, dev->driver);
++
++ // udc_disable (dev);
++ // no more udc irqs
++ // maybe "ACTION=disconnect /sbin/hotplug gadget".
++ }
++ } else if (dev->gadget.speed == USB_SPEED_UNKNOWN) {
++ LED_CONNECTED_ON;
++
++ DMSG("?? connect irq ??\n");
++
++ // if there's no driver bound, ignore; else
++ // udc_enable (dev);
++ // UDC irqs drive the rest.
++ // maybe "ACTION=connect /sbin/hotplug gadget".
++ }
++ return IRQ_HANDLED;
++}
++
++#endif
++#endif
++
++#ifndef enable_disconnect_irq
++#warning USB disconnect() is not yet reported.
++#define enable_disconnect_irq() do {} while (0)
++#define disable_disconnect_irq() do {} while (0)
++#endif
++
++
++/*-------------------------------------------------------------------------*/
++
++static inline void clear_ep_state (struct pxa2xx_udc *dev)
++{
++ unsigned i;
++
++ /* hardware SET_{CONFIGURATION,INTERFACE} automagic resets endpoint
++ * fifos, and pending transactions mustn't be continued in any case.
++ */
++ for (i = 1; i < PXA_UDC_NUM_ENDPOINTS; i++)
++ nuke(&dev->ep[i], -ECONNABORTED);
++}
++
++static void udc_watchdog(unsigned long _dev)
++{
++ struct pxa2xx_udc *dev = (void *)_dev;
++
++ local_irq_disable();
++ if (dev->ep0state == EP0_STALL
++ && (UDCCS0 & UDCCS0_FST) == 0
++ && (UDCCS0 & UDCCS0_SST) == 0) {
++ UDCCS0 = UDCCS0_FST|UDCCS0_FTF;
++ DBG(DBG_VERBOSE, "ep0 re-stall\n");
++ start_watchdog(dev);
++ }
++ local_irq_enable();
++}
++
++static void handle_ep0 (struct pxa2xx_udc *dev)
++{
++ u32 udccs0 = UDCCS0;
++ struct pxa2xx_ep *ep = &dev->ep [0];
++ struct pxa2xx_request *req;
++ union {
++ struct usb_ctrlrequest r;
++ u8 raw [8];
++ u32 word [2];
++ } u;
++
++ if (list_empty(&ep->queue))
++ req = 0;
++ else
++ req = list_entry(ep->queue.next, struct pxa2xx_request, queue);
++
++ /* clear stall status */
++ if (udccs0 & UDCCS0_SST) {
++ nuke(ep, -EPIPE);
++ UDCCS0 = UDCCS0_SST;
++ del_timer(&dev->timer);
++ ep0_idle(dev);
++ }
++
++ /* previous request unfinished? non-error iff back-to-back ... */
++ if ((udccs0 & UDCCS0_SA) != 0 && dev->ep0state != EP0_IDLE) {
++ nuke(ep, 0);
++ del_timer(&dev->timer);
++ ep0_idle(dev);
++ }
++
++ switch (dev->ep0state) {
++ case EP0_IDLE:
++ /* late-breaking status? */
++ udccs0 = UDCCS0;
++
++ /* start control request? */
++ if (likely((udccs0 & (UDCCS0_OPR|UDCCS0_SA|UDCCS0_RNE))
++ == (UDCCS0_OPR|UDCCS0_SA|UDCCS0_RNE))) {
++ int i;
++
++ nuke (ep, -EPROTO);
++
++ /* read SETUP packet */
++ for (i = 0; i < 8; i++) {
++ if (unlikely(!(UDCCS0 & UDCCS0_RNE))) {
++bad_setup:
++ DMSG("SETUP %d!\n", i);
++ goto stall;
++ }
++ u.raw [i] = (u8) UDDR0;
++ }
++ if (unlikely((UDCCS0 & UDCCS0_RNE) != 0))
++ goto bad_setup;
++
++got_setup:
++ le16_to_cpus (&u.r.wValue);
++ le16_to_cpus (&u.r.wIndex);
++ le16_to_cpus (&u.r.wLength);
++
++ LED_EP0_ON;
++ DBG(DBG_VERBOSE, "SETUP %02x.%02x v%04x i%04x l%04x\n",
++ u.r.bRequestType, u.r.bRequest,
++ u.r.wValue, u.r.wIndex, u.r.wLength);
++
++ /* cope with automagic for some standard requests. */
++ dev->req_std = (u.r.bRequestType & USB_TYPE_MASK)
++ == USB_TYPE_STANDARD;
++ dev->req_config = 0;
++ dev->req_pending = 1;
++ switch (u.r.bRequest) {
++ /* hardware restricts gadget drivers here! */
++ case USB_REQ_SET_CONFIGURATION:
++ if (u.r.bRequestType == USB_RECIP_DEVICE) {
++ /* reflect hardware's automagic
++ * up to the gadget driver.
++ */
++config_change:
++ dev->req_config = 1;
++ clear_ep_state(dev);
++ /* if !has_cfr, there's no synch
++ * else use AREN (later) not SA|OPR
++ * USIR0_IR0 acts edge sensitive
++ */
++ }
++ break;
++ /* ... and here, even more ... */
++ case USB_REQ_SET_INTERFACE:
++ if (u.r.bRequestType == USB_RECIP_INTERFACE) {
++ /* udc hardware is broken by design:
++ * - altsetting may only be zero;
++ * - hw resets all interfaces' eps;
++ * - ep reset doesn't include halt(?).
++ */
++ DMSG("broken set_interface (%d/%d)\n",
++ u.r.wIndex, u.r.wValue);
++ goto config_change;
++ }
++ break;
++ /* hardware was supposed to hide this */
++ case USB_REQ_SET_ADDRESS:
++ if (u.r.bRequestType == USB_RECIP_DEVICE) {
++ ep0start(dev, 0, "address");
++ return;
++ }
++ break;
++ }
++
++ if (u.r.bRequestType & USB_DIR_IN)
++ dev->ep0state = EP0_IN_DATA_PHASE;
++ else
++ dev->ep0state = EP0_OUT_DATA_PHASE;
++
++ i = dev->driver->setup(&dev->gadget, &u.r);
++ if (i < 0) {
++ /* hardware automagic preventing STALL... */
++ if (dev->req_config) {
++ /* hardware sometimes neglects to tell
++ * tell us about config change events,
++ * so later ones may fail...
++ */
++ WARN("config change %02x fail %d?\n",
++ u.r.bRequest, i);
++ return;
++ /* TODO experiment: if has_cfr,
++ * hardware didn't ACK; maybe we
++ * could actually STALL!
++ */
++ }
++ DBG(DBG_VERBOSE, "protocol STALL, "
++ "%02x err %d\n", UDCCS0, i);
++stall:
++ /* the watchdog timer helps deal with cases
++ * where udc seems to clear FST wrongly, and
++ * then NAKs instead of STALLing.
++ */
++ ep0start(dev, UDCCS0_FST|UDCCS0_FTF, "stall");
++ start_watchdog(dev);
++ dev->ep0state = EP0_STALL;
++ LED_EP0_OFF;
++
++ /* deferred i/o == no response yet */
++ } else if (dev->req_pending) {
++ if (likely(dev->ep0state == EP0_IN_DATA_PHASE
++ || dev->req_std || u.r.wLength))
++ ep0start(dev, 0, "defer");
++ else
++ ep0start(dev, UDCCS0_IPR, "defer/IPR");
++ }
++
++ /* expect at least one data or status stage irq */
++ return;
++
++ } else if (likely((udccs0 & (UDCCS0_OPR|UDCCS0_SA))
++ == (UDCCS0_OPR|UDCCS0_SA))) {
++ unsigned i;
++
++ /* pxa210/250 erratum 131 for B0/B1 says RNE lies.
++ * still observed on a pxa255 a0.
++ */
++ DBG(DBG_VERBOSE, "e131\n");
++ nuke(ep, -EPROTO);
++
++ /* read SETUP data, but don't trust it too much */
++ for (i = 0; i < 8; i++)
++ u.raw [i] = (u8) UDDR0;
++ if ((u.r.bRequestType & USB_RECIP_MASK)
++ > USB_RECIP_OTHER)
++ goto stall;
++ if (u.word [0] == 0 && u.word [1] == 0)
++ goto stall;
++ goto got_setup;
++ } else {
++ /* some random early IRQ:
++ * - we acked FST
++ * - IPR cleared
++ * - OPR got set, without SA (likely status stage)
++ */
++ UDCCS0 = udccs0 & (UDCCS0_SA|UDCCS0_OPR);
++ }
++ break;
++ case EP0_IN_DATA_PHASE: /* GET_DESCRIPTOR etc */
++ if (udccs0 & UDCCS0_OPR) {
++ UDCCS0 = UDCCS0_OPR|UDCCS0_FTF;
++ DBG(DBG_VERBOSE, "ep0in premature status\n");
++ if (req)
++ done(ep, req, 0);
++ ep0_idle(dev);
++ } else /* irq was IPR clearing */ {
++ if (req) {
++ /* this IN packet might finish the request */
++ (void) write_ep0_fifo(ep, req);
++ } /* else IN token before response was written */
++ }
++ break;
++ case EP0_OUT_DATA_PHASE: /* SET_DESCRIPTOR etc */
++ if (udccs0 & UDCCS0_OPR) {
++ if (req) {
++ /* this OUT packet might finish the request */
++ if (read_ep0_fifo(ep, req))
++ done(ep, req, 0);
++ /* else more OUT packets expected */
++ } /* else OUT token before read was issued */
++ } else /* irq was IPR clearing */ {
++ DBG(DBG_VERBOSE, "ep0out premature status\n");
++ if (req)
++ done(ep, req, 0);
++ ep0_idle(dev);
++ }
++ break;
++ case EP0_END_XFER:
++ if (req)
++ done(ep, req, 0);
++ /* ack control-IN status (maybe in-zlp was skipped)
++ * also appears after some config change events.
++ */
++ if (udccs0 & UDCCS0_OPR)
++ UDCCS0 = UDCCS0_OPR;
++ ep0_idle(dev);
++ break;
++ case EP0_STALL:
++ UDCCS0 = UDCCS0_FST;
++ break;
++ }
++ USIR0 = USIR0_IR0;
++}
++
++static void handle_ep(struct pxa2xx_ep *ep)
++{
++ struct pxa2xx_request *req;
++ int is_in = ep->bEndpointAddress & USB_DIR_IN;
++ int completed;
++ u32 udccs, tmp;
++
++ do {
++ completed = 0;
++ if (likely (!list_empty(&ep->queue)))
++ req = list_entry(ep->queue.next,
++ struct pxa2xx_request, queue);
++ else
++ req = 0;
++
++ // TODO check FST handling
++
++ udccs = *ep->reg_udccs;
++ if (unlikely(is_in)) { /* irq from TPC, SST, or (ISO) TUR */
++ tmp = UDCCS_BI_TUR;
++ if (likely(ep->bmAttributes == USB_ENDPOINT_XFER_BULK))
++ tmp |= UDCCS_BI_SST;
++ tmp &= udccs;
++ if (likely (tmp))
++ *ep->reg_udccs = tmp;
++ if (req && likely ((udccs & UDCCS_BI_TFS) != 0))
++ completed = write_fifo(ep, req);
++
++ } else { /* irq from RPC (or for ISO, ROF) */
++ if (likely(ep->bmAttributes == USB_ENDPOINT_XFER_BULK))
++ tmp = UDCCS_BO_SST | UDCCS_BO_DME;
++ else
++ tmp = UDCCS_IO_ROF | UDCCS_IO_DME;
++ tmp &= udccs;
++ if (likely(tmp))
++ *ep->reg_udccs = tmp;
++
++ /* fifos can hold packets, ready for reading... */
++ if (likely(req != 0)) {
++#ifdef USE_OUT_DMA
++// TODO didn't yet debug out-dma. this approach assumes
++// the worst about short packets and RPC; it might be better.
++
++ if (likely(ep->dma >= 0)) {
++ if (!(udccs & UDCCS_BO_RSP)) {
++ *ep->reg_udccs = UDCCS_BO_RPC;
++ ep->dma_irqs++;
++ return;
++ }
++ }
++#endif
++ completed = read_fifo(ep, req);
++ } else
++ pio_irq_disable (ep->bEndpointAddress);
++ }
++ ep->pio_irqs++;
++ } while (completed);
++}
++
++/*
++ * pxa2xx_udc_irq - interrupt handler
++ *
++ * avoid delays in ep0 processing. the control handshaking isn't always
++ * under software control (pxa250c0 and the pxa255 are better), and delays
++ * could cause usb protocol errors.
++ */
++static irqreturn_t
++pxa2xx_udc_irq(int irq, void *_dev, struct pt_regs *r)
++{
++ struct pxa2xx_udc *dev = _dev;
++ int handled;
++
++ dev->stats.irqs++;
++ HEX_DISPLAY(dev->stats.irqs);
++ do {
++ u32 udccr = UDCCR;
++
++ handled = 0;
++
++ /* SUSpend Interrupt Request */
++ if (unlikely(udccr & UDCCR_SUSIR)) {
++ udc_ack_int_UDCCR(UDCCR_SUSIR);
++ handled = 1;
++ DBG(DBG_VERBOSE, "USB suspend%s\n", is_usb_connected()
++ ? "" : "+disconnect");
++
++ if (!is_usb_connected())
++ stop_activity(dev, dev->driver);
++ else if (dev->gadget.speed != USB_SPEED_UNKNOWN
++ && dev->driver
++ && dev->driver->suspend)
++ dev->driver->suspend(&dev->gadget);
++ ep0_idle (dev);
++ }
++
++ /* RESume Interrupt Request */
++ if (unlikely(udccr & UDCCR_RESIR)) {
++ udc_ack_int_UDCCR(UDCCR_RESIR);
++ handled = 1;
++ DBG(DBG_VERBOSE, "USB resume\n");
++
++ if (dev->gadget.speed != USB_SPEED_UNKNOWN
++ && dev->driver
++ && dev->driver->resume
++ && is_usb_connected())
++ dev->driver->resume(&dev->gadget);
++ }
++
++ /* ReSeT Interrupt Request - USB reset */
++ if (unlikely(udccr & UDCCR_RSTIR)) {
++ udc_ack_int_UDCCR(UDCCR_RSTIR);
++ handled = 1;
++
++ if ((UDCCR & UDCCR_UDA) == 0) {
++ DBG(DBG_VERBOSE, "USB reset start\n");
++ if (dev->gadget.speed != USB_SPEED_UNKNOWN)
++ disable_disconnect_irq();
++
++ /* reset driver and endpoints,
++ * in case that's not yet done
++ */
++ stop_activity (dev, dev->driver);
++
++ } else {
++ INFO("USB reset\n");
++ dev->gadget.speed = USB_SPEED_FULL;
++ LED_CONNECTED_ON;
++ memset(&dev->stats, 0, sizeof dev->stats);
++ /* driver and endpoints are still reset */
++ enable_disconnect_irq();
++ }
++
++ } else {
++ u32 usir0 = USIR0 & ~UICR0;
++ u32 usir1 = USIR1 & ~UICR1;
++ int i;
++
++ if (unlikely (!usir0 && !usir1))
++ continue;
++
++ DBG(DBG_VERY_NOISY, "irq %02x.%02x\n", usir1, usir0);
++
++ /* control traffic */
++ if (usir0 & USIR0_IR0) {
++ dev->ep[0].pio_irqs++;
++ handle_ep0(dev);
++ handled = 1;
++ }
++
++ /* endpoint data transfers */
++ for (i = 0; i < 8; i++) {
++ u32 tmp = 1 << i;
++
++ if (i && (usir0 & tmp)) {
++ handle_ep(&dev->ep[i]);
++ USIR0 |= tmp;
++ handled = 1;
++ }
++ if (usir1 & tmp) {
++ handle_ep(&dev->ep[i+8]);
++ USIR1 |= tmp;
++ handled = 1;
++ }
++ }
++ }
++
++ /* we could also ask for 1 msec SOF (SIR) interrupts */
++
++ } while (handled);
++ return IRQ_HANDLED;
++}
++
++/*-------------------------------------------------------------------------*/
++
++/*
++ * cleanup - free resources allocated during init
++ */
++static void /*__exit and */ __init cleanup(void)
++{
++ struct pxa2xx_udc *dev = the_controller;
++
++ if (!dev)
++ return;
++
++ udc_disable(dev);
++ remove_proc_files();
++ usb_gadget_unregister_driver(dev->driver);
++ if (dev->got_irq) {
++ free_irq(IRQ_USB, dev);
++ dev->got_irq = 0;
++ }
++#ifdef LUBBOCK_USB_DISC_IRQ
++ if (dev->got_disc) {
++ free_irq(LUBBOCK_USB_DISC_IRQ, dev);
++ dev->got_disc = 0;
++ }
++#endif
++ the_controller = 0;
++ release_mem_region(REGISTER_FIRST, REGISTER_LENGTH);
++}
++module_exit (cleanup);
++
++/* this uses load-time allocation and initialization (instead of
++ * doing it at run-time) to save code, eliminate fault paths, and
++ * be more obviously correct.
++ */
++static struct pxa2xx_udc memory = {
++ .gadget = {
++ .ops = &pxa2xx_udc_ops,
++ .ep0 = &memory.ep[0].ep,
++ .name = driver_name,
++ .dev = {
++ .bus_id = "gadget",
++ },
++ },
++
++ /* control endpoint */
++ .ep[0] = {
++ .ep = {
++ .name = ep0name,
++ .ops = &pxa2xx_ep_ops,
++ .maxpacket = EP0_FIFO_SIZE,
++ },
++ .dev = &memory,
++ .reg_udccs = &UDCCS0,
++ .reg_uddr = &UDDR0,
++ },
++
++ /* first group of endpoints */
++ .ep[1] = {
++ .ep = {
++ .name = "ep1in-bulk",
++ .ops = &pxa2xx_ep_ops,
++ .maxpacket = BULK_FIFO_SIZE,
++ },
++ .dev = &memory,
++ .fifo_size = BULK_FIFO_SIZE,
++ .bEndpointAddress = USB_DIR_IN | 1,
++ .bmAttributes = USB_ENDPOINT_XFER_BULK,
++ .reg_udccs = &UDCCS1,
++ .reg_uddr = &UDDR1,
++ drcmr (25)
++ },
++ .ep[2] = {
++ .ep = {
++ .name = "ep2out-bulk",
++ .ops = &pxa2xx_ep_ops,
++ .maxpacket = BULK_FIFO_SIZE,
++ },
++ .dev = &memory,
++ .fifo_size = BULK_FIFO_SIZE,
++ .bEndpointAddress = 2,
++ .bmAttributes = USB_ENDPOINT_XFER_BULK,
++ .reg_udccs = &UDCCS2,
++ .reg_ubcr = &UBCR2,
++ .reg_uddr = &UDDR2,
++ drcmr (26)
++ },
++#ifndef CONFIG_USB_PXA2XX_SMALL
++ .ep[3] = {
++ .ep = {
++ .name = "ep3in-iso",
++ .ops = &pxa2xx_ep_ops,
++ .maxpacket = ISO_FIFO_SIZE,
++ },
++ .dev = &memory,
++ .fifo_size = ISO_FIFO_SIZE,
++ .bEndpointAddress = USB_DIR_IN | 3,
++ .bmAttributes = USB_ENDPOINT_XFER_ISOC,
++ .reg_udccs = &UDCCS3,
++ .reg_uddr = &UDDR3,
++ drcmr (27)
++ },
++ .ep[4] = {
++ .ep = {
++ .name = "ep4out-iso",
++ .ops = &pxa2xx_ep_ops,
++ .maxpacket = ISO_FIFO_SIZE,
++ },
++ .dev = &memory,
++ .fifo_size = ISO_FIFO_SIZE,
++ .bEndpointAddress = 4,
++ .bmAttributes = USB_ENDPOINT_XFER_ISOC,
++ .reg_udccs = &UDCCS4,
++ .reg_ubcr = &UBCR4,
++ .reg_uddr = &UDDR4,
++ drcmr (28)
++ },
++ .ep[5] = {
++ .ep = {
++ .name = "ep5in-int",
++ .ops = &pxa2xx_ep_ops,
++ .maxpacket = INT_FIFO_SIZE,
++ },
++ .dev = &memory,
++ .fifo_size = INT_FIFO_SIZE,
++ .bEndpointAddress = USB_DIR_IN | 5,
++ .bmAttributes = USB_ENDPOINT_XFER_INT,
++ .reg_udccs = &UDCCS5,
++ .reg_uddr = &UDDR5,
++ },
++
++ /* second group of endpoints */
++ .ep[6] = {
++ .ep = {
++ .name = "ep6in-bulk",
++ .ops = &pxa2xx_ep_ops,
++ .maxpacket = BULK_FIFO_SIZE,
++ },
++ .dev = &memory,
++ .fifo_size = BULK_FIFO_SIZE,
++ .bEndpointAddress = USB_DIR_IN | 6,
++ .bmAttributes = USB_ENDPOINT_XFER_BULK,
++ .reg_udccs = &UDCCS6,
++ .reg_uddr = &UDDR6,
++ drcmr (30)
++ },
++ .ep[7] = {
++ .ep = {
++ .name = "ep7out-bulk",
++ .ops = &pxa2xx_ep_ops,
++ .maxpacket = BULK_FIFO_SIZE,
++ },
++ .dev = &memory,
++ .fifo_size = BULK_FIFO_SIZE,
++ .bEndpointAddress = 7,
++ .bmAttributes = USB_ENDPOINT_XFER_BULK,
++ .reg_udccs = &UDCCS7,
++ .reg_ubcr = &UBCR7,
++ .reg_uddr = &UDDR7,
++ drcmr (31)
++ },
++ .ep[8] = {
++ .ep = {
++ .name = "ep8in-iso",
++ .ops = &pxa2xx_ep_ops,
++ .maxpacket = ISO_FIFO_SIZE,
++ },
++ .dev = &memory,
++ .fifo_size = ISO_FIFO_SIZE,
++ .bEndpointAddress = USB_DIR_IN | 8,
++ .bmAttributes = USB_ENDPOINT_XFER_ISOC,
++ .reg_udccs = &UDCCS8,
++ .reg_uddr = &UDDR8,
++ drcmr (32)
++ },
++ .ep[9] = {
++ .ep = {
++ .name = "ep9out-iso",
++ .ops = &pxa2xx_ep_ops,
++ .maxpacket = ISO_FIFO_SIZE,
++ },
++ .dev = &memory,
++ .fifo_size = ISO_FIFO_SIZE,
++ .bEndpointAddress = 9,
++ .bmAttributes = USB_ENDPOINT_XFER_ISOC,
++ .reg_udccs = &UDCCS9,
++ .reg_ubcr = &UBCR9,
++ .reg_uddr = &UDDR9,
++ drcmr (33)
++ },
++ .ep[10] = {
++ .ep = {
++ .name = "ep10in-int",
++ .ops = &pxa2xx_ep_ops,
++ .maxpacket = INT_FIFO_SIZE,
++ },
++ .dev = &memory,
++ .fifo_size = INT_FIFO_SIZE,
++ .bEndpointAddress = USB_DIR_IN | 10,
++ .bmAttributes = USB_ENDPOINT_XFER_INT,
++ .reg_udccs = &UDCCS10,
++ .reg_uddr = &UDDR10,
++ },
++
++ /* third group of endpoints */
++ .ep[11] = {
++ .ep = {
++ .name = "ep11in-bulk",
++ .ops = &pxa2xx_ep_ops,
++ .maxpacket = BULK_FIFO_SIZE,
++ },
++ .dev = &memory,
++ .fifo_size = BULK_FIFO_SIZE,
++ .bEndpointAddress = USB_DIR_IN | 11,
++ .bmAttributes = USB_ENDPOINT_XFER_BULK,
++ .reg_udccs = &UDCCS11,
++ .reg_uddr = &UDDR11,
++ drcmr (35)
++ },
++ .ep[12] = {
++ .ep = {
++ .name = "ep12out-bulk",
++ .ops = &pxa2xx_ep_ops,
++ .maxpacket = BULK_FIFO_SIZE,
++ },
++ .dev = &memory,
++ .fifo_size = BULK_FIFO_SIZE,
++ .bEndpointAddress = 12,
++ .bmAttributes = USB_ENDPOINT_XFER_BULK,
++ .reg_udccs = &UDCCS12,
++ .reg_ubcr = &UBCR12,
++ .reg_uddr = &UDDR12,
++ drcmr (36)
++ },
++ .ep[13] = {
++ .ep = {
++ .name = "ep13in-iso",
++ .ops = &pxa2xx_ep_ops,
++ .maxpacket = ISO_FIFO_SIZE,
++ },
++ .dev = &memory,
++ .fifo_size = ISO_FIFO_SIZE,
++ .bEndpointAddress = USB_DIR_IN | 13,
++ .bmAttributes = USB_ENDPOINT_XFER_ISOC,
++ .reg_udccs = &UDCCS13,
++ .reg_uddr = &UDDR13,
++ drcmr (37)
++ },
++ .ep[14] = {
++ .ep = {
++ .name = "ep14out-iso",
++ .ops = &pxa2xx_ep_ops,
++ .maxpacket = ISO_FIFO_SIZE,
++ },
++ .dev = &memory,
++ .fifo_size = ISO_FIFO_SIZE,
++ .bEndpointAddress = 14,
++ .bmAttributes = USB_ENDPOINT_XFER_ISOC,
++ .reg_udccs = &UDCCS14,
++ .reg_ubcr = &UBCR14,
++ .reg_uddr = &UDDR14,
++ drcmr (38)
++ },
++ .ep[15] = {
++ .ep = {
++ .name = "ep15in-int",
++ .ops = &pxa2xx_ep_ops,
++ .maxpacket = INT_FIFO_SIZE,
++ },
++ .dev = &memory,
++ .fifo_size = INT_FIFO_SIZE,
++ .bEndpointAddress = USB_DIR_IN | 15,
++ .bmAttributes = USB_ENDPOINT_XFER_INT,
++ .reg_udccs = &UDCCS15,
++ .reg_uddr = &UDDR15,
++ },
++#endif /* !CONFIG_USB_PXA2XX_SMALL */
++};
++
++#define CP15R0_VENDOR_MASK 0xffffe000
++
++#if defined(CONFIG_ARCH_PXA)
++#define CP15R0_XSCALE_VALUE 0x69052000 /* intel/arm/xscale */
++
++#elif defined(CONFIG_ARCH_IXP425)
++#define CP15R0_XSCALE_VALUE 0x69054000 /* intel/arm/ixp425 */
++
++#endif
++
++#define CP15R0_PROD_MASK 0x000003f0
++#define PXA25x 0x00000100 /* and PXA26x */
++#define PXA210 0x00000120
++
++#define CP15R0_REV_MASK 0x0000000f
++
++#define CP15R0_PRODREV_MASK (CP15R0_PROD_MASK | CP15R0_REV_MASK)
++
++#define PXA255_A0 0x00000106 /* or PXA260_B1 */
++#define PXA250_C0 0x00000105 /* or PXA26x_B0 */
++#define PXA250_B2 0x00000104
++#define PXA250_B1 0x00000103 /* or PXA260_A0 */
++#define PXA250_B0 0x00000102
++#define PXA250_A1 0x00000101
++#define PXA250_A0 0x00000100
++
++#define PXA210_C0 0x00000125
++#define PXA210_B2 0x00000124
++#define PXA210_B1 0x00000123
++#define PXA210_B0 0x00000122
++
++#define IXP425_A0 0x000001c1
++
++/*
++ * init - allocate resources
++ */
++static int __init init(void)
++{
++ struct pxa2xx_udc *dev;
++ int retval, out_dma = 1;
++ u32 chiprev;
++
++ printk(KERN_INFO "%s: version %s\n", driver_name, DRIVER_VERSION);
++
++ /* insist on Intel/ARM/XScale */
++ asm("mrc%? p15, 0, %0, c0, c0" : "=r" (chiprev));
++ if ((chiprev & CP15R0_VENDOR_MASK) != CP15R0_XSCALE_VALUE) {
++ printk(KERN_ERR "%s: not XScale!\n", driver_name);
++ return -ENODEV;
++ }
++
++ /* allocate resources */
++ if (!request_mem_region(REGISTER_FIRST, REGISTER_LENGTH, driver_name))
++ return -EBUSY;
++
++ /* initialize data */
++ dev = &memory;
++
++ init_timer(&dev->timer);
++ dev->timer.function = udc_watchdog;
++ dev->timer.data = (unsigned long) dev;
++
++ /* trigger chiprev-specific logic */
++ switch (chiprev & CP15R0_PRODREV_MASK) {
++#if defined(CONFIG_ARCH_PXA)
++ case PXA255_A0:
++ dev->has_cfr = 1;
++ break;
++ case PXA250_A0:
++ case PXA250_A1:
++ /* A0/A1 "not released"; ep 13, 15 unusable */
++ /* fall through */
++ case PXA250_B2: case PXA210_B2:
++ case PXA250_B1: case PXA210_B1:
++ case PXA250_B0: case PXA210_B0:
++ out_dma = 0;
++ /* fall through */
++ case PXA250_C0: case PXA210_C0:
++ break;
++#elif defined(CONFIG_ARCH_IXP425)
++ case IXP425_A0:
++ out_dma = 0;
++ break;
++#endif
++ default:
++ out_dma = 0;
++ printk(KERN_ERR "%s: unrecognized processor: %08x\n",
++ driver_name, chiprev);
++ return -ENODEV;
++ }
++
++ pr_debug("%s: IRQ %d%s%s%s\n", driver_name, IRQ_USB,
++ dev->has_cfr ? "" : " (!cfr)",
++ out_dma ? "" : " (broken dma-out)",
++ SIZE_STR DMASTR
++ );
++
++#ifdef USE_DMA
++#ifndef USE_OUT_DMA
++ out_dma = 0;
++#endif
++ /* pxa 250 erratum 130 prevents using OUT dma (fixed C0) */
++ if (!out_dma) {
++ DMSG("disabled OUT dma\n");
++ dev->ep[ 2].reg_drcmr = dev->ep[ 4].reg_drcmr = 0;
++ dev->ep[ 7].reg_drcmr = dev->ep[ 9].reg_drcmr = 0;
++ dev->ep[12].reg_drcmr = dev->ep[14].reg_drcmr = 0;
++ }
++#endif
++
++ the_controller = dev;
++ udc_disable(dev);
++ udc_reinit(dev);
++
++ /* irq setup after old hardware state is cleaned up */
++ retval = request_irq(IRQ_USB, pxa2xx_udc_irq,
++ SA_INTERRUPT, driver_name, dev);
++ if (retval != 0) {
++ printk(KERN_ERR "%s: can't get irq %i, err %d\n",
++ driver_name, IRQ_USB, retval);
++ return -EBUSY;
++ }
++ dev->got_irq = 1;
++
++#ifdef LUBBOCK_USB_DISC_IRQ
++ if (machine_is_lubbock()) {
++ disable_irq(LUBBOCK_USB_DISC_IRQ);
++ retval = request_irq(LUBBOCK_USB_DISC_IRQ,
++ usb_connection_irq,
++ SA_INTERRUPT | SA_SAMPLE_RANDOM,
++ driver_name, dev);
++ if (retval != 0) {
++ enable_irq(LUBBOCK_USB_DISC_IRQ);
++ printk(KERN_ERR "%s: can't get irq %i, err %d\n",
++ driver_name, LUBBOCK_USB_DISC_IRQ, retval);
++ cleanup();
++ return retval;
++ }
++ dev->got_disc = 1;
++ }
++#endif
++
++ create_proc_files();
++ return 0;
++}
++module_init (init);
++
++MODULE_DESCRIPTION(DRIVER_DESC);
++MODULE_AUTHOR("Frank Becker, Robert Schwebel, David Brownell");
++MODULE_LICENSE("GPL");
++
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/drivers/usb/gadget/pxa2xx_udc.h kernel/drivers/usb/gadget/pxa2xx_udc.h
+--- /tmp/kernel/drivers/usb/gadget/pxa2xx_udc.h 1970-01-01 01:00:00.000000000 +0100
++++ kernel/drivers/usb/gadget/pxa2xx_udc.h 2005-04-22 17:53:19.496529422 +0200
+@@ -0,0 +1,528 @@
++/*
++ * linux/drivers/usb/gadget/pxa2xx_udc.h
++ * Intel PXA2xx on-chip full speed USB device controller
++ *
++ * Copyright (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
++ * Copyright (C) 2003 David Brownell
++ * Copyright (C) 2003 Joshua Wise
++ *
++ *
++ * 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
++ */
++
++#ifndef __LINUX_USB_GADGET_PXA2XX_H
++#define __LINUX_USB_GADGET_PXA2XX_H
++
++#include <linux/types.h>
++
++/*-------------------------------------------------------------------------*/
++
++/* pxa2xx has this (move to include/asm-arm/arch-pxa/pxa-regs.h) */
++#define UFNRH_SIR (1 << 7) /* SOF interrupt request */
++#define UFNRH_SIM (1 << 6) /* SOF interrupt mask */
++#define UFNRH_IPE14 (1 << 5) /* ISO packet error, ep14 */
++#define UFNRH_IPE9 (1 << 4) /* ISO packet error, ep9 */
++#define UFNRH_IPE4 (1 << 3) /* ISO packet error, ep4 */
++
++/* pxa255 has this (move to include/asm-arm/arch-pxa/pxa-regs.h) */
++#define UDCCFR UDC_RES2 /* UDC Control Function Register */
++#define UDCCFR_AREN (1 << 7) /* ACK response enable (now) */
++#define UDCCFR_ACM (1 << 2) /* ACK control mode (wait for AREN) */
++
++/* for address space reservation */
++#define REGISTER_FIRST ((unsigned long)(&UDCCR))
++#define REGISTER_LAST ((unsigned long)(&UDDR14)) /* not UDDR15! */
++#define REGISTER_LENGTH ((REGISTER_LAST - REGISTER_FIRST) + 4)
++
++/*-------------------------------------------------------------------------*/
++
++struct pxa2xx_udc;
++
++struct pxa2xx_ep {
++ struct usb_ep ep;
++ struct pxa2xx_udc *dev;
++
++ const struct usb_endpoint_descriptor *desc;
++ struct list_head queue;
++ unsigned long pio_irqs;
++ unsigned long dma_irqs;
++ short dma;
++
++ unsigned short fifo_size;
++ u8 bEndpointAddress;
++ u8 bmAttributes;
++
++ unsigned stopped : 1;
++ unsigned dma_fixup : 1;
++
++ /* UDCCS = UDC Control/Status for this EP
++ * UBCR = UDC Byte Count Remaining (contents of OUT fifo)
++ * UDDR = UDC Endpoint Data Register (the fifo)
++ * DRCM = DMA Request Channel Map
++ */
++ volatile u32 *reg_udccs;
++ volatile u32 *reg_ubcr;
++ volatile u32 *reg_uddr;
++#ifdef USE_DMA
++ volatile u32 *reg_drcmr;
++#define drcmr(n) .reg_drcmr = & DRCMR ## n ,
++#else
++#define drcmr(n)
++#endif
++};
++
++struct pxa2xx_request {
++ struct usb_request req;
++ struct list_head queue;
++};
++
++enum ep0_state {
++ EP0_IDLE,
++ EP0_IN_DATA_PHASE,
++ EP0_OUT_DATA_PHASE,
++ EP0_END_XFER,
++ EP0_STALL,
++};
++
++#define EP0_FIFO_SIZE ((unsigned)16)
++#define BULK_FIFO_SIZE ((unsigned)64)
++#define ISO_FIFO_SIZE ((unsigned)256)
++#define INT_FIFO_SIZE ((unsigned)8)
++
++struct udc_stats {
++ struct ep0stats {
++ unsigned long ops;
++ unsigned long bytes;
++ } read, write;
++ unsigned long irqs;
++};
++
++#ifdef CONFIG_USB_PXA2XX_SMALL
++/* when memory's tight, SMALL config saves code+data. */
++#undef USE_DMA
++#define PXA_UDC_NUM_ENDPOINTS 3
++#endif
++
++#ifndef PXA_UDC_NUM_ENDPOINTS
++#define PXA_UDC_NUM_ENDPOINTS 16
++#endif
++
++struct pxa2xx_udc {
++ struct usb_gadget gadget;
++ struct usb_gadget_driver *driver;
++
++ enum ep0_state ep0state;
++ struct udc_stats stats;
++ unsigned got_irq : 1,
++ got_disc : 1,
++ has_cfr : 1,
++ req_pending : 1,
++ req_std : 1,
++ req_config : 1;
++
++#define start_watchdog(dev) mod_timer(&dev->timer, jiffies + (HZ/200))
++ struct timer_list timer;
++
++ struct pxa2xx_ep ep [PXA_UDC_NUM_ENDPOINTS];
++};
++
++/* 2.5 changes ... */
++
++#ifndef container_of
++#define container_of list_entry
++#endif
++
++#ifndef WARN_ON
++#define WARN_ON BUG_ON
++#endif
++
++/*-------------------------------------------------------------------------*/
++
++/* please keep machine-specific defines in alphabetical order. */
++
++// CONFIG_ARCH_ADI_COYOTE behaves
++
++#ifdef CONFIG_ARCH_E7XX
++# include <asm/arch/e7xx-gpio.h>
++#endif
++
++#ifdef CONFIG_ARCH_H1900
++# include <asm/arch/h1900-gpio.h>
++#endif
++
++#ifdef CONFIG_ARCH_H3900
++# include <asm/arch/h3900-gpio.h>
++#endif
++
++#ifdef CONFIG_ARCH_H5400
++# include <asm/arch/h5400-gpio.h>
++#endif
++
++#ifdef CONFIG_ARCH_INNOKOM
++#include <asm/arch/innokom.h>
++#endif
++
++#ifdef CONFIG_ARCH_LUBBOCK
++#include <asm/arch/lubbock.h>
++/* lubbock can also report usb connect/disconnect irqs */
++
++#ifdef DEBUG
++#define HEX_DISPLAY(n) if (machine_is_lubbock()) { LUB_HEXLED = (n); }
++
++#define LED_CONNECTED_ON if (machine_is_lubbock()) { \
++ DISCRETE_LED_ON(D26); }
++#define LED_CONNECTED_OFF if(machine_is_lubbock()) { \
++ DISCRETE_LED_OFF(D26); LUB_HEXLED = 0; }
++#define LED_EP0_ON if (machine_is_lubbock()) { DISCRETE_LED_ON(D25); }
++#define LED_EP0_OFF if (machine_is_lubbock()) { DISCRETE_LED_OFF(D25); }
++#endif /* DEBUG */
++
++#endif
++
++#ifdef CONFIG_ARCH_PXA_CORGI
++/* Sharp Zaurus C-700, C-750, C-760, C-860 */
++#define CORGI_CONNECT_GPIO 45
++/* use the ARM-Linux registered symbol, not a Lineo-private one */
++#define CONFIG_MACH_CORGI
++#endif
++
++#ifdef CONFIG_ARCH_PXA_POODLE
++/* Sharp B-500, SL-5600 */
++#define POODLE_CONNECT_GPIO 20
++/* use the ARM-Linux registered symbol, not a Lineo-private one */
++#define CONFIG_MACH_POODLE
++#endif
++
++/*-------------------------------------------------------------------------*/
++
++/* LEDs are only for debug */
++#ifndef HEX_DISPLAY
++#define HEX_DISPLAY(n) do {} while(0)
++#endif
++
++#ifndef LED_CONNECTED_ON
++#define LED_CONNECTED_ON do {} while(0)
++#define LED_CONNECTED_OFF do {} while(0)
++#endif
++#ifndef LED_EP0_ON
++#define LED_EP0_ON do {} while (0)
++#define LED_EP0_OFF do {} while (0)
++#endif
++
++/*-------------------------------------------------------------------------*/
++
++static struct pxa2xx_udc *the_controller;
++
++/* one GPIO should be used to detect host disconnect */
++static int is_usb_connected(void)
++{
++ static int first = 0;
++
++ // CONFIG_ARCH_ADI_COYOTE cannot detect or force disconnect
++#ifdef CONFIG_ARCH_E7XX
++ if (machine_is_e7xx())
++ return (GPLR(GPIO_E7XX_USB_DISC)
++ & GPIO_bit(GPIO_E7XX_USB_DISC));
++#endif
++#if 0
++#ifdef CONFIG_ARCH_H1900
++ if (machine_is_h1900())
++ return (!(GPLR(GPIO_NR_H1900_USB_DETECT_N)
++ & GPIO_bit(GPIO_NR_H1900_USB_DETECT_N)));
++#endif
++#ifdef CONFIG_ARCH_H3900
++ if (machine_is_h3900())
++ return 1;
++#endif
++#ifdef CONFIG_ARCH_H5400
++ // h5400 ... ?
++#endif
++#endif
++#ifdef CONFIG_ARCH_INNOKOM
++ if (machine_is_innokom())
++ return (GPLR(GPIO_INNOKOM_USB_DISC)
++ & GPIO_bit(GPIO_INNOKOM_USB_DISC));
++#endif
++#ifdef CONFIG_ARCH_LUBBOCK
++ if (machine_is_lubbock())
++ return ((LUB_MISC_RD & (1 << 9)) == 0);
++#endif
++ // Sharp's sources didn't show a corgi or poodle hook
++
++ if (!first) {
++ pr_info("%s: can't check host connect\n", driver_name);
++ first++;
++ }
++ return 1;
++}
++
++static int disc_first = 0;
++
++/* one GPIO should force the host to see this device (or not) */
++static void make_usb_disappear(void)
++{
++ // CONFIG_ARCH_ADI_COYOTE cannot detect or force disconnect
++#ifdef CONFIG_ARCH_E7XX
++ if (machine_is_e7xx()) {
++ GPSR(GPIO_E7XX_USB_PULLUP) = GPIO_bit(GPIO_E7XX_USB_PULLUP);
++ return;
++ }
++#endif
++ // h1900 ... ?
++#ifdef CONFIG_ARCH_H3900
++ if (machine_is_h3900()) {
++ GPDR0 &= ~GPIO_H3900_USBP_PULLUP;
++ return;
++ }
++#endif
++#ifdef CONFIG_ARCH_H5400
++ if (machine_is_h5400()) {
++ GPDR(GPIO_NR_H5400_USB_PULLUP) &=
++ ~GPIO_bit(GPIO_NR_H5400_USB_PULLUP);
++ return;
++ }
++#endif
++#ifdef CONFIG_ARCH_INNOKOM
++ if (machine_is_innokom()) {
++ GPSR(GPIO_INNOKOM_USB_ONOFF) = GPIO_bit(GPIO_INNOKOM_USB_ONOFF);
++ printk("innokom: disappear\n");
++ udelay(5);
++ return;
++ }
++#endif
++#ifdef CONFIG_ARCH_CSB226
++ if (machine_is_csb226()) {
++ GPCR0 |= 0x00000080;
++ printk("csb226: disappear\n");
++ udelay(5);
++ return;
++ }
++#endif
++ // lubbock has no D+ pullup
++#ifdef CONFIG_MACH_CORGI
++ if (machine_is_corgi()) {
++ GPDR(CORGI_CONNECT_GPIO) |= GPIO_bit(CORGI_CONNECT_GPIO);
++ GPCR(CORGI_CONNECT_GPIO) = GPIO_bit(CORGI_CONNECT_GPIO);
++ }
++#endif
++#ifdef CONFIG_MACH_POODLE
++ if (machine_is_poodle()) {
++ GPDR(POODLE_CONNECT_GPIO) |= GPIO_bit(POODLE_CONNECT_GPIO);
++ GPCR(POODLE_CONNECT_GPIO) = GPIO_bit(POODLE_CONNECT_GPIO);
++ }
++#endif
++
++ if (!disc_first) {
++ pr_info("%s: can't force usb disconnect\n", driver_name);
++ disc_first++;
++ }
++}
++
++static void let_usb_appear(void)
++{
++ // CONFIG_ARCH_ADI_COYOTE cannot detect or force disconnect
++#ifdef CONFIG_ARCH_E7XX
++ if (machine_is_e7xx()) {
++ GPCR(GPIO_E7XX_USB_PULLUP) = GPIO_bit(GPIO_E7XX_USB_PULLUP);
++ return;
++ }
++#endif
++ // h1900 ... ?
++#ifdef CONFIG_ARCH_H3900
++ if (machine_is_h3900()) {
++ GPDR0 |= GPIO_H3900_USBP_PULLUP;
++ GPSR0 |= GPIO_H3900_USBP_PULLUP;
++ return;
++ }
++#endif
++#ifdef CONFIG_ARCH_H5400
++ if (machine_is_h5400()) {
++ GPDR(GPIO_NR_H5400_USB_PULLUP) |=
++ GPIO_bit(GPIO_NR_H5400_USB_PULLUP);
++ return;
++ }
++#endif
++#ifdef CONFIG_ARCH_INNOKOM
++ if (machine_is_innokom()) {
++ GPCR(GPIO_INNOKOM_USB_ONOFF) = GPIO_bit(GPIO_INNOKOM_USB_ONOFF);
++ printk("innokom: appear\n");
++ udelay(5);
++ return;
++ }
++#endif
++#ifdef CONFIG_ARCH_CSB226
++ if (machine_is_csb226()) {
++ GPDR0 |= 0x00000080;
++ GPSR0 |= 0x00000080;
++ printk("csb226: appear\n");
++ udelay(5);
++ return;
++ }
++#endif
++ // lubbock has no D+ pullup
++#ifdef CONFIG_MACH_CORGI
++ if (machine_is_corgi()) {
++ GPDR(CORGI_CONNECT_GPIO) |= GPIO_bit(CORGI_CONNECT_GPIO);
++ GPSR(CORGI_CONNECT_GPIO) = GPIO_bit(CORGI_CONNECT_GPIO);
++ }
++#endif
++#ifdef CONFIG_MACH_POODLE
++ if (machine_is_poodle()) {
++ GPDR(POODLE_CONNECT_GPIO) |= GPIO_bit(POODLE_CONNECT_GPIO);
++ GPSR(POODLE_CONNECT_GPIO) = GPIO_bit(POODLE_CONNECT_GPIO);
++ }
++#endif
++
++ if (!disc_first) {
++ pr_info("%s: can't force usb disconnect\n", driver_name);
++ disc_first++;
++ }
++}
++
++/*-------------------------------------------------------------------------*/
++
++/* LEDs are only for debug */
++#ifndef LED_CONNECTED_ON
++#define LED_CONNECTED_ON do {} while(0)
++#define LED_CONNECTED_OFF do {} while(0)
++#endif
++#ifndef LED_EP0_ON
++#define LED_EP0_ON do {} while (0)
++#define LED_EP0_OFF do {} while (0)
++#endif
++
++/*-------------------------------------------------------------------------*/
++
++/*
++ * Debugging support vanishes in non-debug builds. DBG_NORMAL should be
++ * mostly silent during normal use/testing, with no timing side-effects.
++ */
++#define DBG_NORMAL 1 /* error paths, device state transitions */
++#define DBG_VERBOSE 2 /* add some success path trace info */
++#define DBG_NOISY 3 /* ... even more: request level */
++#define DBG_VERY_NOISY 4 /* ... even more: packet level */
++
++#ifdef DEBUG
++
++static const char *state_name[] = {
++ "EP0_IDLE",
++ "EP0_IN_DATA_PHASE", "EP0_OUT_DATA_PHASE",
++ "EP0_END_XFER", "EP0_STALL"
++};
++
++#define DMSG(stuff...) printk(KERN_DEBUG "udc: " stuff)
++
++#ifdef VERBOSE
++# define UDC_DEBUG DBG_VERBOSE
++#else
++# define UDC_DEBUG DBG_NORMAL
++#endif
++
++static void __attribute__ ((__unused__))
++dump_udccr(const char *label)
++{
++ u32 udccr = UDCCR;
++ DMSG("%s %02X =%s%s%s%s%s%s%s%s\n",
++ label, udccr,
++ (udccr & UDCCR_REM) ? " rem" : "",
++ (udccr & UDCCR_RSTIR) ? " rstir" : "",
++ (udccr & UDCCR_SRM) ? " srm" : "",
++ (udccr & UDCCR_SUSIR) ? " susir" : "",
++ (udccr & UDCCR_RESIR) ? " resir" : "",
++ (udccr & UDCCR_RSM) ? " rsm" : "",
++ (udccr & UDCCR_UDA) ? " uda" : "",
++ (udccr & UDCCR_UDE) ? " ude" : "");
++}
++
++static void __attribute__ ((__unused__))
++dump_udccs0(const char *label)
++{
++ u32 udccs0 = UDCCS0;
++
++ DMSG("%s %s %02X =%s%s%s%s%s%s%s%s\n",
++ label, state_name[the_controller->ep0state], udccs0,
++ (udccs0 & UDCCS0_SA) ? " sa" : "",
++ (udccs0 & UDCCS0_RNE) ? " rne" : "",
++ (udccs0 & UDCCS0_FST) ? " fst" : "",
++ (udccs0 & UDCCS0_SST) ? " sst" : "",
++ (udccs0 & UDCCS0_DRWF) ? " dwrf" : "",
++ (udccs0 & UDCCS0_FTF) ? " ftf" : "",
++ (udccs0 & UDCCS0_IPR) ? " ipr" : "",
++ (udccs0 & UDCCS0_OPR) ? " opr" : "");
++}
++
++static void __attribute__ ((__unused__))
++dump_state(struct pxa2xx_udc *dev)
++{
++ u32 tmp;
++ unsigned i;
++
++ DMSG("%s %s, uicr %02X.%02X, usir %02X.%02x, ufnr %02X.%02X\n",
++ is_usb_connected() ? "host " : "disconnected",
++ state_name[dev->ep0state],
++ UICR1, UICR0, USIR1, USIR0, UFNRH, UFNRL);
++ dump_udccr("udccr");
++ if (dev->has_cfr) {
++ tmp = UDCCFR;
++ DMSG("udccfr %02X =%s%s\n", tmp,
++ (tmp & UDCCFR_AREN) ? " aren" : "",
++ (tmp & UDCCFR_ACM) ? " acm" : "");
++ }
++
++ if (!dev->driver) {
++ DMSG("no gadget driver bound\n");
++ return;
++ } else
++ DMSG("ep0 driver '%s'\n", dev->driver->driver.name);
++
++ if (!is_usb_connected())
++ return;
++
++ dump_udccs0 ("udccs0");
++ DMSG("ep0 IN %lu/%lu, OUT %lu/%lu\n",
++ dev->stats.write.bytes, dev->stats.write.ops,
++ dev->stats.read.bytes, dev->stats.read.ops);
++
++ for (i = 1; i < PXA_UDC_NUM_ENDPOINTS; i++) {
++ if (dev->ep [i].desc == 0)
++ continue;
++ DMSG ("udccs%d = %02x\n", i, *dev->ep->reg_udccs);
++ }
++}
++
++#else
++
++#define DMSG(stuff...) do{}while(0)
++
++#define dump_udccr(x) do{}while(0)
++#define dump_udccs0(x) do{}while(0)
++#define dump_state(x) do{}while(0)
++
++#define UDC_DEBUG ((unsigned)0)
++
++#endif
++
++#define DBG(lvl, stuff...) do{if ((lvl) <= UDC_DEBUG) DMSG(stuff);}while(0)
++
++#define WARN(stuff...) printk(KERN_WARNING "udc: " stuff)
++#define INFO(stuff...) printk(KERN_INFO "udc: " stuff)
++
++
++/* 2.4 backport support */
++#define irqreturn_t void
++#define IRQ_HANDLED
++
++
++#endif /* __LINUX_USB_GADGET_PXA2XX_H */
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/drivers/usb/gadget/rndis.c kernel/drivers/usb/gadget/rndis.c
+--- /tmp/kernel/drivers/usb/gadget/rndis.c 1970-01-01 01:00:00.000000000 +0100
++++ kernel/drivers/usb/gadget/rndis.c 2005-04-22 17:53:19.501528608 +0200
+@@ -0,0 +1,1425 @@
++/*
++ * RNDIS MSG parser
++ *
++ * Version: $Id: rndis.c,v 1.19 2004/03/25 21:33:46 robert Exp $
++ *
++ * Authors: Benedikt Spranger, Pengutronix
++ * Robert Schwebel, Pengutronix
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This software was originally developed in conformance with
++ * Microsoft's Remote NDIS Specification License Agreement.
++ *
++ * 03/12/2004 Kai-Uwe Bloem <linux-development@auerswald.de>
++ * Fixed message length bug in init_response
++ *
++ * 03/25/2004 Kai-Uwe Bloem <linux-development@auerswald.de>
++ * Fixed rndis_rm_hdr length bug.
++ *
++ * Copyright (C) 2004 by David Brownell
++ * updates to merge with Linux 2.6, better match RNDIS spec
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/version.h>
++#include <linux/init.h>
++#include <linux/list.h>
++#include <linux/proc_fs.h>
++#include <linux/netdevice.h>
++
++#include <asm/io.h>
++#include <asm/byteorder.h>
++#include <asm/system.h>
++
++
++#undef RNDIS_PM
++#undef VERBOSE
++
++#include "rndis.h"
++
++
++/* The driver for your USB chip needs to support ep0 OUT to work with
++ * RNDIS, plus all three CDC Ethernet endpoints (interrupt not optional).
++ *
++ * Windows hosts need an INF file like Documentation/usb/linux.inf
++ * and will be happier if you provide the host_addr module parameter.
++ */
++
++#if 0
++#define DEBUG(str,args...) do { \
++ if (rndis_debug) \
++ printk(KERN_DEBUG str , ## args ); \
++ } while (0)
++static int rndis_debug = 0;
++
++module_param (rndis_debug, bool, 0);
++MODULE_PARM_DESC (rndis_debug, "enable debugging");
++
++#else
++
++#define rndis_debug 0
++#define DEBUG(str,args...) do{}while(0)
++#endif
++
++#define RNDIS_MAX_CONFIGS 1
++
++
++static rndis_params rndis_per_dev_params [RNDIS_MAX_CONFIGS];
++
++/* Driver Version */
++static const u32 rndis_driver_version = __constant_cpu_to_le32 (1);
++
++/* Function Prototypes */
++static int rndis_init_response (int configNr, rndis_init_msg_type *buf);
++static int rndis_query_response (int configNr, rndis_query_msg_type *buf);
++static int rndis_set_response (int configNr, rndis_set_msg_type *buf);
++static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf);
++static int rndis_keepalive_response (int configNr,
++ rndis_keepalive_msg_type *buf);
++
++static rndis_resp_t *rndis_add_response (int configNr, u32 length);
++
++
++/* NDIS Functions */
++static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
++{
++ int retval = -ENOTSUPP;
++ u32 length = 0;
++ u32 *tmp;
++ int i, count;
++ rndis_query_cmplt_type *resp;
++
++ if (!r) return -ENOMEM;
++ resp = (rndis_query_cmplt_type *) r->buf;
++
++ if (!resp) return -ENOMEM;
++
++ switch (OID) {
++
++ /* general oids (table 4-1) */
++
++ /* mandatory */
++ case OID_GEN_SUPPORTED_LIST:
++ DEBUG ("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__);
++ length = sizeof (oid_supported_list);
++ count = length / sizeof (u32);
++ tmp = (u32 *) ((u8 *)resp + 24);
++ for (i = 0; i < count; i++)
++ tmp[i] = cpu_to_le32 (oid_supported_list[i]);
++ retval = 0;
++ break;
++
++ /* mandatory */
++ case OID_GEN_HARDWARE_STATUS:
++ DEBUG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__);
++ length = 4;
++ /* Bogus question!
++ * Hardware must be ready to receive high level protocols.
++ * BTW:
++ * reddite ergo quae sunt Caesaris Caesari
++ * et quae sunt Dei Deo!
++ */
++ *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
++ retval = 0;
++ break;
++
++ /* mandatory */
++ case OID_GEN_MEDIA_SUPPORTED:
++ DEBUG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__);
++ length = 4;
++ *((u32 *) resp + 6) = cpu_to_le32 (
++ rndis_per_dev_params [configNr].medium);
++ retval = 0;
++ break;
++
++ /* mandatory */
++ case OID_GEN_MEDIA_IN_USE:
++ DEBUG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__);
++ length = 4;
++ /* one medium, one transport... (maybe you do it better) */
++ *((u32 *) resp + 6) = cpu_to_le32 (
++ rndis_per_dev_params [configNr].medium);
++ retval = 0;
++ break;
++
++ /* mandatory */
++ case OID_GEN_MAXIMUM_FRAME_SIZE:
++ DEBUG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__);
++ if (rndis_per_dev_params [configNr].dev) {
++ length = 4;
++ *((u32 *) resp + 6) = cpu_to_le32 (
++ rndis_per_dev_params [configNr].dev->mtu);
++ retval = 0;
++ } else {
++ *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
++ retval = 0;
++ }
++ break;
++
++ /* mandatory */
++ case OID_GEN_LINK_SPEED:
++ DEBUG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__);
++ length = 4;
++ if (rndis_per_dev_params [configNr].media_state
++ == NDIS_MEDIA_STATE_DISCONNECTED)
++ *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
++ else
++ *((u32 *) resp + 6) = cpu_to_le32 (
++ rndis_per_dev_params [configNr].speed);
++ retval = 0;
++ break;
++
++ /* mandatory */
++ case OID_GEN_TRANSMIT_BLOCK_SIZE:
++ DEBUG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__);
++ if (rndis_per_dev_params [configNr].dev) {
++ length = 4;
++ *((u32 *) resp + 6) = cpu_to_le32 (
++ rndis_per_dev_params [configNr].dev->mtu);
++ retval = 0;
++ }
++ break;
++
++ /* mandatory */
++ case OID_GEN_RECEIVE_BLOCK_SIZE:
++ DEBUG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__);
++ if (rndis_per_dev_params [configNr].dev) {
++ length = 4;
++ *((u32 *) resp + 6) = cpu_to_le32 (
++ rndis_per_dev_params [configNr].dev->mtu);
++ retval = 0;
++ }
++ break;
++
++ /* mandatory */
++ case OID_GEN_VENDOR_ID:
++ DEBUG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__);
++ length = 4;
++ *((u32 *) resp + 6) = cpu_to_le32 (
++ rndis_per_dev_params [configNr].vendorID);
++ retval = 0;
++ break;
++
++ /* mandatory */
++ case OID_GEN_VENDOR_DESCRIPTION:
++ DEBUG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__);
++ length = strlen (rndis_per_dev_params [configNr].vendorDescr);
++ memcpy ((u8 *) resp + 24,
++ rndis_per_dev_params [configNr].vendorDescr, length);
++ retval = 0;
++ break;
++
++ case OID_GEN_VENDOR_DRIVER_VERSION:
++ DEBUG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__);
++ length = 4;
++ /* Created as LE */
++ *((u32 *) resp + 6) = rndis_driver_version;
++ retval = 0;
++ break;
++
++ /* mandatory */
++ case OID_GEN_CURRENT_PACKET_FILTER:
++ DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__);
++ length = 4;
++ *((u32 *) resp + 6) = cpu_to_le32 (
++ rndis_per_dev_params[configNr].filter);
++ retval = 0;
++ break;
++
++ /* mandatory */
++ case OID_GEN_MAXIMUM_TOTAL_SIZE:
++ DEBUG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__);
++ length = 4;
++ *((u32 *) resp + 6) = __constant_cpu_to_le32(
++ RNDIS_MAX_TOTAL_SIZE);
++ retval = 0;
++ break;
++
++ /* mandatory */
++ case OID_GEN_MEDIA_CONNECT_STATUS:
++ DEBUG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__);
++ length = 4;
++ *((u32 *) resp + 6) = cpu_to_le32 (
++ rndis_per_dev_params [configNr]
++ .media_state);
++ retval = 0;
++ break;
++
++ case OID_GEN_PHYSICAL_MEDIUM:
++ DEBUG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__);
++ length = 4;
++ *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
++ retval = 0;
++ break;
++
++ /* The RNDIS specification is incomplete/wrong. Some versions
++ * of MS-Windows expect OIDs that aren't specified there. Other
++ * versions emit undefined RNDIS messages. DOCUMENT ALL THESE!
++ */
++ case OID_GEN_MAC_OPTIONS: /* from WinME */
++ DEBUG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__);
++ length = 4;
++ *((u32 *) resp + 6) = __constant_cpu_to_le32(
++ NDIS_MAC_OPTION_RECEIVE_SERIALIZED
++ | NDIS_MAC_OPTION_FULL_DUPLEX);
++ retval = 0;
++ break;
++
++ /* statistics OIDs (table 4-2) */
++
++ /* mandatory */
++ case OID_GEN_XMIT_OK:
++ DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__);
++ if (rndis_per_dev_params [configNr].stats) {
++ length = 4;
++ *((u32 *) resp + 6) = cpu_to_le32 (
++ rndis_per_dev_params [configNr].stats->tx_packets -
++ rndis_per_dev_params [configNr].stats->tx_errors -
++ rndis_per_dev_params [configNr].stats->tx_dropped);
++ retval = 0;
++ } else {
++ *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
++ retval = 0;
++ }
++ break;
++
++ /* mandatory */
++ case OID_GEN_RCV_OK:
++ DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__);
++ if (rndis_per_dev_params [configNr].stats) {
++ length = 4;
++ *((u32 *) resp + 6) = cpu_to_le32 (
++ rndis_per_dev_params [configNr].stats->rx_packets -
++ rndis_per_dev_params [configNr].stats->rx_errors -
++ rndis_per_dev_params [configNr].stats->rx_dropped);
++ retval = 0;
++ } else {
++ *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
++ retval = 0;
++ }
++ break;
++
++ /* mandatory */
++ case OID_GEN_XMIT_ERROR:
++ DEBUG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__);
++ if (rndis_per_dev_params [configNr].stats) {
++ length = 4;
++ *((u32 *) resp + 6) = cpu_to_le32 (
++ rndis_per_dev_params [configNr]
++ .stats->tx_errors);
++ retval = 0;
++ } else {
++ *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
++ retval = 0;
++ }
++ break;
++
++ /* mandatory */
++ case OID_GEN_RCV_ERROR:
++ DEBUG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__);
++ if (rndis_per_dev_params [configNr].stats) {
++ *((u32 *) resp + 6) = cpu_to_le32 (
++ rndis_per_dev_params [configNr]
++ .stats->rx_errors);
++ retval = 0;
++ } else {
++ *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
++ retval = 0;
++ }
++ break;
++
++ /* mandatory */
++ case OID_GEN_RCV_NO_BUFFER:
++ DEBUG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__);
++ if (rndis_per_dev_params [configNr].stats) {
++ *((u32 *) resp + 6) = cpu_to_le32 (
++ rndis_per_dev_params [configNr]
++ .stats->rx_dropped);
++ retval = 0;
++ } else {
++ *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
++ retval = 0;
++ }
++ break;
++
++#ifdef RNDIS_OPTIONAL_STATS
++ case OID_GEN_DIRECTED_BYTES_XMIT:
++ DEBUG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __FUNCTION__);
++ /*
++ * Aunt Tilly's size of shoes
++ * minus antarctica count of penguins
++ * divided by weight of Alpha Centauri
++ */
++ if (rndis_per_dev_params [configNr].stats) {
++ length = 4;
++ *((u32 *) resp + 6) = cpu_to_le32 (
++ (rndis_per_dev_params [configNr]
++ .stats->tx_packets -
++ rndis_per_dev_params [configNr]
++ .stats->tx_errors -
++ rndis_per_dev_params [configNr]
++ .stats->tx_dropped)
++ * 123);
++ retval = 0;
++ } else {
++ *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
++ retval = 0;
++ }
++ break;
++
++ case OID_GEN_DIRECTED_FRAMES_XMIT:
++ DEBUG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__);
++ /* dito */
++ if (rndis_per_dev_params [configNr].stats) {
++ length = 4;
++ *((u32 *) resp + 6) = cpu_to_le32 (
++ (rndis_per_dev_params [configNr]
++ .stats->tx_packets -
++ rndis_per_dev_params [configNr]
++ .stats->tx_errors -
++ rndis_per_dev_params [configNr]
++ .stats->tx_dropped)
++ / 123);
++ retval = 0;
++ } else {
++ *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
++ retval = 0;
++ }
++ break;
++
++ case OID_GEN_MULTICAST_BYTES_XMIT:
++ DEBUG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__);
++ if (rndis_per_dev_params [configNr].stats) {
++ *((u32 *) resp + 6) = cpu_to_le32 (
++ rndis_per_dev_params [configNr]
++ .stats->multicast*1234);
++ retval = 0;
++ } else {
++ *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
++ retval = 0;
++ }
++ break;
++
++ case OID_GEN_MULTICAST_FRAMES_XMIT:
++ DEBUG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__);
++ if (rndis_per_dev_params [configNr].stats) {
++ *((u32 *) resp + 6) = cpu_to_le32 (
++ rndis_per_dev_params [configNr]
++ .stats->multicast);
++ retval = 0;
++ } else {
++ *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
++ retval = 0;
++ }
++ break;
++
++ case OID_GEN_BROADCAST_BYTES_XMIT:
++ DEBUG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__);
++ if (rndis_per_dev_params [configNr].stats) {
++ *((u32 *) resp + 6) = cpu_to_le32 (
++ rndis_per_dev_params [configNr]
++ .stats->tx_packets/42*255);
++ retval = 0;
++ } else {
++ *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
++ retval = 0;
++ }
++ break;
++
++ case OID_GEN_BROADCAST_FRAMES_XMIT:
++ DEBUG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__);
++ if (rndis_per_dev_params [configNr].stats) {
++ *((u32 *) resp + 6) = cpu_to_le32 (
++ rndis_per_dev_params [configNr]
++ .stats->tx_packets/42);
++ retval = 0;
++ } else {
++ *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
++ retval = 0;
++ }
++ break;
++
++ case OID_GEN_DIRECTED_BYTES_RCV:
++ DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__);
++ *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
++ retval = 0;
++ break;
++
++ case OID_GEN_DIRECTED_FRAMES_RCV:
++ DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__);
++ *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
++ retval = 0;
++ break;
++
++ case OID_GEN_MULTICAST_BYTES_RCV:
++ DEBUG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__);
++ if (rndis_per_dev_params [configNr].stats) {
++ *((u32 *) resp + 6) = cpu_to_le32 (
++ rndis_per_dev_params [configNr]
++ .stats->multicast * 1111);
++ retval = 0;
++ } else {
++ *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
++ retval = 0;
++ }
++ break;
++
++ case OID_GEN_MULTICAST_FRAMES_RCV:
++ DEBUG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__);
++ if (rndis_per_dev_params [configNr].stats) {
++ *((u32 *) resp + 6) = cpu_to_le32 (
++ rndis_per_dev_params [configNr]
++ .stats->multicast);
++ retval = 0;
++ } else {
++ *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
++ retval = 0;
++ }
++ break;
++
++ case OID_GEN_BROADCAST_BYTES_RCV:
++ DEBUG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__);
++ if (rndis_per_dev_params [configNr].stats) {
++ *((u32 *) resp + 6) = cpu_to_le32 (
++ rndis_per_dev_params [configNr]
++ .stats->rx_packets/42*255);
++ retval = 0;
++ } else {
++ *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
++ retval = 0;
++ }
++ break;
++
++ case OID_GEN_BROADCAST_FRAMES_RCV:
++ DEBUG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__);
++ if (rndis_per_dev_params [configNr].stats) {
++ *((u32 *) resp + 6) = cpu_to_le32 (
++ rndis_per_dev_params [configNr]
++ .stats->rx_packets/42);
++ retval = 0;
++ } else {
++ *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
++ retval = 0;
++ }
++ break;
++
++ case OID_GEN_RCV_CRC_ERROR:
++ DEBUG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__);
++ if (rndis_per_dev_params [configNr].stats) {
++ *((u32 *) resp + 6) = cpu_to_le32 (
++ rndis_per_dev_params [configNr]
++ .stats->rx_crc_errors);
++ retval = 0;
++ } else {
++ *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
++ retval = 0;
++ }
++ break;
++
++ case OID_GEN_TRANSMIT_QUEUE_LENGTH:
++ DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__);
++ *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
++ retval = 0;
++ break;
++#endif /* RNDIS_OPTIONAL_STATS */
++
++ /* ieee802.3 OIDs (table 4-3) */
++
++ /* mandatory */
++ case OID_802_3_PERMANENT_ADDRESS:
++ DEBUG("%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__);
++ if (rndis_per_dev_params [configNr].dev) {
++ length = ETH_ALEN;
++ memcpy ((u8 *) resp + 24,
++ rndis_per_dev_params [configNr].host_mac,
++ length);
++ retval = 0;
++ } else {
++ *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
++ retval = 0;
++ }
++ break;
++
++ /* mandatory */
++ case OID_802_3_CURRENT_ADDRESS:
++ DEBUG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__);
++ if (rndis_per_dev_params [configNr].dev) {
++ length = ETH_ALEN;
++ memcpy ((u8 *) resp + 24,
++ rndis_per_dev_params [configNr].host_mac,
++ length);
++ retval = 0;
++ }
++ break;
++
++ /* mandatory */
++ case OID_802_3_MULTICAST_LIST:
++ DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
++ length = 4;
++ /* Multicast base address only */
++ *((u32 *) resp + 6) = __constant_cpu_to_le32 (0xE0000000);
++ retval = 0;
++ break;
++
++ /* mandatory */
++ case OID_802_3_MAXIMUM_LIST_SIZE:
++ DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__);
++ length = 4;
++ /* Multicast base address only */
++ *((u32 *) resp + 6) = __constant_cpu_to_le32 (1);
++ retval = 0;
++ break;
++
++ case OID_802_3_MAC_OPTIONS:
++ DEBUG("%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__);
++ break;
++
++ /* ieee802.3 statistics OIDs (table 4-4) */
++
++ /* mandatory */
++ case OID_802_3_RCV_ERROR_ALIGNMENT:
++ DEBUG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __FUNCTION__);
++ if (rndis_per_dev_params [configNr].stats)
++ {
++ length = 4;
++ *((u32 *) resp + 6) = cpu_to_le32 (
++ rndis_per_dev_params [configNr]
++ .stats->rx_frame_errors);
++ retval = 0;
++ }
++ break;
++
++ /* mandatory */
++ case OID_802_3_XMIT_ONE_COLLISION:
++ DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__);
++ length = 4;
++ *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
++ retval = 0;
++ break;
++
++ /* mandatory */
++ case OID_802_3_XMIT_MORE_COLLISIONS:
++ DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__);
++ length = 4;
++ *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
++ retval = 0;
++ break;
++
++#ifdef RNDIS_OPTIONAL_STATS
++ case OID_802_3_XMIT_DEFERRED:
++ DEBUG("%s: OID_802_3_XMIT_DEFERRED\n", __FUNCTION__);
++ /* TODO */
++ break;
++
++ case OID_802_3_XMIT_MAX_COLLISIONS:
++ DEBUG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __FUNCTION__);
++ /* TODO */
++ break;
++
++ case OID_802_3_RCV_OVERRUN:
++ DEBUG("%s: OID_802_3_RCV_OVERRUN\n", __FUNCTION__);
++ /* TODO */
++ break;
++
++ case OID_802_3_XMIT_UNDERRUN:
++ DEBUG("%s: OID_802_3_XMIT_UNDERRUN\n", __FUNCTION__);
++ /* TODO */
++ break;
++
++ case OID_802_3_XMIT_HEARTBEAT_FAILURE:
++ DEBUG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __FUNCTION__);
++ /* TODO */
++ break;
++
++ case OID_802_3_XMIT_TIMES_CRS_LOST:
++ DEBUG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __FUNCTION__);
++ /* TODO */
++ break;
++
++ case OID_802_3_XMIT_LATE_COLLISIONS:
++ DEBUG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __FUNCTION__);
++ /* TODO */
++ break;
++#endif /* RNDIS_OPTIONAL_STATS */
++
++#ifdef RNDIS_PM
++ /* power management OIDs (table 4-5) */
++ case OID_PNP_CAPABILITIES:
++ DEBUG("%s: OID_PNP_CAPABILITIES\n", __FUNCTION__);
++
++ /* just PM, and remote wakeup on link status change
++ * (not magic packet or pattern match)
++ */
++ length = sizeof (struct NDIS_PNP_CAPABILITIES);
++ memset (resp, 0, length);
++ {
++ struct NDIS_PNP_CAPABILITIES *caps = (void *) resp;
++
++ caps->Flags = NDIS_DEVICE_WAKE_UP_ENABLE;
++ caps->WakeUpCapabilities.MinLinkChangeWakeUp
++ = NdisDeviceStateD3;
++
++ /* FIXME then use usb_gadget_wakeup(), and
++ * set USB_CONFIG_ATT_WAKEUP in config desc
++ */
++ }
++ retval = 0;
++ break;
++ case OID_PNP_QUERY_POWER:
++ DEBUG("%s: OID_PNP_QUERY_POWER\n", __FUNCTION__);
++ /* sure, handle any power state that maps to USB suspend */
++ retval = 0;
++ break;
++#endif
++
++ default:
++ printk (KERN_WARNING "%s: query unknown OID 0x%08X\n",
++ __FUNCTION__, OID);
++ }
++
++ resp->InformationBufferOffset = __constant_cpu_to_le32 (16);
++ resp->InformationBufferLength = cpu_to_le32 (length);
++ resp->MessageLength = cpu_to_le32 (24 + length);
++ r->length = 24 + length;
++ return retval;
++}
++
++static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
++ rndis_resp_t *r)
++{
++ rndis_set_cmplt_type *resp;
++ int i, retval = -ENOTSUPP;
++ struct rndis_params *params;
++
++ if (!r)
++ return -ENOMEM;
++ resp = (rndis_set_cmplt_type *) r->buf;
++ if (!resp)
++ return -ENOMEM;
++
++ DEBUG("set OID %08x value, len %d:\n", OID, buf_len);
++ for (i = 0; i < buf_len; i += 16) {
++ DEBUG ("%03d: "
++ " %02x %02x %02x %02x"
++ " %02x %02x %02x %02x"
++ " %02x %02x %02x %02x"
++ " %02x %02x %02x %02x"
++ "\n",
++ i,
++ buf[i], buf [i+1],
++ buf[i+2], buf[i+3],
++ buf[i+4], buf [i+5],
++ buf[i+6], buf[i+7],
++ buf[i+8], buf [i+9],
++ buf[i+10], buf[i+11],
++ buf[i+12], buf [i+13],
++ buf[i+14], buf[i+15]);
++ }
++
++ switch (OID) {
++ case OID_GEN_CURRENT_PACKET_FILTER:
++ params = &rndis_per_dev_params [configNr];
++ retval = 0;
++
++ /* FIXME use these NDIS_PACKET_TYPE_* bitflags to
++ * filter packets in hard_start_xmit()
++ * NDIS_PACKET_TYPE_x == USB_CDC_PACKET_TYPE_x for x in:
++ * PROMISCUOUS, DIRECTED,
++ * MULTICAST, ALL_MULTICAST, BROADCAST
++ */
++ params->filter = cpu_to_le32p((u32 *)buf);
++ DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
++ __FUNCTION__, params->filter);
++
++ /* this call has a significant side effect: it's
++ * what makes the packet flow start and stop, like
++ * activating the CDC Ethernet altsetting.
++ */
++ if (params->filter) {
++ params->state = RNDIS_DATA_INITIALIZED;
++ netif_carrier_on(params->dev);
++ if (netif_running(params->dev))
++ netif_wake_queue (params->dev);
++ } else {
++ params->state = RNDIS_INITIALIZED;
++ netif_carrier_off (params->dev);
++ netif_stop_queue (params->dev);
++ }
++ break;
++
++ case OID_802_3_MULTICAST_LIST:
++ /* I think we can ignore this */
++ DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
++ retval = 0;
++ break;
++#if 0
++ case OID_GEN_RNDIS_CONFIG_PARAMETER:
++ {
++ struct rndis_config_parameter *param;
++ param = (struct rndis_config_parameter *) buf;
++ DEBUG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n",
++ __FUNCTION__,
++ min(cpu_to_le32(param->ParameterNameLength),80),
++ buf + param->ParameterNameOffset);
++ retval = 0;
++ }
++ break;
++#endif
++
++#ifdef RNDIS_PM
++ case OID_PNP_SET_POWER:
++ DEBUG ("OID_PNP_SET_POWER\n");
++ /* sure, handle any power state that maps to USB suspend */
++ retval = 0;
++ break;
++
++ case OID_PNP_ENABLE_WAKE_UP:
++ /* always-connected ... */
++ DEBUG ("OID_PNP_ENABLE_WAKE_UP\n");
++ retval = 0;
++ break;
++
++ // no PM resume patterns supported (specified where?)
++ // so OID_PNP_{ADD,REMOVE}_WAKE_UP_PATTERN always fails
++#endif
++
++ default:
++ printk (KERN_WARNING "%s: set unknown OID 0x%08X, size %d\n",
++ __FUNCTION__, OID, buf_len);
++ }
++
++ return retval;
++}
++
++/*
++ * Response Functions
++ */
++
++static int rndis_init_response (int configNr, rndis_init_msg_type *buf)
++{
++ rndis_init_cmplt_type *resp;
++ rndis_resp_t *r;
++
++ if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;
++
++ r = rndis_add_response (configNr, sizeof (rndis_init_cmplt_type));
++
++ if (!r) return -ENOMEM;
++
++ resp = (rndis_init_cmplt_type *) r->buf;
++
++ if (!resp) return -ENOMEM;
++
++ resp->MessageType = __constant_cpu_to_le32 (
++ REMOTE_NDIS_INITIALIZE_CMPLT);
++ resp->MessageLength = __constant_cpu_to_le32 (52);
++ resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
++ resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
++ resp->MajorVersion = __constant_cpu_to_le32 (RNDIS_MAJOR_VERSION);
++ resp->MinorVersion = __constant_cpu_to_le32 (RNDIS_MINOR_VERSION);
++ resp->DeviceFlags = __constant_cpu_to_le32 (RNDIS_DF_CONNECTIONLESS);
++ resp->Medium = __constant_cpu_to_le32 (RNDIS_MEDIUM_802_3);
++ resp->MaxPacketsPerTransfer = __constant_cpu_to_le32 (1);
++ resp->MaxTransferSize = cpu_to_le32 (
++ rndis_per_dev_params [configNr].dev->mtu
++ + sizeof (struct ethhdr)
++ + sizeof (struct rndis_packet_msg_type)
++ + 22);
++ resp->PacketAlignmentFactor = __constant_cpu_to_le32 (0);
++ resp->AFListOffset = __constant_cpu_to_le32 (0);
++ resp->AFListSize = __constant_cpu_to_le32 (0);
++
++ if (rndis_per_dev_params [configNr].ack)
++ rndis_per_dev_params [configNr].ack (
++ rndis_per_dev_params [configNr].dev);
++
++ return 0;
++}
++
++static int rndis_query_response (int configNr, rndis_query_msg_type *buf)
++{
++ rndis_query_cmplt_type *resp;
++ rndis_resp_t *r;
++
++ // DEBUG("%s: OID = %08X\n", __FUNCTION__, cpu_to_le32(buf->OID));
++ if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;
++
++ /*
++ * we need more memory:
++ * oid_supported_list is the largest answer
++ */
++ r = rndis_add_response (configNr, sizeof (oid_supported_list));
++
++ if (!r) return -ENOMEM;
++ resp = (rndis_query_cmplt_type *) r->buf;
++
++ if (!resp) return -ENOMEM;
++
++ resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_QUERY_CMPLT);
++ resp->MessageLength = __constant_cpu_to_le32 (24);
++ resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
++
++ if (gen_ndis_query_resp (configNr, cpu_to_le32 (buf->OID), r)) {
++ /* OID not supported */
++ resp->Status = __constant_cpu_to_le32 (
++ RNDIS_STATUS_NOT_SUPPORTED);
++ resp->InformationBufferLength = __constant_cpu_to_le32 (0);
++ resp->InformationBufferOffset = __constant_cpu_to_le32 (0);
++ } else
++ resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
++
++ if (rndis_per_dev_params [configNr].ack)
++ rndis_per_dev_params [configNr].ack (
++ rndis_per_dev_params [configNr].dev);
++ return 0;
++}
++
++static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
++{
++ u32 BufLength, BufOffset;
++ rndis_set_cmplt_type *resp;
++ rndis_resp_t *r;
++
++ r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type));
++
++ if (!r) return -ENOMEM;
++ resp = (rndis_set_cmplt_type *) r->buf;
++ if (!resp) return -ENOMEM;
++
++ BufLength = cpu_to_le32 (buf->InformationBufferLength);
++ BufOffset = cpu_to_le32 (buf->InformationBufferOffset);
++
++#ifdef VERBOSE
++ DEBUG("%s: Length: %d\n", __FUNCTION__, BufLength);
++ DEBUG("%s: Offset: %d\n", __FUNCTION__, BufOffset);
++ DEBUG("%s: InfoBuffer: ", __FUNCTION__);
++
++ for (i = 0; i < BufLength; i++) {
++ DEBUG ("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
++ }
++
++ DEBUG ("\n");
++#endif
++
++ resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_SET_CMPLT);
++ resp->MessageLength = __constant_cpu_to_le32 (16);
++ resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
++ if (gen_ndis_set_resp (configNr, cpu_to_le32 (buf->OID),
++ ((u8 *) buf) + 8 + BufOffset, BufLength, r))
++ resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_NOT_SUPPORTED);
++ else resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
++
++ if (rndis_per_dev_params [configNr].ack)
++ rndis_per_dev_params [configNr].ack (
++ rndis_per_dev_params [configNr].dev);
++
++ return 0;
++}
++
++static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf)
++{
++ rndis_reset_cmplt_type *resp;
++ rndis_resp_t *r;
++
++ r = rndis_add_response (configNr, sizeof (rndis_reset_cmplt_type));
++
++ if (!r) return -ENOMEM;
++ resp = (rndis_reset_cmplt_type *) r->buf;
++ if (!resp) return -ENOMEM;
++
++ resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_RESET_CMPLT);
++ resp->MessageLength = __constant_cpu_to_le32 (16);
++ resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
++ /* resent information */
++ resp->AddressingReset = __constant_cpu_to_le32 (1);
++
++ if (rndis_per_dev_params [configNr].ack)
++ rndis_per_dev_params [configNr].ack (
++ rndis_per_dev_params [configNr].dev);
++
++ return 0;
++}
++
++static int rndis_keepalive_response (int configNr,
++ rndis_keepalive_msg_type *buf)
++{
++ rndis_keepalive_cmplt_type *resp;
++ rndis_resp_t *r;
++
++ /* host "should" check only in RNDIS_DATA_INITIALIZED state */
++
++ r = rndis_add_response (configNr, sizeof (rndis_keepalive_cmplt_type));
++ resp = (rndis_keepalive_cmplt_type *) r->buf;
++ if (!resp) return -ENOMEM;
++
++ resp->MessageType = __constant_cpu_to_le32 (
++ REMOTE_NDIS_KEEPALIVE_CMPLT);
++ resp->MessageLength = __constant_cpu_to_le32 (16);
++ resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
++ resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
++
++ if (rndis_per_dev_params [configNr].ack)
++ rndis_per_dev_params [configNr].ack (
++ rndis_per_dev_params [configNr].dev);
++
++ return 0;
++}
++
++
++/*
++ * Device to Host Comunication
++ */
++static int rndis_indicate_status_msg (int configNr, u32 status)
++{
++ rndis_indicate_status_msg_type *resp;
++ rndis_resp_t *r;
++
++ if (rndis_per_dev_params [configNr].state == RNDIS_UNINITIALIZED)
++ return -ENOTSUPP;
++
++ r = rndis_add_response (configNr,
++ sizeof (rndis_indicate_status_msg_type));
++ if (!r) return -ENOMEM;
++
++ resp = (rndis_indicate_status_msg_type *) r->buf;
++ if (!resp) return -ENOMEM;
++
++ resp->MessageType = __constant_cpu_to_le32 (
++ REMOTE_NDIS_INDICATE_STATUS_MSG);
++ resp->MessageLength = __constant_cpu_to_le32 (20);
++ resp->Status = cpu_to_le32 (status);
++ resp->StatusBufferLength = __constant_cpu_to_le32 (0);
++ resp->StatusBufferOffset = __constant_cpu_to_le32 (0);
++
++ if (rndis_per_dev_params [configNr].ack)
++ rndis_per_dev_params [configNr].ack (
++ rndis_per_dev_params [configNr].dev);
++ return 0;
++}
++
++int rndis_signal_connect (int configNr)
++{
++ rndis_per_dev_params [configNr].media_state
++ = NDIS_MEDIA_STATE_CONNECTED;
++ return rndis_indicate_status_msg (configNr,
++ RNDIS_STATUS_MEDIA_CONNECT);
++}
++
++int rndis_signal_disconnect (int configNr)
++{
++ rndis_per_dev_params [configNr].media_state
++ = NDIS_MEDIA_STATE_DISCONNECTED;
++ return rndis_indicate_status_msg (configNr,
++ RNDIS_STATUS_MEDIA_DISCONNECT);
++}
++
++void rndis_set_host_mac (int configNr, const u8 *addr)
++{
++ rndis_per_dev_params [configNr].host_mac = addr;
++}
++
++/*
++ * Message Parser
++ */
++int rndis_msg_parser (u8 configNr, u8 *buf)
++{
++ u32 MsgType, MsgLength, *tmp;
++ struct rndis_params *params;
++
++ if (!buf)
++ return -ENOMEM;
++
++ tmp = (u32 *) buf;
++ MsgType = cpu_to_le32p(tmp++);
++ MsgLength = cpu_to_le32p(tmp++);
++
++ if (configNr >= RNDIS_MAX_CONFIGS)
++ return -ENOTSUPP;
++ params = &rndis_per_dev_params [configNr];
++
++ /* For USB: responses may take up to 10 seconds */
++ switch (MsgType)
++ {
++ case REMOTE_NDIS_INITIALIZE_MSG:
++ DEBUG("%s: REMOTE_NDIS_INITIALIZE_MSG\n",
++ __FUNCTION__ );
++ params->state = RNDIS_INITIALIZED;
++ return rndis_init_response (configNr,
++ (rndis_init_msg_type *) buf);
++
++ case REMOTE_NDIS_HALT_MSG:
++ DEBUG("%s: REMOTE_NDIS_HALT_MSG\n",
++ __FUNCTION__ );
++ params->state = RNDIS_UNINITIALIZED;
++ if (params->dev) {
++ netif_carrier_off (params->dev);
++ netif_stop_queue (params->dev);
++ }
++ return 0;
++
++ case REMOTE_NDIS_QUERY_MSG:
++ return rndis_query_response (configNr,
++ (rndis_query_msg_type *) buf);
++
++ case REMOTE_NDIS_SET_MSG:
++ return rndis_set_response (configNr,
++ (rndis_set_msg_type *) buf);
++
++ case REMOTE_NDIS_RESET_MSG:
++ DEBUG("%s: REMOTE_NDIS_RESET_MSG\n",
++ __FUNCTION__ );
++ return rndis_reset_response (configNr,
++ (rndis_reset_msg_type *) buf);
++
++ case REMOTE_NDIS_KEEPALIVE_MSG:
++ /* For USB: host does this every 5 seconds */
++#ifdef VERBOSE
++ DEBUG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n",
++ __FUNCTION__ );
++#endif
++ return rndis_keepalive_response (configNr,
++ (rndis_keepalive_msg_type *)
++ buf);
++
++ default:
++ /* At least Windows XP emits some undefined RNDIS messages.
++ * In one case those messages seemed to relate to the host
++ * suspending itself.
++ */
++ printk (KERN_WARNING
++ "%s: unknown RNDIS message 0x%08X len %d\n",
++ __FUNCTION__ , MsgType, MsgLength);
++ {
++ unsigned i;
++ for (i = 0; i < MsgLength; i += 16) {
++ DEBUG ("%03d: "
++ " %02x %02x %02x %02x"
++ " %02x %02x %02x %02x"
++ " %02x %02x %02x %02x"
++ " %02x %02x %02x %02x"
++ "\n",
++ i,
++ buf[i], buf [i+1],
++ buf[i+2], buf[i+3],
++ buf[i+4], buf [i+5],
++ buf[i+6], buf[i+7],
++ buf[i+8], buf [i+9],
++ buf[i+10], buf[i+11],
++ buf[i+12], buf [i+13],
++ buf[i+14], buf[i+15]);
++ }
++ }
++ break;
++ }
++
++ return -ENOTSUPP;
++}
++
++int rndis_register (int (* rndis_control_ack) (struct net_device *))
++{
++ u8 i;
++
++ for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
++ if (!rndis_per_dev_params [i].used) {
++ rndis_per_dev_params [i].used = 1;
++ rndis_per_dev_params [i].ack = rndis_control_ack;
++ DEBUG("%s: configNr = %d\n", __FUNCTION__, i);
++ return i;
++ }
++ }
++ DEBUG("failed\n");
++
++ return -1;
++}
++
++void rndis_deregister (int configNr)
++{
++ DEBUG("%s: \n", __FUNCTION__ );
++
++ if (configNr >= RNDIS_MAX_CONFIGS) return;
++ rndis_per_dev_params [configNr].used = 0;
++
++ return;
++}
++
++int rndis_set_param_dev (u8 configNr, struct net_device *dev,
++ struct net_device_stats *stats)
++{
++ DEBUG("%s:\n", __FUNCTION__ );
++ if (!dev || !stats) return -1;
++ if (configNr >= RNDIS_MAX_CONFIGS) return -1;
++
++ rndis_per_dev_params [configNr].dev = dev;
++ rndis_per_dev_params [configNr].stats = stats;
++
++ return 0;
++}
++
++int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
++{
++ DEBUG("%s:\n", __FUNCTION__ );
++ if (!vendorDescr) return -1;
++ if (configNr >= RNDIS_MAX_CONFIGS) return -1;
++
++ rndis_per_dev_params [configNr].vendorID = vendorID;
++ rndis_per_dev_params [configNr].vendorDescr = vendorDescr;
++
++ return 0;
++}
++
++int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed)
++{
++ DEBUG("%s:\n", __FUNCTION__ );
++ if (configNr >= RNDIS_MAX_CONFIGS) return -1;
++
++ rndis_per_dev_params [configNr].medium = medium;
++ rndis_per_dev_params [configNr].speed = speed;
++
++ return 0;
++}
++
++void rndis_add_hdr (struct sk_buff *skb)
++{
++ if (!skb) return;
++ skb_push (skb, sizeof (struct rndis_packet_msg_type));
++ memset (skb->data, 0, sizeof (struct rndis_packet_msg_type));
++ *((u32 *) skb->data) = __constant_cpu_to_le32 (1);
++ *((u32 *) skb->data + 1) = cpu_to_le32(skb->len);
++ *((u32 *) skb->data + 2) = __constant_cpu_to_le32 (36);
++ *((u32 *) skb->data + 3) = cpu_to_le32(skb->len - 44);
++
++ return;
++}
++
++void rndis_free_response (int configNr, u8 *buf)
++{
++ rndis_resp_t *r;
++ struct list_head *act, *tmp;
++
++ list_for_each_safe (act, tmp,
++ &(rndis_per_dev_params [configNr].resp_queue))
++ {
++ r = list_entry (act, rndis_resp_t, list);
++ if (r && r->buf == buf) {
++ list_del (&r->list);
++ kfree (r);
++ }
++ }
++}
++
++u8 *rndis_get_next_response (int configNr, u32 *length)
++{
++ rndis_resp_t *r;
++ struct list_head *act, *tmp;
++
++ if (!length) return NULL;
++
++ list_for_each_safe (act, tmp,
++ &(rndis_per_dev_params [configNr].resp_queue))
++ {
++ r = list_entry (act, rndis_resp_t, list);
++ if (!r->send) {
++ r->send = 1;
++ *length = r->length;
++ return r->buf;
++ }
++ }
++
++ return NULL;
++}
++
++static rndis_resp_t *rndis_add_response (int configNr, u32 length)
++{
++ rndis_resp_t *r;
++
++ r = kmalloc (sizeof (rndis_resp_t) + length, GFP_ATOMIC);
++ if (!r) return NULL;
++
++ r->buf = (u8 *) (r + 1);
++ r->length = length;
++ r->send = 0;
++
++ list_add_tail (&r->list,
++ &(rndis_per_dev_params [configNr].resp_queue));
++ return r;
++}
++
++int rndis_rm_hdr (u8 *buf, u32 *length)
++{
++ u32 i, messageLen, dataOffset, *tmp;
++
++ tmp = (u32 *) buf;
++
++ if (!buf || !length) return -1;
++ if (cpu_to_le32p(tmp++) != 1) return -1;
++
++ messageLen = cpu_to_le32p(tmp++);
++ dataOffset = cpu_to_le32p(tmp++) + 8;
++
++ if (messageLen < dataOffset || messageLen > *length) return -1;
++
++ for (i = dataOffset; i < messageLen; i++)
++ buf [i - dataOffset] = buf [i];
++
++ *length = messageLen - dataOffset;
++
++ return 0;
++}
++
++#ifdef CONFIG_USB_GADGET_DEBUG_FILES
++
++static int rndis_proc_read (char *page, char **start, off_t off, int count, int *eof,
++ void *data)
++{
++ char *out = page;
++ int len;
++ rndis_params *param = (rndis_params *) data;
++
++ out += snprintf (out, count,
++ "Config Nr. %d\n"
++ "used : %s\n"
++ "state : %s\n"
++ "medium : 0x%08X\n"
++ "speed : %d\n"
++ "cable : %s\n"
++ "vendor ID : 0x%08X\n"
++ "vendor : %s\n",
++ param->confignr, (param->used) ? "y" : "n",
++ ({ char *s = "?";
++ switch (param->state) {
++ case RNDIS_UNINITIALIZED:
++ s = "RNDIS_UNINITIALIZED"; break;
++ case RNDIS_INITIALIZED:
++ s = "RNDIS_INITIALIZED"; break;
++ case RNDIS_DATA_INITIALIZED:
++ s = "RNDIS_DATA_INITIALIZED"; break;
++ }; s; }),
++ param->medium,
++ (param->media_state) ? 0 : param->speed*100,
++ (param->media_state) ? "disconnected" : "connected",
++ param->vendorID, param->vendorDescr);
++
++ len = out - page;
++ len -= off;
++
++ if (len < count) {
++ *eof = 1;
++ if (len <= 0)
++ return 0;
++ } else
++ len = count;
++
++ *start = page + off;
++ return len;
++}
++
++static int rndis_proc_write (struct file *file, const char __user *buffer,
++ unsigned long count, void *data)
++{
++ rndis_params *p = data;
++ u32 speed = 0;
++ int i, fl_speed = 0;
++
++ for (i = 0; i < count; i++) {
++ char c;
++ if (get_user(c, buffer))
++ return -EFAULT;
++ switch (c) {
++ case '0':
++ case '1':
++ case '2':
++ case '3':
++ case '4':
++ case '5':
++ case '6':
++ case '7':
++ case '8':
++ case '9':
++ fl_speed = 1;
++ speed = speed*10 + c - '0';
++ break;
++ case 'C':
++ case 'c':
++ rndis_signal_connect (p->confignr);
++ break;
++ case 'D':
++ case 'd':
++ rndis_signal_disconnect(p->confignr);
++ break;
++ default:
++ if (fl_speed) p->speed = speed;
++ else DEBUG ("%c is not valid\n", c);
++ break;
++ }
++
++ buffer++;
++ }
++
++ return count;
++}
++
++#define NAME_TEMPLATE "driver/rndis-%03d"
++
++static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS];
++
++#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
++
++
++int __init rndis_init (void)
++{
++ u8 i;
++
++ for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
++#ifdef CONFIG_USB_GADGET_DEBUG_FILES
++ char name [20];
++
++ sprintf (name, NAME_TEMPLATE, i);
++ if (!(rndis_connect_state [i]
++ = create_proc_entry (name, 0660, NULL)))
++ {
++ DEBUG ("%s :remove entries", __FUNCTION__);
++ while (i) {
++ sprintf (name, NAME_TEMPLATE, --i);
++ remove_proc_entry (name, NULL);
++ }
++ DEBUG ("\n");
++ return -EIO;
++ }
++
++ rndis_connect_state [i]->nlink = 1;
++ rndis_connect_state [i]->write_proc = rndis_proc_write;
++ rndis_connect_state [i]->read_proc = rndis_proc_read;
++ rndis_connect_state [i]->data = (void *)
++ (rndis_per_dev_params + i);
++#endif
++ rndis_per_dev_params [i].confignr = i;
++ rndis_per_dev_params [i].used = 0;
++ rndis_per_dev_params [i].state = RNDIS_UNINITIALIZED;
++ rndis_per_dev_params [i].media_state
++ = NDIS_MEDIA_STATE_DISCONNECTED;
++ INIT_LIST_HEAD (&(rndis_per_dev_params [i].resp_queue));
++ }
++
++ return 0;
++}
++
++void rndis_exit (void)
++{
++#ifdef CONFIG_USB_GADGET_DEBUG_FILES
++ u8 i;
++ char name [20];
++
++ for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
++ sprintf (name, NAME_TEMPLATE, i);
++ remove_proc_entry (name, NULL);
++ }
++#endif
++}
++
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/drivers/usb/gadget/rndis.h kernel/drivers/usb/gadget/rndis.h
+--- /tmp/kernel/drivers/usb/gadget/rndis.h 1970-01-01 01:00:00.000000000 +0100
++++ kernel/drivers/usb/gadget/rndis.h 2005-04-22 17:53:19.504528119 +0200
+@@ -0,0 +1,348 @@
++/*
++ * RNDIS Definitions for Remote NDIS
++ *
++ * Version: $Id: rndis.h,v 1.15 2004/03/25 21:33:46 robert Exp $
++ *
++ * Authors: Benedikt Spranger, Pengutronix
++ * Robert Schwebel, Pengutronix
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This software was originally developed in conformance with
++ * Microsoft's Remote NDIS Specification License Agreement.
++ */
++
++#ifndef _LINUX_RNDIS_H
++#define _LINUX_RNDIS_H
++
++#include "ndis.h"
++
++#define RNDIS_MAXIMUM_FRAME_SIZE 1518
++#define RNDIS_MAX_TOTAL_SIZE 1558
++
++/* Remote NDIS Versions */
++#define RNDIS_MAJOR_VERSION 1
++#define RNDIS_MINOR_VERSION 0
++
++/* Status Values */
++#define RNDIS_STATUS_SUCCESS 0x00000000U /* Success */
++#define RNDIS_STATUS_FAILURE 0xC0000001U /* Unspecified error */
++#define RNDIS_STATUS_INVALID_DATA 0xC0010015U /* Invalid data */
++#define RNDIS_STATUS_NOT_SUPPORTED 0xC00000BBU /* Unsupported request */
++#define RNDIS_STATUS_MEDIA_CONNECT 0x4001000BU /* Device connected */
++#define RNDIS_STATUS_MEDIA_DISCONNECT 0x4001000CU /* Device disconnected */
++/* For all not specified status messages:
++ * RNDIS_STATUS_Xxx -> NDIS_STATUS_Xxx
++ */
++
++/* Message Set for Connectionless (802.3) Devices */
++#define REMOTE_NDIS_INITIALIZE_MSG 0x00000002U /* Initialize device */
++#define REMOTE_NDIS_HALT_MSG 0x00000003U
++#define REMOTE_NDIS_QUERY_MSG 0x00000004U
++#define REMOTE_NDIS_SET_MSG 0x00000005U
++#define REMOTE_NDIS_RESET_MSG 0x00000006U
++#define REMOTE_NDIS_INDICATE_STATUS_MSG 0x00000007U
++#define REMOTE_NDIS_KEEPALIVE_MSG 0x00000008U
++
++/* Message completion */
++#define REMOTE_NDIS_INITIALIZE_CMPLT 0x80000002U
++#define REMOTE_NDIS_QUERY_CMPLT 0x80000004U
++#define REMOTE_NDIS_SET_CMPLT 0x80000005U
++#define REMOTE_NDIS_RESET_CMPLT 0x80000006U
++#define REMOTE_NDIS_KEEPALIVE_CMPLT 0x80000008U
++
++/* Device Flags */
++#define RNDIS_DF_CONNECTIONLESS 0x00000001U
++#define RNDIS_DF_CONNECTION_ORIENTED 0x00000002U
++
++#define RNDIS_MEDIUM_802_3 0x00000000U
++
++/* from drivers/net/sk98lin/h/skgepnmi.h */
++#define OID_PNP_CAPABILITIES 0xFD010100
++#define OID_PNP_SET_POWER 0xFD010101
++#define OID_PNP_QUERY_POWER 0xFD010102
++#define OID_PNP_ADD_WAKE_UP_PATTERN 0xFD010103
++#define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xFD010104
++#define OID_PNP_ENABLE_WAKE_UP 0xFD010106
++
++
++/* supported OIDs */
++static const u32 oid_supported_list [] =
++{
++ /* the general stuff */
++ OID_GEN_SUPPORTED_LIST,
++ OID_GEN_HARDWARE_STATUS,
++ OID_GEN_MEDIA_SUPPORTED,
++ OID_GEN_MEDIA_IN_USE,
++ OID_GEN_MAXIMUM_FRAME_SIZE,
++ OID_GEN_LINK_SPEED,
++ OID_GEN_TRANSMIT_BLOCK_SIZE,
++ OID_GEN_RECEIVE_BLOCK_SIZE,
++ OID_GEN_VENDOR_ID,
++ OID_GEN_VENDOR_DESCRIPTION,
++ OID_GEN_VENDOR_DRIVER_VERSION,
++ OID_GEN_CURRENT_PACKET_FILTER,
++ OID_GEN_MAXIMUM_TOTAL_SIZE,
++ OID_GEN_MEDIA_CONNECT_STATUS,
++ OID_GEN_PHYSICAL_MEDIUM,
++#if 0
++ OID_GEN_RNDIS_CONFIG_PARAMETER,
++#endif
++
++ /* the statistical stuff */
++ OID_GEN_XMIT_OK,
++ OID_GEN_RCV_OK,
++ OID_GEN_XMIT_ERROR,
++ OID_GEN_RCV_ERROR,
++ OID_GEN_RCV_NO_BUFFER,
++#ifdef RNDIS_OPTIONAL_STATS
++ OID_GEN_DIRECTED_BYTES_XMIT,
++ OID_GEN_DIRECTED_FRAMES_XMIT,
++ OID_GEN_MULTICAST_BYTES_XMIT,
++ OID_GEN_MULTICAST_FRAMES_XMIT,
++ OID_GEN_BROADCAST_BYTES_XMIT,
++ OID_GEN_BROADCAST_FRAMES_XMIT,
++ OID_GEN_DIRECTED_BYTES_RCV,
++ OID_GEN_DIRECTED_FRAMES_RCV,
++ OID_GEN_MULTICAST_BYTES_RCV,
++ OID_GEN_MULTICAST_FRAMES_RCV,
++ OID_GEN_BROADCAST_BYTES_RCV,
++ OID_GEN_BROADCAST_FRAMES_RCV,
++ OID_GEN_RCV_CRC_ERROR,
++ OID_GEN_TRANSMIT_QUEUE_LENGTH,
++#endif /* RNDIS_OPTIONAL_STATS */
++
++ /* mandatory 802.3 */
++ /* the general stuff */
++ OID_802_3_PERMANENT_ADDRESS,
++ OID_802_3_CURRENT_ADDRESS,
++ OID_802_3_MULTICAST_LIST,
++ OID_802_3_MAC_OPTIONS,
++ OID_802_3_MAXIMUM_LIST_SIZE,
++
++ /* the statistical stuff */
++ OID_802_3_RCV_ERROR_ALIGNMENT,
++ OID_802_3_XMIT_ONE_COLLISION,
++ OID_802_3_XMIT_MORE_COLLISIONS,
++#ifdef RNDIS_OPTIONAL_STATS
++ OID_802_3_XMIT_DEFERRED,
++ OID_802_3_XMIT_MAX_COLLISIONS,
++ OID_802_3_RCV_OVERRUN,
++ OID_802_3_XMIT_UNDERRUN,
++ OID_802_3_XMIT_HEARTBEAT_FAILURE,
++ OID_802_3_XMIT_TIMES_CRS_LOST,
++ OID_802_3_XMIT_LATE_COLLISIONS,
++#endif /* RNDIS_OPTIONAL_STATS */
++
++#ifdef RNDIS_PM
++ /* PM and wakeup are mandatory for USB: */
++
++ /* power management */
++ OID_PNP_CAPABILITIES,
++ OID_PNP_QUERY_POWER,
++ OID_PNP_SET_POWER,
++
++ /* wake up host */
++ OID_PNP_ENABLE_WAKE_UP,
++ OID_PNP_ADD_WAKE_UP_PATTERN,
++ OID_PNP_REMOVE_WAKE_UP_PATTERN,
++#endif
++};
++
++
++typedef struct rndis_init_msg_type
++{
++ u32 MessageType;
++ u32 MessageLength;
++ u32 RequestID;
++ u32 MajorVersion;
++ u32 MinorVersion;
++ u32 MaxTransferSize;
++} rndis_init_msg_type;
++
++typedef struct rndis_init_cmplt_type
++{
++ u32 MessageType;
++ u32 MessageLength;
++ u32 RequestID;
++ u32 Status;
++ u32 MajorVersion;
++ u32 MinorVersion;
++ u32 DeviceFlags;
++ u32 Medium;
++ u32 MaxPacketsPerTransfer;
++ u32 MaxTransferSize;
++ u32 PacketAlignmentFactor;
++ u32 AFListOffset;
++ u32 AFListSize;
++} rndis_init_cmplt_type;
++
++typedef struct rndis_halt_msg_type
++{
++ u32 MessageType;
++ u32 MessageLength;
++ u32 RequestID;
++} rndis_halt_msg_type;
++
++typedef struct rndis_query_msg_type
++{
++ u32 MessageType;
++ u32 MessageLength;
++ u32 RequestID;
++ u32 OID;
++ u32 InformationBufferLength;
++ u32 InformationBufferOffset;
++ u32 DeviceVcHandle;
++} rndis_query_msg_type;
++
++typedef struct rndis_query_cmplt_type
++{
++ u32 MessageType;
++ u32 MessageLength;
++ u32 RequestID;
++ u32 Status;
++ u32 InformationBufferLength;
++ u32 InformationBufferOffset;
++} rndis_query_cmplt_type;
++
++typedef struct rndis_set_msg_type
++{
++ u32 MessageType;
++ u32 MessageLength;
++ u32 RequestID;
++ u32 OID;
++ u32 InformationBufferLength;
++ u32 InformationBufferOffset;
++ u32 DeviceVcHandle;
++} rndis_set_msg_type;
++
++typedef struct rndis_set_cmplt_type
++{
++ u32 MessageType;
++ u32 MessageLength;
++ u32 RequestID;
++ u32 Status;
++} rndis_set_cmplt_type;
++
++typedef struct rndis_reset_msg_type
++{
++ u32 MessageType;
++ u32 MessageLength;
++ u32 Reserved;
++} rndis_reset_msg_type;
++
++typedef struct rndis_reset_cmplt_type
++{
++ u32 MessageType;
++ u32 MessageLength;
++ u32 Status;
++ u32 AddressingReset;
++} rndis_reset_cmplt_type;
++
++typedef struct rndis_indicate_status_msg_type
++{
++ u32 MessageType;
++ u32 MessageLength;
++ u32 Status;
++ u32 StatusBufferLength;
++ u32 StatusBufferOffset;
++} rndis_indicate_status_msg_type;
++
++typedef struct rndis_keepalive_msg_type
++{
++ u32 MessageType;
++ u32 MessageLength;
++ u32 RequestID;
++} rndis_keepalive_msg_type;
++
++typedef struct rndis_keepalive_cmplt_type
++{
++ u32 MessageType;
++ u32 MessageLength;
++ u32 RequestID;
++ u32 Status;
++} rndis_keepalive_cmplt_type;
++
++struct rndis_packet_msg_type
++{
++ u32 MessageType;
++ u32 MessageLength;
++ u32 DataOffset;
++ u32 DataLength;
++ u32 OOBDataOffset;
++ u32 OOBDataLength;
++ u32 NumOOBDataElements;
++ u32 PerPacketInfoOffset;
++ u32 PerPacketInfoLength;
++ u32 VcHandle;
++ u32 Reserved;
++};
++
++struct rndis_config_parameter
++{
++ u32 ParameterNameOffset;
++ u32 ParameterNameLength;
++ u32 ParameterType;
++ u32 ParameterValueOffset;
++ u32 ParameterValueLength;
++};
++
++/* implementation specific */
++enum rndis_state
++{
++ RNDIS_UNINITIALIZED,
++ RNDIS_INITIALIZED,
++ RNDIS_DATA_INITIALIZED,
++};
++
++typedef struct rndis_resp_t
++{
++ struct list_head list;
++ u8 *buf;
++ u32 length;
++ int send;
++} rndis_resp_t;
++
++typedef struct rndis_params
++{
++ u8 confignr;
++ int used;
++ enum rndis_state state;
++ u32 filter;
++ u32 medium;
++ u32 speed;
++ u32 media_state;
++ const u8 *host_mac;
++ struct net_device *dev;
++ struct net_device_stats *stats;
++ u32 vendorID;
++ const char *vendorDescr;
++ int (*ack) (struct net_device *);
++ struct list_head resp_queue;
++} rndis_params;
++
++/* RNDIS Message parser and other useless functions */
++int rndis_msg_parser (u8 configNr, u8 *buf);
++int rndis_register (int (*rndis_control_ack) (struct net_device *));
++void rndis_deregister (int configNr);
++int rndis_set_param_dev (u8 configNr, struct net_device *dev,
++ struct net_device_stats *stats);
++int rndis_set_param_vendor (u8 configNr, u32 vendorID,
++ const char *vendorDescr);
++int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed);
++void rndis_add_hdr (struct sk_buff *skb);
++int rndis_rm_hdr (u8 *buf, u32 *length);
++u8 *rndis_get_next_response (int configNr, u32 *length);
++void rndis_free_response (int configNr, u8 *buf);
++
++int rndis_signal_connect (int configNr);
++int rndis_signal_disconnect (int configNr);
++int rndis_state (int configNr);
++extern void rndis_set_host_mac (int configNr, const u8 *addr);
++
++int __init rndis_init (void);
++void rndis_exit (void);
++
++#endif /* _LINUX_RNDIS_H */
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/drivers/usb/gadget/superh_udc.c kernel/drivers/usb/gadget/superh_udc.c
+--- /tmp/kernel/drivers/usb/gadget/superh_udc.c 1970-01-01 01:00:00.000000000 +0100
++++ kernel/drivers/usb/gadget/superh_udc.c 2005-04-22 17:53:19.510527142 +0200
+@@ -0,0 +1,1819 @@
++/*
++ * Renesas SuperH USB 1.1 device controller (found on SH7705, SH7727...)
++ *
++ * Copyright (C) 2003 Renesas Technology Europe Limited
++ * Copyright (C) 2003 Julian Back (jback@mpc-data.co.uk), MPC Data Limited
++ *
++ * 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
++ */
++
++/*
++ * This is a driver for the USB Device Controller found on Renesas SH
++ * processors. This is a full-speed controller which has four
++ * endpoints in a single fixed configuration.
++ *
++ * Limitations
++ *
++ * Only tested on SH7705. Mostly tested with Mass Storage gadget
++ * using Bulk-Only Transport. It has been tested with Linux 2.4,
++ * Linux 2.6, Windows 2000 and Windows XP hosts.
++ *
++ * DMA is not (yet) implemented.
++ *
++ * Handling of application stalls is tricky. We set a bit to stall an
++ * endpoint. When the host tries to access the ep it gets a stall and
++ * another stall bit is latched by the device. The host clears the
++ * stall with a clear feature but the hardware doesn't inform us, the
++ * latched bit is cleared but not the bit we have set, so the next
++ * time the host accesses the ep it will get another stall and the
++ * latch will be set again unless we have cleared our stall bit. The
++ * solution adopted in this driver is to use a timer to clear the
++ * application stall bit some time after setting the stall. This
++ * seems to work most of the time but is not 100% reliable. Because
++ * of this it is best to avoid USB protocols that require the USB
++ * device to stall the host. Unfortunately USB mass storage does
++ * require the device to stall when it gets unsupported commands,
++ * Linux hosts don't send any of these unsupported commands but
++ * Windows hosts do.
++ *
++ * Another place where the hardware is too clever is in the handling
++ * of setup packets. Many setup packets including SET_INTERFACE and
++ * SET_CONFIGURATION are handled by the hardware without informing the
++ * driver software. But we need to inform the gadget driver of at
++ * least one of these as it uses this to kick of it's data processing.
++ * The solution adopted is that after we have recieved N setup packets
++ * following a bus reset a fake SET_CONFIGURATION is sent to the
++ * gadget. We also have to arrange things so that the reply to the
++ * fake packet is not sent out.
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/ioport.h>
++#include <linux/types.h>
++#include <linux/version.h>
++#include <linux/errno.h>
++#include <linux/delay.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/timer.h>
++#include <linux/list.h>
++#include <linux/interrupt.h>
++#include <linux/proc_fs.h>
++#include <linux/mm.h>
++
++#include <asm/atomic.h>
++#include <asm/byteorder.h>
++#include <asm/dma.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/system.h>
++#include <asm/unaligned.h>
++
++#include <linux/usb_ch9.h>
++#include <linux/usb_gadget.h>
++
++#undef DEBUG
++#undef VERY_NOISY
++
++#define DRIVER_DESC "SuperH USB Peripheral Controller"
++#define DRIVER_VERSION "alpha (11 November 2003)"
++
++#ifdef USE_DMA
++#error "DMA not supported"
++#endif
++
++static const char driver_name [] = "superh_udc";
++static const char driver_desc [] = DRIVER_DESC;
++
++static const char ep0name [] = "ep0";
++static const char *ep_name [] = {
++ ep0name,
++ "ep1out-bulk",
++ "ep2in-bulk",
++ "ep3in-bulk",
++};
++
++static struct superh_udc *the_controller;
++
++#include "superh_udc.h"
++
++/* High priority interrupts */
++#define F0_HIGH (EP1_FULL | EP2_TR | EP2_EMPTY )
++#define F1_HIGH (0)
++
++/* Low priority interrupts */
++#define F0_LOW (BRST | SETUP_TS | EP0o_TS | EP0i_TR | EP0i_TS)
++#define F1_LOW (EP3_TR | EP3_TS | VBUSF)
++
++/* How long to leave the stall bit set - this value is quite critical
++ * to making stalls work. Unfortunately it doesn't seem possible to
++ * get a value that will work reliably with both fast and slow
++ * machines.
++ */
++#define STALL_TIME (HZ/75)
++
++/* Number of endpoints to check in the unstall timer. It should not
++ * be necessary to unstall bulk endpoints using the timer as long as
++ * the gadget code is aware that this device cannot stall properly
++ * (see the file backed storage gadget for an example). But if the
++ * UDC driver stalls ep0 due to a bad SETUP then the timer is still
++ * required otherwise the stall will never get cleared. If it is
++ * necessary to unstall all endpoints using the timer then set this to
++ * 4.
++ */
++#define EP_TO_UNSTALL 1
++
++/* Number of packets to wait for before sending a fake
++ * SET_CONFIGURATION to the gadget driver
++ */
++#define DEFAULT_SETUP_COUNT 7
++#define RESET_SETUP_COUNT 2
++
++/* How long to wait for the number of packets specified above */
++#define SETUP_TIME (HZ/10 )
++
++static void superh_ep_fifo_flush(struct usb_ep *_ep);
++static void stop_activity(struct superh_udc *dev, struct usb_gadget_driver *driver);
++static int superh_ep_set_halt(struct usb_ep *_ep, int value);
++static void udc_timer(unsigned long _dev);
++static struct superh_request* process_ep_req(struct superh_ep *ep,
++ struct superh_request *req);
++static void done(struct superh_ep *ep, struct superh_request *req, int status);
++
++/*
++ * IO
++ */
++
++static inline void and_b(u8 mask, unsigned long addr)
++{
++ ctrl_outb(ctrl_inb(addr) & mask, addr);
++}
++
++
++static inline void or_b(u8 mask, unsigned long addr)
++{
++ ctrl_outb(ctrl_inb(addr) | mask, addr);
++}
++
++
++static inline void ep0_idle (struct superh_udc *dev)
++{
++ DBG(DBG_VERY_NOISY, "ep0_idle\n");
++ dev->ep0state = EP0_IDLE;
++}
++
++
++static void init_udc_timer(struct superh_udc *dev)
++{
++ init_timer(&dev->timer);
++ dev->timer.function = udc_timer;
++ dev->timer.data = (unsigned long) dev;
++ dev->timer.expires = jiffies + STALL_TIME;
++ add_timer(&dev->timer);
++}
++
++/* Send a fake SET_CONFIGURATION to the gadget to start it up.
++ * Needed because the hardware doesn't let us know when the real packet
++ * has arrived.
++ */
++static void send_fake_config(struct superh_udc *dev)
++{
++ struct usb_ctrlrequest r;
++ dev->fake_config = 1;
++ dev->setup_countdown = 0;
++ r.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD
++ | USB_RECIP_DEVICE;
++ r.bRequest = USB_REQ_SET_CONFIGURATION;
++ r.wValue = 1; /* configuration to select */
++ r.wIndex = 0;
++ r.wLength = 0;
++ if (dev->driver->setup(&dev->gadget, &r) < 0) {
++ DMSG("SET_CONFIGURATION failed.\n");
++ }
++}
++
++/*
++ * Timer function. Clears stall from any stalled endpoints as we
++ * don't get informed when the host has sent a clear feature.
++ */
++static void udc_timer(unsigned long _dev)
++{
++ struct superh_udc *dev = (void *)_dev;
++ int i;
++ unsigned long flags;
++
++ local_irq_save(flags);
++
++ if (atomic_read(&dev->in_interrupt) == 0) {
++
++ /* Check if a bus reset has been done and we haven't faked a SET_CONFIGURATION */
++ if (dev->gadget.speed != USB_SPEED_UNKNOWN
++ && dev->setup_countdown > 0
++ && jiffies - dev->reset_time > SETUP_TIME
++ &&list_empty(&dev->ep[0].queue)) {
++ send_fake_config(dev);
++ }
++
++ /* Check if any end points are halted and restart them */
++ for (i = 0; i < EP_TO_UNSTALL; i++) {
++ struct superh_ep *ep = &dev->ep[i];
++ if (ep->halted) {
++ DBG(DBG_VERBOSE, "unstalling ep %d\n", i);
++ superh_ep_set_halt(&ep->ep, 0);
++ if (likely (!list_empty(&ep->queue))) {
++ struct superh_request *req
++ = list_entry(ep->queue.next,
++ struct superh_request, queue);
++ process_ep_req(ep, req);
++ }
++ }
++ }
++ }
++
++ init_udc_timer(dev);
++
++ local_irq_restore(flags);
++}
++
++/*
++ * done - retire a request; caller blocked irqs
++ */
++static void done(struct superh_ep *ep, struct superh_request *req, int status)
++{
++ unsigned stopped = ep->stopped;
++
++ DBG(DBG_NOISY, "done: %s %p %d\n", ep->ep.name, req, status);
++
++ list_del_init(&req->queue);
++
++ if (likely (req->req.status == -EINPROGRESS))
++ req->req.status = status;
++ else
++ status = req->req.status;
++
++ if (status && status != -ESHUTDOWN)
++ DBG(DBG_VERBOSE, "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;
++ req->req.complete(&ep->ep, &req->req);
++ ep->stopped = stopped;
++}
++
++/*
++ * Enable interrupts for the specified endpoint
++ */
++static inline void pio_irq_enable(struct superh_ep *ep)
++{
++ or_b(ep->interrupt_mask, ep->interrupt_reg);
++}
++
++/*
++ * Disable interrupts for the specified endpoint
++ */
++static inline void pio_irq_disable(struct superh_ep *ep)
++{
++ and_b(~ep->interrupt_mask, ep->interrupt_reg);
++}
++
++/*
++ * nuke - dequeue ALL requests
++ */
++static void nuke(struct superh_ep *ep, int status)
++{
++ struct superh_request *req;
++
++ DBG(DBG_NOISY, "nuke %s %d\n", ep->ep.name, status);
++
++ /* called with irqs blocked */
++#ifdef USE_DMA
++ if (ep->dma >= 0 && !ep->stopped)
++ cancel_dma(ep);
++#endif
++ while (!list_empty(&ep->queue)) {
++ req = list_entry(ep->queue.next,
++ struct superh_request,
++ queue);
++ done(ep, req, status);
++ }
++
++ if (ep->desc)
++ pio_irq_disable (ep);
++}
++
++static inline void clear_ep_state (struct superh_udc *dev)
++{
++ unsigned i;
++
++ /* hardware SET_{CONFIGURATION,INTERFACE} automagic resets endpoint
++ * fifos, and pending transactions mustn't be continued in any case.
++ */
++ for (i = 1; i < 4; i++)
++ nuke(&dev->ep[i], -ECONNABORTED);
++}
++
++/*
++ * write a packet to an endpoint data register
++ */
++static int
++write_packet(u32 epdr, struct superh_request *req, unsigned max)
++{
++ u8 *buf;
++ unsigned length, count;
++
++ buf = req->req.buf + req->req.actual;
++ prefetch(buf);
++
++ /* how big will this packet be? */
++ length = min(req->req.length - req->req.actual, max);
++ req->req.actual += length;
++
++ count = length;
++ while (likely(count--))
++ ctrl_outb(*buf++, epdr);
++
++ return length;
++}
++
++static int
++write_ep0_fifo (struct superh_ep *ep, struct superh_request *req)
++{
++ unsigned count;
++ int is_short;
++
++ count = write_packet(USBEPDR0I, req, EP0_FIFO_SIZE);
++ ep->dev->stats.write.bytes += count;
++
++ /* last packet "must be" short (or a zlp) */
++ is_short = (count != EP0_FIFO_SIZE);
++
++ DBG(DBG_VERY_NOISY, "ep0in %d bytes %d left %p\n", count,
++ req->req.length - req->req.actual, req);
++
++ ctrl_outb(EP0i_PKTE, USBTRG);
++
++ if (unlikely (is_short)) {
++ ep->dev->ep0state = EP0_END_XFER;
++
++ count = req->req.length;
++ done (ep, req, 0);
++ /*
++ * If we have received a specified number of setups
++ * after a bus reset or connect then fake a
++ * SET_CONFIGURATION to the driver (as we don't get
++ * them from the hardware).
++ */
++ if (ep->dev->setup_countdown >= 0)
++ ep->dev->setup_countdown--;
++ if (ep->dev->setup_countdown == 0) {
++ send_fake_config(ep->dev);
++ }
++ }
++
++ return is_short;
++}
++
++/*
++ * handle_ep0_setup
++ *
++ * Handles a SETUP request on EP0
++ */
++static void handle_ep0_setup(struct superh_udc* dev)
++{
++ int i;
++ union { u8 raw [8]; struct usb_ctrlrequest r; } u;
++
++ for (i = 0; i < 8; i++) {
++ u.raw[i] = ctrl_inb(USBEPDR0S);
++ }
++
++ /* Send ACK */
++ ctrl_outb(EP0s_RDFN, USBTRG);
++
++ le16_to_cpus (&u.r.wValue);
++ le16_to_cpus (&u.r.wIndex);
++ le16_to_cpus (&u.r.wLength);
++
++ DBG(DBG_VERBOSE, "SETUP %02x.%02x v%04x i%04x l%04x\n",
++ u.r.bRequestType, u.r.bRequest,
++ u.r.wValue, u.r.wIndex, u.r.wLength);
++
++ if (u.r.bRequestType & USB_DIR_IN) {
++ DBG(DBG_VERY_NOISY, "handle_ep0_setup: EP0_IN_DATA_PHASE\n");
++ dev->ep0state = EP0_IN_DATA_PHASE;
++ }
++ else {
++ DBG(DBG_VERY_NOISY, "handle_ep0_setup: EP0_OUT_DATA_PHASE\n");
++ dev->ep0state = EP0_OUT_DATA_PHASE;
++ }
++
++ i = dev->driver->setup(&dev->gadget, &u.r);
++ if (i < 0) {
++ DMSG("SETUP %02x.%02x v%04x i%04x l%04x failed\n",
++ u.r.bRequestType, u.r.bRequest,
++ u.r.wValue, u.r.wIndex, u.r.wLength);
++ superh_ep_set_halt(&dev->ep[0].ep, 1);
++ }
++}
++
++/*
++ * write to an IN endpoint fifo, as many packets as possible.
++ * irqs will use this to write the rest later.
++ * caller guarantees at least one packet buffer is ready.
++ */
++static int
++write_fifo (struct superh_ep *ep, struct superh_request *req)
++{
++ unsigned max;
++
++ DBG(DBG_VERY_NOISY, "write_fifo\n");
++
++ if ((ep->bEndpointAddress & USB_DIR_IN) != USB_DIR_IN) {
++ DMSG("write_fifo from invalid EP (%s)\n", ep->ep.name);
++ return -EINVAL;
++ }
++
++ max = ep->desc->wMaxPacketSize;
++ do {
++ unsigned count;
++ int is_last, is_short;
++
++ count = write_packet(ep->fifo_reg, req, max);
++
++ /* last packet is usually short (or a zlp) */
++ if (unlikely (count != max))
++ is_last = is_short = 1;
++ else {
++ if (likely(req->req.length != req->req.actual)
++ || req->req.zero)
++ is_last = 0;
++ else
++ is_last = 1;
++ /* interrupt/iso maxpacket may not fill the fifo */
++ is_short = unlikely (max < ep->ep.maxpacket);
++
++ /* FIXME ep.maxpacket should be the current size,
++ * modified (for periodic endpoints) when the
++ * ep is enabled. do that, re-init as needed,
++ * and change maxpacket refs accordingly.
++ */
++ }
++
++ DBG(DBG_VERY_NOISY, "wrote %s %d bytes%s%s %d left %p\n",
++ ep->ep.name, count,
++ is_last ? "/L" : "", is_short ? "/S" : "",
++ req->req.length - req->req.actual, req);
++
++ /* let loose that packet. maybe try writing another one,
++ * double buffering might work.
++ */
++ or_b(ep->packet_enable_mask, USBTRG);
++
++ /* requests complete when all IN data is in the FIFO */
++ if (is_last) {
++ done (ep, req, 0);
++ if (list_empty(&ep->queue) || unlikely(ep->dma >= 0)) {
++ pio_irq_disable (ep);
++ }
++#ifdef USE_DMA
++ /* TODO */
++ if (unlikely(ep->dma >= 0) && !list_empty(&ep->queue)) {
++ DMSG("%s pio2dma\n", ep->ep.name);
++ req = list_entry(ep->queue.next,
++ struct superh_request, queue);
++ kick_dma(ep,req);
++ return 0;
++ }
++#endif
++ return 1;
++ }
++ /* Only loop if on EP2 as it is double buffered */
++ } while (ep->bEndpointAddress == (2|USB_DIR_IN)
++ && ctrl_inb(USBIFR0) & EP2_EMPTY);
++ return 0;
++}
++
++/*
++ * read_ep0_fifo - unload packets from ep0 control-out fifo. caller
++ * should have made sure there's at least one packet ready.
++ *
++ * returns true if the request completed because of short packet or the
++ * request buffer having filled (and maybe overran till end-of-packet).
++ */
++static int
++read_ep0_fifo(struct superh_ep *ep, struct superh_request *req)
++{
++ u8 *buf;
++ unsigned bufferspace, count;
++
++ DBG(DBG_VERY_NOISY, "read_ep0_fifo\n");
++
++ if (!ep) {
++ DMSG("read_ep0_fifo invalid ep\n");
++ return -EINVAL;
++ }
++
++ if (!req) {
++ DMSG("read_ep0_fifo invalid req\n");
++ return -EINVAL;
++ }
++
++ if (ep->desc != 0) {
++ DMSG("read_ep0_fifo from invalid EP (%s)\n", ep->ep.name);
++ return -EINVAL;
++ }
++
++ /* make sure there's a packet in the FIFO.
++ */
++ if (likely ((ctrl_inb(USBIFR0) & EP0o_TS) == 0)) {
++ buf = req->req.buf + req->req.actual;
++ bufferspace = req->req.length - req->req.actual;
++
++ /* read all bytes from this packet */
++ count = ctrl_inb(USBEPSZ0O);
++ req->req.actual += min (count, bufferspace);
++ DBG(DBG_VERY_NOISY, "read %s %d bytes req %p %d/%d\n",
++ ep->ep.name, count,
++ req, req->req.actual, req->req.length);
++ while (likely (count-- != 0)) {
++ u8 byte = ctrl_inb(USBEPDR0O);
++
++ if (unlikely (bufferspace == 0)) {
++ /* this happens when the driver's buffer
++ * is smaller than what the host sent.
++ * discard the extra data.
++ */
++ if (req->req.status != -EOVERFLOW)
++ DMSG("%s overflow %d\n",
++ ep->ep.name, count);
++ req->req.status = -EOVERFLOW;
++ } else {
++ *buf++ = byte;
++ bufferspace--;
++ }
++ }
++
++ /* Send ACK */
++ or_b(EP0o_RDFN, USBTRG);
++
++ /* completion */
++ if (req->req.actual >= req->req.length) {
++ done (ep, req, 0);
++ ep0_idle(ep->dev);
++ return 1;
++ }
++ }
++
++ return 0;
++}
++
++/*
++ * read_fifo - unload packet(s) from the fifo we use for usb OUT
++ * transfers and put them into the request. caller should have made
++ * sure there's at least one packet ready.
++ *
++ * returns true if the request completed because of short packet or the
++ * request buffer having filled (and maybe overran till end-of-packet).
++ */
++static int
++read_fifo (struct superh_ep *ep, struct superh_request *req)
++{
++ DBG(DBG_VERY_NOISY, "read_fifo\n");
++
++ if ((ep->bEndpointAddress & 0x0f) != 1) {
++ DMSG("read_fifo from invalid EP (%s)\n", ep->ep.name);
++ return -EINVAL;
++ }
++
++ for (;;) {
++ u8 *buf;
++ unsigned bufferspace, count, is_short;
++
++ /* make sure there's a packet in the FIFO.
++ */
++ if (unlikely ((ctrl_inb(USBIFR0) & EP1_FULL) == 0))
++ break;
++ buf = req->req.buf + req->req.actual;
++ bufferspace = req->req.length - req->req.actual;
++
++ /* read all bytes from this packet */
++ count = ctrl_inb(USBEPSZ1);
++ req->req.actual += min (count, bufferspace);
++ is_short = (count < ep->desc->wMaxPacketSize);
++ DBG(DBG_VERY_NOISY, "read %s %d bytes%s req %p %d/%d\n",
++ ep->ep.name, count,
++ is_short ? "/S" : "",
++ req, req->req.actual, req->req.length);
++ while (likely (count-- != 0)) {
++ u8 byte = ctrl_inb(USBEPDR1);
++
++ if (unlikely (bufferspace == 0)) {
++ /* this happens when the driver's buffer
++ * is smaller than what the host sent.
++ * discard the extra data.
++ */
++ if (req->req.status != -EOVERFLOW)
++ DMSG("%s overflow %d\n",
++ ep->ep.name, count);
++ req->req.status = -EOVERFLOW;
++ } else {
++ *buf++ = byte;
++ bufferspace--;
++ }
++ }
++
++ or_b(EP1_RDFN, USBTRG);
++ /* There could now be another packet because of dual buffer */
++
++ /* completion */
++ if (is_short || req->req.actual == req->req.length) {
++ done (ep, req, 0);
++ if (list_empty(&ep->queue))
++ pio_irq_disable (ep);
++ return 1;
++ }
++
++ /* finished that packet. the next one may be waiting... */
++ }
++ return 0;
++}
++
++/*--------------------------------------------------------------------------*/
++/* Interrupt Handler(s)
++ */
++
++/*
++ * superh_udc_irq_f0 - high priority interrupt handler
++ * this deals with data to & from the bulk pipes
++ */
++static void superh_udc_irq_f0(int irq, void *_dev, struct pt_regs *regs)
++{
++ unsigned char f0_status;
++ struct superh_udc *dev = (struct superh_udc*) _dev;
++ struct superh_request *req;
++ struct superh_ep *ep;
++
++ DBG(DBG_NOISY, "superh_udc_irq_f0 %p\n", dev);
++
++ atomic_inc(&dev->in_interrupt);
++
++ dev->stats.irqs++;
++ dev->stats.irq0s++;
++ f0_status = ctrl_inb(USBIFR0);
++
++ /* Acknowledge interrupts */
++ ctrl_outb(~(f0_status & F0_HIGH), USBIFR0);
++
++ if (f0_status & EP1_FULL) {
++ DBG(DBG_NOISY, "superh_udc_irq_f0 %p: EP1 FULL\n", dev);
++ ep = &dev->ep[1];
++
++ if (likely (!list_empty(&ep->queue)))
++ req = list_entry(ep->queue.next,
++ struct superh_request, queue);
++ else
++ req = 0;
++
++ if (req)
++ read_fifo(ep, req);
++ else
++ pio_irq_disable(ep);
++ }
++
++ if ( f0_status & (EP2_TR | EP2_EMPTY) ) {
++ DBG(DBG_NOISY, "superh_udc_irq_f0 %p: EP2 TR | EP2_EMPTY\n", dev);
++ ep = &dev->ep[2];
++
++ if (likely (!list_empty(&ep->queue)))
++ req = list_entry(ep->queue.next,
++ struct superh_request, queue);
++ else
++ req = 0;
++
++ if (req) {
++ if ((f0_status & EP2_TR) && (f0_status & EP2_EMPTY))
++ write_fifo(ep, req);
++ else
++ and_b(~EP2_EMPTY, USBIER0);
++
++ }
++ else {
++ pio_irq_disable(ep);
++ }
++ }
++
++ atomic_dec(&dev->in_interrupt);
++}
++
++/**
++ * superh_udc_irq_f1 - low priority interrupt handler
++ *
++ */
++static void superh_udc_irq_f1(int irq, void *_dev, struct pt_regs *regs)
++{
++ unsigned char f0_status;
++ unsigned char f1_status;
++ struct superh_udc *dev = (struct superh_udc*) _dev;
++
++ atomic_inc(&dev->in_interrupt);;
++
++ dev->stats.irqs++;
++ dev->stats.irq1s++;
++
++ f0_status = ctrl_inb(USBIFR0);
++ f1_status = ctrl_inb(USBIFR1);
++
++ /* Acknowledge interrupts */
++ ctrl_outb(~(f0_status & F0_LOW), USBIFR0);
++ ctrl_outb(~(f1_status & F1_LOW), USBIFR1);
++
++ /* VBUSF indicates the USB being connected/disconnected */
++ if (f1_status & VBUSF) {
++ DBG(DBG_VERY_NOISY, "superh_udc_irq_f1[%lx] VBUSF\n", dev->stats.irqs);
++ if (!is_usb_connected) {
++ /* report disconnect just once */
++ if (dev->gadget.speed != USB_SPEED_UNKNOWN) {
++ DMSG("disconnect %s\n",
++ dev->driver ? dev->driver->driver.name : 0);
++ stop_activity(dev, dev->driver);
++ }
++ }
++ else if (dev->gadget.speed == USB_SPEED_UNKNOWN) {
++ DMSG("connect\n");
++ dev->setup_countdown = DEFAULT_SETUP_COUNT;
++ }
++ }
++
++
++
++ /* Bus Reset */
++ if (f0_status & BRST) {
++ int i;
++ DBG(DBG_VERBOSE, "superh_udc_irq_f1[%lx]: BRST bus reset\n", dev->stats.irqs);
++ /* kill any outstanding requests */
++ for (i = 0; i < 4; i++) {
++ struct superh_ep *ep = &dev->ep[i];
++ nuke(ep, -ESHUTDOWN);
++ ep->halted = 0;
++ ep->stopped = 0;
++ }
++
++ /* reset fifo's and stall's */
++ ctrl_outb( EP3_CLEAR | EP1_CLEAR | EP2_CLEAR | EP0o_CLEAR | EP0i_CLEAR, USBFCLR );
++ ctrl_outb( 0, USBEPSTL );
++ DMSG("gadget driver '%s', address zero\n", dev->driver->driver.name);
++ if (dev->gadget.speed == USB_SPEED_UNKNOWN)
++ init_udc_timer(dev);
++ dev->gadget.speed = USB_SPEED_FULL;
++ memset(&dev->stats, 0, sizeof dev->stats);
++ if (dev->setup_countdown < 0)
++ dev->setup_countdown = RESET_SETUP_COUNT;
++ dev->reset_time = jiffies;
++ dev->fake_config = 0;
++ ep0_idle(dev);
++ }
++
++ /* EPOi Transmit Complete - data to host on EP0 ACKed
++ * EP0i Transfer Request - no data in FIFO to send on EP0
++ * either way we send next data if there is any and the FIFO is not busy
++ * it will interrupt again if we later if we don't send anything.
++ */
++ if ((f0_status & EP0i_TR || f0_status & EP0i_TS)
++ && (ctrl_inb(USBDASTS) & EP0i_DE) == 0) {
++ struct superh_ep *ep = &dev->ep[0];
++ struct superh_request *req;
++ DBG(DBG_VERY_NOISY, "superh_udc_irq_f1[%lx]: ep0i TR\n", dev->stats.irqs);
++ if (!list_empty(&ep->queue)) {
++ req = list_entry(ep->queue.next, struct superh_request, queue);
++ write_ep0_fifo(ep, req);
++ }
++ or_b(EP0i_PKTE, USBTRG);
++ }
++
++ /* Setup Command Receive Complete */
++ if (f0_status & SETUP_TS) {
++ DBG(DBG_NOISY, "superh_udc_irq_f1[%lx]: SETUP TS\n", dev->stats.irqs);
++ or_b( EP0o_CLEAR | EP0i_CLEAR, USBFCLR);
++ handle_ep0_setup(dev);
++ }
++
++ /* EPOo Receive Complete - EP0 has received data from host */
++ if (f0_status & EP0o_TS) {
++ struct superh_request *req;
++ struct superh_ep *ep;
++ DBG(DBG_VERY_NOISY, "superh_int_hndlr_f1[%lx]: ep0o TS\n", dev->stats.irqs);
++ ep = &dev->ep[0];
++
++ if (likely (!list_empty(&ep->queue)))
++ req = list_entry(ep->queue.next,
++ struct superh_request, queue);
++ else
++ req = 0;
++
++ if (req)
++ read_ep0_fifo(ep, req);
++ }
++
++ /* EP3 Transmit Request & Transmit Complete */
++ if ( f1_status & (EP3_TR | EP3_TS) ) {
++ struct superh_request *req;
++ struct superh_ep *ep;
++ DBG(DBG_VERY_NOISY, "superh_udc_irq_f1[%lx]: EP3 TR | EP3_TS (%x)\n", dev->stats.irqs, f1_status);
++ ep = &dev->ep[3];
++
++ if (likely (!list_empty(&ep->queue)))
++ req = list_entry(ep->queue.next,
++ struct superh_request, queue);
++ else
++ req = 0;
++
++ if (req) {
++ if ((f1_status & EP3_TR) && (ctrl_inb(USBDASTS) & EP3_DE) == 0)
++ write_fifo(ep, req);
++
++ }
++ else {
++ pio_irq_disable(ep);
++ }
++ }
++
++ atomic_dec(&dev->in_interrupt);;
++}
++
++
++/*--------------------------------------------------------------------------*/
++
++/*
++ * endpoint enable/disable
++ *
++ * we need to verify the descriptors used to enable endpoints. since superh
++ * endpoint configurations are fixed, and are pretty much always enabled,
++ * there's not a lot to manage here.
++ *
++ */
++static int superh_ep_enable (struct usb_ep *_ep,
++ const struct usb_endpoint_descriptor *desc)
++{
++ struct superh_ep *ep;
++ struct superh_udc *dev;
++
++ DBG(DBG_NOISY, "superh_ep_enable\n");
++
++ ep = container_of (_ep, struct superh_ep, ep);
++ if (!_ep || !desc || ep->desc || _ep->name == ep0name
++ || desc->bDescriptorType != USB_DT_ENDPOINT
++ || ep->bEndpointAddress != desc->bEndpointAddress
++ || ep->ep.maxpacket < desc->wMaxPacketSize) {
++ DMSG("%s, bad ep or descriptor\n", __FUNCTION__);
++ return -EINVAL;
++ }
++
++ /* xfer types must match, except that interrupt ~= bulk */
++ if (ep->bmAttributes != desc->bmAttributes
++ && ep->bmAttributes != USB_ENDPOINT_XFER_BULK
++ && desc->bmAttributes != USB_ENDPOINT_XFER_INT) {
++ DMSG("%s, %s type mismatch\n", __FUNCTION__, _ep->name);
++ return -EINVAL;
++ }
++
++#if 0
++ /* hardware _could_ do smaller, but driver doesn't */
++ if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK
++ && desc->wMaxPacketSize != BULK_FIFO_SIZE)
++ || !desc->wMaxPacketSize) {
++ DMSG("%s, bad %s maxpacket\n", __FUNCTION__, _ep->name);
++ return -ERANGE;
++ }
++#endif
++
++ dev = ep->dev;
++ if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) {
++ DMSG("%s, bogus device state\n", __FUNCTION__);
++ return -ESHUTDOWN;
++ }
++
++ ep->desc = desc;
++ ep->dma = -1;
++ ep->stopped = 0;
++
++ /* flush fifo (mostly for OUT buffers), enable irq */
++ superh_ep_fifo_flush (_ep);
++
++ /* ... reset halt state too, if we could ... */
++
++#ifdef USE_DMA
++
++#endif
++
++ DBG(DBG_VERBOSE, "enabled %s\n", _ep->name);
++ return 0;
++}
++
++static int superh_ep_disable (struct usb_ep *_ep)
++{
++ struct superh_ep *ep;
++
++ DBG(DBG_NOISY, "superh_ep_disable\n");
++
++ ep = container_of (_ep, struct superh_ep, ep);
++ if (!_ep || !ep->desc) {
++ DMSG("%s, %s not enabled\n", __FUNCTION__,
++ _ep ? ep->ep.name : NULL);
++ return -EINVAL;
++ }
++ nuke (ep, -ESHUTDOWN);
++
++#ifdef USE_DMA
++ /* TODO */
++ if (ep->dma >= 0) {
++ *ep->reg_drcmr = 0;
++ pxa_free_dma (ep->dma);
++ ep->dma = -1;
++ }
++#endif
++
++ /* flush fifo (mostly for IN buffers) */
++ superh_ep_fifo_flush (_ep);
++
++ ep->desc = 0;
++ ep->stopped = 1;
++
++ DBG(DBG_VERBOSE, "%s disabled\n", _ep->name);
++ return 0;
++}
++
++/* for the superh, these can just wrap kmalloc/kfree. gadget drivers
++ * must still pass correctly initialized endpoints, since other controller
++ * drivers may care about how it's currently set up (dma issues etc).
++ */
++
++/*
++ * superh_ep_alloc_request - allocate a request data structure
++ */
++static struct usb_request *
++superh_ep_alloc_request (struct usb_ep *_ep, int gfp_flags)
++{
++ struct superh_request *req;
++
++ /* FIXME for bulk out-dma endpoints, preallocate a frame's worth of
++ * (aligned) dma descriptors at the end of the request
++ */
++
++ req = kmalloc (sizeof *req, gfp_flags);
++ if (!req)
++ return 0;
++
++ memset (req, 0, sizeof *req);
++ INIT_LIST_HEAD (&req->queue);
++ DBG(DBG_VERY_NOISY, "superh_ep_alloc_request: %p %d\n", req, list_empty(&req->queue));
++
++ return &req->req;
++}
++
++/*
++ * superh_ep_free_request - deallocate a request data structure
++ */
++static void
++superh_ep_free_request (struct usb_ep *_ep, struct usb_request *_req)
++{
++ struct superh_request *req;
++
++ req = container_of (_req, struct superh_request, req);
++ WARN_ON (!list_empty (&req->queue));
++ kfree(req);
++}
++
++/* SH cache needs flushing with DMA I/O (it's dma-incoherent), but there's
++ * no device-affinity and the heap works perfectly well for i/o buffers.
++ * TODO: check this
++ */
++static void *
++superh_ep_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
++ dma_addr_t *dma, int gfp_flags)
++{
++ char *retval;
++
++ retval = kmalloc (bytes, gfp_flags);
++ if (retval)
++ *dma = virt_to_bus (retval);
++ return retval;
++}
++
++static void
++superh_ep_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma,
++ unsigned bytes)
++{
++ kfree (buf);
++}
++
++static struct superh_request*
++process_ep_req(struct superh_ep *ep, struct superh_request *req)
++{
++ struct superh_udc *dev = ep->dev;
++
++ if (ep->desc == 0 /* ep0 */) {
++ switch (dev->ep0state) {
++ case EP0_IN_DATA_PHASE:
++ DBG(DBG_VERY_NOISY, "superh_ep_queue: EP0_IN_DATA_PHASE\n");
++ dev->stats.write.ops++;
++ if (write_ep0_fifo(ep, req))
++ req = 0;
++ break;
++
++ case EP0_OUT_DATA_PHASE:
++ DBG(DBG_VERY_NOISY, "superh_ep_queue: EP0_OUT_DATA_PHASE\n");
++ dev->stats.read.ops++;
++ if (read_ep0_fifo(ep, req))
++ req = 0;
++ break;
++
++ default:
++ DMSG("ep0 i/o, odd state %d\n", dev->ep0state);
++ return 0;
++ }
++#ifdef USE_DMA
++ /* either start dma or prime pio pump */
++ }
++ else if (ep->dma >= 0) {
++ kick_dma(ep, req);
++#endif
++ /* can the FIFO can satisfy the request immediately? */
++ }
++ else if ((ep->bEndpointAddress & USB_DIR_IN) != 0) {
++ if ((ep->desc->bEndpointAddress & 0x0f) == 2
++ && (ctrl_inb(USBIFR0) & EP2_TR) != 0
++ && write_fifo(ep, req)) {
++ req = 0;
++ }
++ else if ((ep->desc->bEndpointAddress & 0x0f) == 3
++ && (ctrl_inb(USBIFR1) & EP3_TR) != 0
++ && write_fifo(ep, req)) {
++ req = 0;
++ }
++ }
++
++ if (likely (((req && ep->desc) && ep->dma < 0) || ep->desc == 0))
++ pio_irq_enable(ep);
++
++ return req;
++}
++
++
++static int
++superh_ep_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
++{
++ struct superh_request *req;
++ struct superh_ep *ep;
++ struct superh_udc *dev;
++ unsigned long flags;
++
++ req = container_of(_req, struct superh_request, req);
++ ep = container_of(_ep, struct superh_ep, ep);
++
++ DBG(DBG_VERY_NOISY, "superh_ep_queue\n");
++
++ /* If we have just sent a fake configuration request then
++ * this is the reply. We don't want to send it to the host
++ * so just ignore it.
++ */
++ if (ep->desc == 0 /* ep0 */ && ep->dev->fake_config) {
++ DBG(DBG_NOISY, "Ignoring bogus SET_CONFIGURATION response\n");
++ done(ep, req, 0);
++ ep->dev->fake_config = 0;
++ return 1;
++ }
++
++ if (unlikely (!_req || !_req->complete || !_req->buf
++ || !list_empty(&req->queue))) {
++ DMSG("%s, bad params %s, %p, %p, %p, %d\n", __FUNCTION__,
++ ep->ep.name, _req, _req->complete, _req->buf,
++ list_empty(&req->queue));
++ return -EINVAL;
++ }
++
++ if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) {
++ DMSG("%s, bad ep\n", __FUNCTION__);
++ return -EINVAL;
++ }
++
++ dev = ep->dev;
++ if (unlikely (!dev->driver
++ || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
++ DMSG("%s, bogus device state\n", __FUNCTION__);
++ return -ESHUTDOWN;
++ }
++
++#ifdef USE_DMA
++ /* TODO */
++ if (ep->dma >= 0) {
++ unsigned long start = (unsigned long) _req->buf;
++
++ clean_dcache_range(start, start + _req->length);
++ /* or for USB_DIR_OUT, invalidate_dcache_range (...) */
++ }
++#endif
++
++ DBG(DBG_NOISY, "%s queue req %p, len %d buf %p\n",
++ _ep->name, _req, _req->length, _req->buf);
++
++ local_irq_save(flags);
++
++ _req->status = -EINPROGRESS;
++ _req->actual = 0;
++
++ /* kickstart this i/o queue? */
++ if (list_empty(&ep->queue) && !ep->stopped && !ep->halted) {
++ req = process_ep_req(ep, req);
++ }
++
++ /* pio or dma irq handler advances the queue. */
++ if (likely (req != 0))
++ list_add_tail(&req->queue, &ep->queue);
++
++ local_irq_restore(flags);
++
++ return 0;
++}
++
++static int
++superh_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
++{
++ struct superh_ep *ep;
++ struct superh_request *req;
++ unsigned long flags;
++
++ DBG(DBG_NOISY, "superh_ep_dequeue %s\n", _ep->name);
++
++ ep = container_of(_ep, struct superh_ep, ep);
++ req = container_of(_req, struct superh_request, req);
++ if (!_ep || !_req || ep->ep.name == ep0name)
++ return -EINVAL;
++
++ local_irq_save(flags);
++#ifdef USE_DMA
++ if (ep->dma >= 0 && ep->queue.next == &req->queue && !ep->stopped) {
++ cancel_dma(ep);
++ done(ep, req, -ECONNRESET);
++ /* restart i/o */
++ if (!list_empty(&ep->queue)) {
++ req = list_entry(ep->queue.next,
++ struct superh_request, queue);
++ kick_dma(ep, req);
++ }
++ } else
++#endif
++ if (!list_empty(&req->queue))
++ done(ep, req, -ECONNRESET);
++ else
++ req = 0;
++ local_irq_restore(flags);
++
++ return req ? 0 : -EOPNOTSUPP;
++}
++
++/* stall/unstall an endpoint, 0 clears the stall, 1 sets it */
++static int
++superh_ep_set_halt(struct usb_ep *_ep, int value)
++{
++ struct superh_ep *ep;
++ unsigned long flags;
++
++ ep = container_of(_ep, struct superh_ep, ep);
++ if (unlikely (!_ep
++ || (!ep->desc && ep->ep.name != ep0name))
++ || ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
++ DMSG("%s, bad ep\n", __FUNCTION__);
++ return -EINVAL;
++ }
++
++ if (ep->halted == value)
++ return 0;
++
++ local_irq_save(flags);
++
++ if (value == 1 && (ep->bEndpointAddress & USB_DIR_IN) != 0
++ && ((ctrl_inb(USBDASTS) & ep->data_present_mask) != 0
++ || !list_empty(&ep->queue))) {
++ local_irq_restore(flags);
++ DBG(DBG_VERBOSE, "Can't %s on %s\n", value ? " halt" : "clear halt", _ep->name);
++ return -EAGAIN;
++ }
++
++ if (value) {
++ or_b(ep->stall_mask, USBEPSTL);
++ if (!ep->desc) {
++ ep->dev->ep0state = EP0_STALL;
++ }
++ /* disable ep interrupts and set a timer to clear the stall */
++ pio_irq_disable(ep);
++ mod_timer(&ep->dev->timer, jiffies + STALL_TIME);
++ }
++ else {
++ and_b(~ep->stall_mask, USBEPSTL);
++ }
++
++ ep->halted = value;
++
++ local_irq_restore(flags);
++
++ DBG(DBG_VERBOSE, "%s %s\n", _ep->name, value ? " halt" : "clear halt");
++
++ return 0;
++}
++
++static int superh_ep_fifo_status(struct usb_ep *_ep)
++{
++ struct superh_ep *ep;
++
++ DBG(DBG_NOISY, "superh_ep_fifo_status\n");
++
++ ep = container_of(_ep, struct superh_ep, ep);
++ if (!_ep) {
++ DMSG("%s, bad ep\n", __FUNCTION__);
++ return -ENODEV;
++ }
++ if ((ep->bEndpointAddress & USB_DIR_IN) != 0)
++ return -EOPNOTSUPP;
++ if (ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
++ return 0;
++ else {
++ switch (ep->desc->bEndpointAddress & 0x0f) {
++ case 0:
++ return ctrl_inb(USBEPSZ0O);
++ case 1:
++ return ctrl_inb(USBEPSZ1);
++ }
++ }
++
++ return 0;
++}
++
++static void superh_ep_fifo_flush(struct usb_ep *_ep)
++{
++ struct superh_ep *ep;
++
++ DBG(DBG_NOISY, "superh_ep_fifo_flush\n");
++
++ ep = container_of(_ep, struct superh_ep, ep);
++ if (!_ep || ep->ep.name == ep0name || !list_empty(&ep->queue)) {
++ DMSG("%s, bad ep\n", __FUNCTION__);
++ return;
++ }
++
++ or_b(ep->clear_mask, USBFCLR);
++}
++
++static struct usb_ep_ops superh_ep_ops = {
++ .enable = superh_ep_enable,
++ .disable = superh_ep_disable,
++
++ .alloc_request = superh_ep_alloc_request,
++ .free_request = superh_ep_free_request,
++
++ .alloc_buffer = superh_ep_alloc_buffer,
++ .free_buffer = superh_ep_free_buffer,
++
++ .queue = superh_ep_queue,
++ .dequeue = superh_ep_dequeue,
++
++ .set_halt = superh_ep_set_halt,
++ .fifo_status = superh_ep_fifo_status,
++ .fifo_flush = superh_ep_fifo_flush,
++};
++
++/* ---------------------------------------------------------------------------
++ * device-scoped parts of the api to the usb controller hardware
++ * ---------------------------------------------------------------------------
++ */
++
++static int superh_udc_get_frame(struct usb_gadget *_gadget)
++{
++ DBG(DBG_VERY_NOISY, "superh_udc_get_frame\n");
++
++ return -EOPNOTSUPP;
++}
++
++static const struct usb_gadget_ops superh_udc_ops = {
++ .get_frame = superh_udc_get_frame,
++ // no remote wakeup
++ // always selfpowered
++};
++
++
++/* 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";
++
++static int
++udc_proc_read(char *page, char **start, off_t off, int count,
++ int *eof, void *_dev)
++{
++ char *buf = page;
++ struct superh_udc *dev = _dev;
++ char *next = buf;
++ unsigned size = count;
++ unsigned long flags;
++ int t;
++ int i;
++
++ local_irq_save(flags);
++
++ /* basic device status */
++ t = snprintf(next, size,
++ "%s\n%s version: %s\nGadget driver: %s\nHost %s\n\n",
++ driver_desc,
++ driver_name, DRIVER_VERSION,
++ dev->driver ? dev->driver->driver.name : "(none)",
++ is_usb_connected ? "full speed" : "disconnected");
++ size -= t;
++ next += t;
++
++ /* device registers */
++ t = snprintf(next, size,
++ "ifr0 %02X, ifr1 %02X, isr0 %02X, isr1 %02X, ier0 %02X, ier1 %02X\n",
++ ctrl_inb(USBIFR0), ctrl_inb(USBIFR1),
++ ctrl_inb(USBISR0), ctrl_inb(USBISR1),
++ ctrl_inb(USBIER0), ctrl_inb(USBIER1));
++ size -= t;
++ next += t;
++
++ t = snprintf(next, size,
++ "epsz0o %02X, epsz1 %02X, dasts %02X, dmar %02X\n",
++ ctrl_inb(USBEPSZ0O), ctrl_inb(USBEPSZ1),
++ ctrl_inb(USBDASTS), ctrl_inb(USBDMA));
++ size -= t;
++ next += t;
++
++ t = snprintf(next, size,
++ "epstl %02X, xvercr %02X\n",
++ ctrl_inb(USBEPSTL), ctrl_inb(USBXVERCR));
++ size -= t;
++ next += t;
++
++ if (!is_usb_connected || !dev->driver)
++ goto done;
++
++ t = snprintf(next, size, "ep0 IN %lu/%lu, OUT %lu/%lu; irq0s %lu; irq1s %lu\n\n",
++ dev->stats.write.bytes, dev->stats.write.ops,
++ dev->stats.read.bytes, dev->stats.read.ops,
++ dev->stats.irq0s, dev->stats.irq1s);
++ size -= t;
++ next += t;
++
++ /* dump endpoint queues */
++ for (i = 0; i < 4; i++) {
++ struct superh_ep *ep = &dev->ep [i];
++ struct superh_request *req;
++ int t;
++
++ if (i != 0) {
++ const struct usb_endpoint_descriptor *d;
++
++ d = ep->desc;
++ if (!d)
++ continue;
++ t = snprintf(next, size,
++ "%s max %d %s\n",
++ ep->ep.name, le16_to_cpu (d->wMaxPacketSize),
++ (ep->dma >= 0) ? "dma" : "pio");
++
++ } else /* ep0 should only have one transfer queued */
++ t = snprintf(next, size, "ep0 max 8 pio\n");
++ 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) {
++#ifdef USE_DMA
++ if (ep->dma >= 0 && req->queue.prev == &ep->queue)
++ t = snprintf(next, size,
++ "\treq %p len %d/%d "
++ "buf %p (dma%d dcmd %08x)\n",
++ &req->req, req->req.actual,
++ req->req.length, req->req.buf,
++ ep->dma, DCMD(ep->dma)
++ // low 13 bits == bytes-to-go
++ );
++ else
++#endif
++ 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:
++ local_irq_restore(flags);
++ return count - size;
++}
++
++#endif /* UDC_PROC_FILE */
++
++/*-------------------------------------------------------------------------*/
++
++/*
++ * udc_disable - disable USB device controller
++ */
++static void udc_disable(struct superh_udc *dev)
++{
++ /* block all irqs */
++ ctrl_outb( 0, USBIER0);
++ ctrl_outb( 0, USBIER1);
++
++ /* Disable the USB module */
++ or_b(0x80, STBCR3);
++
++ /* Disable the USB clock */
++ ctrl_outw(0xA500, UCLKCR);
++
++ ep0_idle (dev);
++ dev->gadget.speed = USB_SPEED_UNKNOWN;
++}
++
++/*
++ * udc_reinit - initialize software state
++ */
++static void udc_reinit(struct superh_udc *dev)
++{
++ u32 i;
++
++ /* device/ep0 records init */
++ INIT_LIST_HEAD (&dev->gadget.ep_list);
++ dev->gadget.ep0 = &dev->ep[0].ep;
++ INIT_LIST_HEAD (&dev->gadget.ep0->ep_list);
++ dev->ep0state = EP0_IDLE;
++
++ /* basic endpoint records init */
++ for (i = 0; i < 4; i++) {
++ struct superh_ep *ep = &dev->ep[i];
++
++ ep->ep.name = ep_name[i];
++ ep->ep.ops = &superh_ep_ops;
++ if (i != 0)
++ list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
++
++ ep->dev = dev;
++ ep->desc = 0;
++ ep->stopped = 0;
++ ep->halted = 0;
++ ep->dma = -1;
++ INIT_LIST_HEAD (&ep->queue);
++
++ /* address may need USB_DIR_IN, attributes likely wrong */
++ ep->bEndpointAddress = i;
++ ep->bmAttributes = USB_ENDPOINT_XFER_BULK;
++ }
++
++ /* TODO at least from here on, static initialization
++ * would work just as well and would need less code space
++ */
++
++ /* ep0 == control */
++ dev->ep[ 0].ep.maxpacket = EP0_FIFO_SIZE;
++ dev->ep[ 0].data_present_mask = EP0i_DE;
++ dev->ep[ 0].stall_mask = EP0_STL;
++ dev->ep[ 0].interrupt_mask = EP0o_TS | EP0i_TR | EP0i_TS;
++ dev->ep[ 0].interrupt_reg = USBIER0;
++ dev->ep[ 0].clear_mask = EP0i_CLEAR | EP0o_CLEAR;
++ dev->ep[ 0].fifo_reg = 0;
++ dev->ep[ 0].packet_enable_mask = 0;
++
++ dev->ep[ 1].ep.maxpacket = BULK_FIFO_SIZE;
++ dev->ep[ 1].bEndpointAddress |= USB_DIR_OUT;
++ dev->ep[ 1].data_present_mask = 0x00;
++ dev->ep[ 1].stall_mask = EP1_STL;
++ dev->ep[ 1].interrupt_mask = EP1_FULL;
++ dev->ep[ 1].interrupt_reg = USBIER0;
++ dev->ep[ 1].clear_mask = EP1_CLEAR;
++ dev->ep[ 1].fifo_reg = 0;
++ dev->ep[ 1].packet_enable_mask = 0;
++
++ dev->ep[ 2].ep.maxpacket = BULK_FIFO_SIZE;
++ dev->ep[ 2].bEndpointAddress |= USB_DIR_IN;
++ dev->ep[ 2].data_present_mask = EP2_DE;
++ dev->ep[ 2].stall_mask = EP2_STL;
++ dev->ep[ 2].interrupt_mask = EP2_TR | EP2_EMPTY;
++ dev->ep[ 2].interrupt_reg = USBIER0;
++ dev->ep[ 2].clear_mask = EP2_CLEAR;
++ dev->ep[ 2].fifo_reg = USBEPDR2;
++ dev->ep[ 2].packet_enable_mask = EP2_PKTE;
++
++ dev->ep[ 3].ep.maxpacket = INT_FIFO_SIZE;
++ dev->ep[ 3].bEndpointAddress |= USB_DIR_IN;
++ dev->ep[ 3].data_present_mask = EP3_DE;
++ dev->ep[ 3].stall_mask = EP3_STL;
++ dev->ep[ 3].interrupt_mask = EP3_TR | EP3_TS;
++ dev->ep[ 3].interrupt_reg = USBIER1;
++ dev->ep[ 3].clear_mask = EP3_CLEAR;
++ dev->ep[ 3].fifo_reg = USBEPDR3;
++ dev->ep[ 3].packet_enable_mask = EP3_PKTE;
++}
++
++/* until it's enabled, this UDC should be completely invisible
++ * to any USB host.
++ */
++static void udc_enable (struct superh_udc *dev)
++{
++#if defined(CONFIG_CPU_SUBTYPE_SH7727)
++ // Reset and then Select Function USB1_pwr_en out (USB) c.f. Section 26, Table 26.1 PTE2
++ and_w(PN_PB2_MSK, PECR);
++ or_w(PN_PB2_OF, PECR);
++
++ // Reset and then Select Function UCLK c.f. Section 26, Table 26.1, PTD6
++ and_w(PN_PB6_MSK, PDCR);
++ or_w(PN_PB6_OF, PDCR);
++
++ // Stop USB module prior to setting clocks c.f. Section 9.2.3
++ and_b(~MSTP14, STBCR3);
++ or_b(MSTP14, STBCR3);
++
++ // Select external clock, 1/1 divisor c.f. Section 11.3.1
++ or_b(USBDIV_11|USBCKS_EC, EXCPGCR);
++
++ // Start USB c.f. Section 9.2.3
++ and_b(~MSTP14, STBCR3);
++
++ // Disable pullup c.f. Section 23.5.19
++ or_b(PULLUP_E, USBDMA);
++ //and_b(~PULLUP_E, USBDMA);
++
++ // Set port 1 to function, disabled c.f. Section 22.2.1
++ or_w(USB_TRANS_TRAN | USB_SEL_FUNC, EXPFC);
++
++ // Enable pullup c.f. Section 23.5.19a
++ and_b(~PULLUP_E, USBDMA);
++ //or_b(PULLUP_E, USBDMA);
++#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
++ /* Disable the USB module */
++ or_b(0x80, STBCR3);
++
++ /* Set the clock to external & enable */
++ ctrl_outw(0xA5E0, UCLKCR);
++
++ /* Enable the USB module */
++ and_b(0x7f, STBCR3);
++
++ /* Enable USB pins. */
++ ctrl_outw(0x01FD, PMCR); /* VBUS */
++ or_b(PULLUP_E, PMDR);
++#endif
++ dev->gadget.speed = USB_SPEED_UNKNOWN;
++ dev->stats.irqs = 0;
++ dev->stats.irq0s = 0;
++ dev->stats.irq1s = 0;
++
++ // reset fifo's and stall's
++ or_b( EP3_CLEAR | EP1_CLEAR | EP2_CLEAR | EP0o_CLEAR | EP0i_CLEAR, USBFCLR);
++ or_b(0, USBEPSTL);
++
++ /* Setup interrupt priority by using the interrupt select registers */
++ ctrl_outb(F0_LOW, USBISR0);
++ ctrl_outb(F1_LOW, USBISR1);
++
++ /* Enable some interrupts */
++ or_b( BRST | SETUP_TS | EP0o_TS | EP0i_TR | EP0i_TS, USBIER0);
++ or_b( VBUSF, USBIER1);
++}
++
++/* 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 superh_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;
++
++ /* first hook up the driver ... */
++ dev->driver = driver;
++
++ retval = driver->bind(&dev->gadget);
++ if (retval) {
++ DMSG("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.
++ * NOTE: this shouldn't power up until later.
++ */
++ udc_enable(dev);
++
++ DMSG("registered gadget driver '%s'\n", driver->driver.name);
++ dump_state(dev);
++ return 0;
++}
++
++EXPORT_SYMBOL(usb_gadget_register_driver);
++
++static void
++stop_activity(struct superh_udc *dev, struct usb_gadget_driver *driver)
++{
++ int i;
++
++ /* don't disconnect drivers more than once */
++ if (dev->gadget.speed == USB_SPEED_UNKNOWN)
++ driver = 0;
++ dev->gadget.speed = USB_SPEED_UNKNOWN;
++
++ /* prevent new request submissions, kill any outstanding requests */
++ for (i = 0; i < 4; i++) {
++ struct superh_ep *ep = &dev->ep[i];
++
++ ep->stopped = 1;
++ nuke(ep, -ESHUTDOWN);
++ }
++
++ del_timer_sync(&dev->timer);
++
++ /* report disconnect; the driver is already quiesced */
++ if (driver)
++ driver->disconnect(&dev->gadget);
++
++ /* re-init driver-visible data structures */
++ udc_reinit(dev);
++}
++
++int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
++{
++ struct superh_udc *dev = the_controller;
++
++ if (!dev)
++ return -ENODEV;
++ if (!driver || driver != dev->driver)
++ return -EINVAL;
++
++ local_irq_disable();
++ udc_disable(dev);
++ stop_activity(dev, driver);
++ driver->unbind(&dev->gadget);
++ dev->driver = 0;
++ local_irq_enable();
++
++ DMSG("unregistered gadget driver '%s'\n", driver->driver.name);
++ dump_state(dev);
++ return 0;
++}
++
++EXPORT_SYMBOL(usb_gadget_unregister_driver);
++
++
++/*-------------------------------------------------------------------------*/
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,40)
++MODULE_DESCRIPTION(driver_desc);
++#endif
++MODULE_AUTHOR("Julian Back");
++MODULE_LICENSE("GPL");
++
++/*
++ * cleanup - free resources allocated during init
++ */
++static void /*__exit and */ __init cleanup(void)
++{
++ struct superh_udc *dev = the_controller;
++
++ if (!dev)
++ return;
++
++ udc_disable(dev);
++#ifdef UDC_PROC_FILE
++ remove_proc_entry(proc_node_name, NULL);
++#endif
++ usb_gadget_unregister_driver(dev->driver);
++
++ if (dev->got_irq0) {
++ free_irq(USBF0_IRQ, dev);
++ dev->got_irq0 = 0;
++ }
++
++ if (dev->got_irq1) {
++ free_irq(USBF1_IRQ, dev);
++ dev->got_irq1 = 0;
++ }
++
++ the_controller = 0;
++}
++module_exit (cleanup);
++
++/*
++ * init - allocate resources
++ */
++static int __init init(void)
++{
++ static struct superh_udc memory;
++
++ struct superh_udc *dev;
++ int retval;
++
++ printk(KERN_DEBUG "%s: version %s\n", driver_name, DRIVER_VERSION);
++
++ /* initialize data */
++ dev = &memory;
++
++ memset(dev, 0, sizeof *dev);
++ dev->gadget.ops = &superh_udc_ops;
++ dev->gadget.name = driver_name;
++ dev->gadget.dev.bus_id = "udc";
++ dev->gadget.speed = USB_SPEED_UNKNOWN;
++
++ dev->vbusmn = 0;
++
++ atomic_set(&dev->in_interrupt, 0);
++
++ the_controller = dev;
++ udc_disable(dev);
++ udc_reinit(dev);
++
++ /* irq setup after old hardware state is cleaned up */
++ retval = request_irq(USBF0_IRQ, superh_udc_irq_f0,
++ 0/*SA_INTERRUPT | SA_SAMPLE_RANDOM*/,
++ driver_name, dev);
++ if (retval != 0) {
++ printk(KERN_ERR "%s: can't get irq %i, err %d\n",
++ driver_name, USBF0_IRQ, retval);
++ goto failed;
++ }
++ dev->got_irq0 = 1;
++
++ retval = request_irq(USBF1_IRQ, superh_udc_irq_f1,
++ 0/*SA_INTERRUPT | SA_SAMPLE_RANDOM*/,
++ driver_name, dev);
++ if (retval != 0) {
++ printk(KERN_ERR "%s: can't get irq %i, err %d\n",
++ driver_name, USBF1_IRQ, retval);
++ goto failed;
++ }
++ dev->got_irq1 = 1;
++
++ printk(KERN_INFO "%s, IRQs %d %d\n", driver_desc,
++ USBF0_IRQ, USBF1_IRQ);
++ dump_state(dev);
++
++ dev->setup_countdown = DEFAULT_SETUP_COUNT;
++
++#ifdef UDC_PROC_FILE
++ create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev);
++#endif
++
++ return 0;
++
++failed:
++ cleanup();
++ return retval;
++}
++module_init (init);
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/drivers/usb/gadget/superh_udc.h kernel/drivers/usb/gadget/superh_udc.h
+--- /tmp/kernel/drivers/usb/gadget/superh_udc.h 1970-01-01 01:00:00.000000000 +0100
++++ kernel/drivers/usb/gadget/superh_udc.h 2005-04-22 17:53:19.513526654 +0200
+@@ -0,0 +1,363 @@
++/*
++ * Renesas SuperH USB 1.1 device controller (found on SH7705, SH7727...)
++ *
++ * Copyright (C) 2003 Renesas Technology Europe Limited
++ * Copyright (C) 2003 Julian Back (jback@mpc-data.co.uk), MPC Data Limited
++ *
++ * 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
++ */
++
++#ifndef __LINUX_USB_GADGET_SUPERH_UDC_H
++#define __LINUX_USB_GADGET_SUPERH_UDC_H
++
++#include <linux/types.h>
++
++struct superh_udc;
++
++struct superh_ep {
++ struct usb_ep ep;
++ struct superh_udc *dev;
++
++ const struct usb_endpoint_descriptor *desc;
++ struct list_head queue;
++ int dma;
++
++ u8 bEndpointAddress;
++ u8 bmAttributes;
++
++ unsigned stopped : 1;
++ unsigned halted : 1;
++
++ u8 data_present_mask;
++ u8 stall_mask;
++ u8 interrupt_mask;
++ u8 clear_mask;
++ u8 packet_enable_mask;
++ unsigned interrupt_reg;
++ unsigned fifo_reg;
++};
++
++struct superh_request {
++ struct usb_request req;
++ struct list_head queue;
++};
++
++enum ep0_state {
++ EP0_IDLE,
++ EP0_IN_DATA_PHASE,
++ EP0_OUT_DATA_PHASE,
++ EP0_END_XFER,
++ EP0_STALL,
++};
++
++#define EP0_FIFO_SIZE ((unsigned)8)
++#define BULK_FIFO_SIZE ((unsigned)64)
++#define ISO_FIFO_SIZE ((unsigned)0)
++#define INT_FIFO_SIZE ((unsigned)8)
++
++struct udc_stats {
++ struct ep0stats {
++ unsigned long ops;
++ unsigned long bytes;
++ } read, write;
++ unsigned long irqs;
++ unsigned long irq0s;
++ unsigned long irq1s;
++};
++
++struct superh_udc {
++ struct usb_gadget gadget;
++ struct usb_gadget_driver *driver;
++ atomic_t in_interrupt;
++
++ enum ep0_state ep0state;
++ struct udc_stats stats;
++ unsigned int vbusmn;
++ unsigned long vbusf_time;
++ unsigned got_irq0 : 1,
++ got_irq1 : 1,
++ fake_config: 1;
++ int setup_countdown;
++ unsigned long reset_time;
++ struct timer_list timer;
++ struct superh_ep ep [4];
++};
++
++/* 2.5 changes ... */
++
++#ifndef container_of
++#define container_of list_entry
++#endif
++
++#ifndef WARN_ON
++#define WARN_ON BUG_ON
++#endif
++
++/* one I/O pin should be used to detect disconnect */
++#define is_usb_connected ((ctrl_inb(USBIFR1) & VBUSF) != 0)
++
++/* Register addresses - should really be in include/asm-sh */
++
++#ifdef CONFIG_CPU_SUBTYPE_SH7705
++
++#define USBEPDR0I 0xA4480000
++#define USBEPDR0O 0xA4480004
++#define USBEPDR0S 0xA4480008
++#define USBEPDR1 0xA448000C
++#define USBEPDR2 0xA4480010
++#define USBEPDR3 0xA4480014
++#define USBIFR0 0xA4480018
++#define USBIFR1 0xA448001C
++#define USBTRG 0xA4480020
++#define USBFCLR 0xA4480024
++#define USBEPSZ0O 0xA4480028
++#define USBDASTS 0xA448002C
++#define USBEPSTL 0xA4480030
++#define USBIER0 0xA4480034
++#define USBIER1 0xA4480038
++#define USBEPSZ1 0xA448003C
++#define USBDMA 0xA4480040
++#define USBISR0 0xA4480044
++#define USBISR1 0xA4480048
++
++#define USBXVERCR 0xA4480060
++
++#define STBCR3 0xA40A0000
++#define UCLKCR 0xA40A0008
++
++#define PMCR 0xA4000118
++#define PNCR 0xA400011A
++#define PNCR2 0xA405015A
++
++#define PMDR 0xA4000138
++
++#endif
++
++/*
++ * Standby Control Register (STBCR3) c.f. 9.2.3
++ */
++
++#define MSTP14 0x10
++
++/*
++ * EXCPG Control Register (EXCPGCR) c.f. Section 11.3.1
++ */
++
++#define USBDIVS_EL0 0x00
++#define USBDIVS_EL1 0x01
++#define USBDIVS_EL2 0x02
++
++#define USBCKS_EL1 0x04
++#define USBCKS_EL2 0x10
++#define USBCKS_EL3 0x20
++
++#define USBDIV_11 0x00
++#define USBDIV_12 0x01
++#define USBDIV_13 0x02
++
++#define USBCKS_PC 0x00
++#define USBCKS_IC 0x20
++#define USBCKS_BC 0x24
++#define USBCKS_EC 0x30
++
++
++/*
++ * Extra Pin Function Controller (EXPFC) c.f. Section 22.2.1
++ */
++
++#define USB_TRANS_TRAN 0x00
++#define USB_TRANS_DIG 0x02
++
++#define USB_SEL_HOST 0x00
++#define USB_SEL_FUNC 0x01
++
++
++/*
++ * USBDMA Setting Register (USBDMAR) c.f. Section 23.5.19
++ */
++
++#define EP1_DMAE 0x01
++#define EP2_DMAE 0x02
++
++#if defined(CONFIG_CPU_SUBTYPE_SH7727)
++#define PULLUP_E 0x04
++#endif
++
++#if defined(CONFIG_SH_EDOSK7705)
++#define PULLUP_E 0x01
++#endif
++
++/*
++ * USB Interrupt Flag Register 0 (USBIFR0) c.f. Section 23.5.7
++ */
++
++#define BRST 0x80
++#define EP1_FULL 0x40
++#define EP2_TR 0x20
++#define EP2_EMPTY 0x10
++#define SETUP_TS 0x08
++#define EP0o_TS 0x04
++#define EP0i_TR 0x02
++#define EP0i_TS 0x01
++
++
++/*
++ * USB Interrupt Flag Register 1 (USBIFR1) c.f. Section 23.5.8
++ */
++
++#define VBUSMN 0x08
++#define EP3_TR 0x04
++#define EP3_TS 0x02
++#define VBUSF 0x01
++
++/*
++ * USB Trigger Register (USBTRG) c.f. Section 23.5.9
++ */
++
++#define EP0i_PKTE 0x01
++#define EP0o_PKTE 0x02
++#define EP0o_RDFN 0x02
++#define EP0s_PKTE 0x04
++#define EP0s_RDFN 0x04
++
++#define EP2_PKTE 0x10
++#define EP1_PKTE 0x20
++#define EP1_RDFN 0x20
++#define EP3_PKTE 0x40
++
++
++/*
++ * USBFIFO Clear Register (USBFCLR) c.f. Section 23.5.10
++ */
++
++#define EP3_CLEAR 0x40
++#define EP1_CLEAR 0x20
++#define EP2_CLEAR 0x10
++#define EP0o_CLEAR 0x02
++#define EP0i_CLEAR 0x01
++
++
++/*
++ * USBEPSTL Endpoint Stall Register
++ */
++#define EP3_STL 0x08
++#define EP2_STL 0x04
++#define EP1_STL 0x02
++#define EP0_STL 0x01
++
++/*
++ * USBDASTS Data Status Register
++ */
++#define EP3_DE 0x20
++#define EP2_DE 0x10
++#define EP0i_DE 0x01
++
++/*
++ * Port Control Registers (PNCR) c.f. Section 26.2
++ */
++#define PN_PB0_OF 0x0000
++#define PN_PB0_PO 0x0001
++#define PN_PB0_PI_ON 0x0002
++#define PN_PB0_PI_OFF 0x0003
++#define PN_PB0_MSK ~0x0003
++
++#define PN_PB1_OF 0x0000
++#define PN_PB1_PO 0x0004
++#define PN_PB1_PI_ON 0x0008
++#define PN_PB1_PI_OFF 0x000c
++#define PN_PB1_MSK ~0x000c
++
++#define PN_PB2_OF 0x0000
++#define PN_PB2_PO 0x0010
++#define PN_PB2_PI_ON 0x0020
++#define PN_PB2_PI_OFF 0x0030
++#define PN_PB2_MSK ~0x0030
++
++#define PN_PB3_OF 0x0000
++#define PN_PB3_PO 0x0040
++#define PN_PB3_PI_ON 0x0080
++#define PN_PB3_PI_OFF 0x00c0
++#define PN_PB3_MSK ~0x00c0
++
++#define PN_PB4_OF 0x0000
++#define PN_PB4_PO 0x0100
++#define PN_PB4_PI_ON 0x0200
++#define PN_PB4_PI_OFF 0x0300
++#define PN_PB4_MSK ~0x0300
++
++#define PN_PB5_OF 0x0000
++#define PN_PB5_PO 0x0400
++#define PN_PB5_PI_ON 0x0800
++#define PN_PB5_PI_OFF 0x0c00
++#define PN_PB5_MSK ~0x0c00
++
++#define PN_PB6_OF 0x0000
++#define PN_PB6_PO 0x1000
++#define PN_PB6_PI_ON 0x2000
++#define PN_PB6_PI_OFF 0x3000
++#define PN_PB6_MSK ~0x3000
++
++#define PN_PB7_OF 0x0000
++#define PN_PB7_PO 0x4000
++#define PN_PB7_PI_ON 0x8000
++#define PN_PB7_PI_OFF 0xc000
++#define PN_PB7_MSK ~0xc000
++
++/*
++ * Debugging support vanishes in non-debug builds. DBG_NORMAL should be
++ * mostly silent during normal use/testing, with no timing side-effects.
++ */
++#define DBG_NORMAL 1 /* error paths, device state transitions */
++#define DBG_VERBOSE 2 /* add some success path trace info */
++#define DBG_NOISY 3 /* ... even more: request level */
++#define DBG_VERY_NOISY 4 /* ... even more: packet level */
++
++#ifdef DEBUG
++
++#define DMSG(stuff...) printk(KERN_DEBUG "udc: " stuff)
++
++#if defined(VERY_NOISY)
++# define UDC_DEBUG DBG_VERY_NOISY
++#elif defined(NOISY)
++# define UDC_DEBUG DBG_NOISY
++#elif defined(VERBOSE)
++# define UDC_DEBUG DBG_VERBOSE
++#else
++# define UDC_DEBUG DBG_NORMAL
++#endif
++
++static void __attribute__ ((__unused__))
++dump_state(struct superh_udc *dev)
++{
++ if (!is_usb_connected)
++ return;
++}
++
++
++#else
++
++#define DMSG(stuff...) do{}while(0)
++
++#define UDC_DEBUG ((unsigned)0)
++
++#define dump_state(x) do{}while(0)
++
++#endif
++
++#define DBG(lvl, stuff...) do{if ((lvl) <= UDC_DEBUG) DMSG(stuff);}while(0)
++
++#define WARN(stuff...) printk(KERN_WARNING "udc: " stuff)
++
++#endif /* __LINUX_USB_GADGET_SUPERH_UDC_H */
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/drivers/usb/gadget/usbstring.c kernel/drivers/usb/gadget/usbstring.c
+--- /tmp/kernel/drivers/usb/gadget/usbstring.c 1970-01-01 01:00:00.000000000 +0100
++++ kernel/drivers/usb/gadget/usbstring.c 2005-04-22 17:53:19.516526166 +0200
+@@ -0,0 +1,136 @@
++/*
++ * Copyright (C) 2003 David Brownell
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License as published
++ * by the Free Software Foundation; either version 2.1 of the License, or
++ * (at your option) any later version.
++ */
++
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/list.h>
++#include <linux/string.h>
++#include <linux/init.h>
++
++#include <linux/usb_ch9.h>
++#include <linux/usb_gadget.h>
++
++#include <asm/byteorder.h>
++#include <asm/unaligned.h>
++
++
++static int utf8_to_utf16le(const char *s, u16 *cp, unsigned len)
++{
++ int count = 0;
++ u8 c;
++ u16 uchar;
++
++ /* this insists on correct encodings, though not minimal ones.
++ * BUT it currently rejects legit 4-byte UTF-8 code points,
++ * which need surrogate pairs. (Unicode 3.1 can use them.)
++ */
++ while (len != 0 && (c = (u8) *s++) != 0) {
++ if (unlikely(c & 0x80)) {
++ // 2-byte sequence:
++ // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
++ if ((c & 0xe0) == 0xc0) {
++ uchar = (c & 0x1f) << 6;
++
++ c = (u8) *s++;
++ if ((c & 0xc0) != 0xc0)
++ goto fail;
++ c &= 0x3f;
++ uchar |= c;
++
++ // 3-byte sequence (most CJKV characters):
++ // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
++ } else if ((c & 0xf0) == 0xe0) {
++ uchar = (c & 0x0f) << 12;
++
++ c = (u8) *s++;
++ if ((c & 0xc0) != 0xc0)
++ goto fail;
++ c &= 0x3f;
++ uchar |= c << 6;
++
++ c = (u8) *s++;
++ if ((c & 0xc0) != 0xc0)
++ goto fail;
++ c &= 0x3f;
++ uchar |= c;
++
++ /* no bogus surrogates */
++ if (0xd800 <= uchar && uchar <= 0xdfff)
++ goto fail;
++
++ // 4-byte sequence (surrogate pairs, currently rare):
++ // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
++ // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
++ // (uuuuu = wwww + 1)
++ // FIXME accept the surrogate code points (only)
++
++ } else
++ goto fail;
++ } else
++ uchar = c;
++ put_unaligned (cpu_to_le16 (uchar), cp++);
++ count++;
++ len--;
++ }
++ return count;
++fail:
++ return -1;
++}
++
++
++/**
++ * usb_gadget_get_string - fill out a string descriptor
++ * @table: of c strings encoded using UTF-8
++ * @id: string id, from low byte of wValue in get string descriptor
++ * @buf: at least 256 bytes
++ *
++ * Finds the UTF-8 string matching the ID, and converts it into a
++ * string descriptor in utf16-le.
++ * Returns length of descriptor (always even) or negative errno
++ *
++ * If your driver needs stings in multiple languages, you'll probably
++ * "switch (wIndex) { ... }" in your ep0 string descriptor logic,
++ * using this routine after choosing which set of UTF-8 strings to use.
++ * Note that US-ASCII is a strict subset of UTF-8; any string bytes with
++ * the eighth bit set will be multibyte UTF-8 characters, not ISO-8859/1
++ * characters (which are also widely used in C strings).
++ */
++int
++usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf)
++{
++ struct usb_string *s;
++ int len;
++
++ /* descriptor 0 has the language id */
++ if (id == 0) {
++ buf [0] = 4;
++ buf [1] = USB_DT_STRING;
++ buf [2] = (u8) table->language;
++ buf [3] = (u8) (table->language >> 8);
++ return 4;
++ }
++ for (s = table->strings; s && s->s; s++)
++ if (s->id == id)
++ break;
++
++ /* unrecognized: stall. */
++ if (!s || !s->s)
++ return -EINVAL;
++
++ /* string descriptors have length, tag, then UTF16-LE text */
++ len = min ((size_t) 126, strlen (s->s));
++ memset (buf + 2, 0, 2 * len); /* zero all the bytes */
++ len = utf8_to_utf16le(s->s, (u16 *)&buf[2], len);
++ if (len < 0)
++ return -EINVAL;
++ buf [0] = (len + 1) * 2;
++ buf [1] = USB_DT_STRING;
++ return buf [0];
++}
++
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/drivers/usb/gadget/zero.c kernel/drivers/usb/gadget/zero.c
+--- /tmp/kernel/drivers/usb/gadget/zero.c 1970-01-01 01:00:00.000000000 +0100
++++ kernel/drivers/usb/gadget/zero.c 2005-04-22 17:53:19.521525352 +0200
+@@ -0,0 +1,1363 @@
++/*
++ * zero.c -- Gadget Zero, for USB development
++ *
++ * Copyright (C) 2003-2004 David Brownell
++ * 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.
++ */
++
++
++/*
++ * Gadget Zero only needs two bulk endpoints, and is an example of how you
++ * can write a hardware-agnostic gadget driver running inside a USB device.
++ *
++ * Hardware details are visible (see CONFIG_USB_ZERO_* below) but don't
++ * affect most of the driver.
++ *
++ * Use it with the Linux host/master side "usbtest" driver to get a basic
++ * functional test of your device-side usb stack, or with "usb-skeleton".
++ *
++ * It supports two similar configurations. One sinks whatever the usb host
++ * writes, and in return sources zeroes. The other loops whatever the host
++ * writes back, so the host can read it. Module options include:
++ *
++ * buflen=N default N=4096, buffer size used
++ * qlen=N default N=32, how many buffers in the loopback queue
++ * loopdefault default false, list loopback config first
++ *
++ * Many drivers will only have one configuration, letting them be much
++ * simpler if they also don't support high speed operation (like this
++ * driver does).
++ */
++
++#define DEBUG 1
++// #define VERBOSE
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/module.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/unaligned.h>
++
++#include <linux/usb_ch9.h>
++#include <linux/usb_gadget.h>
++
++#include "gadget_chips.h"
++
++
++/*-------------------------------------------------------------------------*/
++
++#define DRIVER_VERSION "St Patrick's Day 2004"
++
++static const char shortname [] = "zero";
++static const char longname [] = "Gadget Zero";
++
++static const char source_sink [] = "source and sink data";
++static const char loopback [] = "loop input to output";
++
++/*-------------------------------------------------------------------------*/
++
++/*
++ * driver assumes self-powered hardware, and
++ * has no way for users to trigger remote wakeup.
++ *
++ * this version autoconfigures as much as possible,
++ * which is reasonable for most "bulk-only" drivers.
++ */
++static const char *EP_IN_NAME; /* source */
++static const char *EP_OUT_NAME; /* sink */
++
++/*-------------------------------------------------------------------------*/
++
++/* big enough to hold our biggest descriptor */
++#define USB_BUFSIZ 256
++
++struct zero_dev {
++ spinlock_t lock;
++ struct usb_gadget *gadget;
++ struct usb_request *req; /* for control responses */
++
++ /* when configured, we have one of two configs:
++ * - source data (in to host) and sink it (out from host)
++ * - or loop it back (out from host back in to host)
++ */
++ u8 config;
++ struct usb_ep *in_ep, *out_ep;
++
++ /* autoresume timer */
++ struct timer_list resume;
++};
++
++#define xprintk(d,level,fmt,args...) \
++ printk(level "%s %s: " fmt , shortname , (d)->gadget->dev.bus_id , \
++ ## 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)
++
++/*-------------------------------------------------------------------------*/
++
++static unsigned buflen = 4096;
++static unsigned qlen = 32;
++static unsigned pattern = 0;
++
++/*
++ * Normally the "loopback" configuration is second (index 1) so
++ * it's not the default. Here's where to change that order, to
++ * work better with hosts where config changes are problematic.
++ * Or controllers (like superh) that only support one config.
++ */
++static int loopdefault = 0;
++
++
++MODULE_PARM (buflen, "i");
++MODULE_PARM_DESC (buflen, "size of i/o buffers");
++
++MODULE_PARM (qlen, "i");
++MODULE_PARM_DESC (qlen, "depth of loopback buffering");
++
++MODULE_PARM (pattern, "i");
++MODULE_PARM_DESC (pattern, "0 for default all-zeroes, 1 for mod63");
++
++MODULE_PARM (loopdefault, "b");
++MODULE_PARM_DESC (loopdefault, "true to have default config be loopback");
++
++/*
++ * if it's nonzero, autoresume says how many seconds to wait
++ * before trying to wake up the host after suspend.
++ */
++static unsigned autoresume = 0;
++MODULE_PARM (autoresume, "i");
++
++/*-------------------------------------------------------------------------*/
++
++/* 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.
++ */
++#ifndef CONFIG_USB_ZERO_HNPTEST
++#define DRIVER_VENDOR_NUM 0x0525 /* NetChip */
++#define DRIVER_PRODUCT_NUM 0xa4a0 /* Linux-USB "Gadget Zero" */
++#else
++#define DRIVER_VENDOR_NUM 0x1a0a /* OTG test device IDs */
++#define DRIVER_PRODUCT_NUM 0xbadd
++#endif
++
++/*-------------------------------------------------------------------------*/
++
++/*
++ * DESCRIPTORS ... most are static, but strings and (full)
++ * configuration descriptors are built on demand.
++ */
++
++#define STRING_MANUFACTURER 25
++#define STRING_PRODUCT 42
++#define STRING_SERIAL 101
++#define STRING_SOURCE_SINK 250
++#define STRING_LOOPBACK 251
++
++/*
++ * This device advertises two configurations; these numbers work
++ * on a pxa250 as well as more flexible hardware.
++ */
++#define CONFIG_SOURCE_SINK 3
++#define CONFIG_LOOPBACK 2
++
++static struct usb_device_descriptor
++device_desc = {
++ .bLength = sizeof device_desc,
++ .bDescriptorType = USB_DT_DEVICE,
++
++ .bcdUSB = __constant_cpu_to_le16 (0x0200),
++ .bDeviceClass = USB_CLASS_VENDOR_SPEC,
++
++ .idVendor = __constant_cpu_to_le16 (DRIVER_VENDOR_NUM),
++ .idProduct = __constant_cpu_to_le16 (DRIVER_PRODUCT_NUM),
++ .iManufacturer = STRING_MANUFACTURER,
++ .iProduct = STRING_PRODUCT,
++ .iSerialNumber = STRING_SERIAL,
++ .bNumConfigurations = 2,
++};
++
++static struct usb_config_descriptor
++source_sink_config = {
++ .bLength = sizeof source_sink_config,
++ .bDescriptorType = USB_DT_CONFIG,
++
++ /* compute wTotalLength on the fly */
++ .bNumInterfaces = 1,
++ .bConfigurationValue = CONFIG_SOURCE_SINK,
++ .iConfiguration = STRING_SOURCE_SINK,
++ .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
++ .bMaxPower = 1, /* self-powered */
++};
++
++static struct usb_config_descriptor
++loopback_config = {
++ .bLength = sizeof loopback_config,
++ .bDescriptorType = USB_DT_CONFIG,
++
++ /* compute wTotalLength on the fly */
++ .bNumInterfaces = 1,
++ .bConfigurationValue = CONFIG_LOOPBACK,
++ .iConfiguration = STRING_LOOPBACK,
++ .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
++ .bMaxPower = 1, /* self-powered */
++};
++
++static struct usb_otg_descriptor
++otg_descriptor = {
++ .bLength = sizeof otg_descriptor,
++ .bDescriptorType = USB_DT_OTG,
++
++ .bmAttributes = USB_OTG_SRP,
++};
++
++/* one interface in each configuration */
++
++static const struct usb_interface_descriptor
++source_sink_intf = {
++ .bLength = sizeof source_sink_intf,
++ .bDescriptorType = USB_DT_INTERFACE,
++
++ .bNumEndpoints = 2,
++ .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
++ .iInterface = STRING_SOURCE_SINK,
++};
++
++static const struct usb_interface_descriptor
++loopback_intf = {
++ .bLength = sizeof loopback_intf,
++ .bDescriptorType = USB_DT_INTERFACE,
++
++ .bNumEndpoints = 2,
++ .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
++ .iInterface = STRING_LOOPBACK,
++};
++
++/* two full speed bulk endpoints; their use is config-dependent */
++
++static struct usb_endpoint_descriptor
++fs_source_desc = {
++ .bLength = USB_DT_ENDPOINT_SIZE,
++ .bDescriptorType = USB_DT_ENDPOINT,
++
++ .bEndpointAddress = USB_DIR_IN,
++ .bmAttributes = USB_ENDPOINT_XFER_BULK,
++};
++
++static struct usb_endpoint_descriptor
++fs_sink_desc = {
++ .bLength = USB_DT_ENDPOINT_SIZE,
++ .bDescriptorType = USB_DT_ENDPOINT,
++
++ .bEndpointAddress = USB_DIR_OUT,
++ .bmAttributes = USB_ENDPOINT_XFER_BULK,
++};
++
++static const struct usb_descriptor_header *fs_source_sink_function [] = {
++ (struct usb_descriptor_header *) &otg_descriptor,
++ (struct usb_descriptor_header *) &source_sink_intf,
++ (struct usb_descriptor_header *) &fs_sink_desc,
++ (struct usb_descriptor_header *) &fs_source_desc,
++ NULL,
++};
++
++static const struct usb_descriptor_header *fs_loopback_function [] = {
++ (struct usb_descriptor_header *) &otg_descriptor,
++ (struct usb_descriptor_header *) &loopback_intf,
++ (struct usb_descriptor_header *) &fs_sink_desc,
++ (struct usb_descriptor_header *) &fs_source_desc,
++ NULL,
++};
++
++#ifdef CONFIG_USB_GADGET_DUALSPEED
++
++/*
++ * 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 struct usb_endpoint_descriptor
++hs_source_desc = {
++ .bLength = USB_DT_ENDPOINT_SIZE,
++ .bDescriptorType = USB_DT_ENDPOINT,
++
++ .bmAttributes = USB_ENDPOINT_XFER_BULK,
++ .wMaxPacketSize = __constant_cpu_to_le16 (512),
++};
++
++static struct usb_endpoint_descriptor
++hs_sink_desc = {
++ .bLength = USB_DT_ENDPOINT_SIZE,
++ .bDescriptorType = USB_DT_ENDPOINT,
++
++ .bmAttributes = USB_ENDPOINT_XFER_BULK,
++ .wMaxPacketSize = __constant_cpu_to_le16 (512),
++};
++
++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_VENDOR_SPEC,
++
++ .bNumConfigurations = 2,
++};
++
++static const struct usb_descriptor_header *hs_source_sink_function [] = {
++ (struct usb_descriptor_header *) &otg_descriptor,
++ (struct usb_descriptor_header *) &source_sink_intf,
++ (struct usb_descriptor_header *) &hs_source_desc,
++ (struct usb_descriptor_header *) &hs_sink_desc,
++ NULL,
++};
++
++static const struct usb_descriptor_header *hs_loopback_function [] = {
++ (struct usb_descriptor_header *) &otg_descriptor,
++ (struct usb_descriptor_header *) &loopback_intf,
++ (struct usb_descriptor_header *) &hs_source_desc,
++ (struct usb_descriptor_header *) &hs_sink_desc,
++ NULL,
++};
++
++/* 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 /* !CONFIG_USB_GADGET_DUALSPEED */
++
++static char manufacturer [50];
++static char serial [40];
++
++/* static strings, in UTF-8 */
++static struct usb_string strings [] = {
++ { STRING_MANUFACTURER, manufacturer, },
++ { STRING_PRODUCT, longname, },
++ { STRING_SERIAL, serial, },
++ { STRING_LOOPBACK, loopback, },
++ { STRING_SOURCE_SINK, source_sink, },
++ { } /* end of list */
++};
++
++static struct usb_gadget_strings stringtab = {
++ .language = 0x0409, /* en-us */
++ .strings = strings,
++};
++
++/*
++ * config descriptors are also handcrafted. these must agree with code
++ * that sets configurations, and with code managing interfaces and their
++ * altsettings. other complexity may come from:
++ *
++ * - high speed support, including "other speed config" rules
++ * - multiple configurations
++ * - interfaces with alternate settings
++ * - embedded class or vendor-specific descriptors
++ *
++ * this handles high speed, and has a second config that could as easily
++ * have been an alternate interface setting (on most hardware).
++ *
++ * NOTE: to demonstrate (and test) more USB capabilities, this driver
++ * should include an altsetting to test interrupt transfers, including
++ * high bandwidth modes at high speed. (Maybe work like Intel's test
++ * device?)
++ */
++static int
++config_buf (struct usb_gadget *gadget,
++ u8 *buf, u8 type, unsigned index)
++{
++ int is_source_sink;
++ int len;
++ const struct usb_descriptor_header **function;
++#ifdef CONFIG_USB_GADGET_DUALSPEED
++ int hs = (gadget->speed == USB_SPEED_HIGH);
++#endif
++
++ /* two configurations will always be index 0 and index 1 */
++ if (index > 1)
++ return -EINVAL;
++ is_source_sink = loopdefault ? (index == 1) : (index == 0);
++
++#ifdef CONFIG_USB_GADGET_DUALSPEED
++ if (type == USB_DT_OTHER_SPEED_CONFIG)
++ hs = !hs;
++ if (hs)
++ function = is_source_sink
++ ? hs_source_sink_function
++ : hs_loopback_function;
++ else
++#endif
++ function = is_source_sink
++ ? fs_source_sink_function
++ : fs_loopback_function;
++
++ /* for now, don't advertise srp-only devices */
++ if (!gadget->is_otg)
++ function++;
++
++ len = usb_gadget_config_buf (is_source_sink
++ ? &source_sink_config
++ : &loopback_config,
++ buf, USB_BUFSIZ, function);
++ if (len < 0)
++ return len;
++ ((struct usb_config_descriptor *) buf)->bDescriptorType = type;
++ return len;
++}
++
++/*-------------------------------------------------------------------------*/
++
++static struct usb_request *
++alloc_ep_req (struct usb_ep *ep, unsigned length)
++{
++ struct usb_request *req;
++
++ req = usb_ep_alloc_request (ep, GFP_ATOMIC);
++ if (req) {
++ req->length = length;
++ req->buf = usb_ep_alloc_buffer (ep, length,
++ &req->dma, GFP_ATOMIC);
++ if (!req->buf) {
++ usb_ep_free_request (ep, req);
++ req = NULL;
++ }
++ }
++ return req;
++}
++
++static void free_ep_req (struct usb_ep *ep, struct usb_request *req)
++{
++ if (req->buf)
++ usb_ep_free_buffer (ep, req->buf, req->dma, req->length);
++ usb_ep_free_request (ep, req);
++}
++
++/*-------------------------------------------------------------------------*/
++
++/* optionally require specific source/sink data patterns */
++
++static int
++check_read_data (
++ struct zero_dev *dev,
++ struct usb_ep *ep,
++ struct usb_request *req
++)
++{
++ unsigned i;
++ u8 *buf = req->buf;
++
++ for (i = 0; i < req->actual; i++, buf++) {
++ switch (pattern) {
++ /* all-zeroes has no synchronization issues */
++ case 0:
++ if (*buf == 0)
++ continue;
++ break;
++ /* mod63 stays in sync with short-terminated transfers,
++ * or otherwise when host and gadget agree on how large
++ * each usb transfer request should be. resync is done
++ * with set_interface or set_config.
++ */
++ case 1:
++ if (*buf == (u8)(i % 63))
++ continue;
++ break;
++ }
++ ERROR (dev, "bad OUT byte, buf [%d] = %d\n", i, *buf);
++ usb_ep_set_halt (ep);
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static void
++reinit_write_data (
++ struct zero_dev *dev,
++ struct usb_ep *ep,
++ struct usb_request *req
++)
++{
++ unsigned i;
++ u8 *buf = req->buf;
++
++ switch (pattern) {
++ case 0:
++ memset (req->buf, 0, req->length);
++ break;
++ case 1:
++ for (i = 0; i < req->length; i++)
++ *buf++ = (u8) (i % 63);
++ break;
++ }
++}
++
++/* if there is only one request in the queue, there'll always be an
++ * irq delay between end of one request and start of the next.
++ * that prevents using hardware dma queues.
++ */
++static void source_sink_complete (struct usb_ep *ep, struct usb_request *req)
++{
++ struct zero_dev *dev = ep->driver_data;
++ int status = req->status;
++
++ switch (status) {
++
++ case 0: /* normal completion? */
++ if (ep == dev->out_ep)
++ check_read_data (dev, ep, req);
++ else
++ reinit_write_data (dev, ep, req);
++ break;
++
++ /* this endpoint is normally active while we're configured */
++ case -ECONNABORTED: /* hardware forced ep reset */
++ case -ECONNRESET: /* request dequeued */
++ case -ESHUTDOWN: /* disconnect from host */
++ VDBG (dev, "%s gone (%d), %d/%d\n", ep->name, status,
++ req->actual, req->length);
++ if (ep == dev->out_ep)
++ check_read_data (dev, ep, req);
++ free_ep_req (ep, req);
++ return;
++
++ case -EOVERFLOW: /* buffer overrun on read means that
++ * we didn't provide a big enough
++ * buffer.
++ */
++ default:
++#if 1
++ DBG (dev, "%s complete --> %d, %d/%d\n", ep->name,
++ status, req->actual, req->length);
++#endif
++ case -EREMOTEIO: /* short read */
++ break;
++ }
++
++ status = usb_ep_queue (ep, req, GFP_ATOMIC);
++ if (status) {
++ ERROR (dev, "kill %s: resubmit %d bytes --> %d\n",
++ ep->name, req->length, status);
++ usb_ep_set_halt (ep);
++ /* FIXME recover later ... somehow */
++ }
++}
++
++static struct usb_request *
++source_sink_start_ep (struct usb_ep *ep, int gfp_flags)
++{
++ struct usb_request *req;
++ int status;
++
++ req = alloc_ep_req (ep, buflen);
++ if (!req)
++ return NULL;
++
++ memset (req->buf, 0, req->length);
++ req->complete = source_sink_complete;
++
++ if (strcmp (ep->name, EP_IN_NAME) == 0)
++ reinit_write_data (ep->driver_data, ep, req);
++
++ status = usb_ep_queue (ep, req, gfp_flags);
++ if (status) {
++ struct zero_dev *dev = ep->driver_data;
++
++ ERROR (dev, "start %s --> %d\n", ep->name, status);
++ free_ep_req (ep, req);
++ req = NULL;
++ }
++
++ return req;
++}
++
++static int
++set_source_sink_config (struct zero_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;
++
++ /* one endpoint writes (sources) zeroes 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;
++ if (source_sink_start_ep (ep, gfp_flags) != 0) {
++ dev->in_ep = ep;
++ continue;
++ }
++ usb_ep_disable (ep);
++ result = -EIO;
++ }
++
++ /* one endpoint reads (sinks) anything out (from the host) */
++ } 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;
++ if (source_sink_start_ep (ep, gfp_flags) != 0) {
++ dev->out_ep = ep;
++ continue;
++ }
++ usb_ep_disable (ep);
++ result = -EIO;
++ }
++
++ /* ignore any other endpoints */
++ } else
++ continue;
++
++ /* stop on error */
++ ERROR (dev, "can't start %s, result %d\n", ep->name, result);
++ break;
++ }
++ if (result == 0)
++ DBG (dev, "buflen %d\n", buflen);
++
++ /* caller is responsible for cleanup on error */
++ return result;
++}
++
++/*-------------------------------------------------------------------------*/
++
++static void loopback_complete (struct usb_ep *ep, struct usb_request *req)
++{
++ struct zero_dev *dev = ep->driver_data;
++ int status = req->status;
++
++ switch (status) {
++
++ case 0: /* normal completion? */
++ if (ep == dev->out_ep) {
++ /* loop this OUT packet back IN to the host */
++ req->zero = (req->actual < req->length);
++ req->length = req->actual;
++ status = usb_ep_queue (dev->in_ep, req, GFP_ATOMIC);
++ if (status == 0)
++ return;
++
++ /* "should never get here" */
++ ERROR (dev, "can't loop %s to %s: %d\n",
++ ep->name, dev->in_ep->name,
++ status);
++ }
++
++ /* queue the buffer for some later OUT packet */
++ req->length = buflen;
++ status = usb_ep_queue (dev->out_ep, req, GFP_ATOMIC);
++ if (status == 0)
++ return;
++
++ /* "should never get here" */
++ /* FALLTHROUGH */
++
++ default:
++ ERROR (dev, "%s loop complete --> %d, %d/%d\n", ep->name,
++ status, req->actual, req->length);
++ /* FALLTHROUGH */
++
++ /* NOTE: since this driver doesn't maintain an explicit record
++ * of requests it submitted (just maintains qlen count), we
++ * rely on the hardware driver to clean up on disconnect or
++ * endpoint disable.
++ */
++ case -ECONNABORTED: /* hardware forced ep reset */
++ case -ECONNRESET: /* request dequeued */
++ case -ESHUTDOWN: /* disconnect from host */
++ free_ep_req (ep, req);
++ return;
++ }
++}
++
++static int
++set_loopback_config (struct zero_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;
++
++ /* 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;
++ 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;
++ continue;
++ }
++
++ /* ignore any other endpoints */
++ } else
++ continue;
++
++ /* stop on error */
++ ERROR (dev, "can't enable %s, result %d\n", ep->name, result);
++ break;
++ }
++
++ /* allocate a bunch of read buffers and queue them all at once.
++ * we buffer at most 'qlen' transfers; fewer if any need more
++ * than 'buflen' bytes each.
++ */
++ if (result == 0) {
++ struct usb_request *req;
++ unsigned i;
++
++ ep = dev->out_ep;
++ for (i = 0; i < qlen && result == 0; i++) {
++ req = alloc_ep_req (ep, buflen);
++ if (req) {
++ req->complete = loopback_complete;
++ result = usb_ep_queue (ep, req, GFP_ATOMIC);
++ if (result)
++ DBG (dev, "%s queue req --> %d\n",
++ ep->name, result);
++ } else
++ result = -ENOMEM;
++ }
++ }
++ if (result == 0)
++ DBG (dev, "qlen %d, buflen %d\n", qlen, buflen);
++
++ /* caller is responsible for cleanup on error */
++ return result;
++}
++
++/*-------------------------------------------------------------------------*/
++
++static void zero_reset_config (struct zero_dev *dev)
++{
++ if (dev->config == 0)
++ return;
++
++ DBG (dev, "reset config\n");
++
++ /* 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 = NULL;
++ }
++ if (dev->out_ep) {
++ usb_ep_disable (dev->out_ep);
++ dev->out_ep = NULL;
++ }
++ dev->config = 0;
++ del_timer (&dev->resume);
++}
++
++/* change our operational config. this code must agree with the code
++ * that returns config descriptors, and altsetting code.
++ *
++ * it's also responsible for power management interactions. some
++ * configurations might not work with our current power sources.
++ *
++ * note that some device controller hardware will constrain what this
++ * code can do, perhaps by disallowing more than one configuration or
++ * by limiting configuration choices (like the pxa2xx).
++ */
++static int
++zero_set_config (struct zero_dev *dev, unsigned number, int gfp_flags)
++{
++ int result = 0;
++ struct usb_gadget *gadget = dev->gadget;
++
++ if (number == dev->config)
++ return 0;
++
++ if (gadget_is_sa1100 (gadget) && dev->config) {
++ /* tx fifo is full, but we can't clear it...*/
++ INFO (dev, "can't change configurations\n");
++ return -ESPIPE;
++ }
++ zero_reset_config (dev);
++
++ switch (number) {
++ case CONFIG_SOURCE_SINK:
++ result = set_source_sink_config (dev, gfp_flags);
++ break;
++ case CONFIG_LOOPBACK:
++ result = set_loopback_config (dev, gfp_flags);
++ break;
++ default:
++ result = -EINVAL;
++ /* FALL THROUGH */
++ case 0:
++ return result;
++ }
++
++ if (!result && (!dev->in_ep || !dev->out_ep))
++ result = -ENODEV;
++ if (result)
++ zero_reset_config (dev);
++ else {
++ char *speed;
++
++ switch (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;
++ }
++
++ dev->config = number;
++ INFO (dev, "%s speed config #%d: %s\n", speed, number,
++ (number == CONFIG_SOURCE_SINK)
++ ? source_sink : loopback);
++ }
++ return result;
++}
++
++/*-------------------------------------------------------------------------*/
++
++static void zero_setup_complete (struct usb_ep *ep, struct usb_request *req)
++{
++ if (req->status || req->actual != req->length)
++ DBG ((struct zero_dev *) ep->driver_data,
++ "setup complete --> %d, %d/%d\n",
++ req->status, req->actual, req->length);
++}
++
++/*
++ * The setup() callback implements all the ep0 functionality that's
++ * not handled lower down, in hardware or the hardware driver (like
++ * device and endpoint feature flags, and their status). It's all
++ * housekeeping for the gadget function we're implementing. Most of
++ * the work is in config-specific setup.
++ */
++static int
++zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
++{
++ struct zero_dev *dev = get_gadget_data (gadget);
++ struct usb_request *req = dev->req;
++ int value = -EOPNOTSUPP;
++
++ /* usually this stores reply data in the pre-allocated ep0 buffer,
++ * but config change events will reconfigure hardware.
++ */
++ req->zero = 0;
++ switch (ctrl->bRequest) {
++
++ case USB_REQ_GET_DESCRIPTOR:
++ if (ctrl->bRequestType != USB_DIR_IN)
++ goto unknown;
++ switch (ctrl->wValue >> 8) {
++
++ case USB_DT_DEVICE:
++ value = min (ctrl->wLength, (u16) sizeof device_desc);
++ memcpy (req->buf, &device_desc, value);
++ break;
++#ifdef CONFIG_USB_GADGET_DUALSPEED
++ case USB_DT_DEVICE_QUALIFIER:
++ if (!gadget->is_dualspeed)
++ break;
++ value = min (ctrl->wLength, (u16) sizeof dev_qualifier);
++ memcpy (req->buf, &dev_qualifier, value);
++ break;
++
++ case USB_DT_OTHER_SPEED_CONFIG:
++ if (!gadget->is_dualspeed)
++ break;
++ // FALLTHROUGH
++#endif /* CONFIG_USB_GADGET_DUALSPEED */
++ case USB_DT_CONFIG:
++ value = config_buf (gadget, req->buf,
++ ctrl->wValue >> 8,
++ ctrl->wValue & 0xff);
++ if (value >= 0)
++ value = min (ctrl->wLength, (u16) value);
++ break;
++
++ case USB_DT_STRING:
++ /* wIndex == language code.
++ * this driver only handles one language, you can
++ * add string tables for other languages, using
++ * any UTF-8 characters
++ */
++ value = usb_gadget_get_string (&stringtab,
++ ctrl->wValue & 0xff, req->buf);
++ if (value >= 0)
++ value = min (ctrl->wLength, (u16) value);
++ break;
++ }
++ break;
++
++ /* currently two configs, two speeds */
++ case USB_REQ_SET_CONFIGURATION:
++ if (ctrl->bRequestType != 0)
++ goto unknown;
++ if (gadget->a_hnp_support)
++ DBG (dev, "HNP available\n");
++ else if (gadget->a_alt_hnp_support)
++ DBG (dev, "HNP needs a different root port\n");
++ else
++ VDBG (dev, "HNP inactive\n");
++ spin_lock (&dev->lock);
++ value = zero_set_config (dev, ctrl->wValue, GFP_ATOMIC);
++ spin_unlock (&dev->lock);
++ break;
++ case USB_REQ_GET_CONFIGURATION:
++ if (ctrl->bRequestType != USB_DIR_IN)
++ goto unknown;
++ *(u8 *)req->buf = dev->config;
++ value = min (ctrl->wLength, (u16) 1);
++ break;
++
++ /* until we add altsetting support, or other interfaces,
++ * only 0/0 are possible. pxa2xx only supports 0/0 (poorly)
++ * and already killed pending endpoint I/O.
++ */
++ case USB_REQ_SET_INTERFACE:
++ if (ctrl->bRequestType != USB_RECIP_INTERFACE)
++ goto unknown;
++ spin_lock (&dev->lock);
++ if (dev->config && ctrl->wIndex == 0 && ctrl->wValue == 0) {
++ u8 config = dev->config;
++
++ /* resets interface configuration, forgets about
++ * previous transaction state (queued bufs, etc)
++ * and re-inits endpoint state (toggle etc)
++ * no response queued, just zero status == success.
++ * if we had more than one interface we couldn't
++ * use this "reset the config" shortcut.
++ */
++ zero_reset_config (dev);
++ zero_set_config (dev, config, GFP_ATOMIC);
++ value = 0;
++ }
++ spin_unlock (&dev->lock);
++ break;
++ case USB_REQ_GET_INTERFACE:
++ if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE))
++ goto unknown;
++ if (!dev->config)
++ break;
++ if (ctrl->wIndex != 0) {
++ value = -EDOM;
++ break;
++ }
++ *(u8 *)req->buf = 0;
++ value = min (ctrl->wLength, (u16) 1);
++ break;
++
++ /*
++ * These are the same vendor-specific requests supported by
++ * Intel's USB 2.0 compliance test devices. We exceed that
++ * device spec by allowing multiple-packet requests.
++ */
++ case 0x5b: /* control WRITE test -- fill the buffer */
++ if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR))
++ goto unknown;
++ if (ctrl->wValue || ctrl->wIndex)
++ break;
++ /* just read that many bytes into the buffer */
++ if (ctrl->wLength > USB_BUFSIZ)
++ break;
++ value = ctrl->wLength;
++ break;
++ case 0x5c: /* control READ test -- return the buffer */
++ if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR))
++ goto unknown;
++ if (ctrl->wValue || ctrl->wIndex)
++ break;
++ /* expect those bytes are still in the buffer; send back */
++ if (ctrl->wLength > USB_BUFSIZ
++ || ctrl->wLength != req->length)
++ break;
++ value = ctrl->wLength;
++ break;
++
++ default:
++unknown:
++ VDBG (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;
++ req->zero = value < ctrl->wLength
++ && (value % gadget->ep0->maxpacket) == 0;
++ value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
++ if (value < 0) {
++ DBG (dev, "ep_queue --> %d\n", value);
++ req->status = 0;
++ zero_setup_complete (gadget->ep0, req);
++ }
++ }
++
++ /* device either stalls (value < 0) or reports success */
++ return value;
++}
++
++static void
++zero_disconnect (struct usb_gadget *gadget)
++{
++ struct zero_dev *dev = get_gadget_data (gadget);
++ unsigned long flags;
++
++ spin_lock_irqsave (&dev->lock, flags);
++ zero_reset_config (dev);
++
++ /* a more significant application might have some non-usb
++ * activities to quiesce here, saving resources like power
++ * or pushing the notification up a network stack.
++ */
++ spin_unlock_irqrestore (&dev->lock, flags);
++
++ /* next we may get setup() calls to enumerate new connections;
++ * or an unbind() during shutdown (including removing module).
++ */
++}
++
++static void
++zero_autoresume (unsigned long _dev)
++{
++ struct zero_dev *dev = (struct zero_dev *) _dev;
++ int status;
++
++ /* normally the host would be woken up for something
++ * more significant than just a timer firing...
++ */
++ if (dev->gadget->speed != USB_SPEED_UNKNOWN) {
++ status = usb_gadget_wakeup (dev->gadget);
++ DBG (dev, "wakeup --> %d\n", status);
++ }
++}
++
++/*-------------------------------------------------------------------------*/
++
++static void
++zero_unbind (struct usb_gadget *gadget)
++{
++ struct zero_dev *dev = get_gadget_data (gadget);
++
++ DBG (dev, "unbind\n");
++
++ /* we've already been disconnected ... no i/o is active */
++ if (dev->req)
++ free_ep_req (gadget->ep0, dev->req);
++ del_timer_sync (&dev->resume);
++ kfree (dev);
++ set_gadget_data (gadget, NULL);
++}
++
++static int
++zero_bind (struct usb_gadget *gadget)
++{
++ struct zero_dev *dev;
++ struct usb_ep *ep;
++
++ /* Bulk-only drivers like this one SHOULD be able to
++ * autoconfigure on any sane usb controller driver,
++ * but there may also be important quirks to address.
++ */
++ usb_ep_autoconfig_reset (gadget);
++ ep = usb_ep_autoconfig (gadget, &fs_source_desc);
++ if (!ep) {
++autoconf_fail:
++ printk (KERN_ERR "%s: can't autoconfigure on %s\n",
++ shortname, gadget->name);
++ return -ENODEV;
++ }
++ EP_IN_NAME = ep->name;
++ ep->driver_data = ep; /* claim */
++
++ ep = usb_ep_autoconfig (gadget, &fs_sink_desc);
++ if (!ep)
++ goto autoconf_fail;
++ EP_OUT_NAME = ep->name;
++ ep->driver_data = ep; /* claim */
++
++
++ /*
++ * DRIVER POLICY CHOICE: you may want to do this differently.
++ * One thing to avoid is reusing a bcdDevice revision code
++ * with different host-visible configurations or behavior
++ * restrictions -- using ep1in/ep2out vs ep1out/ep3in, etc
++ */
++ if (gadget_is_net2280 (gadget)) {
++ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0201);
++ } else if (gadget_is_pxa (gadget)) {
++ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0203);
++#if 0
++ } else if (gadget_is_sh(gadget)) {
++ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0204);
++ /* SH has only one configuration; see "loopdefault" */
++ device_desc.bNumConfigurations = 1;
++ /* FIXME make 1 == default.bConfigurationValue */
++#endif
++ } else if (gadget_is_sa1100 (gadget)) {
++ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0205);
++ } else if (gadget_is_goku (gadget)) {
++ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0206);
++ } else if (gadget_is_mq11xx (gadget)) {
++ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0207);
++ } else if (gadget_is_omap (gadget)) {
++ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0208);
++ } else if (gadget_is_lh7a40x(gadget)) {
++ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0209);
++ } else if (gadget_is_n9604(gadget)) {
++ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0210);
++ } else if (gadget_is_pxa27x(gadget)) {
++ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0211);
++ } else if (gadget_is_s3c2410(gadget)) {
++ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0212);
++ } else if (gadget_is_at91(gadget)) {
++ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0213);
++ } else {
++ /* gadget zero is so simple (for now, no altsettings) that
++ * it SHOULD NOT have problems with bulk-capable hardware.
++ * so warn about unrcognized controllers, don't panic.
++ *
++ * things like configuration and altsetting numbering
++ * can need hardware-specific attention though.
++ */
++ printk (KERN_WARNING "%s: controller '%s' not recognized\n",
++ shortname, gadget->name);
++ device_desc.bcdDevice = __constant_cpu_to_le16 (0x9999);
++ }
++
++
++ /* ok, we made sense of the hardware ... */
++ dev = kmalloc (sizeof *dev, SLAB_KERNEL);
++ if (!dev)
++ return -ENOMEM;
++ memset (dev, 0, sizeof *dev);
++ spin_lock_init (&dev->lock);
++ dev->gadget = gadget;
++ set_gadget_data (gadget, dev);
++
++ /* preallocate control response and buffer */
++ dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);
++ if (!dev->req)
++ goto enomem;
++ dev->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ,
++ &dev->req->dma, GFP_KERNEL);
++ if (!dev->req->buf)
++ goto enomem;
++
++ dev->req->complete = zero_setup_complete;
++
++ device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
++
++#ifdef CONFIG_USB_GADGET_DUALSPEED
++ /* assume ep0 uses the same value for both speeds ... */
++ dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
++
++ /* and that all endpoints are dual-speed */
++ hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
++ hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
++#endif
++
++ if (gadget->is_otg) {
++ otg_descriptor.bmAttributes |= USB_OTG_HNP,
++ source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
++ loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
++ }
++
++ if (gadget->is_otg) {
++ otg_descriptor.bmAttributes |= USB_OTG_HNP,
++ source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
++ loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
++ }
++
++ usb_gadget_set_selfpowered (gadget);
++
++ init_timer (&dev->resume);
++ dev->resume.function = zero_autoresume;
++ dev->resume.data = (unsigned long) dev;
++ if (autoresume) {
++ source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
++ loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
++ }
++
++ gadget->ep0->driver_data = dev;
++
++ INFO (dev, "%s, version: " DRIVER_VERSION "\n", longname);
++ INFO (dev, "using %s, OUT %s IN %s\n", gadget->name,
++ EP_OUT_NAME, EP_IN_NAME);
++
++ snprintf (manufacturer, sizeof manufacturer,
++ UTS_SYSNAME " " UTS_RELEASE " with %s",
++ gadget->name);
++
++ return 0;
++
++enomem:
++ zero_unbind (gadget);
++ return -ENOMEM;
++}
++
++/*-------------------------------------------------------------------------*/
++
++static void
++zero_suspend (struct usb_gadget *gadget)
++{
++ struct zero_dev *dev = get_gadget_data (gadget);
++
++ if (gadget->speed == USB_SPEED_UNKNOWN)
++ return;
++
++ if (autoresume) {
++ mod_timer (&dev->resume, jiffies + (HZ * autoresume));
++ DBG (dev, "suspend, wakeup in %d seconds\n", autoresume);
++ } else
++ DBG (dev, "suspend\n");
++}
++
++static void
++zero_resume (struct usb_gadget *gadget)
++{
++ struct zero_dev *dev = get_gadget_data (gadget);
++
++ DBG (dev, "resume\n");
++ del_timer (&dev->resume);
++}
++
++
++/*-------------------------------------------------------------------------*/
++
++static struct usb_gadget_driver zero_driver = {
++#ifdef CONFIG_USB_GADGET_DUALSPEED
++ .speed = USB_SPEED_HIGH,
++#else
++ .speed = USB_SPEED_FULL,
++#endif
++ .function = (char *) longname,
++ .bind = zero_bind,
++ .unbind = zero_unbind,
++
++ .setup = zero_setup,
++ .disconnect = zero_disconnect,
++
++ .suspend = zero_suspend,
++ .resume = zero_resume,
++
++ .driver = {
++ .name = (char *) shortname,
++ // .shutdown = ...
++ // .suspend = ...
++ // .resume = ...
++ },
++};
++
++MODULE_AUTHOR ("David Brownell");
++MODULE_LICENSE ("Dual BSD/GPL");
++
++
++static int __init init (void)
++{
++ /* a real value would likely come through some id prom
++ * or module option. this one takes at least two packets.
++ */
++ strncpy (serial, "0123456789.0123456789.0123456789", sizeof serial);
++ serial [sizeof serial - 1] = 0;
++
++ return usb_gadget_register_driver (&zero_driver);
++}
++module_init (init);
++
++static void __exit cleanup (void)
++{
++ usb_gadget_unregister_driver (&zero_driver);
++}
++module_exit (cleanup);
++
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/include/linux/moduleparam.h kernel/include/linux/moduleparam.h
+--- /tmp/kernel/include/linux/moduleparam.h 1970-01-01 01:00:00.000000000 +0100
++++ kernel/include/linux/moduleparam.h 2005-04-22 17:53:19.357552052 +0200
+@@ -0,0 +1,25 @@
++#ifndef _LINUX_MODULE_PARAMS_H
++#define _LINUX_MODULE_PARAMS_H
++/* Macros for (very simple) module parameter compatibility with 2.6. */
++#include <linux/module.h>
++
++/* type is byte, short, ushort, int, uint, long, ulong, bool. (2.6
++ has more, but they are not supported). perm is permissions when
++ it appears in sysfs: 0 means doens't appear, 0444 means read-only
++ by everyone, 0644 means changable dynamically by root, etc. name
++ must be in scope (unlike MODULE_PARM).
++*/
++#define module_param(name, type, perm) \
++ static inline void *__check_existence_##name(void) { return &name; } \
++ MODULE_PARM(name, _MODULE_PARM_STRING_ ## type)
++
++#define _MODULE_PARM_STRING_byte "b"
++#define _MODULE_PARM_STRING_short "h"
++#define _MODULE_PARM_STRING_ushort "h"
++#define _MODULE_PARM_STRING_int "i"
++#define _MODULE_PARM_STRING_uint "i"
++#define _MODULE_PARM_STRING_long "l"
++#define _MODULE_PARM_STRING_ulong "l"
++#define _MODULE_PARM_STRING_bool "i"
++
++#endif /* _LINUX_MODULE_PARAM_TYPES_H */
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/include/linux/usb_cdc.h kernel/include/linux/usb_cdc.h
+--- /tmp/kernel/include/linux/usb_cdc.h 1970-01-01 01:00:00.000000000 +0100
++++ kernel/include/linux/usb_cdc.h 2005-04-22 17:53:19.360551563 +0200
+@@ -0,0 +1,204 @@
++/*
++ * USB Communications Device Class (CDC) definitions
++ *
++ * CDC says how to talk to lots of different types of network adapters,
++ * notably ethernet adapters and various modems. It's used mostly with
++ * firmware based USB peripherals.
++ *
++ * (C) Copyright 2005 by David Brownell
++ * All Rights Reserved.
++ *
++ * This software is licensed under the GNU GPL version 2.
++ */
++
++#define USB_CDC_SUBCLASS_ACM 0x02
++#define USB_CDC_SUBCLASS_ETHERNET 0x06
++#define USB_CDC_SUBCLASS_WHCM 0x08
++#define USB_CDC_SUBCLASS_DMM 0x09
++#define USB_CDC_SUBCLASS_MDLM 0x0a
++#define USB_CDC_SUBCLASS_OBEX 0x0b
++
++#define USB_CDC_PROTO_NONE 0
++
++#define USB_CDC_ACM_PROTO_AT_V25TER 1
++#define USB_CDC_ACM_PROTO_AT_PCCA101 2
++#define USB_CDC_ACM_PROTO_AT_PCCA101_WAKE 3
++#define USB_CDC_ACM_PROTO_AT_GSM 4
++#define USB_CDC_ACM_PROTO_AT_3G 5
++#define USB_CDC_ACM_PROTO_AT_CDMA 6
++#define USB_CDC_ACM_PROTO_VENDOR 0xff
++
++/*-------------------------------------------------------------------------*/
++
++/* 2.6 "sparse" support for checking beyond what GCC does */
++
++#define __le16 u16
++#define __le32 u32
++
++/*-------------------------------------------------------------------------*/
++
++/*
++ * Class-Specific descriptors ... there are a couple dozen of them
++ */
++
++#define USB_CDC_HEADER_TYPE 0x00 /* header_desc */
++#define USB_CDC_CALL_MANAGEMENT_TYPE 0x01 /* call_mgmt_descriptor */
++#define USB_CDC_ACM_TYPE 0x02 /* acm_descriptor */
++#define USB_CDC_UNION_TYPE 0x06 /* union_desc */
++#define USB_CDC_COUNTRY_TYPE 0x07
++#define USB_CDC_ETHERNET_TYPE 0x0f /* ether_desc */
++#define USB_CDC_WHCM_TYPE 0x11
++#define USB_CDC_MDLM_TYPE 0x12 /* mdlm_desc */
++#define USB_CDC_MDLM_DETAIL_TYPE 0x13 /* mdlm_detail_desc */
++#define USB_CDC_DMM_TYPE 0x14
++#define USB_CDC_OBEX_TYPE 0x15
++
++/* "Header Functional Descriptor" from CDC spec 5.2.3.1 */
++struct usb_cdc_header_desc {
++ __u8 bLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubType;
++
++ __le16 bcdCDC;
++} __attribute__ ((packed));
++
++/* "Call Management Descriptor" from CDC spec 5.2.3.2 */
++struct usb_cdc_call_mgmt_descriptor {
++ __u8 bLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubType;
++
++ __u8 bmCapabilities;
++#define USB_CDC_CALL_MGMT_CAP_CALL_MGMT 0x01
++#define USB_CDC_CALL_MGMT_CAP_DATA_INTF 0x02
++
++ __u8 bDataInterface;
++} __attribute__ ((packed));
++
++/* "Abstract Control Management Descriptor" from CDC spec 5.2.3.3 */
++struct usb_cdc_acm_descriptor {
++ __u8 bLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubType;
++
++ __u8 bmCapabilities;
++} __attribute__ ((packed));
++
++/* "Union Functional Descriptor" from CDC spec 5.2.3.8 */
++struct usb_cdc_union_desc {
++ __u8 bLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubType;
++
++ __u8 bMasterInterface0;
++ __u8 bSlaveInterface0;
++ /* ... and there could be other slave interfaces */
++} __attribute__ ((packed));
++
++/* "Ethernet Networking Functional Descriptor" from CDC spec 5.2.3.16 */
++struct usb_cdc_ether_desc {
++ __u8 bLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubType;
++
++ __u8 iMACAddress;
++ __le32 bmEthernetStatistics;
++ __le16 wMaxSegmentSize;
++ __le16 wNumberMCFilters;
++ __u8 bNumberPowerFilters;
++} __attribute__ ((packed));
++
++/* "MDLM Functional Descriptor" from CDC WMC spec 6.7.2.3 */
++struct usb_cdc_mdlm_desc {
++ __u8 bLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubType;
++
++ __le16 bcdVersion;
++ __u8 bGUID[16];
++} __attribute__ ((packed));
++
++/* "MDLM Detail Functional Descriptor" from CDC WMC spec 6.7.2.4 */
++struct usb_cdc_mdlm_detail_desc {
++ __u8 bLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubType;
++
++ /* type is associated with mdlm_desc.bGUID */
++ __u8 bGuidDescriptorType;
++ __u8 bDetailData[];
++} __attribute__ ((packed));
++
++/*-------------------------------------------------------------------------*/
++
++/*
++ * Class-Specific Control Requests (6.2)
++ *
++ * section 3.6.2.1 table 4 has the ACM profile, for modems.
++ * section 3.8.2 table 10 has the ethernet profile.
++ *
++ * Microsoft's RNDIS stack for Ethernet is a vendor-specific CDC ACM variant,
++ * heavily dependent on the encapsulated (proprietary) command mechanism.
++ */
++
++#define USB_CDC_SEND_ENCAPSULATED_COMMAND 0x00
++#define USB_CDC_GET_ENCAPSULATED_RESPONSE 0x01
++#define USB_CDC_REQ_SET_LINE_CODING 0x20
++#define USB_CDC_REQ_GET_LINE_CODING 0x21
++#define USB_CDC_REQ_SET_CONTROL_LINE_STATE 0x22
++#define USB_CDC_REQ_SEND_BREAK 0x23
++#define USB_CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40
++#define USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER 0x41
++#define USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER 0x42
++#define USB_CDC_SET_ETHERNET_PACKET_FILTER 0x43
++#define USB_CDC_GET_ETHERNET_STATISTIC 0x44
++
++/* Line Coding Structure from CDC spec 6.2.13 */
++struct usb_cdc_line_coding {
++ __le32 dwDTERate;
++ __u8 bCharFormat;
++#define USB_CDC_1_STOP_BITS 0
++#define USB_CDC_1_5_STOP_BITS 1
++#define USB_CDC_2_STOP_BITS 2
++
++ __u8 bParityType;
++#define USB_CDC_NO_PARITY 0
++#define USB_CDC_ODD_PARITY 1
++#define USB_CDC_EVEN_PARITY 2
++#define USB_CDC_MARK_PARITY 3
++#define USB_CDC_SPACE_PARITY 4
++
++ __u8 bDataBits;
++} __attribute__ ((packed));
++
++/* table 62; bits in multicast filter */
++#define USB_CDC_PACKET_TYPE_PROMISCUOUS (1 << 0)
++#define USB_CDC_PACKET_TYPE_ALL_MULTICAST (1 << 1) /* no filter */
++#define USB_CDC_PACKET_TYPE_DIRECTED (1 << 2)
++#define USB_CDC_PACKET_TYPE_BROADCAST (1 << 3)
++#define USB_CDC_PACKET_TYPE_MULTICAST (1 << 4) /* filtered */
++
++
++/*-------------------------------------------------------------------------*/
++
++/*
++ * Class-Specific Notifications (6.3) sent by interrupt transfers
++ *
++ * section 3.8.2 table 11 of the CDC spec lists Ethernet notifications
++ * section 3.6.2.1 table 5 specifies ACM notifications, accepted by RNDIS
++ * RNDIS also defines its own bit-incompatible notifications
++ */
++
++#define USB_CDC_NOTIFY_NETWORK_CONNECTION 0x00
++#define USB_CDC_NOTIFY_RESPONSE_AVAILABLE 0x01
++#define USB_CDC_NOTIFY_SERIAL_STATE 0x20
++#define USB_CDC_NOTIFY_SPEED_CHANGE 0x2a
++
++struct usb_cdc_notification {
++ __u8 bmRequestType;
++ __u8 bNotificationType;
++ __le16 wValue;
++ __le16 wIndex;
++ __le16 wLength;
++} __attribute__ ((packed));
++
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/include/linux/usb_ch9.h kernel/include/linux/usb_ch9.h
+--- /tmp/kernel/include/linux/usb_ch9.h 1970-01-01 01:00:00.000000000 +0100
++++ kernel/include/linux/usb_ch9.h 2005-04-22 17:53:19.363551075 +0200
+@@ -0,0 +1,384 @@
++/*
++ * This file holds USB constants and structures that are needed for USB
++ * device APIs. These are used by the USB device model, which is defined
++ * in chapter 9 of the USB 2.0 specification. Linux has several APIs in C
++ * that need these:
++ *
++ * - the master/host side Linux-USB kernel driver API;
++ * - the "usbfs" user space API; and
++ * - (eventually) a Linux "gadget" slave/device side driver API.
++ *
++ * USB 2.0 adds an additional "On The Go" (OTG) mode, which lets systems
++ * act either as a USB master/host or as a USB slave/device. That means
++ * the master and slave side APIs will benefit from working well together.
++ */
++
++#ifndef __LINUX_USB_CH9_H
++#define __LINUX_USB_CH9_H
++
++#include <asm/types.h> /* __u8 etc */
++
++/*-------------------------------------------------------------------------*/
++
++/* CONTROL REQUEST SUPPORT */
++
++/*
++ * USB directions
++ *
++ * This bit flag is used in endpoint descriptors' bEndpointAddress field.
++ * It's also one of three fields in control requests bRequestType.
++ */
++#define USB_DIR_OUT 0 /* to device */
++#define USB_DIR_IN 0x80 /* to host */
++
++/*
++ * USB types, the second of three bRequestType fields
++ */
++#define USB_TYPE_MASK (0x03 << 5)
++#define USB_TYPE_STANDARD (0x00 << 5)
++#define USB_TYPE_CLASS (0x01 << 5)
++#define USB_TYPE_VENDOR (0x02 << 5)
++#define USB_TYPE_RESERVED (0x03 << 5)
++
++/*
++ * USB recipients, the third of three bRequestType fields
++ */
++#define USB_RECIP_MASK 0x1f
++#define USB_RECIP_DEVICE 0x00
++#define USB_RECIP_INTERFACE 0x01
++#define USB_RECIP_ENDPOINT 0x02
++#define USB_RECIP_OTHER 0x03
++
++/*
++ * Standard requests, for the bRequest field of a SETUP packet.
++ *
++ * These are qualified by the bRequestType field, so that for example
++ * TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved
++ * by a GET_STATUS request.
++ */
++#define USB_REQ_GET_STATUS 0x00
++#define USB_REQ_CLEAR_FEATURE 0x01
++#define USB_REQ_SET_FEATURE 0x03
++#define USB_REQ_SET_ADDRESS 0x05
++#define USB_REQ_GET_DESCRIPTOR 0x06
++#define USB_REQ_SET_DESCRIPTOR 0x07
++#define USB_REQ_GET_CONFIGURATION 0x08
++#define USB_REQ_SET_CONFIGURATION 0x09
++#define USB_REQ_GET_INTERFACE 0x0A
++#define USB_REQ_SET_INTERFACE 0x0B
++#define USB_REQ_SYNCH_FRAME 0x0C
++
++/*
++ * USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and
++ * are read as a bit array returned by USB_REQ_GET_STATUS. (So there
++ * are at most sixteen features of each type.)
++ */
++#define USB_DEVICE_SELF_POWERED 0 /* (read only) */
++#define USB_DEVICE_REMOTE_WAKEUP 1 /* dev may initiate wakeup */
++#define USB_DEVICE_TEST_MODE 2 /* (high speed only) */
++#define USB_DEVICE_B_HNP_ENABLE 3 /* dev may initiate HNP */
++#define USB_DEVICE_A_HNP_SUPPORT 4 /* RH port supports HNP */
++#define USB_DEVICE_A_ALT_HNP_SUPPORT 5 /* other RH port does */
++#define USB_DEVICE_DEBUG_MODE 6 /* (special devices only) */
++
++#define USB_ENDPOINT_HALT 0 /* IN/OUT will STALL */
++
++
++/**
++ * struct usb_ctrlrequest - SETUP data for a USB device control request
++ * @bRequestType: matches the USB bmRequestType field
++ * @bRequest: matches the USB bRequest field
++ * @wValue: matches the USB wValue field (le16 byte order)
++ * @wIndex: matches the USB wIndex field (le16 byte order)
++ * @wLength: matches the USB wLength field (le16 byte order)
++ *
++ * This structure is used to send control requests to a USB device. It matches
++ * the different fields of the USB 2.0 Spec section 9.3, table 9-2. See the
++ * USB spec for a fuller description of the different fields, and what they are
++ * used for.
++ *
++ * Note that the driver for any interface can issue control requests.
++ * For most devices, interfaces don't coordinate with each other, so
++ * such requests may be made at any time.
++ */
++struct usb_ctrlrequest {
++ __u8 bRequestType;
++ __u8 bRequest;
++ __u16 wValue;
++ __u16 wIndex;
++ __u16 wLength;
++} __attribute__ ((packed));
++
++/*-------------------------------------------------------------------------*/
++
++/*
++ * STANDARD DESCRIPTORS ... as returned by GET_DESCRIPTOR, or
++ * (rarely) accepted by SET_DESCRIPTOR.
++ *
++ * Note that all multi-byte values here are encoded in little endian
++ * byte order "on the wire". But when exposed through Linux-USB APIs,
++ * they've been converted to cpu byte order.
++ */
++
++/*
++ * Descriptor types ... USB 2.0 spec table 9.5
++ */
++#define USB_DT_DEVICE 0x01
++#define USB_DT_CONFIG 0x02
++#define USB_DT_STRING 0x03
++#define USB_DT_INTERFACE 0x04
++#define USB_DT_ENDPOINT 0x05
++#define USB_DT_DEVICE_QUALIFIER 0x06
++#define USB_DT_OTHER_SPEED_CONFIG 0x07
++#define USB_DT_INTERFACE_POWER 0x08
++/* these are from a minor usb 2.0 revision (ECN) */
++#define USB_DT_OTG 0x09
++#define USB_DT_DEBUG 0x0a
++#define USB_DT_INTERFACE_ASSOCIATION 0x0b
++
++/* conventional codes for class-specific descriptors */
++#define USB_DT_CS_DEVICE 0x21
++#define USB_DT_CS_CONFIG 0x22
++#define USB_DT_CS_STRING 0x23
++#define USB_DT_CS_INTERFACE 0x24
++#define USB_DT_CS_ENDPOINT 0x25
++
++/* All standard descriptors have these 2 fields at the beginning */
++struct usb_descriptor_header {
++ __u8 bLength;
++ __u8 bDescriptorType;
++} __attribute__ ((packed));
++
++
++/*-------------------------------------------------------------------------*/
++
++/* USB_DT_DEVICE: Device descriptor */
++struct usb_device_descriptor {
++ __u8 bLength;
++ __u8 bDescriptorType;
++
++ __u16 bcdUSB;
++ __u8 bDeviceClass;
++ __u8 bDeviceSubClass;
++ __u8 bDeviceProtocol;
++ __u8 bMaxPacketSize0;
++ __u16 idVendor;
++ __u16 idProduct;
++ __u16 bcdDevice;
++ __u8 iManufacturer;
++ __u8 iProduct;
++ __u8 iSerialNumber;
++ __u8 bNumConfigurations;
++} __attribute__ ((packed));
++
++#define USB_DT_DEVICE_SIZE 18
++
++
++/*
++ * Device and/or Interface Class codes
++ * as found in bDeviceClass or bInterfaceClass
++ * and defined by www.usb.org documents
++ */
++#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */
++#define USB_CLASS_AUDIO 1
++#define USB_CLASS_COMM 2
++#define USB_CLASS_HID 3
++#define USB_CLASS_PHYSICAL 5
++#define USB_CLASS_STILL_IMAGE 6
++#define USB_CLASS_PRINTER 7
++#define USB_CLASS_MASS_STORAGE 8
++#define USB_CLASS_HUB 9
++#define USB_CLASS_CDC_DATA 0x0a
++#define USB_CLASS_CSCID 0x0b /* chip+ smart card */
++#define USB_CLASS_CONTENT_SEC 0x0d /* content security */
++#define USB_CLASS_VIDEO 0x0e
++#define USB_CLASS_APP_SPEC 0xfe
++#define USB_CLASS_VENDOR_SPEC 0xff
++
++/*-------------------------------------------------------------------------*/
++
++/* USB_DT_CONFIG: Configuration descriptor information.
++ *
++ * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the
++ * descriptor type is different. Highspeed-capable devices can look
++ * different depending on what speed they're currently running. Only
++ * devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG
++ * descriptors.
++ */
++struct usb_config_descriptor {
++ __u8 bLength;
++ __u8 bDescriptorType;
++
++ __u16 wTotalLength;
++ __u8 bNumInterfaces;
++ __u8 bConfigurationValue;
++ __u8 iConfiguration;
++ __u8 bmAttributes;
++ __u8 bMaxPower;
++} __attribute__ ((packed));
++
++#define USB_DT_CONFIG_SIZE 9
++
++/* from config descriptor bmAttributes */
++#define USB_CONFIG_ATT_ONE (1 << 7) /* must be set */
++#define USB_CONFIG_ATT_SELFPOWER (1 << 6) /* self powered */
++#define USB_CONFIG_ATT_WAKEUP (1 << 5) /* can wakeup */
++
++/*-------------------------------------------------------------------------*/
++
++/* USB_DT_STRING: String descriptor */
++struct usb_string_descriptor {
++ __u8 bLength;
++ __u8 bDescriptorType;
++
++ __u16 wData[1]; /* UTF-16LE encoded */
++} __attribute__ ((packed));
++
++/* note that "string" zero is special, it holds language codes that
++ * the device supports, not Unicode characters.
++ */
++
++/*-------------------------------------------------------------------------*/
++
++/* USB_DT_INTERFACE: Interface descriptor */
++struct usb_interface_descriptor {
++ __u8 bLength;
++ __u8 bDescriptorType;
++
++ __u8 bInterfaceNumber;
++ __u8 bAlternateSetting;
++ __u8 bNumEndpoints;
++ __u8 bInterfaceClass;
++ __u8 bInterfaceSubClass;
++ __u8 bInterfaceProtocol;
++ __u8 iInterface;
++} __attribute__ ((packed));
++
++#define USB_DT_INTERFACE_SIZE 9
++
++/*-------------------------------------------------------------------------*/
++
++/* USB_DT_ENDPOINT: Endpoint descriptor */
++struct usb_endpoint_descriptor {
++ __u8 bLength;
++ __u8 bDescriptorType;
++
++ __u8 bEndpointAddress;
++ __u8 bmAttributes;
++ __u16 wMaxPacketSize;
++ __u8 bInterval;
++
++ // NOTE: these two are _only_ in audio endpoints.
++ // use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof.
++ __u8 bRefresh;
++ __u8 bSynchAddress;
++} __attribute__ ((packed));
++
++#define USB_DT_ENDPOINT_SIZE 7
++#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
++
++
++/*
++ * Endpoints
++ */
++#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */
++#define USB_ENDPOINT_DIR_MASK 0x80
++
++#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */
++#define USB_ENDPOINT_XFER_CONTROL 0
++#define USB_ENDPOINT_XFER_ISOC 1
++#define USB_ENDPOINT_XFER_BULK 2
++#define USB_ENDPOINT_XFER_INT 3
++
++
++/*-------------------------------------------------------------------------*/
++
++/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */
++struct usb_qualifier_descriptor {
++ __u8 bLength;
++ __u8 bDescriptorType;
++
++ __u16 bcdUSB;
++ __u8 bDeviceClass;
++ __u8 bDeviceSubClass;
++ __u8 bDeviceProtocol;
++ __u8 bMaxPacketSize0;
++ __u8 bNumConfigurations;
++ __u8 bRESERVED;
++} __attribute__ ((packed));
++
++
++/*-------------------------------------------------------------------------*/
++
++/* USB_DT_OTG (from OTG 1.0a supplement) */
++struct usb_otg_descriptor {
++ __u8 bLength;
++ __u8 bDescriptorType;
++
++ __u8 bmAttributes; /* support for HNP, SRP, etc */
++} __attribute__ ((packed));
++
++/* from usb_otg_descriptor.bmAttributes */
++#define USB_OTG_SRP (1 << 0)
++#define USB_OTG_HNP (1 << 1) /* swap host/device roles */
++
++/*-------------------------------------------------------------------------*/
++
++/* USB_DT_DEBUG: for special highspeed devices, replacing serial console */
++struct usb_debug_descriptor {
++ __u8 bLength;
++ __u8 bDescriptorType;
++
++ /* bulk endpoints with 8 byte maxpacket */
++ __u8 bDebugInEndpoint;
++ __u8 bDebugOutEndpoint;
++};
++
++/*-------------------------------------------------------------------------*/
++
++/* USB_DT_INTERFACE_ASSOCIATION: groups interfaces */
++struct usb_interface_assoc_descriptor {
++ __u8 bLength;
++ __u8 bDescriptorType;
++
++ __u8 bFirstInterface;
++ __u8 bInterfaceCount;
++ __u8 bFunctionClass;
++ __u8 bFunctionSubClass;
++ __u8 bFunctionProtocol;
++ __u8 iFunction;
++} __attribute__ ((packed));
++
++
++/*-------------------------------------------------------------------------*/
++
++/* USB 2.0 defines three speeds, here's how Linux identifies them */
++
++enum usb_device_speed {
++ USB_SPEED_UNKNOWN = 0, /* enumerating */
++ USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */
++ USB_SPEED_HIGH /* usb 2.0 */
++};
++
++enum usb_device_state {
++ /* NOTATTACHED isn't in the USB spec, and this state acts
++ * the same as ATTACHED ... but it's clearer this way.
++ */
++ USB_STATE_NOTATTACHED = 0,
++
++ /* the chapter 9 device states */
++ USB_STATE_ATTACHED,
++ USB_STATE_POWERED,
++ USB_STATE_DEFAULT, /* limited function */
++ USB_STATE_ADDRESS,
++ USB_STATE_CONFIGURED, /* most functions */
++
++ USB_STATE_SUSPENDED
++
++ /* NOTE: there are actually four different SUSPENDED
++ * states, returning to POWERED, DEFAULT, ADDRESS, or
++ * CONFIGURED respectively when SOF tokens flow again.
++ */
++};
++
++#endif /* __LINUX_USB_CH9_H */
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/include/linux/usb_gadget.h kernel/include/linux/usb_gadget.h
+--- /tmp/kernel/include/linux/usb_gadget.h 1970-01-01 01:00:00.000000000 +0100
++++ kernel/include/linux/usb_gadget.h 2005-04-22 17:53:19.367550424 +0200
+@@ -0,0 +1,896 @@
++/*
++ * <linux/usb_gadget.h>
++ *
++ * We call the USB code inside a Linux-based peripheral device a "gadget"
++ * driver, except for the hardware-specific bus glue. One USB host can
++ * master many USB gadgets, but the gadgets are only slaved to one host.
++ *
++ *
++ * (C) Copyright 2002-2004 by David Brownell
++ * All Rights Reserved.
++ *
++ * This software is licensed under the GNU GPL version 2.
++ */
++
++#ifndef __LINUX_USB_GADGET_H
++#define __LINUX_USB_GADGET_H
++
++#ifdef __KERNEL__
++
++struct usb_ep;
++
++/**
++ * struct usb_request - describes one i/o request
++ * @buf: Buffer used for data. Always provide this; some controllers
++ * only use PIO, or don't use DMA for some endpoints.
++ * @dma: DMA address corresponding to 'buf'. If you don't set this
++ * field, and the usb controller needs one, it is responsible
++ * for mapping and unmapping the buffer.
++ * @length: Length of that data
++ * @no_interrupt: If true, hints that no completion irq is needed.
++ * Helpful sometimes with deep request queues that are handled
++ * directly by DMA controllers.
++ * @zero: If true, when writing data, makes the last packet be "short"
++ * by adding a zero length packet as needed;
++ * @short_not_ok: When reading data, makes short packets be
++ * treated as errors (queue stops advancing till cleanup).
++ * @complete: Function called when request completes, so this request and
++ * its buffer may be re-used.
++ * Reads terminate with a short packet, or when the buffer fills,
++ * whichever comes first. When writes terminate, some data bytes
++ * will usually still be in flight (often in a hardware fifo).
++ * Errors (for reads or writes) stop the queue from advancing
++ * until the completion function returns, so that any transfers
++ * invalidated by the error may first be dequeued.
++ * @context: For use by the completion callback
++ * @list: For use by the gadget driver.
++ * @status: Reports completion code, zero or a negative errno.
++ * Normally, faults block the transfer queue from advancing until
++ * the completion callback returns.
++ * Code "-ESHUTDOWN" indicates completion caused by device disconnect,
++ * or when the driver disabled the endpoint.
++ * @actual: Reports bytes transferred to/from the buffer. For reads (OUT
++ * transfers) this may be less than the requested length. If the
++ * short_not_ok flag is set, short reads are treated as errors
++ * even when status otherwise indicates successful completion.
++ * Note that for writes (IN transfers) some data bytes may still
++ * reside in a device-side FIFO when the request is reported as
++ * complete.
++ *
++ * These are allocated/freed through the endpoint they're used with. The
++ * hardware's driver can add extra per-request data to the memory it returns,
++ * which often avoids separate memory allocations (potential failures),
++ * later when the request is queued.
++ *
++ * Request flags affect request handling, such as whether a zero length
++ * packet is written (the "zero" flag), whether a short read should be
++ * treated as an error (blocking request queue advance, the "short_not_ok"
++ * flag), or hinting that an interrupt is not required (the "no_interrupt"
++ * flag, for use with deep request queues).
++ *
++ * Bulk endpoints can use any size buffers, and can also be used for interrupt
++ * transfers. interrupt-only endpoints can be much less functional.
++ */
++ // NOTE this is analagous to 'struct urb' on the host side,
++ // except that it's thinner and promotes more pre-allocation.
++
++struct usb_request {
++ void *buf;
++ unsigned length;
++ dma_addr_t dma;
++
++ unsigned no_interrupt:1;
++ unsigned zero:1;
++ unsigned short_not_ok:1;
++
++ void (*complete)(struct usb_ep *ep,
++ struct usb_request *req);
++ void *context;
++ struct list_head list;
++
++ int status;
++ unsigned actual;
++};
++
++/*-------------------------------------------------------------------------*/
++
++/* endpoint-specific parts of the api to the usb controller hardware.
++ * unlike the urb model, (de)multiplexing layers are not required.
++ * (so this api could slash overhead if used on the host side...)
++ *
++ * note that device side usb controllers commonly differ in how many
++ * endpoints they support, as well as their capabilities.
++ */
++struct usb_ep_ops {
++ int (*enable) (struct usb_ep *ep,
++ const struct usb_endpoint_descriptor *desc);
++ int (*disable) (struct usb_ep *ep);
++
++ struct usb_request *(*alloc_request) (struct usb_ep *ep,
++ int gfp_flags);
++ void (*free_request) (struct usb_ep *ep, struct usb_request *req);
++
++ void *(*alloc_buffer) (struct usb_ep *ep, unsigned bytes,
++ dma_addr_t *dma, int gfp_flags);
++ void (*free_buffer) (struct usb_ep *ep, void *buf, dma_addr_t dma,
++ unsigned bytes);
++ // NOTE: on 2.6, drivers may also use dma_map() and
++ // dma_sync_single_*() to directly manage dma overhead.
++
++ int (*queue) (struct usb_ep *ep, struct usb_request *req,
++ int gfp_flags);
++ int (*dequeue) (struct usb_ep *ep, struct usb_request *req);
++
++ int (*set_halt) (struct usb_ep *ep, int value);
++ int (*fifo_status) (struct usb_ep *ep);
++ void (*fifo_flush) (struct usb_ep *ep);
++};
++
++/**
++ * struct usb_ep - device side representation of USB endpoint
++ * @name:identifier for the endpoint, such as "ep-a" or "ep9in-bulk"
++ * @ops: Function pointers used to access hardware-specific operations.
++ * @ep_list:the gadget's ep_list holds all of its endpoints
++ * @maxpacket:The maximum packet size used on this endpoint. The initial
++ * value can sometimes be reduced (hardware allowing), according to
++ * the endpoint descriptor used to configure the endpoint.
++ * @driver_data:for use by the gadget driver. all other fields are
++ * read-only to gadget drivers.
++ *
++ * the bus controller driver lists all the general purpose endpoints in
++ * gadget->ep_list. the control endpoint (gadget->ep0) is not in that list,
++ * and is accessed only in response to a driver setup() callback.
++ */
++struct usb_ep {
++ void *driver_data;
++
++ const char *name;
++ const struct usb_ep_ops *ops;
++ struct list_head ep_list;
++ unsigned maxpacket:16;
++};
++
++/*-------------------------------------------------------------------------*/
++
++/**
++ * usb_ep_enable - configure endpoint, making it usable
++ * @ep:the endpoint being configured. may not be the endpoint named "ep0".
++ * drivers discover endpoints through the ep_list of a usb_gadget.
++ * @desc:descriptor for desired behavior. caller guarantees this pointer
++ * remains valid until the endpoint is disabled; the data byte order
++ * is little-endian (usb-standard).
++ *
++ * when configurations are set, or when interface settings change, the driver
++ * will enable or disable the relevant endpoints. while it is enabled, an
++ * endpoint may be used for i/o until the driver receives a disconnect() from
++ * the host or until the endpoint is disabled.
++ *
++ * the ep0 implementation (which calls this routine) must ensure that the
++ * hardware capabilities of each endpoint match the descriptor provided
++ * for it. for example, an endpoint named "ep2in-bulk" would be usable
++ * for interrupt transfers as well as bulk, but it likely couldn't be used
++ * for iso transfers or for endpoint 14. some endpoints are fully
++ * configurable, with more generic names like "ep-a". (remember that for
++ * USB, "in" means "towards the USB master".)
++ *
++ * returns zero, or a negative error code.
++ */
++static inline int
++usb_ep_enable (struct usb_ep *ep, const struct usb_endpoint_descriptor *desc)
++{
++ return ep->ops->enable (ep, desc);
++}
++
++/**
++ * usb_ep_disable - endpoint is no longer usable
++ * @ep:the endpoint being unconfigured. may not be the endpoint named "ep0".
++ *
++ * no other task may be using this endpoint when this is called.
++ * any pending and uncompleted requests will complete with status
++ * indicating disconnect (-ESHUTDOWN) before this call returns.
++ * gadget drivers must call usb_ep_enable() again before queueing
++ * requests to the endpoint.
++ *
++ * returns zero, or a negative error code.
++ */
++static inline int
++usb_ep_disable (struct usb_ep *ep)
++{
++ return ep->ops->disable (ep);
++}
++
++/**
++ * usb_ep_alloc_request - allocate a request object to use with this endpoint
++ * @ep:the endpoint to be used with with the request
++ * @gfp_flags:GFP_* flags to use
++ *
++ * Request objects must be allocated with this call, since they normally
++ * need controller-specific setup and may even need endpoint-specific
++ * resources such as allocation of DMA descriptors.
++ * Requests may be submitted with usb_ep_queue(), and receive a single
++ * completion callback. Free requests with usb_ep_free_request(), when
++ * they are no longer needed.
++ *
++ * Returns the request, or null if one could not be allocated.
++ */
++static inline struct usb_request *
++usb_ep_alloc_request (struct usb_ep *ep, int gfp_flags)
++{
++ return ep->ops->alloc_request (ep, gfp_flags);
++}
++
++/**
++ * usb_ep_free_request - frees a request object
++ * @ep:the endpoint associated with the request
++ * @req:the request being freed
++ *
++ * Reverses the effect of usb_ep_alloc_request().
++ * Caller guarantees the request is not queued, and that it will
++ * no longer be requeued (or otherwise used).
++ */
++static inline void
++usb_ep_free_request (struct usb_ep *ep, struct usb_request *req)
++{
++ ep->ops->free_request (ep, req);
++}
++
++/**
++ * usb_ep_alloc_buffer - allocate an I/O buffer
++ * @ep:the endpoint associated with the buffer
++ * @len:length of the desired buffer
++ * @dma:pointer to the buffer's DMA address; must be valid
++ * @gfp_flags:GFP_* flags to use
++ *
++ * Returns a new buffer, or null if one could not be allocated.
++ * The buffer is suitably aligned for dma, if that endpoint uses DMA,
++ * and the caller won't have to care about dma-inconsistency
++ * or any hidden "bounce buffer" mechanism. No additional per-request
++ * DMA mapping will be required for such buffers.
++ * Free it later with usb_ep_free_buffer().
++ *
++ * You don't need to use this call to allocate I/O buffers unless you
++ * want to make sure drivers don't incur costs for such "bounce buffer"
++ * copies or per-request DMA mappings.
++ */
++static inline void *
++usb_ep_alloc_buffer (struct usb_ep *ep, unsigned len, dma_addr_t *dma,
++ int gfp_flags)
++{
++ return ep->ops->alloc_buffer (ep, len, dma, gfp_flags);
++}
++
++/**
++ * usb_ep_free_buffer - frees an i/o buffer
++ * @ep:the endpoint associated with the buffer
++ * @buf:CPU view address of the buffer
++ * @dma:the buffer's DMA address
++ * @len:length of the buffer
++ *
++ * reverses the effect of usb_ep_alloc_buffer().
++ * caller guarantees the buffer will no longer be accessed
++ */
++static inline void
++usb_ep_free_buffer (struct usb_ep *ep, void *buf, dma_addr_t dma, unsigned len)
++{
++ ep->ops->free_buffer (ep, buf, dma, len);
++}
++
++/**
++ * usb_ep_queue - queues (submits) an I/O request to an endpoint.
++ * @ep:the endpoint associated with the request
++ * @req:the request being submitted
++ * @gfp_flags: GFP_* flags to use in case the lower level driver couldn't
++ * pre-allocate all necessary memory with the request.
++ *
++ * This tells the device controller to perform the specified request through
++ * that endpoint (reading or writing a buffer). When the request completes,
++ * including being canceled by usb_ep_dequeue(), the request's completion
++ * routine is called to return the request to the driver. Any endpoint
++ * (except control endpoints like ep0) may have more than one transfer
++ * request queued; they complete in FIFO order. Once a gadget driver
++ * submits a request, that request may not be examined or modified until it
++ * is given back to that driver through the completion callback.
++ *
++ * Each request is turned into one or more packets. The controller driver
++ * never merges adjacent requests into the same packet. OUT transfers
++ * will sometimes use data that's already buffered in the hardware.
++ * Drivers can rely on the fact that the first byte of the request's buffer
++ * always corresponds to the first byte of some USB packet, for both
++ * IN and OUT transfers.
++ *
++ * Bulk endpoints can queue any amount of data; the transfer is packetized
++ * automatically. The last packet will be short if the request doesn't fill it
++ * out completely. Zero length packets (ZLPs) should be avoided in portable
++ * protocols since not all usb hardware can successfully handle zero length
++ * packets. (ZLPs may be explicitly written, and may be implicitly written if
++ * the request 'zero' flag is set.) Bulk endpoints may also be used
++ * for interrupt transfers; but the reverse is not true, and some endpoints
++ * won't support every interrupt transfer. (Such as 768 byte packets.)
++ *
++ * Interrupt-only endpoints are less functional than bulk endpoints, for
++ * example by not supporting queueing or not handling buffers that are
++ * larger than the endpoint's maxpacket size. They may also treat data
++ * toggle differently.
++ *
++ * Control endpoints ... after getting a setup() callback, the driver queues
++ * one response (even if it would be zero length). That enables the
++ * status ack, after transfering data as specified in the response. Setup
++ * functions may return negative error codes to generate protocol stalls.
++ * (Note that some USB device controllers disallow protocol stall responses
++ * in some cases.) When control responses are deferred (the response is
++ * written after the setup callback returns), then usb_ep_set_halt() may be
++ * used on ep0 to trigger protocol stalls.
++ *
++ * For periodic endpoints, like interrupt or isochronous ones, the usb host
++ * arranges to poll once per interval, and the gadget driver usually will
++ * have queued some data to transfer at that time.
++ *
++ * Returns zero, or a negative error code. Endpoints that are not enabled
++ * report errors; errors will also be
++ * reported when the usb peripheral is disconnected.
++ */
++static inline int
++usb_ep_queue (struct usb_ep *ep, struct usb_request *req, int gfp_flags)
++{
++ return ep->ops->queue (ep, req, gfp_flags);
++}
++
++/**
++ * usb_ep_dequeue - dequeues (cancels, unlinks) an I/O request from an endpoint
++ * @ep:the endpoint associated with the request
++ * @req:the request being canceled
++ *
++ * if the request is still active on the endpoint, it is dequeued and its
++ * completion routine is called (with status -ECONNRESET); else a negative
++ * error code is returned.
++ *
++ * note that some hardware can't clear out write fifos (to unlink the request
++ * at the head of the queue) except as part of disconnecting from usb. such
++ * restrictions prevent drivers from supporting configuration changes,
++ * even to configuration zero (a "chapter 9" requirement).
++ */
++static inline int usb_ep_dequeue (struct usb_ep *ep, struct usb_request *req)
++{
++ return ep->ops->dequeue (ep, req);
++}
++
++/**
++ * usb_ep_set_halt - sets the endpoint halt feature.
++ * @ep: the non-isochronous endpoint being stalled
++ *
++ * Use this to stall an endpoint, perhaps as an error report.
++ * Except for control endpoints,
++ * the endpoint stays halted (will not stream any data) until the host
++ * clears this feature; drivers may need to empty the endpoint's request
++ * queue first, to make sure no inappropriate transfers happen.
++ *
++ * Note that while an endpoint CLEAR_FEATURE will be invisible to the
++ * gadget driver, a SET_INTERFACE will not be. To reset endpoints for the
++ * current altsetting, see usb_ep_clear_halt(). When switching altsettings,
++ * it's simplest to use usb_ep_enable() or usb_ep_disable() for the endpoints.
++ *
++ * Returns zero, or a negative error code. On success, this call sets
++ * underlying hardware state that blocks data transfers.
++ * Attempts to halt IN endpoints will fail (returning -EAGAIN) if any
++ * transfer requests are still queued, or if the controller hardware
++ * (usually a FIFO) still holds bytes that the host hasn't collected.
++ */
++static inline int
++usb_ep_set_halt (struct usb_ep *ep)
++{
++ return ep->ops->set_halt (ep, 1);
++}
++
++/**
++ * usb_ep_clear_halt - clears endpoint halt, and resets toggle
++ * @ep:the bulk or interrupt endpoint being reset
++ *
++ * Use this when responding to the standard usb "set interface" request,
++ * for endpoints that aren't reconfigured, after clearing any other state
++ * in the endpoint's i/o queue.
++ *
++ * Returns zero, or a negative error code. On success, this call clears
++ * the underlying hardware state reflecting endpoint halt and data toggle.
++ * Note that some hardware can't support this request (like pxa2xx_udc),
++ * and accordingly can't correctly implement interface altsettings.
++ */
++static inline int
++usb_ep_clear_halt (struct usb_ep *ep)
++{
++ return ep->ops->set_halt (ep, 0);
++}
++
++/**
++ * usb_ep_fifo_status - returns number of bytes in fifo, or error
++ * @ep: the endpoint whose fifo status is being checked.
++ *
++ * FIFO endpoints may have "unclaimed data" in them in certain cases,
++ * such as after aborted transfers. Hosts may not have collected all
++ * the IN data written by the gadget driver (and reported by a request
++ * completion). The gadget driver may not have collected all the data
++ * written OUT to it by the host. Drivers that need precise handling for
++ * fault reporting or recovery may need to use this call.
++ *
++ * This returns the number of such bytes in the fifo, or a negative
++ * errno if the endpoint doesn't use a FIFO or doesn't support such
++ * precise handling.
++ */
++static inline int
++usb_ep_fifo_status (struct usb_ep *ep)
++{
++ if (ep->ops->fifo_status)
++ return ep->ops->fifo_status (ep);
++ else
++ return -EOPNOTSUPP;
++}
++
++/**
++ * usb_ep_fifo_flush - flushes contents of a fifo
++ * @ep: the endpoint whose fifo is being flushed.
++ *
++ * This call may be used to flush the "unclaimed data" that may exist in
++ * an endpoint fifo after abnormal transaction terminations. The call
++ * must never be used except when endpoint is not being used for any
++ * protocol translation.
++ */
++static inline void
++usb_ep_fifo_flush (struct usb_ep *ep)
++{
++ if (ep->ops->fifo_flush)
++ ep->ops->fifo_flush (ep);
++}
++
++
++/*-------------------------------------------------------------------------*/
++
++struct usb_gadget;
++
++/* the rest of the api to the controller hardware: device operations,
++ * which don't involve endpoints (or i/o).
++ */
++struct usb_gadget_ops {
++ int (*get_frame)(struct usb_gadget *);
++ int (*wakeup)(struct usb_gadget *);
++ int (*set_selfpowered) (struct usb_gadget *, int is_selfpowered);
++ int (*vbus_session) (struct usb_gadget *, int is_active);
++ int (*vbus_draw) (struct usb_gadget *, unsigned mA);
++ int (*pullup) (struct usb_gadget *, int is_on);
++ int (*ioctl)(struct usb_gadget *,
++ unsigned code, unsigned long param);
++};
++
++/**
++ * struct usb_gadget - represents a usb slave device
++ * @ops: Function pointers used to access hardware-specific operations.
++ * @ep0: Endpoint zero, used when reading or writing responses to
++ * driver setup() requests
++ * @ep_list: List of other endpoints supported by the device.
++ * @speed: Speed of current connection to USB host.
++ * @is_dualspeed: True if the controller supports both high and full speed
++ * operation. If it does, the gadget driver must also support both.
++ * @is_otg: True if the USB device port uses a Mini-AB jack, so that the
++ * gadget driver must provide a USB OTG descriptor.
++ * @is_a_peripheral: False unless is_otg, the "A" end of a USB cable
++ * is in the Mini-AB jack, and HNP has been used to switch roles
++ * so that the "A" device currently acts as A-Peripheral, not A-Host.
++ * @a_hnp_support: OTG device feature flag, indicating that the A-Host
++ * supports HNP at this port.
++ * @a_alt_hnp_support: OTG device feature flag, indicating that the A-Host
++ * only supports HNP on a different root port.
++ * @b_hnp_enable: OTG device feature flag, indicating that the A-Host
++ * enabled HNP support.
++ * @name: Identifies the controller hardware type. Used in diagnostics
++ * and sometimes configuration.
++ * @dev: Driver model state for this abstract device.
++ *
++ * Gadgets have a mostly-portable "gadget driver" implementing device
++ * functions, handling all usb configurations and interfaces. Gadget
++ * drivers talk to hardware-specific code indirectly, through ops vectors.
++ * That insulates the gadget driver from hardware details, and packages
++ * the hardware endpoints through generic i/o queues. The "usb_gadget"
++ * and "usb_ep" interfaces provide that insulation from the hardware.
++ *
++ * Except for the driver data, all fields in this structure are
++ * read-only to the gadget driver. That driver data is part of the
++ * "driver model" infrastructure in 2.6 (and later) kernels, and for
++ * earlier systems is grouped in a similar structure that's not known
++ * to the rest of the kernel.
++ *
++ * Values of the three OTG device feature flags are updated before the
++ * setup() call corresponding to USB_REQ_SET_CONFIGURATION, and before
++ * driver suspend() calls. They are valid only when is_otg, and when the
++ * device is acting as a B-Peripheral (so is_a_peripheral is false).
++ */
++struct usb_gadget {
++ /* readonly to gadget driver */
++ const struct usb_gadget_ops *ops;
++ struct usb_ep *ep0;
++ struct list_head ep_list; /* of usb_ep */
++ enum usb_device_speed speed;
++ unsigned is_dualspeed:1;
++ unsigned is_otg:1;
++ unsigned is_a_peripheral:1;
++ unsigned b_hnp_enable:1;
++ unsigned a_hnp_support:1;
++ unsigned a_alt_hnp_support:1;
++ const char *name;
++
++ struct __gadget_device {
++ const char *bus_id;
++ void *driver_data;
++ } dev;
++};
++
++static inline void set_gadget_data (struct usb_gadget *gadget, void *data)
++ { gadget->dev.driver_data = data; }
++static inline void *get_gadget_data (struct usb_gadget *gadget)
++ { return gadget->dev.driver_data; }
++
++
++/* iterates the non-control endpoints; 'tmp' is a struct usb_ep pointer */
++#define gadget_for_each_ep(tmp,gadget) \
++ list_for_each_entry(tmp, &(gadget)->ep_list, ep_list)
++
++#ifndef list_for_each_entry
++/* not available in 2.4.18 */
++#define list_for_each_entry(pos, head, member) \
++ for (pos = list_entry((head)->next, typeof(*pos), member), \
++ prefetch(pos->member.next); \
++ &pos->member != (head); \
++ pos = list_entry(pos->member.next, typeof(*pos), member), \
++ prefetch(pos->member.next))
++#endif
++
++
++/**
++ * usb_gadget_frame_number - returns the current frame number
++ * @gadget: controller that reports the frame number
++ *
++ * Returns the usb frame number, normally eleven bits from a SOF packet,
++ * or negative errno if this device doesn't support this capability.
++ */
++static inline int usb_gadget_frame_number (struct usb_gadget *gadget)
++{
++ return gadget->ops->get_frame (gadget);
++}
++
++/**
++ * usb_gadget_wakeup - tries to wake up the host connected to this gadget
++ * @gadget: controller used to wake up the host
++ *
++ * Returns zero on success, else negative error code if the hardware
++ * doesn't support such attempts, or its support has not been enabled
++ * by the usb host. Drivers must return device descriptors that report
++ * their ability to support this, or hosts won't enable it.
++ *
++ * This may also try to use SRP to wake the host and start enumeration,
++ * even if OTG isn't otherwise in use. OTG devices may also start
++ * remote wakeup even when hosts don't explicitly enable it.
++ */
++static inline int usb_gadget_wakeup (struct usb_gadget *gadget)
++{
++ if (!gadget->ops->wakeup)
++ return -EOPNOTSUPP;
++ return gadget->ops->wakeup (gadget);
++}
++
++/**
++ * usb_gadget_set_selfpowered - sets the device selfpowered feature.
++ * @gadget:the device being declared as self-powered
++ *
++ * this affects the device status reported by the hardware driver
++ * to reflect that it now has a local power supply.
++ *
++ * returns zero on success, else negative errno.
++ */
++static inline int
++usb_gadget_set_selfpowered (struct usb_gadget *gadget)
++{
++ if (!gadget->ops->set_selfpowered)
++ return -EOPNOTSUPP;
++ return gadget->ops->set_selfpowered (gadget, 1);
++}
++
++/**
++ * usb_gadget_clear_selfpowered - clear the device selfpowered feature.
++ * @gadget:the device being declared as bus-powered
++ *
++ * this affects the device status reported by the hardware driver.
++ * some hardware may not support bus-powered operation, in which
++ * case this feature's value can never change.
++ *
++ * returns zero on success, else negative errno.
++ */
++static inline int
++usb_gadget_clear_selfpowered (struct usb_gadget *gadget)
++{
++ if (!gadget->ops->set_selfpowered)
++ return -EOPNOTSUPP;
++ return gadget->ops->set_selfpowered (gadget, 0);
++}
++
++/**
++ * usb_gadget_vbus_connect - Notify controller that VBUS is powered
++ * @gadget:The device which now has VBUS power.
++ *
++ * This call is used by a driver for an external transceiver (or GPIO)
++ * that detects a VBUS power session starting. Common responses include
++ * resuming the controller, activating the D+ (or D-) pullup to let the
++ * host detect that a USB device is attached, and starting to draw power
++ * (8mA or possibly more, especially after SET_CONFIGURATION).
++ *
++ * Returns zero on success, else negative errno.
++ */
++static inline int
++usb_gadget_vbus_connect(struct usb_gadget *gadget)
++{
++ if (!gadget->ops->vbus_session)
++ return -EOPNOTSUPP;
++ return gadget->ops->vbus_session (gadget, 1);
++}
++
++/**
++ * usb_gadget_vbus_draw - constrain controller's VBUS power usage
++ * @gadget:The device whose VBUS usage is being described
++ * @mA:How much current to draw, in milliAmperes. This should be twice
++ * the value listed in the configuration descriptor bMaxPower field.
++ *
++ * This call is used by gadget drivers during SET_CONFIGURATION calls,
++ * reporting how much power the device may consume. For example, this
++ * could affect how quickly batteries are recharged.
++ *
++ * Returns zero on success, else negative errno.
++ */
++static inline int
++usb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA)
++{
++ if (!gadget->ops->vbus_draw)
++ return -EOPNOTSUPP;
++ return gadget->ops->vbus_draw (gadget, mA);
++}
++
++/**
++ * usb_gadget_vbus_disconnect - notify controller about VBUS session end
++ * @gadget:the device whose VBUS supply is being described
++ *
++ * This call is used by a driver for an external transceiver (or GPIO)
++ * that detects a VBUS power session ending. Common responses include
++ * reversing everything done in usb_gadget_vbus_connect().
++ *
++ * Returns zero on success, else negative errno.
++ */
++static inline int
++usb_gadget_vbus_disconnect(struct usb_gadget *gadget)
++{
++ if (!gadget->ops->vbus_session)
++ return -EOPNOTSUPP;
++ return gadget->ops->vbus_session (gadget, 0);
++}
++
++/**
++ * usb_gadget_connect - software-controlled connect to USB host
++ * @gadget:the peripheral being connected
++ *
++ * Enables the D+ (or potentially D-) pullup. The host will start
++ * enumerating this gadget when the pullup is active and a VBUS session
++ * is active (the link is powered). This pullup is always enabled unless
++ * usb_gadget_disconnect() has been used to disable it.
++ *
++ * Returns zero on success, else negative errno.
++ */
++static inline int
++usb_gadget_connect (struct usb_gadget *gadget)
++{
++ if (!gadget->ops->pullup)
++ return -EOPNOTSUPP;
++ return gadget->ops->pullup (gadget, 1);
++}
++
++/**
++ * usb_gadget_disconnect - software-controlled disconnect from USB host
++ * @gadget:the peripheral being disconnected
++ *
++ * Disables the D+ (or potentially D-) pullup, which the host may see
++ * as a disconnect (when a VBUS session is active). Not all systems
++ * support software pullup controls.
++ *
++ * This routine may be used during the gadget driver bind() call to prevent
++ * the peripheral from ever being visible to the USB host, unless later
++ * usb_gadget_connect() is called. For example, user mode components may
++ * need to be activated before the system can talk to hosts.
++ *
++ * Returns zero on success, else negative errno.
++ */
++static inline int
++usb_gadget_disconnect (struct usb_gadget *gadget)
++{
++ if (!gadget->ops->pullup)
++ return -EOPNOTSUPP;
++ return gadget->ops->pullup (gadget, 0);
++}
++
++
++
++/*-------------------------------------------------------------------------*/
++
++/**
++ * struct usb_gadget_driver - driver for usb 'slave' devices
++ * @function: String describing the gadget's function
++ * @speed: Highest speed the driver handles.
++ * @bind: Invoked when the driver is bound to a gadget, usually
++ * after registering the driver.
++ * At that point, ep0 is fully initialized, and ep_list holds
++ * the currently-available endpoints.
++ * Called in a context that permits sleeping.
++ * @setup: Invoked for ep0 control requests that aren't handled by
++ * the hardware level driver. Most calls must be handled by
++ * the gadget driver, including descriptor and configuration
++ * management. The 16 bit members of the setup data are in
++ * cpu order. Called in_interrupt; this may not sleep. Driver
++ * queues a response to ep0, or returns negative to stall.
++ * @disconnect: Invoked after all transfers have been stopped,
++ * when the host is disconnected. May be called in_interrupt; this
++ * may not sleep. Some devices can't detect disconnect, so this might
++ * not be called except as part of controller shutdown.
++ * @unbind: Invoked when the driver is unbound from a gadget,
++ * usually from rmmod (after a disconnect is reported).
++ * Called in a context that permits sleeping.
++ * @suspend: Invoked on USB suspend. May be called in_interrupt.
++ * @resume: Invoked on USB resume. May be called in_interrupt.
++ * @driver: Driver model state for this driver.
++ *
++ * Devices are disabled till a gadget driver successfully bind()s, which
++ * means the driver will handle setup() requests needed to enumerate (and
++ * meet "chapter 9" requirements) then do some useful work.
++ *
++ * If gadget->is_otg is true, the gadget driver must provide an OTG
++ * descriptor during enumeration, or else fail the bind() call. In such
++ * cases, no USB traffic may flow until both bind() returns without
++ * having called usb_gadget_disconnect(), and the USB host stack has
++ * initialized.
++ *
++ * Drivers use hardware-specific knowledge to configure the usb hardware.
++ * endpoint addressing is only one of several hardware characteristics that
++ * are in descriptors the ep0 implementation returns from setup() calls.
++ *
++ * Except for ep0 implementation, most driver code shouldn't need change to
++ * run on top of different usb controllers. It'll use endpoints set up by
++ * that ep0 implementation.
++ *
++ * The usb controller driver handles a few standard usb requests. Those
++ * include set_address, and feature flags for devices, interfaces, and
++ * endpoints (the get_status, set_feature, and clear_feature requests).
++ *
++ * Accordingly, the driver's setup() callback must always implement all
++ * get_descriptor requests, returning at least a device descriptor and
++ * a configuration descriptor. Drivers must make sure the endpoint
++ * descriptors match any hardware constraints. Some hardware also constrains
++ * other descriptors. (The pxa250 allows only configurations 1, 2, or 3).
++ *
++ * The driver's setup() callback must also implement set_configuration,
++ * and should also implement set_interface, get_configuration, and
++ * get_interface. Setting a configuration (or interface) is where
++ * endpoints should be activated or (config 0) shut down.
++ *
++ * (Note that only the default control endpoint is supported. Neither
++ * hosts nor devices generally support control traffic except to ep0.)
++ *
++ * Most devices will ignore USB suspend/resume operations, and so will
++ * not provide those callbacks. However, some may need to change modes
++ * when the host is not longer directing those activities. For example,
++ * local controls (buttons, dials, etc) may need to be re-enabled since
++ * the (remote) host can't do that any longer; or an error state might
++ * be cleared, to make the device behave identically whether or not
++ * power is maintained.
++ */
++struct usb_gadget_driver {
++ char *function;
++ enum usb_device_speed speed;
++ int (*bind)(struct usb_gadget *);
++ void (*unbind)(struct usb_gadget *);
++ int (*setup)(struct usb_gadget *,
++ const struct usb_ctrlrequest *);
++ void (*disconnect)(struct usb_gadget *);
++ void (*suspend)(struct usb_gadget *);
++ void (*resume)(struct usb_gadget *);
++
++ // FIXME support safe rmmod
++ struct __gadget_driver {
++ const char *name;
++ void *driver_data;
++ } driver;
++};
++
++
++
++/*-------------------------------------------------------------------------*/
++
++/* driver modules register and unregister, as usual.
++ * these calls must be made in a context that can sleep.
++ *
++ * these will usually be implemented directly by the hardware-dependent
++ * usb bus interface driver, which will only support a single driver.
++ */
++
++/**
++ * usb_gadget_register_driver - register a gadget driver
++ * @driver:the driver being registered
++ *
++ * Call this in your gadget driver's module initialization function,
++ * to tell the underlying usb controller driver about your driver.
++ * The driver's bind() function will be called to bind it to a
++ * gadget. This function must be called in a context that can sleep.
++ */
++int usb_gadget_register_driver (struct usb_gadget_driver *driver);
++
++/**
++ * usb_gadget_unregister_driver - unregister a gadget driver
++ * @driver:the driver being unregistered
++ *
++ * Call this in your gadget driver's module cleanup function,
++ * to tell the underlying usb controller that your driver is
++ * going away. If the controller is connected to a USB host,
++ * it will first disconnect(). The driver is also requested
++ * to unbind() and clean up any device state, before this procedure
++ * finally returns.
++ * This function must be called in a context that can sleep.
++ */
++int usb_gadget_unregister_driver (struct usb_gadget_driver *driver);
++
++/*-------------------------------------------------------------------------*/
++
++/* utility to simplify dealing with string descriptors */
++
++/**
++ * struct usb_string - wraps a C string and its USB id
++ * @id:the (nonzero) ID for this string
++ * @s:the string, in UTF-8 encoding
++ *
++ * If you're using usb_gadget_get_string(), use this to wrap a string
++ * together with its ID.
++ */
++struct usb_string {
++ u8 id;
++ const char *s;
++};
++
++/**
++ * struct usb_gadget_strings - a set of USB strings in a given language
++ * @language:identifies the strings' language (0x0409 for en-us)
++ * @strings:array of strings with their ids
++ *
++ * If you're using usb_gadget_get_string(), use this to wrap all the
++ * strings for a given language.
++ */
++struct usb_gadget_strings {
++ u16 language; /* 0x0409 for en-us */
++ struct usb_string *strings;
++};
++
++/* put descriptor for string with that id into buf (buflen >= 256) */
++int usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf);
++
++/*-------------------------------------------------------------------------*/
++
++/* utility to simplify managing config descriptors */
++
++/* write vector of descriptors into buffer */
++int usb_descriptor_fillbuf(void *, unsigned,
++ const struct usb_descriptor_header **);
++
++/* build config descriptor from single descriptor vector */
++int usb_gadget_config_buf(const struct usb_config_descriptor *config,
++ void *buf, unsigned buflen, const struct usb_descriptor_header **desc);
++
++/*-------------------------------------------------------------------------*/
++
++/* utility wrapping a simple endpoint selection policy */
++
++extern struct usb_ep *usb_ep_autoconfig (struct usb_gadget *,
++ struct usb_endpoint_descriptor *) __init;
++
++extern void usb_ep_autoconfig_reset (struct usb_gadget *) __init;
++
++#endif /* __KERNEL__ */
++
++#endif /* __LINUX_USB_GADGET_H */
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/include/linux/usb_gadgetfs.h kernel/include/linux/usb_gadgetfs.h
+--- /tmp/kernel/include/linux/usb_gadgetfs.h 1970-01-01 01:00:00.000000000 +0100
++++ kernel/include/linux/usb_gadgetfs.h 2005-04-22 17:53:19.370549935 +0200
+@@ -0,0 +1,75 @@
++
++#include <asm/types.h>
++#include <asm/ioctl.h>
++
++#include <linux/usb_ch9.h>
++
++/*
++ * Filesystem based user-mode API to USB Gadget controller hardware
++ *
++ * Almost everything can be done with only read and write operations,
++ * on endpoint files found in one directory. They are configured by
++ * writing descriptors, and then may be used for normal stream style
++ * i/o requests. When ep0 is configured, the device can enumerate;
++ * when it's closed, the device disconnects from usb.
++ *
++ * Configuration and device descriptors get written to /dev/gadget/$CHIP,
++ * which may then be used to read usb_gadgetfs_event structs. The driver
++ * may activate endpoints as it handles SET_CONFIGURATION setup events,
++ * or earlier; writing endpoint descriptors to /dev/gadget/$ENDPOINT
++ * then performing data transfers by reading or writing.
++ */
++
++/*
++ * Events are delivered on the ep0 file descriptor, if the user mode driver
++ * reads from this file descriptor after writing the descriptors. Don't
++ * stop polling this descriptor, if you write that kind of driver.
++ */
++
++enum usb_gadgetfs_event_type {
++ GADGETFS_NOP = 0,
++
++ GADGETFS_CONNECT,
++ GADGETFS_DISCONNECT,
++ GADGETFS_SETUP,
++ GADGETFS_SUSPEND,
++ // and likely more !
++};
++
++struct usb_gadgetfs_event {
++ enum usb_gadgetfs_event_type type;
++ union {
++ // NOP, DISCONNECT, SUSPEND: nothing
++ // ... some hardware can't report disconnection
++
++ // CONNECT: just the speed
++ enum usb_device_speed speed;
++
++ // SETUP: packet; DATA phase i/o precedes next event
++ // (setup.bmRequestType & USB_DIR_IN) flags direction
++ // ... includes SET_CONFIGURATION, SET_INTERFACE
++ struct usb_ctrlrequest setup;
++ } u;
++};
++
++
++/* endpoint ioctls */
++
++/* IN transfers may be reported to the gadget driver as complete
++ * when the fifo is loaded, before the host reads the data;
++ * OUT transfers may be reported to the host's "client" driver as
++ * complete when they're sitting in the FIFO unread.
++ * THIS returns how many bytes are "unclaimed" in the endpoint fifo
++ * (needed for precise fault handling, when the hardware allows it)
++ */
++#define GADGETFS_FIFO_STATUS _IO('g',1)
++
++/* discards any unclaimed data in the fifo. */
++#define GADGETFS_FIFO_FLUSH _IO('g',2)
++
++/* resets endpoint halt+toggle; used to implement set_interface.
++ * some hardware (like pxa2xx) can't support this.
++ */
++#define GADGETFS_CLEAR_HALT _IO('g',3)
++
++
+diff -x '*~' -x '.*' -r -N -u /tmp/kernel/include/linux/usb_scanner_ioctl.h kernel/include/linux/usb_scanner_ioctl.h
+--- /tmp/kernel/include/linux/usb_scanner_ioctl.h 1970-01-01 01:00:00.000000000 +0100
++++ kernel/include/linux/usb_scanner_ioctl.h 2005-04-22 17:53:19.372549610 +0200
+@@ -0,0 +1,9 @@
++/* USB Scanner IOCTLS */
++
++/* read vendor and product IDs from the scanner */
++#define SCANNER_IOCTL_VENDOR _IOR('U', 0x20, int)
++#define SCANNER_IOCTL_PRODUCT _IOR('U', 0x21, int)
++/* send/recv a control message to the scanner */
++#define SCANNER_IOCTL_CTRLMSG _IOWR('U', 0x22, struct usb_ctrlrequest )
++
++