summaryrefslogtreecommitdiff
path: root/drivers/usb/class
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <greg@kroah.com>2002-04-04 18:53:38 -0800
committerGreg Kroah-Hartman <greg@kroah.com>2002-04-04 18:53:38 -0800
commitdff4eb9d31108f3028a4aaa1a19096a29932afb7 (patch)
treeac99bc5dbe61c04fa92d5c912bcbb635eb5fca45 /drivers/usb/class
parent03943afd2cede3e02cd89fbb3cb518692e4a77be (diff)
USB
moved class/storage/ back to storage/ created input/ orderd the makefiles and config.in menus better.
Diffstat (limited to 'drivers/usb/class')
-rw-r--r--drivers/usb/class/Config.in36
-rw-r--r--drivers/usb/class/Makefile17
-rw-r--r--drivers/usb/class/cdc-ether.c1365
-rw-r--r--drivers/usb/class/cdc-ether.h98
-rw-r--r--drivers/usb/class/hid-core.c1530
-rw-r--r--drivers/usb/class/hid-debug.h386
-rw-r--r--drivers/usb/class/hid-input.c460
-rw-r--r--drivers/usb/class/hid.h421
-rw-r--r--drivers/usb/class/hiddev.c699
-rw-r--r--drivers/usb/class/storage/Makefile32
-rw-r--r--drivers/usb/class/storage/datafab.c806
-rw-r--r--drivers/usb/class/storage/datafab.h40
-rw-r--r--drivers/usb/class/storage/debug.c369
-rw-r--r--drivers/usb/class/storage/debug.h69
-rw-r--r--drivers/usb/class/storage/dpcm.c82
-rw-r--r--drivers/usb/class/storage/dpcm.h34
-rw-r--r--drivers/usb/class/storage/freecom.c707
-rw-r--r--drivers/usb/class/storage/freecom.h36
-rw-r--r--drivers/usb/class/storage/initializers.c60
-rw-r--r--drivers/usb/class/storage/initializers.h44
-rw-r--r--drivers/usb/class/storage/isd200.c1749
-rw-r--r--drivers/usb/class/storage/isd200.h31
-rw-r--r--drivers/usb/class/storage/jumpshot.c804
-rw-r--r--drivers/usb/class/storage/jumpshot.h39
-rw-r--r--drivers/usb/class/storage/protocol.c339
-rw-r--r--drivers/usb/class/storage/protocol.h65
-rw-r--r--drivers/usb/class/storage/scsiglue.c900
-rw-r--r--drivers/usb/class/storage/scsiglue.h53
-rw-r--r--drivers/usb/class/storage/sddr09.c1058
-rw-r--r--drivers/usb/class/storage/sddr09.h44
-rw-r--r--drivers/usb/class/storage/shuttle_usbat.c1083
-rw-r--r--drivers/usb/class/storage/shuttle_usbat.h79
-rw-r--r--drivers/usb/class/storage/transport.c1268
-rw-r--r--drivers/usb/class/storage/transport.h156
-rw-r--r--drivers/usb/class/storage/unusual_devs.h477
-rw-r--r--drivers/usb/class/storage/usb.c1149
-rw-r--r--drivers/usb/class/storage/usb.h191
-rw-r--r--drivers/usb/class/usbkbd.c309
-rw-r--r--drivers/usb/class/usbmouse.c217
39 files changed, 5 insertions, 17297 deletions
diff --git a/drivers/usb/class/Config.in b/drivers/usb/class/Config.in
index 4f607b443e8e..94fedd1f9c30 100644
--- a/drivers/usb/class/Config.in
+++ b/drivers/usb/class/Config.in
@@ -4,44 +4,16 @@
comment 'USB Device Class drivers'
dep_tristate ' USB Audio support' CONFIG_USB_AUDIO $CONFIG_USB $CONFIG_SOUND
dep_tristate ' USB Bluetooth support (EXPERIMENTAL)' CONFIG_USB_BLUETOOTH $CONFIG_USB $CONFIG_EXPERIMENTAL
-if [ "$CONFIG_SCSI" = "n" ]; then
- comment ' SCSI support is needed for USB Storage'
-fi
-dep_tristate ' USB Mass Storage support' CONFIG_USB_STORAGE $CONFIG_USB $CONFIG_SCSI
- dep_mbool ' USB Mass Storage verbose debug' CONFIG_USB_STORAGE_DEBUG $CONFIG_USB_STORAGE
- dep_mbool ' Datafab MDCFE-B Compact Flash Reader support' CONFIG_USB_STORAGE_DATAFAB $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
- dep_mbool ' Freecom USB/ATAPI Bridge support' CONFIG_USB_STORAGE_FREECOM $CONFIG_USB_STORAGE
- dep_mbool ' ISD-200 USB/ATA Bridge support' CONFIG_USB_STORAGE_ISD200 $CONFIG_USB_STORAGE
- dep_mbool ' Microtech CompactFlash/SmartMedia support' CONFIG_USB_STORAGE_DPCM $CONFIG_USB_STORAGE
- dep_mbool ' HP CD-Writer 82xx support' CONFIG_USB_STORAGE_HP8200e $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
- dep_mbool ' SanDisk SDDR-09 (and other SmartMedia) support' CONFIG_USB_STORAGE_SDDR09 $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
- dep_mbool ' Lexar Jumpshot Compact Flash Reader' CONFIG_USB_STORAGE_JUMPSHOT $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
- dep_tristate ' USB Modem (CDC ACM) support' CONFIG_USB_ACM $CONFIG_USB
- dep_tristate ' USB CDC Ethernet support (EXPERIMENTAL)' CONFIG_USB_CDCETHER $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
- dep_tristate ' USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
-
-comment 'USB Human Interface Devices (HID)'
-dep_tristate ' USB Human Interface Device (full HID) support' CONFIG_USB_HID $CONFIG_USB
-if [ "$CONFIG_INPUT" = "n" ]; then
- comment ' Input core support is needed for USB HID input layer or HIDBP support'
-fi
-dep_mbool ' HID input layer support' CONFIG_USB_HIDINPUT $CONFIG_INPUT $CONFIG_USB_HID
-dep_mbool ' /dev/hiddev raw HID device support' CONFIG_USB_HIDDEV $CONFIG_USB_HID
+dep_tristate ' USB Modem (CDC ACM) support' CONFIG_USB_ACM $CONFIG_USB
+dep_tristate ' USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
-if [ "$CONFIG_USB_HID" != "y" ]; then
- dep_tristate ' USB HIDBP Keyboard (basic) support' CONFIG_USB_KBD $CONFIG_USB $CONFIG_INPUT
- dep_tristate ' USB HIDBP Mouse (basic) support' CONFIG_USB_MOUSE $CONFIG_USB $CONFIG_INPUT
-fi
# Turn on CONFIG_USB_CLASS if any of the drivers are compiled into the kernel
# to make our Makefile logic a bit simpler.
-if [ "$CONFIG_USB_AUDIO" = "y" -o "$CONFIG_USB_BLUETOOTH" = "y" -o "$CONFIG_USB_ACM" = "y" ]; then
- define_bool CONFIG_USB_CLASS y
-fi
-if [ "$CONFIG_USB_CDCETHER" = "y" -o "$CONFIG_USB_PRINTER" = "y" ]; then
+if [ "$CONFIG_USB_AUDIO" = "y" -o "$CONFIG_USB_BLUETOOTH" = "y" ]; then
define_bool CONFIG_USB_CLASS y
fi
-if [ "$CONFIG_USB_HID" = "y" -o "$CONFIG_USB_KBD" = "y" -o "$CONFIG_USB_MOUSE" = "y" ]; then
+if [ "$CONFIG_USB_ACM" = "y" -o "$CONFIG_USB_PRINTER" = "y" ]; then
define_bool CONFIG_USB_CLASS y
fi
diff --git a/drivers/usb/class/Makefile b/drivers/usb/class/Makefile
index da255cfc23fd..53443b76f9ef 100644
--- a/drivers/usb/class/Makefile
+++ b/drivers/usb/class/Makefile
@@ -1,28 +1,13 @@
#
# Makefile for USB Class drivers
+# (one step up from the misc category)
#
O_TARGET := usb-class.o
-# Multipart objects.
-hid-objs := hid-core.o
-
-# Optional parts of multipart objects.
-ifeq ($(CONFIG_USB_HIDDEV),y)
- hid-objs += hiddev.o
-endif
-ifeq ($(CONFIG_USB_HIDINPUT),y)
- hid-objs += hid-input.o
-endif
-
-
obj-$(CONFIG_USB_ACM) += cdc-acm.o
obj-$(CONFIG_USB_AUDIO) += audio.o
obj-$(CONFIG_USB_BLUETOOTH) += bluetooth.o
-obj-$(CONFIG_USB_CDCETHER) += cdc-ether.o
-obj-$(CONFIG_USB_HID) += hid.o
-obj-$(CONFIG_USB_KBD) += usbkbd.o
-obj-$(CONFIG_USB_MOUSE) += usbmouse.o
obj-$(CONFIG_USB_PRINTER) += printer.o
diff --git a/drivers/usb/class/cdc-ether.c b/drivers/usb/class/cdc-ether.c
deleted file mode 100644
index 3b41f2a445dc..000000000000
--- a/drivers/usb/class/cdc-ether.c
+++ /dev/null
@@ -1,1365 +0,0 @@
-// Portions of this file taken from
-// Petko Manolov - Petkan (petkan@dce.bg)
-// from his driver pegasus.c
-
-/*
- * 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/sched.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/usb.h>
-#include <linux/module.h>
-#include "cdc-ether.h"
-
-static const char *version = __FILE__ ": v0.98.5 22 Sep 2001 Brad Hards and another";
-
-/* Take any CDC device, and sort it out in probe() */
-static struct usb_device_id CDCEther_ids[] = {
- { USB_DEVICE_INFO(USB_CLASS_COMM, 0, 0) },
- { } /* Terminating null entry */
-};
-
-/*
- * module parameter that provides an alternate upper limit on the
- * number of multicast filters we use, with a default to use all
- * the filters available to us. Note that the actual number used
- * is the lesser of this parameter and the number returned in the
- * descriptor for the particular device. See Table 41 of the CDC
- * spec for more info on the descriptor limit.
- */
-static int multicast_filter_limit = 32767;
-
-
-//////////////////////////////////////////////////////////////////////////////
-// Callback routines from USB device /////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-static void read_bulk_callback( struct urb *urb )
-{
- ether_dev_t *ether_dev = urb->context;
- struct net_device *net;
- int count = urb->actual_length, res;
- struct sk_buff *skb;
-
- // Sanity check
- if ( !ether_dev || !(ether_dev->flags & CDC_ETHER_RUNNING) ) {
- dbg("BULK IN callback but driver is not active!");
- return;
- }
-
- net = ether_dev->net;
- if ( !netif_device_present(net) ) {
- // Somebody killed our network interface...
- return;
- }
-
- if ( ether_dev->flags & CDC_ETHER_RX_BUSY ) {
- // Are we already trying to receive a frame???
- ether_dev->stats.rx_errors++;
- dbg("ether_dev Rx busy");
- return;
- }
-
- // We are busy, leave us alone!
- ether_dev->flags |= CDC_ETHER_RX_BUSY;
-
- switch ( urb->status ) {
- case 0:
- break;
- case -ETIMEDOUT:
- dbg( "no repsonse in BULK IN" );
- ether_dev->flags &= ~CDC_ETHER_RX_BUSY;
- break;
- default:
- dbg( "%s: RX status %d", net->name, urb->status );
- goto goon;
- }
-
- // Check to make sure we got some data...
- if ( !count ) {
- // We got no data!!!
- goto goon;
- }
-
- // Tell the kernel we want some memory
- if ( !(skb = dev_alloc_skb(count)) ) {
- // We got no receive buffer.
- goto goon;
- }
-
- // Here's where it came from
- skb->dev = net;
-
- // Now we copy it over
- eth_copy_and_sum(skb, ether_dev->rx_buff, count, 0);
-
- // Not sure
- skb_put(skb, count);
- // Not sure here either
- skb->protocol = eth_type_trans(skb, net);
-
- // Ship it off to the kernel
- netif_rx(skb);
-
- // update out statistics
- ether_dev->stats.rx_packets++;
- ether_dev->stats.rx_bytes += count;
-
-goon:
- // Prep the USB to wait for another frame
- FILL_BULK_URB( ether_dev->rx_urb, ether_dev->usb,
- usb_rcvbulkpipe(ether_dev->usb, ether_dev->data_ep_in),
- ether_dev->rx_buff, ether_dev->wMaxSegmentSize,
- read_bulk_callback, ether_dev );
-
- // Give this to the USB subsystem so it can tell us
- // when more data arrives.
- if ( (res = usb_submit_urb(ether_dev->rx_urb, GFP_KERNEL)) ) {
- warn( __FUNCTION__ " failed submint rx_urb %d", res);
- }
-
- // We are no longer busy, show us the frames!!!
- ether_dev->flags &= ~CDC_ETHER_RX_BUSY;
-}
-
-static void write_bulk_callback( struct urb *urb )
-{
- ether_dev_t *ether_dev = urb->context;
-
- // Sanity check
- if ( !ether_dev || !(ether_dev->flags & CDC_ETHER_RUNNING) ) {
- // We are insane!!!
- err( "write_bulk_callback: device not running" );
- return;
- }
-
- // Do we still have a valid kernel network device?
- if ( !netif_device_present(ether_dev->net) ) {
- // Someone killed our network interface.
- err( "write_bulk_callback: net device not present" );
- return;
- }
-
- // Hmm... What on Earth could have happened???
- if ( urb->status ) {
- info("%s: TX status %d", ether_dev->net->name, urb->status);
- }
-
- // Update the network interface and tell it we are
- // ready for another frame
- ether_dev->net->trans_start = jiffies;
- netif_wake_queue( ether_dev->net );
-}
-
-//static void intr_callback( struct urb *urb )
-//{
-// ether_dev_t *ether_dev = urb->context;
-// struct net_device *net;
-// __u8 *d;
-//
-// if ( !ether_dev )
-// return;
-//
-// switch ( urb->status ) {
-// case 0:
-// break;
-// case -ENOENT:
-// return;
-// default:
-// info("intr status %d", urb->status);
-// }
-//
-// d = urb->transfer_buffer;
-// net = ether_dev->net;
-// if ( d[0] & 0xfc ) {
-// ether_dev->stats.tx_errors++;
-// if ( d[0] & TX_UNDERRUN )
-// ether_dev->stats.tx_fifo_errors++;
-// if ( d[0] & (EXCESSIVE_COL | JABBER_TIMEOUT) )
-// ether_dev->stats.tx_aborted_errors++;
-// if ( d[0] & LATE_COL )
-// ether_dev->stats.tx_window_errors++;
-// if ( d[0] & (NO_CARRIER | LOSS_CARRIER) )
-// ether_dev->stats.tx_carrier_errors++;
-// }
-//}
-
-//////////////////////////////////////////////////////////////////////////////
-// Routines for turning net traffic on and off on the USB side ///////////////
-//////////////////////////////////////////////////////////////////////////////
-
-static inline int enable_net_traffic( ether_dev_t *ether_dev )
-{
- struct usb_device *usb = ether_dev->usb;
-
- // Here would be the time to set the data interface to the configuration where
- // it has two endpoints that use a protocol we can understand.
-
- if (usb_set_interface( usb,
- ether_dev->data_bInterfaceNumber,
- ether_dev->data_bAlternateSetting_with_traffic ) ) {
- err("usb_set_interface() failed" );
- err("Attempted to set interface %d", ether_dev->data_bInterfaceNumber);
- err("To alternate setting %d", ether_dev->data_bAlternateSetting_with_traffic);
- return -1;
- }
- return 0;
-}
-
-static inline void disable_net_traffic( ether_dev_t *ether_dev )
-{
- // The thing to do is to set the data interface to the alternate setting that has
- // no endpoints. This is what the spec suggests.
-
- if (ether_dev->data_interface_altset_num_without_traffic >= 0 ) {
- if (usb_set_interface( ether_dev->usb,
- ether_dev->data_bInterfaceNumber,
- ether_dev->data_bAlternateSetting_without_traffic ) ) {
- err("usb_set_interface() failed");
- }
- } else {
- // Some devices just may not support this...
- warn("No way to disable net traffic");
- }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Callback routines for kernel Ethernet Device //////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-static void CDCEther_tx_timeout( struct net_device *net )
-{
- ether_dev_t *ether_dev = net->priv;
-
- // Sanity check
- if ( !ether_dev ) {
- // Seems to be a case of insanity here
- return;
- }
-
- // Tell syslog we are hosed.
- warn("%s: Tx timed out.", net->name);
-
- // Tear the waiting frame off the list
- ether_dev->tx_urb->transfer_flags |= USB_ASYNC_UNLINK;
- usb_unlink_urb( ether_dev->tx_urb );
-
- // Update statistics
- ether_dev->stats.tx_errors++;
-}
-
-static int CDCEther_start_xmit( struct sk_buff *skb, struct net_device *net )
-{
- ether_dev_t *ether_dev = net->priv;
- int count;
- int res;
-
- // If we are told to transmit an ethernet frame that fits EXACTLY
- // into an integer number of USB packets, we force it to send one
- // more byte so the device will get a runt USB packet signalling the
- // end of the ethernet frame
- if ( (skb->len) ^ (ether_dev->data_ep_out_size) ) {
- // It was not an exact multiple
- // no need to add anything extra
- count = skb->len;
- } else {
- // Add one to make it NOT an exact multiple
- count = skb->len + 1;
- }
-
- // Tell the kernel, "No more frames 'til we are done
- // with this one.'
- netif_stop_queue( net );
-
- // Copy it from kernel memory to OUR memory
- memcpy(ether_dev->tx_buff, skb->data, skb->len);
-
- // Fill in the URB for shipping it out.
- FILL_BULK_URB( ether_dev->tx_urb, ether_dev->usb,
- usb_sndbulkpipe(ether_dev->usb, ether_dev->data_ep_out),
- ether_dev->tx_buff, ether_dev->wMaxSegmentSize,
- write_bulk_callback, ether_dev );
-
- // Tell the URB how much it will be transporting today
- ether_dev->tx_urb->transfer_buffer_length = count;
-
- // Send the URB on its merry way.
- if ((res = usb_submit_urb(ether_dev->tx_urb, GFP_KERNEL))) {
- // Hmm... It didn't go. Tell someone...
- warn("failed tx_urb %d", res);
- // update some stats...
- ether_dev->stats.tx_errors++;
- // and tell the kernel to give us another.
- // Maybe we'll get it right next time.
- netif_start_queue( net );
- } else {
- // Okay, it went out.
- // Update statistics
- ether_dev->stats.tx_packets++;
- ether_dev->stats.tx_bytes += skb->len;
- // And tell the kernel when the last transmit occurred.
- net->trans_start = jiffies;
- }
-
- // We are done with the kernel's memory
- dev_kfree_skb(skb);
-
- // We are done here.
- return 0;
-}
-
-static struct net_device_stats *CDCEther_netdev_stats( struct net_device *net )
-{
- // Easy enough!
- return &((ether_dev_t *)net->priv)->stats;
-}
-
-static int CDCEther_open(struct net_device *net)
-{
- ether_dev_t *ether_dev = (ether_dev_t *)net->priv;
- int res;
-
- // Turn on the USB and let the packets flow!!!
- if ( (res = enable_net_traffic( ether_dev )) ) {
- err( __FUNCTION__ "can't enable_net_traffic() - %d", res );
- return -EIO;
- }
-
- // Prep a receive URB
- FILL_BULK_URB( ether_dev->rx_urb, ether_dev->usb,
- usb_rcvbulkpipe(ether_dev->usb, ether_dev->data_ep_in),
- ether_dev->rx_buff, ether_dev->wMaxSegmentSize,
- read_bulk_callback, ether_dev );
-
- // Put it out there so the device can send us stuff
- if ( (res = usb_submit_urb(ether_dev->rx_urb, GFP_KERNEL)) )
- {
- // Hmm... Okay...
- warn( __FUNCTION__ " failed rx_urb %d", res );
- }
-
- // Tell the kernel we are ready to start receiving from it
- netif_start_queue( net );
-
- // We are up and running.
- ether_dev->flags |= CDC_ETHER_RUNNING;
-
- // Let's get ready to move frames!!!
- return 0;
-}
-
-static int CDCEther_close( struct net_device *net )
-{
- ether_dev_t *ether_dev = net->priv;
-
- // We are no longer running.
- ether_dev->flags &= ~CDC_ETHER_RUNNING;
-
- // Tell the kernel to stop sending us stuff
- netif_stop_queue( net );
-
- // If we are not already unplugged, turn off USB
- // traffic
- if ( !(ether_dev->flags & CDC_ETHER_UNPLUG) ) {
- disable_net_traffic( ether_dev );
- }
-
- // We don't need the URBs anymore.
- usb_unlink_urb( ether_dev->rx_urb );
- usb_unlink_urb( ether_dev->tx_urb );
- usb_unlink_urb( ether_dev->intr_urb );
-
- // That's it. I'm done.
- return 0;
-}
-
-static int CDCEther_ioctl( struct net_device *net, struct ifreq *rq, int cmd )
-{
- //__u16 *data = (__u16 *)&rq->ifr_data;
- //ether_dev_t *ether_dev = net->priv;
-
- // No support here yet.
- // Do we need support???
- switch(cmd) {
- case SIOCDEVPRIVATE:
- return -EOPNOTSUPP;
- case SIOCDEVPRIVATE+1:
- return -EOPNOTSUPP;
- case SIOCDEVPRIVATE+2:
- //return 0;
- return -EOPNOTSUPP;
- default:
- return -EOPNOTSUPP;
- }
-}
-
-static void CDC_SetEthernetPacketFilter (ether_dev_t *ether_dev)
-{
- usb_control_msg(ether_dev->usb,
- usb_sndctrlpipe(ether_dev->usb, 0),
- SET_ETHERNET_PACKET_FILTER, /* request */
- USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_INTERFACE, /* request type */
- cpu_to_le16(ether_dev->mode_flags), /* value */
- cpu_to_le16((u16)ether_dev->comm_interface), /* index */
- NULL,
- 0, /* size */
- HZ); /* timeout */
-}
-
-
-static void CDCEther_set_multicast( struct net_device *net )
-{
- ether_dev_t *ether_dev = net->priv;
- int i;
- __u8 *buff;
-
-
- // Tell the kernel to stop sending us frames while we get this
- // all set up.
- netif_stop_queue(net);
-
- /* Note: do not reorder, GCC is clever about common statements. */
- if (net->flags & IFF_PROMISC) {
- /* Unconditionally log net taps. */
- info( "%s: Promiscuous mode enabled", net->name);
- ether_dev->mode_flags = MODE_FLAG_PROMISCUOUS |
- MODE_FLAG_ALL_MULTICAST |
- MODE_FLAG_DIRECTED |
- MODE_FLAG_BROADCAST |
- MODE_FLAG_MULTICAST;
- } else if (net->mc_count > ether_dev->wNumberMCFilters) {
- /* Too many to filter perfectly -- accept all multicasts. */
- info("%s: set too many MC filters, using allmulti", net->name);
- ether_dev->mode_flags = MODE_FLAG_ALL_MULTICAST |
- MODE_FLAG_DIRECTED |
- MODE_FLAG_BROADCAST |
- MODE_FLAG_MULTICAST;
- } else if (net->flags & IFF_ALLMULTI) {
- /* Filter in software */
- info("%s: using allmulti", net->name);
- ether_dev->mode_flags = MODE_FLAG_ALL_MULTICAST |
- MODE_FLAG_DIRECTED |
- MODE_FLAG_BROADCAST |
- MODE_FLAG_MULTICAST;
- } else {
- /* do multicast filtering in hardware */
- struct dev_mc_list *mclist;
- info("%s: set multicast filters", net->name);
- ether_dev->mode_flags = MODE_FLAG_ALL_MULTICAST |
- MODE_FLAG_DIRECTED |
- MODE_FLAG_BROADCAST |
- MODE_FLAG_MULTICAST;
- buff = kmalloc(6 * net->mc_count, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
- for (i = 0, mclist = net->mc_list;
- mclist && i < net->mc_count;
- i++, mclist = mclist->next) {
- memcpy(&mclist->dmi_addr, &buff[i * 6], 6);
- }
-#if 0
- usb_control_msg(ether_dev->usb,
- usb_sndctrlpipe(ether_dev->usb, 0),
- SET_ETHERNET_MULTICAST_FILTER, /* request */
- USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_INTERFACE, /* request type */
- cpu_to_le16(net->mc_count), /* value */
- cpu_to_le16((u16)ether_dev->comm_interface), /* index */
- buff,
- (6* net->mc_count), /* size */
- HZ); /* timeout */
-#endif
- kfree(buff);
- }
-
-#if 0
- CDC_SetEthernetPacketFilter(ether_dev);
-#endif
- // Tell the kernel to start giving frames to us again.
- netif_wake_queue(net);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Routines used to parse out the Functional Descriptors /////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-static int parse_header_functional_descriptor( int *bFunctionLength,
- int bDescriptorType,
- int bDescriptorSubtype,
- unsigned char *data,
- ether_dev_t *ether_dev,
- int *requirements )
-{
- // Check to make sure we haven't seen one of these already.
- if ( (~*requirements) & REQ_HDR_FUNC_DESCR ) {
- err( "Multiple Header Functional Descriptors found." );
- return -1;
- }
-
- // Is it the right size???
- if (*bFunctionLength != 5) {
- info( "Invalid length in Header Functional Descriptor" );
- // This is a hack to get around a particular device (NO NAMES)
- // It has this function length set to the length of the
- // whole class-specific descriptor
- *bFunctionLength = 5;
- }
-
- // Nothing extremely useful here.
- // We'll keep it for posterity
- ether_dev->bcdCDC = data[0] + (data[1] << 8);
- dbg( "Found Header descriptor, CDC version %x", ether_dev->bcdCDC);
-
- // We've seen one of these
- *requirements &= ~REQ_HDR_FUNC_DESCR;
-
- // It's all good.
- return 0;
-}
-
-static int parse_union_functional_descriptor( int *bFunctionLength,
- int bDescriptorType,
- int bDescriptorSubtype,
- unsigned char *data,
- ether_dev_t *ether_dev,
- int *requirements )
-{
- // Check to make sure we haven't seen one of these already.
- if ( (~*requirements) & REQ_UNION_FUNC_DESCR ) {
- err( "Multiple Union Functional Descriptors found." );
- return -1;
- }
-
- // Is it the right size?
- if (*bFunctionLength != 5) {
- // It is NOT the size we expected.
- err( "Unsupported length in Union Functional Descriptor" );
- return -1;
- }
-
- // Sanity check of sorts
- if (ether_dev->comm_interface != data[0]) {
- // This tells us that we are chasing the wrong comm
- // interface or we are crazy or something else weird.
- if (ether_dev->comm_interface == data[1]) {
- info( "Probably broken Union descriptor, fudging data interface" );
- // We'll need this in a few microseconds,
- // so guess here, and hope for the best
- ether_dev->data_interface = data[0];
- } else {
- err( "Union Functional Descriptor is broken beyond repair" );
- return -1;
- }
- } else{ // Descriptor is OK
- // We'll need this in a few microseconds!
- ether_dev->data_interface = data[1];
- }
-
- // We've seen one of these now.
- *requirements &= ~REQ_UNION_FUNC_DESCR;
-
- // Done
- return 0;
-}
-
-static int parse_ethernet_functional_descriptor( int *bFunctionLength,
- int bDescriptorType,
- int bDescriptorSubtype,
- unsigned char *data,
- ether_dev_t *ether_dev,
- int *requirements )
-{
- // Check to make sure we haven't seen one of these already.
- if ( (~*requirements) & REQ_ETH_FUNC_DESCR ) {
- err( "Multiple Ethernet Functional Descriptors found." );
- return -1;
- }
-
- // Is it the right size?
- if (*bFunctionLength != 13) {
- err( "Invalid length in Ethernet Networking Functional Descriptor" );
- return -1;
- }
-
- // Lots of goodies from this one. They are all important.
- ether_dev->iMACAddress = data[0];
- ether_dev->bmEthernetStatistics = data[1] + (data[2] << 8) + (data[3] << 16) + (data[4] << 24);
- ether_dev->wMaxSegmentSize = data[5] + (data[6] << 8);
- ether_dev->wNumberMCFilters = (data[7] + (data[8] << 8)) & 0x00007FFF;
- if (ether_dev->wNumberMCFilters > multicast_filter_limit) {
- ether_dev->wNumberMCFilters = multicast_filter_limit;
- }
- ether_dev->bNumberPowerFilters = data[9];
-
- // We've seen one of these now.
- *requirements &= ~REQ_ETH_FUNC_DESCR;
-
- // That's all she wrote.
- return 0;
-}
-
-static int parse_protocol_unit_functional_descriptor( int *bFunctionLength,
- int bDescriptorType,
- int bDescriptorSubtype,
- unsigned char *data,
- ether_dev_t *ether_dev,
- int *requirements )
-{
- // There should only be one type if we are sane
- if (bDescriptorType != CS_INTERFACE) {
- info( "Invalid bDescriptorType found." );
- return -1;
- }
-
- // The Subtype tells the tale.
- switch (bDescriptorSubtype){
- case 0x00: // Header Functional Descriptor
- return parse_header_functional_descriptor( bFunctionLength,
- bDescriptorType,
- bDescriptorSubtype,
- data,
- ether_dev,
- requirements );
- break;
- case 0x06: // Union Functional Descriptor
- return parse_union_functional_descriptor( bFunctionLength,
- bDescriptorType,
- bDescriptorSubtype,
- data,
- ether_dev,
- requirements );
- break;
- case 0x0F: // Ethernet Networking Functional Descriptor
- return parse_ethernet_functional_descriptor( bFunctionLength,
- bDescriptorType,
- bDescriptorSubtype,
- data,
- ether_dev,
- requirements );
- break;
- default: // We don't support this at this time...
- // However that doesn't necessarily indicate an error.
- dbg( "Unexpected header type %x:", bDescriptorSubtype );
- return 0;
- }
- // How did we get here???
- return -1;
-}
-
-static int parse_ethernet_class_information( unsigned char *data, int length, ether_dev_t *ether_dev )
-{
- int loc = 0;
- int rc;
- int bFunctionLength;
- int bDescriptorType;
- int bDescriptorSubtype;
- int requirements = REQUIREMENTS_TOTAL;
-
- // As long as there is something here, we will try to parse it
- while (loc < length) {
- // Length
- bFunctionLength = data[loc];
- loc++;
-
- // Type
- bDescriptorType = data[loc];
- loc++;
-
- // Subtype
- bDescriptorSubtype = data[loc];
- loc++;
-
- // ship this off to be processed elsewhere.
- rc = parse_protocol_unit_functional_descriptor( &bFunctionLength,
- bDescriptorType,
- bDescriptorSubtype,
- &data[loc],
- ether_dev,
- &requirements );
- // Did it process okay?
- if (rc) {
- // Something was hosed somewhere.
- // No need to continue;
- err("Bad descriptor parsing: %x", rc );
- return -1;
- }
- // We have already taken three bytes.
- loc += (bFunctionLength - 3);
- }
- // Check to see if we got everything we need.
- if (requirements) {
- // We missed some of the requirements...
- err( "Not all required functional descriptors present 0x%08X", requirements );
- return -1;
- }
- // We got everything.
- return 0;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Routine to check for the existence of the Functional Descriptors //////////
-//////////////////////////////////////////////////////////////////////////////
-
-static int find_and_parse_ethernet_class_information( struct usb_device *device, ether_dev_t *ether_dev )
-{
- struct usb_config_descriptor *conf = NULL;
- struct usb_interface *comm_intf_group = NULL;
- struct usb_interface_descriptor *comm_intf = NULL;
- int rc = -1;
- // The assumption here is that find_ethernet_comm_interface
- // and find_valid_configuration
- // have already filled in the information about where to find
- // the a valid commication interface.
-
- conf = &( device->config[ether_dev->configuration_num] );
- comm_intf_group = &( conf->interface[ether_dev->comm_interface] );
- comm_intf = &( comm_intf_group->altsetting[ether_dev->comm_interface_altset_num] );
- // Let's check and see if it has the extra information we need...
-
- if (comm_intf->extralen > 0) {
- // This is where the information is SUPPOSED to be.
- rc = parse_ethernet_class_information( comm_intf->extra, comm_intf->extralen, ether_dev );
- } else if (conf->extralen > 0) {
- // This is a hack. The spec says it should be at the interface
- // location checked above. However I have seen it here also.
- // This is the same device that requires the functional descriptor hack above
- warn( "Ethernet information found at device configuration. This is broken." );
- rc = parse_ethernet_class_information( conf->extra, conf->extralen, ether_dev );
- } else {
- // I don't know where else to look.
- warn( "No ethernet information found." );
- rc = -1;
- }
- return rc;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Routines to verify the data interface /////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-static int get_data_interface_endpoints( struct usb_device *device, ether_dev_t *ether_dev )
-{
- struct usb_config_descriptor *conf = NULL;
- struct usb_interface *data_intf_group = NULL;
- struct usb_interface_descriptor *data_intf = NULL;
-
- // Walk through and get to the data interface we are checking.
- conf = &( device->config[ether_dev->configuration_num] );
- data_intf_group = &( conf->interface[ether_dev->data_interface] );
- data_intf = &( data_intf_group->altsetting[ether_dev->data_interface_altset_num_with_traffic] );
-
- // Start out assuming we won't find anything we can use
- ether_dev->data_ep_in = 0;
- ether_dev->data_ep_out = 0;
-
- // If these are not BULK endpoints, we don't want them
- if ( data_intf->endpoint[0].bmAttributes != 0x02 ) {
- return -1;
- } if ( data_intf->endpoint[1].bmAttributes != 0x02 ) {
- return -1;
- }
-
- // Check the first endpoint to see if it is IN or OUT
- if ( data_intf->endpoint[0].bEndpointAddress & 0x80 ) {
- // This endpoint is IN
- ether_dev->data_ep_in = data_intf->endpoint[0].bEndpointAddress & 0x7F;
- } else {
- // This endpoint is OUT
- ether_dev->data_ep_out = data_intf->endpoint[0].bEndpointAddress & 0x7F;
- ether_dev->data_ep_out_size = data_intf->endpoint[0].wMaxPacketSize;
- }
-
- // Check the second endpoint to see if it is IN or OUT
- if ( data_intf->endpoint[1].bEndpointAddress & 0x80 ) {
- // This endpoint is IN
- ether_dev->data_ep_in = data_intf->endpoint[1].bEndpointAddress & 0x7F;
- } else {
- // This endpoint is OUT
- ether_dev->data_ep_out = data_intf->endpoint[1].bEndpointAddress & 0x7F;
- ether_dev->data_ep_out_size = data_intf->endpoint[1].wMaxPacketSize;
- }
-
- // Now make sure we got both an IN and an OUT
- if (ether_dev->data_ep_in && ether_dev->data_ep_out) {
- // We did get both, we are in good shape...
- info( "detected BULK OUT packets of size %d", ether_dev->data_ep_out_size );
- return 0;
- }
- return -1;
-}
-
-static int verify_ethernet_data_interface( struct usb_device *device, ether_dev_t *ether_dev )
-{
- struct usb_config_descriptor *conf = NULL;
- struct usb_interface *data_intf_group = NULL;
- struct usb_interface_descriptor *data_intf = NULL;
- int rc = -1;
- int status;
- int altset_num;
-
- // The assumption here is that parse_ethernet_class_information()
- // and find_valid_configuration()
- // have already filled in the information about where to find
- // a data interface
- conf = &( device->config[ether_dev->configuration_num] );
- data_intf_group = &( conf->interface[ether_dev->data_interface] );
-
- // start out assuming we won't find what we are looking for.
- ether_dev->data_interface_altset_num_with_traffic = -1;
- ether_dev->data_bAlternateSetting_with_traffic = -1;
- ether_dev->data_interface_altset_num_without_traffic = -1;
- ether_dev->data_bAlternateSetting_without_traffic = -1;
-
- // Walk through every possible setting for this interface until
- // we find what makes us happy.
- for ( altset_num = 0; altset_num < data_intf_group->num_altsetting; altset_num++ ) {
- data_intf = &( data_intf_group->altsetting[altset_num] );
-
- // Is this a data interface we like?
- if ( ( data_intf->bInterfaceClass == 0x0A )
- && ( data_intf->bInterfaceSubClass == 0x00 )
- && ( data_intf->bInterfaceProtocol == 0x00 ) ) {
- if ( data_intf->bNumEndpoints == 2 ) {
- // We are required to have one of these.
- // An interface with 2 endpoints to send Ethernet traffic back and forth
- // It actually may be possible that the device might only
- // communicate in a vendor specific manner.
- // That would not be very nice.
- // We can add that one later.
- ether_dev->data_bInterfaceNumber = data_intf->bInterfaceNumber;
- ether_dev->data_interface_altset_num_with_traffic = altset_num;
- ether_dev->data_bAlternateSetting_with_traffic = data_intf->bAlternateSetting;
- status = get_data_interface_endpoints( device, ether_dev );
- if (!status) {
- rc = 0;
- }
- }
- if ( data_intf->bNumEndpoints == 0 ) {
- // According to the spec we are SUPPOSED to have one of these
- // In fact the device is supposed to come up in this state.
- // However, I have seen a device that did not have such an interface.
- // So it must be just optional for our driver...
- ether_dev->data_bInterfaceNumber = data_intf->bInterfaceNumber;
- ether_dev->data_interface_altset_num_without_traffic = altset_num;
- ether_dev->data_bAlternateSetting_without_traffic = data_intf->bAlternateSetting;
- }
- }
- }
- return rc;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Routine to find a communication interface /////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-static int find_ethernet_comm_interface( struct usb_device *device, ether_dev_t *ether_dev )
-{
- struct usb_config_descriptor *conf = NULL;
- struct usb_interface *comm_intf_group = NULL;
- struct usb_interface_descriptor *comm_intf = NULL;
- int intf_num;
- int altset_num;
- int rc;
-
- conf = &( device->config[ether_dev->configuration_num] );
-
- // We need to check and see if any of these interfaces are something we want.
- // Walk through each interface one at a time
- for ( intf_num = 0; intf_num < conf->bNumInterfaces; intf_num++ ) {
- comm_intf_group = &( conf->interface[intf_num] );
- // Now for each of those interfaces, check every possible
- // alternate setting.
- for ( altset_num = 0; altset_num < comm_intf_group->num_altsetting; altset_num++ ) {
- comm_intf = &( comm_intf_group->altsetting[altset_num] );
-
- // Is this a communication class of interface of the
- // ethernet subclass variety.
- if ( ( comm_intf->bInterfaceClass == 0x02 )
- && ( comm_intf->bInterfaceSubClass == 0x06 )
- && ( comm_intf->bInterfaceProtocol == 0x00 ) ) {
- if ( comm_intf->bNumEndpoints == 1 ) {
- // Good, we found one, we will try this one
- // Fill in the structure...
- ether_dev->comm_interface = intf_num;
- ether_dev->comm_bInterfaceNumber = comm_intf->bInterfaceNumber;
- ether_dev->comm_interface_altset_num = altset_num;
- ether_dev->comm_bAlternateSetting = comm_intf->bAlternateSetting;
-
- // Look for the Ethernet Functional Descriptors
- rc = find_and_parse_ethernet_class_information( device, ether_dev );
- if (rc) {
- // Nope this was no good after all.
- continue;
- }
-
- // Check that we really can talk to the data
- // interface
- // This includes # of endpoints, protocols,
- // etc.
- rc = verify_ethernet_data_interface( device, ether_dev );
- if (rc) {
- // We got something we didn't like
- continue;
- }
- // This communication interface seems to give us everything
- // we require. We have all the ethernet info we need.
- // Let's get out of here and go home right now.
- return 0;
- } else {
- // bNumEndPoints != 1
- // We found an interface that had the wrong number of
- // endpoints but would have otherwise been okay
- } // end bNumEndpoints check.
- } // end interface specifics check.
- } // end for altset_num
- } // end for intf_num
- return -1;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Routine to go through all configurations and find one that ////////////////
-// is an Ethernet Networking Device //////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-static int find_valid_configuration( struct usb_device *device, ether_dev_t *ether_dev )
-{
- struct usb_config_descriptor *conf = NULL;
- int conf_num;
- int rc;
-
- // We will try each and every possible configuration
- for ( conf_num = 0; conf_num < device->descriptor.bNumConfigurations; conf_num++ ) {
- conf = &( device->config[conf_num] );
-
- // Our first requirement : 2 interfaces
- if ( conf->bNumInterfaces != 2 ) {
- // I currently don't know how to handle devices with any number of interfaces
- // other than 2.
- continue;
- }
-
- // This one passed our first check, fill in some
- // useful data
- ether_dev->configuration_num = conf_num;
- ether_dev->bConfigurationValue = conf->bConfigurationValue;
-
- // Now run it through the ringers and see what comes
- // out the other side.
- rc = find_ethernet_comm_interface( device, ether_dev );
-
- // Check if we found an ethernet Communcation Device
- if ( !rc ) {
- // We found one.
- return 0;
- }
- }
- // None of the configurations suited us.
- return -1;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Routine that checks a given configuration to see if any driver ////////////
-// has claimed any of the devices interfaces /////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-static int check_for_claimed_interfaces( struct usb_config_descriptor *config )
-{
- struct usb_interface *comm_intf_group;
- int intf_num;
-
- // Go through all the interfaces and make sure none are
- // claimed by anybody else.
- for ( intf_num = 0; intf_num < config->bNumInterfaces; intf_num++ ) {
- comm_intf_group = &( config->interface[intf_num] );
- if ( usb_interface_claimed( comm_intf_group ) ) {
- // Somebody has beat us to this guy.
- // We can't change the configuration out from underneath of whoever
- // is using this device, so we will go ahead and give up.
- return -1;
- }
- }
- // We made it all the way through.
- // I guess no one has claimed any of these interfaces.
- return 0;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Routines to ask for and set the kernel network interface's MAC address ////
-// Used by driver's probe routine ////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-static inline unsigned char hex2dec( unsigned char digit )
-{
- // Is there a standard way to do this???
- // I have written this code TOO MANY times.
- if ( (digit >= '0') && (digit <= '9') ) {
- return (digit - '0');
- }
- if ( (digit >= 'a') && (digit <= 'f') ) {
- return (digit - 'a' + 10);
- }
- if ( (digit >= 'A') && (digit <= 'F') ) {
- return (digit - 'A' + 10);
- }
- return 0;
-}
-
-static void set_ethernet_addr( ether_dev_t *ether_dev )
-{
- unsigned char mac_addr[6];
- int i;
- int len;
- unsigned char buffer[13];
-
- // Let's assume we don't get anything...
- mac_addr[0] = 0x00;
- mac_addr[1] = 0x00;
- mac_addr[2] = 0x00;
- mac_addr[3] = 0x00;
- mac_addr[4] = 0x00;
- mac_addr[5] = 0x00;
-
- // Let's ask the device...
- len = usb_string(ether_dev->usb, ether_dev->iMACAddress, buffer, 13);
-
- // Sanity check!
- if (len != 12) {
- // You gotta love failing sanity checks
- err("Attempting to get MAC address returned %d bytes", len);
- return;
- }
-
- // Fill in the mac_addr
- for (i = 0; i < 6; i++) {
- mac_addr[i] = ( hex2dec( buffer[2 * i] ) << 4 ) + hex2dec( buffer[2 * i + 1] );
- }
-
- // Now copy it over to the kernel's network driver.
- memcpy( ether_dev->net->dev_addr, mac_addr, sizeof(mac_addr) );
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Routine to print to syslog information about the driver ///////////////////
-// Used by driver's probe routine ////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-void log_device_info(ether_dev_t *ether_dev)
-{
- int len;
- int string_num;
- unsigned char manu[256];
- unsigned char prod[256];
- unsigned char sern[256];
- unsigned char *mac_addr;
-
- // Default empty strings in case we don't find a real one
- manu[0] = 0x00;
- prod[0] = 0x00;
- sern[0] = 0x00;
-
- // Try to get the device Manufacturer
- string_num = ether_dev->usb->descriptor.iManufacturer;
- if (string_num) {
- // Put it into its buffer
- len = usb_string(ether_dev->usb, string_num, manu, 255);
- // Just to be safe
- manu[len] = 0x00;
- }
-
- // Try to get the device Product Name
- string_num = ether_dev->usb->descriptor.iProduct;
- if (string_num) {
- // Put it into its buffer
- len = usb_string(ether_dev->usb, string_num, prod, 255);
- // Just to be safe
- prod[len] = 0x00;
- }
-
- // Try to get the device Serial Number
- string_num = ether_dev->usb->descriptor.iSerialNumber;
- if (string_num) {
- // Put it into its buffer
- len = usb_string(ether_dev->usb, string_num, sern, 255);
- // Just to be safe
- sern[len] = 0x00;
- }
-
- // This makes it easier for us to print
- mac_addr = ether_dev->net->dev_addr;
-
- // Now send everything we found to the syslog
- info( "%s: %s %s %s %02X:%02X:%02X:%02X:%02X:%02X",
- ether_dev->net->name, manu, prod, sern, mac_addr[0],
- mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4],
- mac_addr[5] );
-}
-
-/* Forward declaration */
-static struct usb_driver CDCEther_driver ;
-
-//////////////////////////////////////////////////////////////////////////////
-// Module's probe routine ////////////////////////////////////////////////////
-// claims interfaces if they are for an Ethernet CDC /////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-static void * CDCEther_probe( struct usb_device *usb, unsigned int ifnum,
- const struct usb_device_id *id)
-{
- struct net_device *net;
- ether_dev_t *ether_dev;
- int rc;
-
- // First we should check the active configuration to see if
- // any other driver has claimed any of the interfaces.
- if ( check_for_claimed_interfaces( usb->actconfig ) ) {
- // Someone has already put there grubby paws on this device.
- // We don't want it now...
- return NULL;
- }
-
- // We might be finding a device we can use.
- // We all go ahead and allocate our storage space.
- // We need to because we have to start filling in the data that
- // we are going to need later.
- if(!(ether_dev = kmalloc(sizeof(ether_dev_t), GFP_KERNEL))) {
- err("out of memory allocating device structure");
- return NULL;
- }
-
- // Zero everything out.
- memset(ether_dev, 0, sizeof(ether_dev_t));
-
- ether_dev->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!ether_dev->rx_urb) {
- kfree(ether_dev);
- return NULL;
- }
- ether_dev->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!ether_dev->tx_urb) {
- usb_free_urb(ether_dev->rx_urb);
- kfree(ether_dev);
- return NULL;
- }
- ether_dev->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!ether_dev->intr_urb) {
- usb_free_urb(ether_dev->tx_urb);
- usb_free_urb(ether_dev->rx_urb);
- kfree(ether_dev);
- return NULL;
- }
-
- // Let's see if we can find a configuration we can use.
- rc = find_valid_configuration( usb, ether_dev );
- if (rc) {
- // Nope we couldn't find one we liked.
- // This device was not meant for us to control.
- kfree( ether_dev );
- return NULL;
- }
-
- // Now that we FOUND a configuration. let's try to make the
- // device go into it.
- if ( usb_set_configuration( usb, ether_dev->bConfigurationValue ) ) {
- err("usb_set_configuration() failed");
- kfree( ether_dev );
- return NULL;
- }
-
- // Now set the communication interface up as required.
- if (usb_set_interface(usb, ether_dev->comm_bInterfaceNumber, ether_dev->comm_bAlternateSetting)) {
- err("usb_set_interface() failed");
- kfree( ether_dev );
- return NULL;
- }
-
- // Only turn traffic on right now if we must...
- if (ether_dev->data_interface_altset_num_without_traffic >= 0) {
- // We found an alternate setting for the data
- // interface that allows us to turn off traffic.
- // We should use it.
- if (usb_set_interface( usb,
- ether_dev->data_bInterfaceNumber,
- ether_dev->data_bAlternateSetting_without_traffic)) {
- err("usb_set_interface() failed");
- kfree( ether_dev );
- return NULL;
- }
- } else {
- // We didn't find an alternate setting for the data
- // interface that would let us turn off traffic.
- // Oh well, let's go ahead and do what we must...
- if (usb_set_interface( usb,
- ether_dev->data_bInterfaceNumber,
- ether_dev->data_bAlternateSetting_with_traffic)) {
- err("usb_set_interface() failed");
- kfree( ether_dev );
- return NULL;
- }
- }
-
- // Now we need to get a kernel Ethernet interface.
- net = init_etherdev( NULL, 0 );
- if ( !net ) {
- // Hmm... The kernel is not sharing today...
- // Fine, we didn't want it anyway...
- err( "Unable to initialize ethernet device" );
- kfree( ether_dev );
- return NULL;
- }
-
- // Now that we have an ethernet device, let's set it up
- // (And I don't mean "set [it] up the bomb".)
- net->priv = ether_dev;
- SET_MODULE_OWNER(net);
- net->open = CDCEther_open;
- net->stop = CDCEther_close;
- net->watchdog_timeo = CDC_ETHER_TX_TIMEOUT;
- net->tx_timeout = CDCEther_tx_timeout; // TX timeout function
- net->do_ioctl = CDCEther_ioctl;
- net->hard_start_xmit = CDCEther_start_xmit;
- net->set_multicast_list = CDCEther_set_multicast;
- net->get_stats = CDCEther_netdev_stats;
- net->mtu = ether_dev->wMaxSegmentSize - 14;
-
- // We'll keep track of this information for later...
- ether_dev->usb = usb;
- ether_dev->net = net;
-
- // and don't forget the MAC address.
- set_ethernet_addr( ether_dev );
-
- // Send a message to syslog about what we are handling
- log_device_info( ether_dev );
-
- // I claim this interface to be a CDC Ethernet Networking device
- usb_driver_claim_interface( &CDCEther_driver,
- &(usb->config[ether_dev->configuration_num].interface[ether_dev->comm_interface]),
- ether_dev );
- // I claim this interface to be a CDC Ethernet Networking device
- usb_driver_claim_interface( &CDCEther_driver,
- &(usb->config[ether_dev->configuration_num].interface[ether_dev->data_interface]),
- ether_dev );
-
- // Does this REALLY do anything???
- usb_inc_dev_use( usb );
-
- // TODO - last minute HACK
- ether_dev->comm_ep_in = 5;
-
- // Okay, we are finally done...
- return NULL;
-}
-
-
-//////////////////////////////////////////////////////////////////////////////
-// Module's disconnect routine ///////////////////////////////////////////////
-// Called when the driver is unloaded or the device is unplugged /////////////
-// (Whichever happens first assuming the driver suceeded at its probe) ///////
-//////////////////////////////////////////////////////////////////////////////
-
-static void CDCEther_disconnect( struct usb_device *usb, void *ptr )
-{
- ether_dev_t *ether_dev = ptr;
-
- // Sanity check!!!
- if ( !ether_dev || !ether_dev->usb ) {
- // We failed. We are insane!!!
- warn("unregistering non-existant device");
- return;
- }
-
- // Make sure we fail the sanity check if we try this again.
- ether_dev->usb = NULL;
-
- // It is possible that this function is called before
- // the "close" function.
- // This tells the close function we are already disconnected
- ether_dev->flags |= CDC_ETHER_UNPLUG;
-
- // We don't need the network device any more
- unregister_netdev( ether_dev->net );
-
- // For sanity checks
- ether_dev->net = NULL;
-
- // I ask again, does this do anything???
- usb_dec_dev_use( usb );
-
- // We are done with this interface
- usb_driver_release_interface( &CDCEther_driver,
- &(usb->config[ether_dev->configuration_num].interface[ether_dev->comm_interface]) );
-
- // We are done with this interface too
- usb_driver_release_interface( &CDCEther_driver,
- &(usb->config[ether_dev->configuration_num].interface[ether_dev->data_interface]) );
-
- // No more tied up kernel memory
- usb_free_urb(ether_dev->intr_urb);
- usb_free_urb(ether_dev->rx_urb);
- usb_free_urb(ether_dev->rx_urb);
- kfree( ether_dev );
-
- // This does no good, but it looks nice!
- ether_dev = NULL;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Driver info ///////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-static struct usb_driver CDCEther_driver = {
- name: "CDCEther",
- probe: CDCEther_probe,
- disconnect: CDCEther_disconnect,
- id_table: CDCEther_ids,
-};
-
-//////////////////////////////////////////////////////////////////////////////
-// init and exit routines called when driver is installed and uninstalled ////
-//////////////////////////////////////////////////////////////////////////////
-
-int __init CDCEther_init(void)
-{
- info( "%s", version );
- return usb_register( &CDCEther_driver );
-}
-
-void __exit CDCEther_exit(void)
-{
- usb_deregister( &CDCEther_driver );
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Module info ///////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-module_init( CDCEther_init );
-module_exit( CDCEther_exit );
-
-MODULE_AUTHOR("Brad Hards and another");
-MODULE_DESCRIPTION("USB CDC Ethernet driver");
-MODULE_LICENSE("GPL");
-
-MODULE_PARM (multicast_filter_limit, "i");
-MODULE_PARM_DESC (multicast_filter_limit, "CDCEther maximum number of filtered multicast addresses");
-
-MODULE_DEVICE_TABLE (usb, CDCEther_ids);
-
-//////////////////////////////////////////////////////////////////////////////
-// End of file ///////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
diff --git a/drivers/usb/class/cdc-ether.h b/drivers/usb/class/cdc-ether.h
deleted file mode 100644
index e91c2115ac3a..000000000000
--- a/drivers/usb/class/cdc-ether.h
+++ /dev/null
@@ -1,98 +0,0 @@
-// Portions of this file taken from
-// Petko Manolov - Petkan (petkan@dce.bg)
-// from his driver pegasus.h
-
-/*
- * 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 CS_INTERFACE 0x24
-
-#define CDC_ETHER_MAX_MTU 1536
-
-#define CDC_ETHER_PRESENT 0x00000001
-#define CDC_ETHER_RUNNING 0x00000002
-#define CDC_ETHER_TX_BUSY 0x00000004
-#define CDC_ETHER_RX_BUSY 0x00000008
-#define CDC_ETHER_UNPLUG 0x00000040
-
-#define CDC_ETHER_TX_TIMEOUT (HZ*10)
-
-#define TX_UNDERRUN 0x80
-#define EXCESSIVE_COL 0x40
-#define LATE_COL 0x20
-#define NO_CARRIER 0x10
-#define LOSS_CARRIER 0x08
-#define JABBER_TIMEOUT 0x04
-
-#define CDC_ETHER_REQT_READ 0xc0
-#define CDC_ETHER_REQT_WRITE 0x40
-#define CDC_ETHER_REQ_GET_REGS 0xf0
-#define CDC_ETHER_REQ_SET_REGS 0xf1
-#define CDC_ETHER_REQ_SET_REG PIPERIDER_REQ_SET_REGS
-#define ALIGN(x) x __attribute__((aligned(L1_CACHE_BYTES)))
-
-#define MODE_FLAG_PROMISCUOUS (1<<0)
-#define MODE_FLAG_ALL_MULTICAST (1<<1)
-#define MODE_FLAG_DIRECTED (1<<2)
-#define MODE_FLAG_BROADCAST (1<<3)
-#define MODE_FLAG_MULTICAST (1<<4)
-
-#define SET_ETHERNET_MULTICAST_FILTER 0x40
-#define SET_ETHERNET_PACKET_FILTER 0x43
-
-typedef struct _ether_dev_t {
- struct usb_device *usb;
- struct net_device *net;
- struct net_device_stats stats;
- unsigned flags;
- int configuration_num;
- int bConfigurationValue;
- int comm_interface;
- int comm_bInterfaceNumber;
- int comm_interface_altset_num;
- int comm_bAlternateSetting;
- int comm_ep_in;
- int data_interface;
- int data_bInterfaceNumber;
- int data_interface_altset_num_with_traffic;
- int data_bAlternateSetting_with_traffic;
- int data_interface_altset_num_without_traffic;
- int data_bAlternateSetting_without_traffic;
- int data_ep_in;
- int data_ep_out;
- int data_ep_out_size;
- __u16 bcdCDC;
- __u8 iMACAddress;
- __u32 bmEthernetStatistics;
- __u16 wMaxSegmentSize;
- __u16 mode_flags;
- __u16 wNumberMCFilters;
- __u8 bNumberPowerFilters;
- int intr_interval;
- struct urb *rx_urb, *tx_urb, *intr_urb;
- unsigned char ALIGN(rx_buff[CDC_ETHER_MAX_MTU]);
- unsigned char ALIGN(tx_buff[CDC_ETHER_MAX_MTU]);
- unsigned char ALIGN(intr_buff[8]);
-} ether_dev_t;
-
-#define REQ_HDR_FUNC_DESCR 0x0001
-#define REQ_UNION_FUNC_DESCR 0x0002
-#define REQ_ETH_FUNC_DESCR 0x0004
-#define REQUIREMENTS_TOTAL 0x0007
-
-
-
diff --git a/drivers/usb/class/hid-core.c b/drivers/usb/class/hid-core.c
deleted file mode 100644
index 245ad1a0b5af..000000000000
--- a/drivers/usb/class/hid-core.c
+++ /dev/null
@@ -1,1530 +0,0 @@
-/*
- * $Id: hid-core.c,v 1.42 2002/01/27 00:22:46 vojtech Exp $
- *
- * Copyright (c) 1999 Andreas Gal
- * Copyright (c) 2000-2001 Vojtech Pavlik
- *
- * USB HID support for Linux
- */
-
-/*
- * 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
- *
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/list.h>
-#include <linux/mm.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <asm/unaligned.h>
-#include <asm/byteorder.h>
-#include <linux/input.h>
-
-#undef DEBUG
-#undef DEBUG_DATA
-
-#include <linux/usb.h>
-
-#include "hid.h"
-#include <linux/hiddev.h>
-
-/*
- * Version Information
- */
-
-#define DRIVER_VERSION "v1.31"
-#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik <vojtech@ucw.cz>"
-#define DRIVER_DESC "USB HID core driver"
-#define DRIVER_LICENSE "GPL"
-
-static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick",
- "Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"};
-
-/*
- * Register a new report for a device.
- */
-
-static struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id)
-{
- struct hid_report_enum *report_enum = device->report_enum + type;
- struct hid_report *report;
-
- if (report_enum->report_id_hash[id])
- return report_enum->report_id_hash[id];
-
- if (!(report = kmalloc(sizeof(struct hid_report), GFP_KERNEL)))
- return NULL;
- memset(report, 0, sizeof(struct hid_report));
-
- if (id != 0) report_enum->numbered = 1;
-
- report->id = id;
- report->type = type;
- report->size = 0;
- report->device = device;
- report_enum->report_id_hash[id] = report;
-
- list_add_tail(&report->list, &report_enum->report_list);
-
- return report;
-}
-
-/*
- * Register a new field for this report.
- */
-
-static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values)
-{
- struct hid_field *field;
-
- if (report->maxfield == HID_MAX_FIELDS) {
- dbg("too many fields in report");
- return NULL;
- }
-
- if (!(field = kmalloc(sizeof(struct hid_field) + usages * sizeof(struct hid_usage)
- + values * sizeof(unsigned), GFP_KERNEL))) return NULL;
-
- memset(field, 0, sizeof(struct hid_field) + usages * sizeof(struct hid_usage)
- + values * sizeof(unsigned));
-
- report->field[report->maxfield] = field;
- field->usage = (struct hid_usage *)(field + 1);
- field->value = (unsigned *)(field->usage + usages);
- field->report = report;
- field->index = report->maxfield++;
-
- return field;
-}
-
-/*
- * Open a collection. The type/usage is pushed on the stack.
- */
-
-static int open_collection(struct hid_parser *parser, unsigned type)
-{
- struct hid_collection *collection;
- unsigned usage;
-
- usage = parser->local.usage[0];
-
- if (type == HID_COLLECTION_APPLICATION
- && parser->device->maxapplication < HID_MAX_APPLICATIONS)
- parser->device->application[parser->device->maxapplication++] = usage;
-
- if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) {
- dbg("collection stack overflow");
- return -1;
- }
-
- collection = parser->collection_stack + parser->collection_stack_ptr++;
- collection->type = type;
- collection->usage = usage;
-
- return 0;
-}
-
-/*
- * Close a collection.
- */
-
-static int close_collection(struct hid_parser *parser)
-{
- if (!parser->collection_stack_ptr) {
- dbg("collection stack underflow");
- return -1;
- }
- parser->collection_stack_ptr--;
- return 0;
-}
-
-/*
- * Climb up the stack, search for the specified collection type
- * and return the usage.
- */
-
-static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type)
-{
- int n;
- for (n = parser->collection_stack_ptr - 1; n >= 0; n--)
- if (parser->collection_stack[n].type == type)
- return parser->collection_stack[n].usage;
- return 0; /* we know nothing about this usage type */
-}
-
-/*
- * Add a usage to the temporary parser table.
- */
-
-static int hid_add_usage(struct hid_parser *parser, unsigned usage)
-{
- if (parser->local.usage_index >= HID_MAX_USAGES) {
- dbg("usage index exceeded");
- return -1;
- }
- parser->local.usage[parser->local.usage_index++] = usage;
- return 0;
-}
-
-/*
- * Register a new field for this report.
- */
-
-static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsigned flags)
-{
- struct hid_report *report;
- struct hid_field *field;
- int usages;
- unsigned offset;
- int i;
-
- if (!(report = hid_register_report(parser->device, report_type, parser->global.report_id))) {
- dbg("hid_register_report failed");
- return -1;
- }
-
- if (parser->global.logical_maximum <= parser->global.logical_minimum) {
- dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum);
- return -1;
- }
- usages = parser->local.usage_index;
-
- offset = report->size;
- report->size += parser->global.report_size * parser->global.report_count;
-
- if (usages == 0)
- return 0; /* ignore padding fields */
-
- if ((field = hid_register_field(report, usages, parser->global.report_count)) == NULL)
- return 0;
-
- field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL);
- field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL);
- field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION);
-
- for (i = 0; i < usages; i++)
- field->usage[i].hid = parser->local.usage[i];
-
- field->maxusage = usages;
- field->flags = flags;
- field->report_offset = offset;
- field->report_type = report_type;
- field->report_size = parser->global.report_size;
- field->report_count = parser->global.report_count;
- field->logical_minimum = parser->global.logical_minimum;
- field->logical_maximum = parser->global.logical_maximum;
- field->physical_minimum = parser->global.physical_minimum;
- field->physical_maximum = parser->global.physical_maximum;
- field->unit_exponent = parser->global.unit_exponent;
- field->unit = parser->global.unit;
-
- return 0;
-}
-
-/*
- * Read data value from item.
- */
-
-static __inline__ __u32 item_udata(struct hid_item *item)
-{
- switch (item->size) {
- case 1: return item->data.u8;
- case 2: return item->data.u16;
- case 4: return item->data.u32;
- }
- return 0;
-}
-
-static __inline__ __s32 item_sdata(struct hid_item *item)
-{
- switch (item->size) {
- case 1: return item->data.s8;
- case 2: return item->data.s16;
- case 4: return item->data.s32;
- }
- return 0;
-}
-
-/*
- * Process a global item.
- */
-
-static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
-{
- switch (item->tag) {
-
- case HID_GLOBAL_ITEM_TAG_PUSH:
-
- if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) {
- dbg("global enviroment stack overflow");
- return -1;
- }
-
- memcpy(parser->global_stack + parser->global_stack_ptr++,
- &parser->global, sizeof(struct hid_global));
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_POP:
-
- if (!parser->global_stack_ptr) {
- dbg("global enviroment stack underflow");
- return -1;
- }
-
- memcpy(&parser->global, parser->global_stack + --parser->global_stack_ptr,
- sizeof(struct hid_global));
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_USAGE_PAGE:
- parser->global.usage_page = item_udata(item);
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM:
- parser->global.logical_minimum = item_sdata(item);
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM:
- if (parser->global.logical_minimum < 0)
- parser->global.logical_maximum = item_sdata(item);
- else
- parser->global.logical_maximum = item_udata(item);
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM:
- parser->global.physical_minimum = item_sdata(item);
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM:
- if (parser->global.physical_minimum < 0)
- parser->global.physical_maximum = item_sdata(item);
- else
- parser->global.physical_maximum = item_udata(item);
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT:
- parser->global.unit_exponent = item_sdata(item);
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_UNIT:
- parser->global.unit = item_udata(item);
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
- if ((parser->global.report_size = item_udata(item)) > 32) {
- dbg("invalid report_size %d", parser->global.report_size);
- return -1;
- }
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_REPORT_COUNT:
- if ((parser->global.report_count = item_udata(item)) > HID_MAX_USAGES) {
- dbg("invalid report_count %d", parser->global.report_count);
- return -1;
- }
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_REPORT_ID:
- if ((parser->global.report_id = item_udata(item)) == 0) {
- dbg("report_id 0 is invalid");
- return -1;
- }
- return 0;
-
- default:
- dbg("unknown global tag 0x%x", item->tag);
- return -1;
- }
-}
-
-/*
- * Process a local item.
- */
-
-static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
-{
- __u32 data;
- unsigned n;
-
- if (item->size == 0) {
- dbg("item data expected for local item");
- return -1;
- }
-
- data = item_udata(item);
-
- switch (item->tag) {
-
- case HID_LOCAL_ITEM_TAG_DELIMITER:
-
- if (data) {
- /*
- * We treat items before the first delimiter
- * as global to all usage sets (branch 0).
- * In the moment we process only these global
- * items and the first delimiter set.
- */
- if (parser->local.delimiter_depth != 0) {
- dbg("nested delimiters");
- return -1;
- }
- parser->local.delimiter_depth++;
- parser->local.delimiter_branch++;
- } else {
- if (parser->local.delimiter_depth < 1) {
- dbg("bogus close delimiter");
- return -1;
- }
- parser->local.delimiter_depth--;
- }
- return 1;
-
- case HID_LOCAL_ITEM_TAG_USAGE:
-
- if (parser->local.delimiter_branch > 1) {
- dbg("alternative usage ignored");
- return 0;
- }
-
- if (item->size <= 2)
- data = (parser->global.usage_page << 16) + data;
-
- return hid_add_usage(parser, data);
-
- case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
-
- if (parser->local.delimiter_branch > 1) {
- dbg("alternative usage ignored");
- return 0;
- }
-
- if (item->size <= 2)
- data = (parser->global.usage_page << 16) + data;
-
- parser->local.usage_minimum = data;
- return 0;
-
- case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
-
- if (parser->local.delimiter_branch > 1) {
- dbg("alternative usage ignored");
- return 0;
- }
-
- if (item->size <= 2)
- data = (parser->global.usage_page << 16) + data;
-
- for (n = parser->local.usage_minimum; n <= data; n++)
- if (hid_add_usage(parser, n)) {
- dbg("hid_add_usage failed\n");
- return -1;
- }
- return 0;
-
- default:
-
- dbg("unknown local item tag 0x%x", item->tag);
- return 0;
- }
- return 0;
-}
-
-/*
- * Process a main item.
- */
-
-static int hid_parser_main(struct hid_parser *parser, struct hid_item *item)
-{
- __u32 data;
- int ret;
-
- data = item_udata(item);
-
- switch (item->tag) {
- case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION:
- ret = open_collection(parser, data & 3);
- break;
- case HID_MAIN_ITEM_TAG_END_COLLECTION:
- ret = close_collection(parser);
- break;
- case HID_MAIN_ITEM_TAG_INPUT:
- ret = hid_add_field(parser, HID_INPUT_REPORT, data);
- break;
- case HID_MAIN_ITEM_TAG_OUTPUT:
- ret = hid_add_field(parser, HID_OUTPUT_REPORT, data);
- break;
- case HID_MAIN_ITEM_TAG_FEATURE:
- ret = hid_add_field(parser, HID_FEATURE_REPORT, data);
- break;
- default:
- dbg("unknown main item tag 0x%x", item->tag);
- ret = 0;
- }
-
- memset(&parser->local, 0, sizeof(parser->local)); /* Reset the local parser environment */
-
- return ret;
-}
-
-/*
- * Process a reserved item.
- */
-
-static int hid_parser_reserved(struct hid_parser *parser, struct hid_item *item)
-{
- dbg("reserved item type, tag 0x%x", item->tag);
- return 0;
-}
-
-/*
- * Free a report and all registered fields. The field->usage and
- * field->value table's are allocated behind the field, so we need
- * only to free(field) itself.
- */
-
-static void hid_free_report(struct hid_report *report)
-{
- unsigned n;
-
- for (n = 0; n < report->maxfield; n++)
- kfree(report->field[n]);
- kfree(report);
-}
-
-/*
- * Free a device structure, all reports, and all fields.
- */
-
-static void hid_free_device(struct hid_device *device)
-{
- unsigned i,j;
-
- for (i = 0; i < HID_REPORT_TYPES; i++) {
- struct hid_report_enum *report_enum = device->report_enum + i;
-
- for (j = 0; j < 256; j++) {
- struct hid_report *report = report_enum->report_id_hash[j];
- if (report) hid_free_report(report);
- }
- }
-
- if (device->rdesc) kfree(device->rdesc);
-}
-
-/*
- * Fetch a report description item from the data stream. We support long
- * items, though they are not used yet.
- */
-
-static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
-{
- u8 b;
-
- if ((end - start) <= 0)
- return NULL;
-
- b = *start++;
-
- item->type = (b >> 2) & 3;
- item->tag = (b >> 4) & 15;
-
- if (item->tag == HID_ITEM_TAG_LONG) {
-
- item->format = HID_ITEM_FORMAT_LONG;
-
- if ((end - start) < 2)
- return NULL;
-
- item->size = *start++;
- item->tag = *start++;
-
- if ((end - start) < item->size)
- return NULL;
-
- item->data.longdata = start;
- start += item->size;
- return start;
- }
-
- item->format = HID_ITEM_FORMAT_SHORT;
- item->size = b & 3;
-
- switch (item->size) {
-
- case 0:
- return start;
-
- case 1:
- if ((end - start) < 1)
- return NULL;
- item->data.u8 = *start++;
- return start;
-
- case 2:
- if ((end - start) < 2)
- return NULL;
- item->data.u16 = le16_to_cpu(get_unaligned(((__u16*)start)++));
- return start;
-
- case 3:
- item->size++;
- if ((end - start) < 4)
- return NULL;
- item->data.u32 = le32_to_cpu(get_unaligned(((__u32*)start)++));
- return start;
- }
-
- return NULL;
-}
-
-/*
- * Parse a report description into a hid_device structure. Reports are
- * enumerated, fields are attached to these reports.
- */
-
-static struct hid_device *hid_parse_report(__u8 *start, unsigned size)
-{
- struct hid_device *device;
- struct hid_parser *parser;
- struct hid_item item;
- __u8 *end;
- unsigned i;
- static int (*dispatch_type[])(struct hid_parser *parser,
- struct hid_item *item) = {
- hid_parser_main,
- hid_parser_global,
- hid_parser_local,
- hid_parser_reserved
- };
-
- if (!(device = kmalloc(sizeof(struct hid_device), GFP_KERNEL)))
- return NULL;
- memset(device, 0, sizeof(struct hid_device));
-
- for (i = 0; i < HID_REPORT_TYPES; i++)
- INIT_LIST_HEAD(&device->report_enum[i].report_list);
-
- if (!(device->rdesc = (__u8 *)kmalloc(size, GFP_KERNEL))) {
- kfree(device);
- return NULL;
- }
- memcpy(device->rdesc, start, size);
-
- if (!(parser = kmalloc(sizeof(struct hid_parser), GFP_KERNEL))) {
- kfree(device->rdesc);
- kfree(device);
- return NULL;
- }
- memset(parser, 0, sizeof(struct hid_parser));
- parser->device = device;
-
- end = start + size;
- while ((start = fetch_item(start, end, &item)) != 0) {
-
- if (item.format != HID_ITEM_FORMAT_SHORT) {
- dbg("unexpected long global item");
- hid_free_device(device);
- kfree(parser);
- return NULL;
- }
-
- if (dispatch_type[item.type](parser, &item)) {
- dbg("item %u %u %u %u parsing failed\n",
- item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
- hid_free_device(device);
- kfree(parser);
- return NULL;
- }
-
- if (start == end) {
- if (parser->collection_stack_ptr) {
- dbg("unbalanced collection at end of report description");
- hid_free_device(device);
- kfree(parser);
- return NULL;
- }
- if (parser->local.delimiter_depth) {
- dbg("unbalanced delimiter at end of report description");
- hid_free_device(device);
- kfree(parser);
- return NULL;
- }
- kfree(parser);
- return device;
- }
- }
-
- dbg("item fetching failed at offset %d\n", (int)(end - start));
- hid_free_device(device);
- kfree(parser);
- return NULL;
-}
-
-/*
- * Convert a signed n-bit integer to signed 32-bit integer. Common
- * cases are done through the compiler, the screwed things has to be
- * done by hand.
- */
-
-static __inline__ __s32 snto32(__u32 value, unsigned n)
-{
- switch (n) {
- case 8: return ((__s8)value);
- case 16: return ((__s16)value);
- case 32: return ((__s32)value);
- }
- return value & (1 << (n - 1)) ? value | (-1 << n) : value;
-}
-
-/*
- * Convert a signed 32-bit integer to a signed n-bit integer.
- */
-
-static __inline__ __u32 s32ton(__s32 value, unsigned n)
-{
- __s32 a = value >> (n - 1);
- if (a && a != -1) return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1;
- return value & ((1 << n) - 1);
-}
-
-/*
- * Extract/implement a data field from/to a report.
- */
-
-static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
-{
- report += (offset >> 5) << 2; offset &= 31;
- return (le64_to_cpu(get_unaligned((__u64*)report)) >> offset) & ((1 << n) - 1);
-}
-
-static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value)
-{
- report += (offset >> 5) << 2; offset &= 31;
- put_unaligned((get_unaligned((__u64*)report)
- & cpu_to_le64(~((((__u64) 1 << n) - 1) << offset)))
- | cpu_to_le64((__u64)value << offset), (__u64*)report);
-}
-
-/*
- * Search an array for a value.
- */
-
-static __inline__ int search(__s32 *array, __s32 value, unsigned n)
-{
- while (n--) if (*array++ == value) return 0;
- return -1;
-}
-
-static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value)
-{
- hid_dump_input(usage, value);
- if (hid->claimed & HID_CLAIMED_INPUT)
- hidinput_hid_event(hid, field, usage, value);
-#ifdef CONFIG_USB_HIDDEV
- if (hid->claimed & HID_CLAIMED_HIDDEV) {
- struct hiddev_usage_ref uref;
- unsigned type = field->report_type;
- uref.report_type =
- (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT :
- ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT :
- ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0));
- uref.report_id = field->report->id;
- uref.field_index = field->index;
- uref.usage_index = (usage - field->usage);
- uref.usage_code = usage->hid;
- uref.value = value;
- hiddev_hid_event(hid, &uref);
- }
-#endif
-}
-
-/*
- * Analyse a received field, and fetch the data from it. The field
- * content is stored for next report processing (we do differential
- * reporting to the layer).
- */
-
-static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data)
-{
- unsigned n;
- unsigned count = field->report_count;
- unsigned offset = field->report_offset;
- unsigned size = field->report_size;
- __s32 min = field->logical_minimum;
- __s32 max = field->logical_maximum;
- __s32 value[count]; /* WARNING: gcc specific */
-
- for (n = 0; n < count; n++) {
-
- value[n] = min < 0 ? snto32(extract(data, offset + n * size, size), size) :
- extract(data, offset + n * size, size);
-
- if (!(field->flags & HID_MAIN_ITEM_VARIABLE) /* Ignore report if ErrorRollOver */
- && value[n] >= min && value[n] <= max
- && field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1)
- return;
- }
-
- for (n = 0; n < count; n++) {
-
- if (HID_MAIN_ITEM_VARIABLE & field->flags) {
-
- if (field->flags & HID_MAIN_ITEM_RELATIVE) {
- if (!value[n]) continue;
- } else {
- if (value[n] == field->value[n]) continue;
- }
- hid_process_event(hid, field, &field->usage[n], value[n]);
- continue;
- }
-
- if (field->value[n] >= min && field->value[n] <= max
- && field->usage[field->value[n] - min].hid
- && search(value, field->value[n], count))
- hid_process_event(hid, field, &field->usage[field->value[n] - min], 0);
-
- if (value[n] >= min && value[n] <= max
- && field->usage[value[n] - min].hid
- && search(field->value, value[n], count))
- hid_process_event(hid, field, &field->usage[value[n] - min], 1);
- }
-
- memcpy(field->value, value, count * sizeof(__s32));
-}
-
-static int hid_input_report(int type, struct urb *urb)
-{
- struct hid_device *hid = urb->context;
- struct hid_report_enum *report_enum = hid->report_enum + type;
- u8 *data = urb->transfer_buffer;
- int len = urb->actual_length;
- struct hid_report *report;
- int n, size;
-
- if (!len) {
- dbg("empty report");
- return -1;
- }
-
-#ifdef DEBUG_DATA
- printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", len, report_enum->numbered ? "" : "un");
-#endif
-
- n = 0; /* Normally report number is 0 */
- if (report_enum->numbered) { /* Device uses numbered reports, data[0] is report number */
- n = *data++;
- len--;
- }
-
-#ifdef DEBUG_DATA
- {
- int i;
- printk(KERN_DEBUG __FILE__ ": report %d (size %u) = ", n, len);
- for (i = 0; i < n; i++)
- printk(" %02x", data[i]);
- printk("\n");
- }
-#endif
-
- if (!(report = report_enum->report_id_hash[n])) {
- dbg("undefined report_id %d received", n);
- return -1;
- }
-
-#ifdef CONFIG_USB_HIDDEV
- /* Notify listeners that a report has been received */
- if (hid->claimed & HID_CLAIMED_HIDDEV) {
- struct hiddev_usage_ref uref;
- memset(&uref, 0, sizeof(uref));
- uref.report_type =
- (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT :
- ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT :
- ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0));
- uref.report_id = report->id;
- uref.field_index = HID_FIELD_INDEX_NONE;
- hiddev_hid_event(hid, &uref);
- }
-#endif
-
- size = ((report->size - 1) >> 3) + 1;
-
- if (len < size) {
- dbg("report %d is too short, (%d < %d)", report->id, len, size);
- return -1;
- }
-
- for (n = 0; n < report->maxfield; n++)
- hid_input_field(hid, report->field[n], data);
-
- return 0;
-}
-
-/*
- * Input interrupt completion handler.
- */
-
-static void hid_irq_in(struct urb *urb)
-{
- if (urb->status) {
- dbg("nonzero status in input irq %d", urb->status);
- return;
- }
-
- hid_input_report(HID_INPUT_REPORT, urb);
-}
-
-/*
- * Output the field into the report.
- */
-
-static void hid_output_field(struct hid_field *field, __u8 *data)
-{
- unsigned count = field->report_count;
- unsigned offset = field->report_offset;
- unsigned size = field->report_size;
- unsigned n;
-
- for (n = 0; n < count; n++) {
- if (field->logical_minimum < 0) /* signed values */
- implement(data, offset + n * size, size, s32ton(field->value[n], size));
- else /* unsigned values */
- implement(data, offset + n * size, size, field->value[n]);
- }
-}
-
-/*
- * Create a report.
- */
-
-void hid_output_report(struct hid_report *report, __u8 *data)
-{
- unsigned n;
- for (n = 0; n < report->maxfield; n++)
- hid_output_field(report->field[n], data);
-}
-
-/*
- * Set a field value. The report this field belongs to has to be
- * created and transfered to the device, to set this value in the
- * device.
- */
-
-int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
-{
- unsigned size = field->report_size;
-
- hid_dump_input(field->usage + offset, value);
-
- if (offset >= field->report_count) {
- dbg("offset (%d) exceeds report_count (%d)", offset, field->report_count);
- hid_dump_field(field, 8);
- return -1;
- }
- if (field->logical_minimum < 0) {
- if (value != snto32(s32ton(value, size), size)) {
- dbg("value %d is out of range", value);
- return -1;
- }
- }
- field->value[offset] = value;
- return 0;
-}
-
-int hid_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field)
-{
- struct hid_report_enum *report_enum = hid->report_enum + HID_OUTPUT_REPORT;
- struct list_head *list = report_enum->report_list.next;
- int i, j;
-
- while (list != &report_enum->report_list) {
- struct hid_report *report = (struct hid_report *) list;
- list = list->next;
- for (i = 0; i < report->maxfield; i++) {
- *field = report->field[i];
- for (j = 0; j < (*field)->maxusage; j++)
- if ((*field)->usage[j].type == type && (*field)->usage[j].code == code)
- return j;
- }
- }
- return -1;
-}
-
-/*
- * Find a report with a specified HID usage.
- */
-
-int hid_find_report_by_usage(struct hid_device *hid, __u32 wanted_usage, struct hid_report **report, int type)
-{
- struct hid_report_enum *report_enum = hid->report_enum + type;
- struct list_head *list = report_enum->report_list.next;
- int i, j;
-
- while (list != &report_enum->report_list) {
- *report = (struct hid_report *) list;
- list = list->next;
- for (i = 0; i < (*report)->maxfield; i++) {
- struct hid_field *field = (*report)->field[i];
- for (j = 0; j < field->maxusage; j++)
- if (field->logical == wanted_usage)
- return j;
- }
- }
- return -1;
-}
-
-int hid_find_field_in_report(struct hid_report *report, __u32 wanted_usage, struct hid_field **field)
-{
- int i, j;
-
- for (i = 0; i < report->maxfield; i++) {
- *field = report->field[i];
- for (j = 0; j < (*field)->maxusage; j++)
- if ((*field)->usage[j].hid == wanted_usage)
- return j;
- }
-
- return -1;
-}
-
-static int hid_submit_out(struct hid_device *hid)
-{
- struct hid_report *report;
-
- report = hid->out[hid->outtail];
-
- hid_output_report(report, hid->outbuf);
- hid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1;
- hid->urbout->dev = hid->dev;
-
- dbg("submitting out urb");
-
- if (usb_submit_urb(hid->urbout, GFP_ATOMIC)) {
- err("usb_submit_urb(out) failed");
- return -1;
- }
-
- return 0;
-}
-
-static int hid_submit_ctrl(struct hid_device *hid)
-{
- struct hid_report *report;
- unsigned char dir;
-
- report = hid->ctrl[hid->ctrltail].report;
- dir = hid->ctrl[hid->ctrltail].dir;
-
- if (dir == USB_DIR_OUT)
- hid_output_report(report, hid->ctrlbuf);
-
- hid->urbctrl->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + ((report->id > 0) && (dir != USB_DIR_OUT));
- hid->urbctrl->pipe = (dir == USB_DIR_OUT) ? usb_sndctrlpipe(hid->dev, 0) : usb_rcvctrlpipe(hid->dev, 0);
- hid->urbctrl->dev = hid->dev;
-
- hid->cr.bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir;
- hid->cr.bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : HID_REQ_GET_REPORT;
- hid->cr.wValue = ((report->type + 1) << 8) | report->id;
- hid->cr.wIndex = cpu_to_le16(hid->ifnum);
- hid->cr.wLength = cpu_to_le16(hid->urbctrl->transfer_buffer_length);
-
- dbg("submitting ctrl urb");
-
- if (usb_submit_urb(hid->urbctrl, GFP_ATOMIC)) {
- err("usb_submit_urb(ctrl) failed");
- return -1;
- }
-
- return 0;
-}
-
-/*
- * Output interrupt completion handler.
- */
-
-static void hid_irq_out(struct urb *urb)
-{
- struct hid_device *hid = urb->context;
- unsigned long flags;
-
- if (urb->status)
- warn("output irq status %d received", urb->status);
-
- spin_lock_irqsave(&hid->outlock, flags);
-
- hid->outtail = (hid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1);
-
- if (hid->outhead != hid->outtail) {
- hid_submit_out(hid);
- spin_unlock_irqrestore(&hid->outlock, flags);
- return;
- }
-
- clear_bit(HID_OUT_RUNNING, &hid->iofl);
-
- spin_unlock_irqrestore(&hid->outlock, flags);
-
- wake_up(&hid->wait);
-}
-
-/*
- * Control pipe completion handler.
- */
-
-static void hid_ctrl(struct urb *urb)
-{
- struct hid_device *hid = urb->context;
- unsigned long flags;
-
- if (urb->status)
- warn("ctrl urb status %d received", urb->status);
-
- spin_lock_irqsave(&hid->ctrllock, flags);
-
- if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN)
- hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb);
-
- hid->ctrltail = (hid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
-
- if (hid->ctrlhead != hid->ctrltail) {
- hid_submit_ctrl(hid);
- spin_unlock_irqrestore(&hid->ctrllock, flags);
- return;
- }
-
- clear_bit(HID_CTRL_RUNNING, &hid->iofl);
-
- spin_unlock_irqrestore(&hid->ctrllock, flags);
-
- wake_up(&hid->wait);
-}
-
-void hid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir)
-{
- int head;
- unsigned long flags;
-
- if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN)
- return;
-
- if (hid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) {
-
- spin_lock_irqsave(&hid->outlock, flags);
-
- if ((head = (hid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == hid->outtail) {
- spin_unlock_irqrestore(&hid->outlock, flags);
- warn("output queue full");
- return;
- }
-
- hid->out[hid->outhead] = report;
- hid->outhead = head;
-
- if (!test_and_set_bit(HID_OUT_RUNNING, &hid->iofl))
- hid_submit_out(hid);
-
- spin_unlock_irqrestore(&hid->outlock, flags);
- return;
- }
-
- spin_lock_irqsave(&hid->ctrllock, flags);
-
- if ((head = (hid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == hid->ctrltail) {
- spin_unlock_irqrestore(&hid->ctrllock, flags);
- warn("control queue full");
- return;
- }
-
- hid->ctrl[hid->ctrlhead].report = report;
- hid->ctrl[hid->ctrlhead].dir = dir;
- hid->ctrlhead = head;
-
- if (!test_and_set_bit(HID_CTRL_RUNNING, &hid->iofl))
- hid_submit_ctrl(hid);
-
- spin_unlock_irqrestore(&hid->ctrllock, flags);
-}
-
-int hid_wait_io(struct hid_device *hid)
-{
- DECLARE_WAITQUEUE(wait, current);
- int timeout = 10*HZ;
-
- set_current_state(TASK_UNINTERRUPTIBLE);
- add_wait_queue(&hid->wait, &wait);
-
- while (timeout && test_bit(HID_CTRL_RUNNING, &hid->iofl) &&
- test_bit(HID_OUT_RUNNING, &hid->iofl))
- timeout = schedule_timeout(timeout);
-
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&hid->wait, &wait);
-
- if (!timeout) {
- dbg("timeout waiting for ctrl or out queue to clear");
- return -1;
- }
-
- return 0;
-}
-
-static int hid_get_class_descriptor(struct usb_device *dev, int ifnum,
- unsigned char type, void *buf, int size)
-{
- return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN,
- (type << 8), ifnum, buf, size, HZ * USB_CTRL_GET_TIMEOUT);
-}
-
-int hid_open(struct hid_device *hid)
-{
- if (hid->open++)
- return 0;
-
- hid->urbin->dev = hid->dev;
-
- if (usb_submit_urb(hid->urbin, GFP_KERNEL))
- return -EIO;
-
- return 0;
-}
-
-void hid_close(struct hid_device *hid)
-{
- if (!--hid->open)
- usb_unlink_urb(hid->urbin);
-}
-
-/*
- * Initialize all reports
- */
-
-void hid_init_reports(struct hid_device *hid)
-{
- struct hid_report_enum *report_enum;
- struct hid_report *report;
- struct list_head *list;
- int len;
-
- report_enum = hid->report_enum + HID_INPUT_REPORT;
- list = report_enum->report_list.next;
- while (list != &report_enum->report_list) {
- report = (struct hid_report *) list;
- hid_submit_report(hid, report, USB_DIR_IN);
- list = list->next;
- }
-
- report_enum = hid->report_enum + HID_FEATURE_REPORT;
- list = report_enum->report_list.next;
- while (list != &report_enum->report_list) {
- report = (struct hid_report *) list;
- hid_submit_report(hid, report, USB_DIR_IN);
- list = list->next;
- }
-
- if (hid_wait_io(hid)) {
- warn("timeout initializing reports\n");
- return;
- }
-
- report_enum = hid->report_enum + HID_INPUT_REPORT;
- list = report_enum->report_list.next;
- while (list != &report_enum->report_list) {
- report = (struct hid_report *) list;
- len = ((report->size - 1) >> 3) + 1 + report_enum->numbered;
- if (len > hid->urbin->transfer_buffer_length)
- hid->urbin->transfer_buffer_length = len < HID_BUFFER_SIZE ? len : HID_BUFFER_SIZE;
- usb_control_msg(hid->dev, usb_sndctrlpipe(hid->dev, 0),
- 0x0a, USB_TYPE_CLASS | USB_RECIP_INTERFACE, report->id,
- hid->ifnum, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
- list = list->next;
- }
-}
-
-#define USB_VENDOR_ID_WACOM 0x056a
-#define USB_DEVICE_ID_WACOM_GRAPHIRE 0x0010
-#define USB_DEVICE_ID_WACOM_INTUOS 0x0020
-
-#define USB_VENDOR_ID_GRIFFIN 0x077d
-#define USB_DEVICE_ID_POWERMATE 0x0410
-#define USB_DEVICE_ID_SOUNDKNOB 0x04AA
-
-#define USB_VENDOR_ID_ATEN 0x0557
-#define USB_DEVICE_ID_ATEN_UC100KM 0x2004
-#define USB_DEVICE_ID_ATEN_CS124U 0x2202
-#define USB_DEVICE_ID_ATEN_2PORTKVM 0x2204
-
-struct hid_blacklist {
- __u16 idVendor;
- __u16 idProduct;
- unsigned quirks;
-} hid_blacklist[] = {
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 1, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 2, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 3, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 4, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
- { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
- { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
- { 0, 0 }
-};
-
-static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum)
-{
- struct usb_interface_descriptor *interface = dev->actconfig->interface[ifnum].altsetting + 0;
- struct hid_descriptor *hdesc;
- struct hid_device *hid;
- unsigned quirks = 0, rsize = 0;
- char *buf;
- int n;
-
- for (n = 0; hid_blacklist[n].idVendor; n++)
- if ((hid_blacklist[n].idVendor == dev->descriptor.idVendor) &&
- (hid_blacklist[n].idProduct == dev->descriptor.idProduct))
- quirks = hid_blacklist[n].quirks;
-
- if (quirks & HID_QUIRK_IGNORE)
- return NULL;
-
- if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) && ((!interface->bNumEndpoints) ||
- usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
- dbg("class descriptor not present\n");
- return NULL;
- }
-
- for (n = 0; n < hdesc->bNumDescriptors; n++)
- if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT)
- rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength);
-
- if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) {
- dbg("weird size of report descriptor (%u)", rsize);
- return NULL;
- }
-
- {
- __u8 rdesc[rsize];
-
- if ((n = hid_get_class_descriptor(dev, interface->bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) {
- dbg("reading report descriptor failed");
- return NULL;
- }
-
-#ifdef DEBUG_DATA
- printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n);
- for (n = 0; n < rsize; n++)
- printk(" %02x", (unsigned) rdesc[n]);
- printk("\n");
-#endif
-
- if (!(hid = hid_parse_report(rdesc, rsize))) {
- dbg("parsing report descriptor failed");
- return NULL;
- }
- }
-
- hid->quirks = quirks;
-
- for (n = 0; n < interface->bNumEndpoints; n++) {
-
- struct usb_endpoint_descriptor *endpoint = &interface->endpoint[n];
- int pipe;
-
- if ((endpoint->bmAttributes & 3) != 3) /* Not an interrupt endpoint */
- continue;
-
- if (endpoint->bEndpointAddress & USB_DIR_IN) {
- if (hid->urbin)
- continue;
- if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL)))
- goto fail;
- pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
- FILL_INT_URB(hid->urbin, dev, pipe, hid->inbuf, 0, hid_irq_in, hid, endpoint->bInterval);
- } else {
- if (hid->urbout)
- continue;
- if (!(hid->urbout = usb_alloc_urb(0, GFP_KERNEL)))
- goto fail;
- pipe = usb_sndbulkpipe(dev, endpoint->bEndpointAddress);
- FILL_BULK_URB(hid->urbout, dev, pipe, hid->outbuf, 0, hid_irq_out, hid);
- }
- }
-
- if (!hid->urbin) {
- err("couldn't find an input interrupt endpoint");
- goto fail;
- }
-
- init_waitqueue_head(&hid->wait);
-
- hid->outlock = SPIN_LOCK_UNLOCKED;
- hid->ctrllock = SPIN_LOCK_UNLOCKED;
-
- hid->version = hdesc->bcdHID;
- hid->country = hdesc->bCountryCode;
- hid->dev = dev;
- hid->ifnum = interface->bInterfaceNumber;
-
- hid->name[0] = 0;
-
- if (!(buf = kmalloc(64, GFP_KERNEL)))
- goto fail;
-
- if (usb_string(dev, dev->descriptor.iManufacturer, buf, 64) > 0) {
- strcat(hid->name, buf);
- if (usb_string(dev, dev->descriptor.iProduct, buf, 64) > 0)
- sprintf(hid->name, "%s %s", hid->name, buf);
- } else
- sprintf(hid->name, "%04x:%04x", dev->descriptor.idVendor, dev->descriptor.idProduct);
-
- usb_make_path(dev, buf, 63);
- sprintf(hid->phys, "%s/input%d", buf, ifnum);
-
- if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0)
- hid->uniq[0] = 0;
-
- kfree(buf);
-
- hid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);
- FILL_CONTROL_URB(hid->urbctrl, dev, 0, (void*) &hid->cr, hid->ctrlbuf, 1, hid_ctrl, hid);
-
- return hid;
-
-fail:
-
- hid_free_device(hid);
- if (hid->urbin) usb_free_urb(hid->urbin);
- if (hid->urbout) usb_free_urb(hid->urbout);
- if (hid->urbctrl) usb_free_urb(hid->urbctrl);
-
- return NULL;
-}
-
-static void* hid_probe(struct usb_device *dev, unsigned int ifnum,
- const struct usb_device_id *id)
-{
- struct hid_device *hid;
- char path[64];
- int i;
- char *c;
-
- dbg("HID probe called for ifnum %d", ifnum);
-
- if (!(hid = usb_hid_configure(dev, ifnum)))
- return NULL;
-
- hid_init_reports(hid);
- hid_dump_device(hid);
-
- if (!hidinput_connect(hid))
- hid->claimed |= HID_CLAIMED_INPUT;
- if (!hiddev_connect(hid))
- hid->claimed |= HID_CLAIMED_HIDDEV;
-
- if (!hid->claimed) {
- hid_free_device(hid);
- return NULL;
- }
-
- printk(KERN_INFO);
-
- if (hid->claimed & HID_CLAIMED_INPUT)
- printk("input");
- if (hid->claimed == (HID_CLAIMED_INPUT | HID_CLAIMED_HIDDEV))
- printk(",");
- if (hid->claimed & HID_CLAIMED_HIDDEV)
- printk("hiddev%d", hid->minor);
-
- c = "Device";
- for (i = 0; i < hid->maxapplication; i++)
- if ((hid->application[i] & 0xffff) < ARRAY_SIZE(hid_types)) {
- c = hid_types[hid->application[i] & 0xffff];
- break;
- }
-
- usb_make_path(dev, path, 63);
-
- printk(": USB HID v%x.%02x %s [%s] on %s\n",
- hid->version >> 8, hid->version & 0xff, c, hid->name, path);
-
- return hid;
-}
-
-static void hid_disconnect(struct usb_device *dev, void *ptr)
-{
- struct hid_device *hid = ptr;
-
- usb_unlink_urb(hid->urbin);
- usb_unlink_urb(hid->urbout);
- usb_unlink_urb(hid->urbctrl);
-
- if (hid->claimed & HID_CLAIMED_INPUT)
- hidinput_disconnect(hid);
- if (hid->claimed & HID_CLAIMED_HIDDEV)
- hiddev_disconnect(hid);
-
- usb_free_urb(hid->urbin);
- usb_free_urb(hid->urbctrl);
- if (hid->urbout)
- usb_free_urb(hid->urbout);
-
- hid_free_device(hid);
-}
-
-static struct usb_device_id hid_usb_ids [] = {
- { match_flags: USB_DEVICE_ID_MATCH_INT_CLASS,
- bInterfaceClass: USB_INTERFACE_CLASS_HID },
- { } /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, hid_usb_ids);
-
-static struct usb_driver hid_driver = {
- name: "hid",
- probe: hid_probe,
- disconnect: hid_disconnect,
- id_table: hid_usb_ids,
-};
-
-static int __init hid_init(void)
-{
- hiddev_init();
- usb_register(&hid_driver);
- info(DRIVER_VERSION ":" DRIVER_DESC);
-
- return 0;
-}
-
-static void __exit hid_exit(void)
-{
- hiddev_exit();
- usb_deregister(&hid_driver);
-}
-
-module_init(hid_init);
-module_exit(hid_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE(DRIVER_LICENSE);
diff --git a/drivers/usb/class/hid-debug.h b/drivers/usb/class/hid-debug.h
deleted file mode 100644
index ba2f9ef54937..000000000000
--- a/drivers/usb/class/hid-debug.h
+++ /dev/null
@@ -1,386 +0,0 @@
-/*
- * $Id: hid-debug.h,v 1.8 2001/09/25 09:37:57 vojtech Exp $
- *
- * (c) 1999 Andreas Gal <gal@cs.uni-magdeburg.de>
- * (c) 2000-2001 Vojtech Pavlik <vojtech@ucw.cz>
- *
- * Some debug stuff for the HID parser.
- */
-
-/*
- * 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
- *
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
- */
-
-struct hid_usage_entry {
- unsigned page;
- unsigned usage;
- char *description;
-};
-
-static struct hid_usage_entry hid_usage_table[] = {
- { 0, 0, "Undefined" },
- { 1, 0, "GenericDesktop" },
- {0, 0x01, "Pointer"},
- {0, 0x02, "Mouse"},
- {0, 0x04, "Joystick"},
- {0, 0x05, "GamePad"},
- {0, 0x06, "Keyboard"},
- {0, 0x07, "Keypad"},
- {0, 0x08, "MultiAxis"},
- {0, 0x30, "X"},
- {0, 0x31, "Y"},
- {0, 0x32, "Z"},
- {0, 0x33, "Rx"},
- {0, 0x34, "Ry"},
- {0, 0x35, "Rz"},
- {0, 0x36, "Slider"},
- {0, 0x37, "Dial"},
- {0, 0x38, "Wheel"},
- {0, 0x39, "HatSwitch"},
- {0, 0x3a, "CountedBuffer"},
- {0, 0x3b, "ByteCount"},
- {0, 0x3c, "MotionWakeup"},
- {0, 0x3d, "Start"},
- {0, 0x3e, "Select"},
- {0, 0x40, "Vx"},
- {0, 0x41, "Vy"},
- {0, 0x42, "Vz"},
- {0, 0x43, "Vbrx"},
- {0, 0x44, "Vbry"},
- {0, 0x45, "Vbrz"},
- {0, 0x46, "Vno"},
- {0, 0x80, "SystemControl"},
- {0, 0x81, "SystemPowerDown"},
- {0, 0x82, "SystemSleep"},
- {0, 0x83, "SystemWakeUp"},
- {0, 0x84, "SystemContextMenu"},
- {0, 0x85, "SystemMainMenu"},
- {0, 0x86, "SystemAppMenu"},
- {0, 0x87, "SystemMenuHelp"},
- {0, 0x88, "SystemMenuExit"},
- {0, 0x89, "SystemMenuSelect"},
- {0, 0x8a, "SystemMenuRight"},
- {0, 0x8b, "SystemMenuLeft"},
- {0, 0x8c, "SystemMenuUp"},
- {0, 0x8d, "SystemMenuDown"},
- {0, 0x90, "D-padUp"},
- {0, 0x91, "D-padDown"},
- {0, 0x92, "D-padRight"},
- {0, 0x93, "D-padLeft"},
- { 7, 0, "Keyboard" },
- { 8, 0, "LED" },
- { 9, 0, "Button" },
- { 10, 0, "Ordinal" },
- { 12, 0, "Hotkey" },
- { 13, 0, "Digitizers" },
- {0, 0x01, "Digitizer"},
- {0, 0x02, "Pen"},
- {0, 0x03, "LightPen"},
- {0, 0x04, "TouchScreen"},
- {0, 0x05, "TouchPad"},
- {0, 0x20, "Stylus"},
- {0, 0x21, "Puck"},
- {0, 0x22, "Finger"},
- {0, 0x30, "TipPressure"},
- {0, 0x31, "BarrelPressure"},
- {0, 0x32, "InRange"},
- {0, 0x33, "Touch"},
- {0, 0x34, "UnTouch"},
- {0, 0x35, "Tap"},
- {0, 0x39, "TabletFunctionKey"},
- {0, 0x3a, "ProgramChangeKey"},
- {0, 0x3c, "Invert"},
- {0, 0x42, "TipSwitch"},
- {0, 0x43, "SecondaryTipSwitch"},
- {0, 0x44, "BarrelSwitch"},
- {0, 0x45, "Eraser"},
- {0, 0x46, "TabletPick"},
- { 15, 0, "PhysicalInterfaceDevice" },
- {0, 0x00, "Undefined"},
- {0, 0x01, "Physical_Interface_Device"},
- {0, 0x20, "Normal"},
- {0, 0x21, "Set_Effect_Report"},
- {0, 0x22, "Effect_Block_Index"},
- {0, 0x23, "Parameter_Block_Offset"},
- {0, 0x24, "ROM_Flag"},
- {0, 0x25, "Effect_Type"},
- {0, 0x26, "ET_Constant_Force"},
- {0, 0x27, "ET_Ramp"},
- {0, 0x28, "ET_Custom_Force_Data"},
- {0, 0x30, "ET_Square"},
- {0, 0x31, "ET_Sine"},
- {0, 0x32, "ET_Triangle"},
- {0, 0x33, "ET_Sawtooth_Up"},
- {0, 0x34, "ET_Sawtooth_Down"},
- {0, 0x40, "ET_Spring"},
- {0, 0x41, "ET_Damper"},
- {0, 0x42, "ET_Inertia"},
- {0, 0x43, "ET_Friction"},
- {0, 0x50, "Duration"},
- {0, 0x51, "Sample_Period"},
- {0, 0x52, "Gain"},
- {0, 0x53, "Trigger_Button"},
- {0, 0x54, "Trigger_Repeat_Interval"},
- {0, 0x55, "Axes_Enable"},
- {0, 0x56, "Direction_Enable"},
- {0, 0x57, "Direction"},
- {0, 0x58, "Type_Specific_Block_Offset"},
- {0, 0x59, "Block_Type"},
- {0, 0x5A, "Set_Envelope_Report"},
- {0, 0x5B, "Attack_Level"},
- {0, 0x5C, "Attack_Time"},
- {0, 0x5D, "Fade_Level"},
- {0, 0x5E, "Fade_Time"},
- {0, 0x5F, "Set_Condition_Report"},
- {0, 0x60, "CP_Offset"},
- {0, 0x61, "Positive_Coefficient"},
- {0, 0x62, "Negative_Coefficient"},
- {0, 0x63, "Positive_Saturation"},
- {0, 0x64, "Negative_Saturation"},
- {0, 0x65, "Dead_Band"},
- {0, 0x66, "Download_Force_Sample"},
- {0, 0x67, "Isoch_Custom_Force_Enable"},
- {0, 0x68, "Custom_Force_Data_Report"},
- {0, 0x69, "Custom_Force_Data"},
- {0, 0x6A, "Custom_Force_Vendor_Defined_Data"},
- {0, 0x6B, "Set_Custom_Force_Report"},
- {0, 0x6C, "Custom_Force_Data_Offset"},
- {0, 0x6D, "Sample_Count"},
- {0, 0x6E, "Set_Periodic_Report"},
- {0, 0x6F, "Offset"},
- {0, 0x70, "Magnitude"},
- {0, 0x71, "Phase"},
- {0, 0x72, "Period"},
- {0, 0x73, "Set_Constant_Force_Report"},
- {0, 0x74, "Set_Ramp_Force_Report"},
- {0, 0x75, "Ramp_Start"},
- {0, 0x76, "Ramp_End"},
- {0, 0x77, "Effect_Operation_Report"},
- {0, 0x78, "Effect_Operation"},
- {0, 0x79, "Op_Effect_Start"},
- {0, 0x7A, "Op_Effect_Start_Solo"},
- {0, 0x7B, "Op_Effect_Stop"},
- {0, 0x7C, "Loop_Count"},
- {0, 0x7D, "Device_Gain_Report"},
- {0, 0x7E, "Device_Gain"},
- {0, 0x7F, "PID_Pool_Report"},
- {0, 0x80, "RAM_Pool_Size"},
- {0, 0x81, "ROM_Pool_Size"},
- {0, 0x82, "ROM_Effect_Block_Count"},
- {0, 0x83, "Simultaneous_Effects_Max"},
- {0, 0x84, "Pool_Alignment"},
- {0, 0x85, "PID_Pool_Move_Report"},
- {0, 0x86, "Move_Source"},
- {0, 0x87, "Move_Destination"},
- {0, 0x88, "Move_Length"},
- {0, 0x89, "PID_Block_Load_Report"},
- {0, 0x8B, "Block_Load_Status"},
- {0, 0x8C, "Block_Load_Success"},
- {0, 0x8D, "Block_Load_Full"},
- {0, 0x8E, "Block_Load_Error"},
- {0, 0x8F, "Block_Handle"},
- {0, 0x90, "PID_Block_Free_Report"},
- {0, 0x91, "Type_Specific_Block_Handle"},
- {0, 0x92, "PID_State_Report"},
- {0, 0x94, "Effect_Playing"},
- {0, 0x95, "PID_Device_Control_Report"},
- {0, 0x96, "PID_Device_Control"},
- {0, 0x97, "DC_Enable_Actuators"},
- {0, 0x98, "DC_Disable_Actuators"},
- {0, 0x99, "DC_Stop_All_Effects"},
- {0, 0x9A, "DC_Device_Reset"},
- {0, 0x9B, "DC_Device_Pause"},
- {0, 0x9C, "DC_Device_Continue"},
- {0, 0x9F, "Device_Paused"},
- {0, 0xA0, "Actuators_Enabled"},
- {0, 0xA4, "Safety_Switch"},
- {0, 0xA5, "Actuator_Override_Switch"},
- {0, 0xA6, "Actuator_Power"},
- {0, 0xA7, "Start_Delay"},
- {0, 0xA8, "Parameter_Block_Size"},
- {0, 0xA9, "Device_Managed_Pool"},
- {0, 0xAA, "Shared_Parameter_Blocks"},
- {0, 0xAB, "Create_New_Effect_Report"},
- {0, 0xAC, "RAM_Pool_Available"},
- { 0, 0, NULL }
-};
-
-static void resolv_usage_page(unsigned page) {
- struct hid_usage_entry *p;
-
- for (p = hid_usage_table; p->description; p++)
- if (p->page == page) {
- printk("%s", p->description);
- return;
- }
- printk("%04x", page);
-}
-
-static void resolv_usage(unsigned usage) {
- struct hid_usage_entry *p;
-
- resolv_usage_page(usage >> 16);
- printk(".");
- for (p = hid_usage_table; p->description; p++)
- if (p->page == (usage >> 16)) {
- for(++p; p->description && p->page == 0; p++)
- if (p->usage == (usage & 0xffff)) {
- printk("%s", p->description);
- return;
- }
- break;
- }
- printk("%04x", usage & 0xffff);
-}
-
-__inline__ static void tab(int n) {
- while (n--) printk(" ");
-}
-
-static void hid_dump_field(struct hid_field *field, int n) {
- int j;
-
- if (field->physical) {
- tab(n);
- printk("Physical(");
- resolv_usage(field->physical); printk(")\n");
- }
- if (field->logical) {
- tab(n);
- printk("Logical(");
- resolv_usage(field->logical); printk(")\n");
- }
- tab(n); printk("Usage(%d)\n", field->maxusage);
- for (j = 0; j < field->maxusage; j++) {
- tab(n+2);resolv_usage(field->usage[j].hid); printk("\n");
- }
- if (field->logical_minimum != field->logical_maximum) {
- tab(n); printk("Logical Minimum(%d)\n", field->logical_minimum);
- tab(n); printk("Logical Maximum(%d)\n", field->logical_maximum);
- }
- if (field->physical_minimum != field->physical_maximum) {
- tab(n); printk("Physical Minimum(%d)\n", field->physical_minimum);
- tab(n); printk("Physical Maximum(%d)\n", field->physical_maximum);
- }
- if (field->unit_exponent) {
- tab(n); printk("Unit Exponent(%d)\n", field->unit_exponent);
- }
- if (field->unit) {
- char *systems[5] = { "None", "SI Linear", "SI Rotation", "English Linear", "English Rotation" };
- char *units[5][8] = {
- { "None", "None", "None", "None", "None", "None", "None", "None" },
- { "None", "Centimeter", "Gram", "Seconds", "Kelvin", "Ampere", "Candela", "None" },
- { "None", "Radians", "Gram", "Seconds", "Kelvin", "Ampere", "Candela", "None" },
- { "None", "Inch", "Slug", "Seconds", "Fahrenheit", "Ampere", "Candela", "None" },
- { "None", "Degrees", "Slug", "Seconds", "Fahrenheit", "Ampere", "Candela", "None" }
- };
-
- int i;
- int sys;
- __u32 data = field->unit;
-
- /* First nibble tells us which system we're in. */
- sys = data & 0xf;
- data >>= 4;
-
- if(sys > 4) {
- tab(n); printk("Unit(Invalid)\n");
- }
- else {
- int earlier_unit = 0;
-
- tab(n); printk("Unit(%s : ", systems[sys]);
-
- for (i=1 ; i<sizeof(__u32)*2 ; i++) {
- char nibble = data & 0xf;
- data >>= 4;
- if (nibble != 0) {
- if(earlier_unit++ > 0)
- printk("*");
- printk("%s", units[sys][i]);
- if(nibble != 1) {
- /* This is a _signed_ nibble(!) */
-
- int val = nibble & 0x7;
- if(nibble & 0x08)
- val = -((0x7 & ~val) +1);
- printk("^%d", val);
- }
- }
- }
- printk(")\n");
- }
- }
- tab(n); printk("Report Size(%u)\n", field->report_size);
- tab(n); printk("Report Count(%u)\n", field->report_count);
- tab(n); printk("Report Offset(%u)\n", field->report_offset);
-
- tab(n); printk("Flags( ");
- j = field->flags;
- printk("%s", HID_MAIN_ITEM_CONSTANT & j ? "Constant " : "");
- printk("%s", HID_MAIN_ITEM_VARIABLE & j ? "Variable " : "Array ");
- printk("%s", HID_MAIN_ITEM_RELATIVE & j ? "Relative " : "Absolute ");
- printk("%s", HID_MAIN_ITEM_WRAP & j ? "Wrap " : "");
- printk("%s", HID_MAIN_ITEM_NONLINEAR & j ? "NonLinear " : "");
- printk("%s", HID_MAIN_ITEM_NO_PREFERRED & j ? "NoPrefferedState " : "");
- printk("%s", HID_MAIN_ITEM_NULL_STATE & j ? "NullState " : "");
- printk("%s", HID_MAIN_ITEM_VOLATILE & j ? "Volatile " : "");
- printk("%s", HID_MAIN_ITEM_BUFFERED_BYTE & j ? "BufferedByte " : "");
- printk(")\n");
-}
-
-static void hid_dump_device(struct hid_device *device) {
- struct hid_report_enum *report_enum;
- struct hid_report *report;
- struct list_head *list;
- unsigned i,k;
- static char *table[] = {"INPUT", "OUTPUT", "FEATURE"};
-
- for (i = 0; i < device->maxapplication; i++) {
- printk("Application(");
- resolv_usage(device->application[i]);
- printk(")\n");
- }
-
- for (i = 0; i < HID_REPORT_TYPES; i++) {
- report_enum = device->report_enum + i;
- list = report_enum->report_list.next;
- while (list != &report_enum->report_list) {
- report = (struct hid_report *) list;
- tab(2);
- printk("%s", table[i]);
- if (report->id)
- printk("(%d)", report->id);
- printk("[%s]", table[report->type]);
- printk("\n");
- for (k = 0; k < report->maxfield; k++) {
- tab(4);
- printk("Field(%d)\n", k);
- hid_dump_field(report->field[k], 6);
- }
- list = list->next;
- }
- }
-}
-
-static void hid_dump_input(struct hid_usage *usage, __s32 value) {
- printk("hid-debug: input ");
- resolv_usage(usage->hid);
- printk(" = %d\n", value);
-}
diff --git a/drivers/usb/class/hid-input.c b/drivers/usb/class/hid-input.c
deleted file mode 100644
index b45938b18cc8..000000000000
--- a/drivers/usb/class/hid-input.c
+++ /dev/null
@@ -1,460 +0,0 @@
-/*
- * $Id: hid-input.c,v 1.18 2001/11/07 09:01:18 vojtech Exp $
- *
- * Copyright (c) 2000-2001 Vojtech Pavlik
- *
- * USB HID to Linux Input mapping
- */
-
-/*
- * 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
- *
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/input.h>
-#include <linux/usb.h>
-
-#include "hid.h"
-
-#define unk KEY_UNKNOWN
-
-static unsigned char hid_keyboard[256] = {
- 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
- 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3,
- 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26,
- 27, 43, 84, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
- 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
- 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
- 72, 73, 82, 83, 86,127,116,117, 85, 89, 90, 91, 92, 93, 94, 95,
- 120,121,122,123,134,138,130,132,128,129,131,137,133,135,136,113,
- 115,114,unk,unk,unk,124,unk,181,182,183,184,185,186,187,188,189,
- 190,191,192,193,194,195,196,197,198,unk,unk,unk,unk,unk,unk,unk,
- unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
- unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
- unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
- unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
- 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
- 150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
-};
-
-static struct {
- __s32 x;
- __s32 y;
-} hid_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
-
-static void hidinput_configure_usage(struct hid_device *device, struct hid_field *field, struct hid_usage *usage)
-{
- struct input_dev *input = &device->input;
- int max;
- int is_abs = 0;
- unsigned long *bit;
-
- switch (usage->hid & HID_USAGE_PAGE) {
-
- case HID_UP_KEYBOARD:
-
- set_bit(EV_REP, input->evbit);
- usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
-
- if ((usage->hid & HID_USAGE) < 256) {
- if (!(usage->code = hid_keyboard[usage->hid & HID_USAGE]))
- return;
- clear_bit(usage->code, bit);
- } else
- usage->code = KEY_UNKNOWN;
-
- break;
-
- case HID_UP_BUTTON:
-
- usage->code = ((usage->hid - 1) & 0xf) + 0x100;
- usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
-
- switch (field->application) {
- case HID_GD_GAMEPAD: usage->code += 0x10;
- case HID_GD_JOYSTICK: usage->code += 0x10;
- case HID_GD_MOUSE: usage->code += 0x10; break;
- default:
- if (field->physical == HID_GD_POINTER)
- usage->code += 0x10;
- break;
- }
- break;
-
- case HID_UP_GENDESK:
-
- if ((usage->hid & 0xf0) == 0x80) { /* SystemControl */
- switch (usage->hid & 0xf) {
- case 0x1: usage->code = KEY_POWER; break;
- case 0x2: usage->code = KEY_SLEEP; break;
- case 0x3: usage->code = KEY_WAKEUP; break;
- default: usage->code = KEY_UNKNOWN; break;
- }
- usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
- break;
- }
-
- usage->code = usage->hid & 0xf;
-
- if (field->report_size == 1) {
- usage->code = BTN_MISC;
- usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
- break;
- }
-
- if (field->flags & HID_MAIN_ITEM_RELATIVE) {
- usage->type = EV_REL; bit = input->relbit; max = REL_MAX;
- break;
- }
-
- usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX;
-
- if (usage->hid == HID_GD_HATSWITCH) {
- usage->code = ABS_HAT0X;
- usage->hat_min = field->logical_minimum;
- usage->hat_max = field->logical_maximum;
- }
- break;
-
- case HID_UP_LED:
-
- usage->code = (usage->hid - 1) & 0xf;
- usage->type = EV_LED; bit = input->ledbit; max = LED_MAX;
- break;
-
- case HID_UP_DIGITIZER:
-
- switch (usage->hid & 0xff) {
-
- case 0x30: /* TipPressure */
-
- if (!test_bit(BTN_TOUCH, input->keybit)) {
- device->quirks |= HID_QUIRK_NOTOUCH;
- set_bit(EV_KEY, input->evbit);
- set_bit(BTN_TOUCH, input->keybit);
- }
- usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX;
- usage->code = ABS_PRESSURE;
- clear_bit(usage->code, bit);
- break;
-
- case 0x32: /* InRange */
-
- usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
- switch (field->physical & 0xff) {
- case 0x21: usage->code = BTN_TOOL_MOUSE; break;
- case 0x22: usage->code = BTN_TOOL_FINGER; break;
- default: usage->code = BTN_TOOL_PEN; break;
- }
- break;
-
- case 0x3c: /* Invert */
-
- usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
- usage->code = BTN_TOOL_RUBBER;
- clear_bit(usage->code, bit);
- break;
-
- case 0x33: /* Touch */
- case 0x42: /* TipSwitch */
- case 0x43: /* TipSwitch2 */
-
- device->quirks &= ~HID_QUIRK_NOTOUCH;
- usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
- usage->code = BTN_TOUCH;
- clear_bit(usage->code, bit);
- break;
-
- case 0x44: /* BarrelSwitch */
-
- usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
- usage->code = BTN_STYLUS;
- clear_bit(usage->code, bit);
- break;
-
- default: goto unknown;
- }
- break;
-
- case HID_UP_CONSUMER: /* USB HUT v1.1, pages 56-62 */
-
- set_bit(EV_REP, input->evbit);
- switch (usage->hid & HID_USAGE) {
- case 0x000: usage->code = 0; break;
- case 0x034: usage->code = KEY_SLEEP; break;
- case 0x036: usage->code = BTN_MISC; break;
- case 0x08a: usage->code = KEY_WWW; break;
- case 0x095: usage->code = KEY_HELP; break;
-
- case 0x0b0: usage->code = KEY_PLAY; break;
- case 0x0b1: usage->code = KEY_PAUSE; break;
- case 0x0b2: usage->code = KEY_RECORD; break;
- case 0x0b3: usage->code = KEY_FASTFORWARD; break;
- case 0x0b4: usage->code = KEY_REWIND; break;
- case 0x0b5: usage->code = KEY_NEXTSONG; break;
- case 0x0b6: usage->code = KEY_PREVIOUSSONG; break;
- case 0x0b7: usage->code = KEY_STOPCD; break;
- case 0x0b8: usage->code = KEY_EJECTCD; break;
- case 0x0cd: usage->code = KEY_PLAYPAUSE; break;
- case 0x0e0: is_abs = 1;
- usage->code = ABS_VOLUME;
- break;
- case 0x0e2: usage->code = KEY_MUTE; break;
- case 0x0e5: usage->code = KEY_BASSBOOST; break;
- case 0x0e9: usage->code = KEY_VOLUMEUP; break;
- case 0x0ea: usage->code = KEY_VOLUMEDOWN; break;
-
- case 0x183: usage->code = KEY_CONFIG; break;
- case 0x18a: usage->code = KEY_MAIL; break;
- case 0x192: usage->code = KEY_CALC; break;
- case 0x194: usage->code = KEY_FILE; break;
- case 0x21a: usage->code = KEY_UNDO; break;
- case 0x21b: usage->code = KEY_COPY; break;
- case 0x21c: usage->code = KEY_CUT; break;
- case 0x21d: usage->code = KEY_PASTE; break;
-
- case 0x221: usage->code = KEY_FIND; break;
- case 0x223: usage->code = KEY_HOMEPAGE; break;
- case 0x224: usage->code = KEY_BACK; break;
- case 0x225: usage->code = KEY_FORWARD; break;
- case 0x226: usage->code = KEY_STOP; break;
- case 0x227: usage->code = KEY_REFRESH; break;
- case 0x22a: usage->code = KEY_BOOKMARKS; break;
-
- default: usage->code = KEY_UNKNOWN; break;
- }
-
- if (is_abs) {
- usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX;
- } else {
- usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
- }
- break;
-
- case HID_UP_HPVENDOR: /* Reported on a Dutch layout HP5308 */
-
- set_bit(EV_REP, input->evbit);
- switch (usage->hid & HID_USAGE) {
- case 0x021: usage->code = KEY_PRINT; break;
- case 0x070: usage->code = KEY_HP; break;
- case 0x071: usage->code = KEY_CAMERA; break;
- case 0x072: usage->code = KEY_SOUND; break;
- case 0x073: usage->code = KEY_QUESTION; break;
-
- case 0x080: usage->code = KEY_EMAIL; break;
- case 0x081: usage->code = KEY_CHAT; break;
- case 0x082: usage->code = KEY_SEARCH; break;
- case 0x083: usage->code = KEY_CONNECT; break;
- case 0x084: usage->code = KEY_FINANCE; break;
- case 0x085: usage->code = KEY_SPORT; break;
- case 0x086: usage->code = KEY_SHOP; break;
-
- default: usage->code = KEY_UNKNOWN; break;
-
- }
-
- usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
- break;
-
- default:
- unknown:
-
- if (field->report_size == 1) {
-
- if (field->report->type == HID_OUTPUT_REPORT) {
- usage->code = LED_MISC;
- usage->type = EV_LED; bit = input->ledbit; max = LED_MAX;
- break;
- }
-
- usage->code = BTN_MISC;
- usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
- break;
- }
-
- if (field->flags & HID_MAIN_ITEM_RELATIVE) {
- usage->code = REL_MISC;
- usage->type = EV_REL; bit = input->relbit; max = REL_MAX;
- break;
- }
-
- usage->code = ABS_MISC;
- usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX;
- break;
- }
-
- set_bit(usage->type, input->evbit);
-
- while (usage->code <= max && test_and_set_bit(usage->code, bit)) {
- usage->code = find_next_zero_bit(bit, max + 1, usage->code);
- }
-
- if (usage->code > max) return;
-
- if (usage->type == EV_ABS) {
- int a = field->logical_minimum;
- int b = field->logical_maximum;
-
- input->absmin[usage->code] = a;
- input->absmax[usage->code] = b;
- input->absfuzz[usage->code] = (b - a) >> 8;
- input->absflat[usage->code] = (b - a) >> 4;
- }
-
- if (usage->hat_min != usage->hat_max) {
- int i;
- for (i = usage->code; i < usage->code + 2 && i <= max; i++) {
- input->absmax[i] = 1;
- input->absmin[i] = -1;
- input->absfuzz[i] = 0;
- input->absflat[i] = 0;
- }
- set_bit(usage->code + 1, input->absbit);
- }
-}
-
-void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value)
-{
- struct input_dev *input = &hid->input;
- int *quirks = &hid->quirks;
-
- if (usage->hat_min != usage->hat_max) {
- value = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1;
- if (value < 0 || value > 8) value = 0;
- input_event(input, usage->type, usage->code , hid_hat_to_axis[value].x);
- input_event(input, usage->type, usage->code + 1, hid_hat_to_axis[value].y);
- return;
- }
-
- if (usage->hid == (HID_UP_DIGITIZER | 0x003c)) { /* Invert */
- *quirks = value ? (*quirks | HID_QUIRK_INVERT) : (*quirks & ~HID_QUIRK_INVERT);
- return;
- }
-
- if (usage->hid == (HID_UP_DIGITIZER | 0x0032)) { /* InRange */
- if (value) {
- input_event(input, usage->type, (*quirks & HID_QUIRK_INVERT) ? BTN_TOOL_RUBBER : usage->code, 1);
- return;
- }
- input_event(input, usage->type, usage->code, 0);
- input_event(input, usage->type, BTN_TOOL_RUBBER, 0);
- return;
- }
-
- if (usage->hid == (HID_UP_DIGITIZER | 0x0030) && (*quirks & HID_QUIRK_NOTOUCH)) { /* Pressure */
- int a = field->logical_minimum;
- int b = field->logical_maximum;
- input_event(input, EV_KEY, BTN_TOUCH, value > a + ((b - a) >> 3));
- }
-
- if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UKNOWN */
- return;
-
- input_event(input, usage->type, usage->code, value);
-
- if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY))
- input_event(input, usage->type, usage->code, 0);
-}
-
-static int hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
-{
- struct hid_device *hid = dev->private;
- struct hid_field *field = NULL;
- int offset;
-
- if ((offset = hid_find_field(hid, type, code, &field)) == -1) {
- warn("event field not found");
- return -1;
- }
-
- hid_set_field(field, offset, value);
- hid_submit_report(hid, field->report, USB_DIR_OUT);
-
- return 0;
-}
-
-static int hidinput_open(struct input_dev *dev)
-{
- struct hid_device *hid = dev->private;
- return hid_open(hid);
-}
-
-static void hidinput_close(struct input_dev *dev)
-{
- struct hid_device *hid = dev->private;
- hid_close(hid);
-}
-
-/*
- * Register the input device; print a message.
- * Configure the input layer interface
- * Read all reports and initalize the absoulte field values.
- */
-
-int hidinput_connect(struct hid_device *hid)
-{
- struct usb_device *dev = hid->dev;
- struct hid_report_enum *report_enum;
- struct hid_report *report;
- struct list_head *list;
- int i, j, k;
-
- for (i = 0; i < hid->maxapplication; i++)
- if (IS_INPUT_APPLICATION(hid->application[i]))
- break;
-
- if (i == hid->maxapplication)
- return -1;
-
- hid->input.private = hid;
- hid->input.event = hidinput_input_event;
- hid->input.open = hidinput_open;
- hid->input.close = hidinput_close;
-
- hid->input.name = hid->name;
- hid->input.phys = hid->phys;
- hid->input.uniq = hid->uniq;
- hid->input.idbus = BUS_USB;
- hid->input.idvendor = dev->descriptor.idVendor;
- hid->input.idproduct = dev->descriptor.idProduct;
- hid->input.idversion = dev->descriptor.bcdDevice;
-
- for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
- report_enum = hid->report_enum + k;
- list = report_enum->report_list.next;
- while (list != &report_enum->report_list) {
- report = (struct hid_report *) list;
- for (i = 0; i < report->maxfield; i++)
- for (j = 0; j < report->field[i]->maxusage; j++)
- hidinput_configure_usage(hid, report->field[i], report->field[i]->usage + j);
- list = list->next;
- }
- }
-
- input_register_device(&hid->input);
-
- return 0;
-}
-
-void hidinput_disconnect(struct hid_device *hid)
-{
- input_unregister_device(&hid->input);
-}
diff --git a/drivers/usb/class/hid.h b/drivers/usb/class/hid.h
deleted file mode 100644
index 357e31bd3814..000000000000
--- a/drivers/usb/class/hid.h
+++ /dev/null
@@ -1,421 +0,0 @@
-#ifndef __HID_H
-#define __HID_H
-
-/*
- * $Id: hid.h,v 1.24 2001/12/27 10:37:41 vojtech Exp $
- *
- * Copyright (c) 1999 Andreas Gal
- * Copyright (c) 2000-2001 Vojtech Pavlik
- */
-
-/*
- * 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
- *
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/list.h>
-
-/*
- * USB HID (Human Interface Device) interface class code
- */
-
-#define USB_INTERFACE_CLASS_HID 3
-
-/*
- * HID class requests
- */
-
-#define HID_REQ_GET_REPORT 0x01
-#define HID_REQ_GET_IDLE 0x02
-#define HID_REQ_GET_PROTOCOL 0x03
-#define HID_REQ_SET_REPORT 0x09
-#define HID_REQ_SET_IDLE 0x0A
-#define HID_REQ_SET_PROTOCOL 0x0B
-
-/*
- * HID class descriptor types
- */
-
-#define HID_DT_HID (USB_TYPE_CLASS | 0x01)
-#define HID_DT_REPORT (USB_TYPE_CLASS | 0x02)
-#define HID_DT_PHYSICAL (USB_TYPE_CLASS | 0x03)
-
-/*
- * We parse each description item into this structure. Short items data
- * values are expanded to 32-bit signed int, long items contain a pointer
- * into the data area.
- */
-
-struct hid_item {
- unsigned format;
- __u8 size;
- __u8 type;
- __u8 tag;
- union {
- __u8 u8;
- __s8 s8;
- __u16 u16;
- __s16 s16;
- __u32 u32;
- __s32 s32;
- __u8 *longdata;
- } data;
-};
-
-/*
- * HID report item format
- */
-
-#define HID_ITEM_FORMAT_SHORT 0
-#define HID_ITEM_FORMAT_LONG 1
-
-/*
- * Special tag indicating long items
- */
-
-#define HID_ITEM_TAG_LONG 15
-
-/*
- * HID report descriptor item type (prefix bit 2,3)
- */
-
-#define HID_ITEM_TYPE_MAIN 0
-#define HID_ITEM_TYPE_GLOBAL 1
-#define HID_ITEM_TYPE_LOCAL 2
-#define HID_ITEM_TYPE_RESERVED 3
-
-/*
- * HID report descriptor main item tags
- */
-
-#define HID_MAIN_ITEM_TAG_INPUT 8
-#define HID_MAIN_ITEM_TAG_OUTPUT 9
-#define HID_MAIN_ITEM_TAG_FEATURE 11
-#define HID_MAIN_ITEM_TAG_BEGIN_COLLECTION 10
-#define HID_MAIN_ITEM_TAG_END_COLLECTION 12
-
-/*
- * HID report descriptor main item contents
- */
-
-#define HID_MAIN_ITEM_CONSTANT 0x001
-#define HID_MAIN_ITEM_VARIABLE 0x002
-#define HID_MAIN_ITEM_RELATIVE 0x004
-#define HID_MAIN_ITEM_WRAP 0x008
-#define HID_MAIN_ITEM_NONLINEAR 0x010
-#define HID_MAIN_ITEM_NO_PREFERRED 0x020
-#define HID_MAIN_ITEM_NULL_STATE 0x040
-#define HID_MAIN_ITEM_VOLATILE 0x080
-#define HID_MAIN_ITEM_BUFFERED_BYTE 0x100
-
-/*
- * HID report descriptor collection item types
- */
-
-#define HID_COLLECTION_PHYSICAL 0
-#define HID_COLLECTION_APPLICATION 1
-#define HID_COLLECTION_LOGICAL 2
-
-/*
- * HID report descriptor global item tags
- */
-
-#define HID_GLOBAL_ITEM_TAG_USAGE_PAGE 0
-#define HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM 1
-#define HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM 2
-#define HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM 3
-#define HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM 4
-#define HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT 5
-#define HID_GLOBAL_ITEM_TAG_UNIT 6
-#define HID_GLOBAL_ITEM_TAG_REPORT_SIZE 7
-#define HID_GLOBAL_ITEM_TAG_REPORT_ID 8
-#define HID_GLOBAL_ITEM_TAG_REPORT_COUNT 9
-#define HID_GLOBAL_ITEM_TAG_PUSH 10
-#define HID_GLOBAL_ITEM_TAG_POP 11
-
-/*
- * HID report descriptor local item tags
- */
-
-#define HID_LOCAL_ITEM_TAG_USAGE 0
-#define HID_LOCAL_ITEM_TAG_USAGE_MINIMUM 1
-#define HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM 2
-#define HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX 3
-#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MINIMUM 4
-#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MAXIMUM 5
-#define HID_LOCAL_ITEM_TAG_STRING_INDEX 7
-#define HID_LOCAL_ITEM_TAG_STRING_MINIMUM 8
-#define HID_LOCAL_ITEM_TAG_STRING_MAXIMUM 9
-#define HID_LOCAL_ITEM_TAG_DELIMITER 10
-
-/*
- * HID usage tables
- */
-
-#define HID_USAGE_PAGE 0xffff0000
-
-#define HID_UP_GENDESK 0x00010000
-#define HID_UP_KEYBOARD 0x00070000
-#define HID_UP_LED 0x00080000
-#define HID_UP_BUTTON 0x00090000
-#define HID_UP_ORDINAL 0x000a0000
-#define HID_UP_CONSUMER 0x000c0000
-#define HID_UP_DIGITIZER 0x000d0000
-#define HID_UP_PID 0x000f0000
-#define HID_UP_HPVENDOR 0xff7f0000
-
-#define HID_USAGE 0x0000ffff
-
-#define HID_GD_POINTER 0x00010001
-#define HID_GD_MOUSE 0x00010002
-#define HID_GD_JOYSTICK 0x00010004
-#define HID_GD_GAMEPAD 0x00010005
-#define HID_GD_HATSWITCH 0x00010039
-
-/*
- * HID report types --- Ouch! HID spec says 1 2 3!
- */
-
-#define HID_INPUT_REPORT 0
-#define HID_OUTPUT_REPORT 1
-#define HID_FEATURE_REPORT 2
-
-/*
- * HID device quirks.
- */
-
-#define HID_QUIRK_INVERT 0x01
-#define HID_QUIRK_NOTOUCH 0x02
-#define HID_QUIRK_IGNORE 0x04
-#define HID_QUIRK_NOGET 0x08
-
-/*
- * This is the global enviroment of the parser. This information is
- * persistent for main-items. The global enviroment can be saved and
- * restored with PUSH/POP statements.
- */
-
-struct hid_global {
- unsigned usage_page;
- __s32 logical_minimum;
- __s32 logical_maximum;
- __s32 physical_minimum;
- __s32 physical_maximum;
- __s32 unit_exponent;
- unsigned unit;
- unsigned report_id;
- unsigned report_size;
- unsigned report_count;
-};
-
-/*
- * This is the local enviroment. It is resistent up the next main-item.
- */
-
-#define HID_MAX_DESCRIPTOR_SIZE 4096
-#define HID_MAX_USAGES 1024
-#define HID_MAX_APPLICATIONS 16
-
-struct hid_local {
- unsigned usage[HID_MAX_USAGES]; /* usage array */
- unsigned usage_index;
- unsigned usage_minimum;
- unsigned delimiter_depth;
- unsigned delimiter_branch;
-};
-
-/*
- * This is the collection stack. We climb up the stack to determine
- * application and function of each field.
- */
-
-struct hid_collection {
- unsigned type;
- unsigned usage;
-};
-
-struct hid_usage {
- unsigned hid; /* hid usage code */
- __u16 code; /* input driver code */
- __u8 type; /* input driver type */
- __s8 hat_min; /* hat switch fun */
- __s8 hat_max; /* ditto */
-};
-
-struct hid_field {
- unsigned physical; /* physical usage for this field */
- unsigned logical; /* logical usage for this field */
- unsigned application; /* application usage for this field */
- struct hid_usage *usage; /* usage table for this function */
- unsigned maxusage; /* maximum usage index */
- unsigned flags; /* main-item flags (i.e. volatile,array,constant) */
- unsigned report_offset; /* bit offset in the report */
- unsigned report_size; /* size of this field in the report */
- unsigned report_count; /* number of this field in the report */
- unsigned report_type; /* (input,output,feature) */
- __s32 *value; /* last known value(s) */
- __s32 logical_minimum;
- __s32 logical_maximum;
- __s32 physical_minimum;
- __s32 physical_maximum;
- __s32 unit_exponent;
- unsigned unit;
- struct hid_report *report; /* associated report */
- unsigned index; /* index into report->field[] */
-};
-
-#define HID_MAX_FIELDS 64
-
-struct hid_report {
- struct list_head list;
- unsigned id; /* id of this report */
- unsigned type; /* report type */
- struct hid_field *field[HID_MAX_FIELDS]; /* fields of the report */
- unsigned maxfield; /* maximum valid field index */
- unsigned size; /* size of the report (bits) */
- struct hid_device *device; /* associated device */
-};
-
-struct hid_report_enum {
- unsigned numbered;
- struct list_head report_list;
- struct hid_report *report_id_hash[256];
-};
-
-#define HID_REPORT_TYPES 3
-
-#define HID_BUFFER_SIZE 32
-#define HID_CONTROL_FIFO_SIZE 64
-#define HID_OUTPUT_FIFO_SIZE 64
-
-struct hid_control_fifo {
- unsigned char dir;
- struct hid_report *report;
-};
-
-#define HID_CLAIMED_INPUT 1
-#define HID_CLAIMED_HIDDEV 2
-
-#define HID_CTRL_RUNNING 1
-#define HID_OUT_RUNNING 2
-
-struct hid_device { /* device report descriptor */
- __u8 *rdesc;
- unsigned rsize;
- unsigned application[HID_MAX_APPLICATIONS]; /* List of HID applications */
- unsigned maxapplication; /* Number of applications */
- unsigned version; /* HID version */
- unsigned country; /* HID country */
- struct hid_report_enum report_enum[HID_REPORT_TYPES];
-
- struct usb_device *dev; /* USB device */
- int ifnum; /* USB interface number */
-
- unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
-
- struct urb *urbin; /* Input URB */
- char inbuf[HID_BUFFER_SIZE]; /* Input buffer */
-
- struct urb *urbctrl; /* Control URB */
- struct usb_ctrlrequest cr; /* Control request struct */
- struct hid_control_fifo ctrl[HID_CONTROL_FIFO_SIZE]; /* Control fifo */
- unsigned char ctrlhead, ctrltail; /* Control fifo head & tail */
- char ctrlbuf[HID_BUFFER_SIZE]; /* Control buffer */
- spinlock_t ctrllock; /* Control fifo spinlock */
-
- struct urb *urbout; /* Output URB */
- struct hid_report *out[HID_CONTROL_FIFO_SIZE]; /* Output pipe fifo */
- unsigned char outhead, outtail; /* Output pipe fifo head & tail */
- char outbuf[HID_BUFFER_SIZE]; /* Output buffer */
- spinlock_t outlock; /* Output fifo spinlock */
-
- unsigned claimed; /* Claimed by hidinput, hiddev? */
- unsigned quirks; /* Various quirks the device can pull on us */
-
- struct input_dev input; /* The input structure */
- void *hiddev; /* The hiddev structure */
- int minor; /* Hiddev minor number */
-
- wait_queue_head_t wait; /* For sleeping */
-
- int open; /* is the device open by anyone? */
- char name[128]; /* Device name */
- char phys[64]; /* Device physical location */
- char uniq[64]; /* Device unique identifier (serial #) */
-};
-
-#define HID_GLOBAL_STACK_SIZE 4
-#define HID_COLLECTION_STACK_SIZE 4
-
-struct hid_parser {
- struct hid_global global;
- struct hid_global global_stack[HID_GLOBAL_STACK_SIZE];
- unsigned global_stack_ptr;
- struct hid_local local;
- struct hid_collection collection_stack[HID_COLLECTION_STACK_SIZE];
- unsigned collection_stack_ptr;
- struct hid_device *device;
-};
-
-struct hid_class_descriptor {
- __u8 bDescriptorType;
- __u16 wDescriptorLength;
-} __attribute__ ((packed));
-
-struct hid_descriptor {
- __u8 bLength;
- __u8 bDescriptorType;
- __u16 bcdHID;
- __u8 bCountryCode;
- __u8 bNumDescriptors;
-
- struct hid_class_descriptor desc[1];
-} __attribute__ ((packed));
-
-#ifdef DEBUG
-#include "hid-debug.h"
-#else
-#define hid_dump_input(a,b) do { } while (0)
-#define hid_dump_device(c) do { } while (0)
-#define hid_dump_field(a,b) do { } while (0)
-#endif
-
-#endif
-
-#ifdef CONFIG_USB_HIDINPUT
-/* Applications from HID Usage Tables 4/8/99 Version 1.1 */
-/* We ignore a few input applications that are not widely used */
-#define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || ( a == 0x00010080) || ( a == 0x000c0001))
-extern void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
-extern int hidinput_connect(struct hid_device *);
-extern void hidinput_disconnect(struct hid_device *);
-#else
-#define IS_INPUT_APPLICATION(a) (0)
-static inline void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) { }
-static inline int hidinput_connect(struct hid_device *hid) { return -ENODEV; }
-static inline void hidinput_disconnect(struct hid_device *hid) { }
-#endif
-
-int hid_open(struct hid_device *);
-void hid_close(struct hid_device *);
-int hid_find_field(struct hid_device *, unsigned int, unsigned int, struct hid_field **);
-int hid_set_field(struct hid_field *, unsigned, __s32);
-void hid_submit_report(struct hid_device *, struct hid_report *, unsigned char dir);
-void hid_init_reports(struct hid_device *hid);
diff --git a/drivers/usb/class/hiddev.c b/drivers/usb/class/hiddev.c
deleted file mode 100644
index 206531c7aef7..000000000000
--- a/drivers/usb/class/hiddev.c
+++ /dev/null
@@ -1,699 +0,0 @@
-/*
- * Copyright (c) 2001 Paul Stewart
- * Copyright (c) 2001 Vojtech Pavlik
- *
- * HID char devices, giving access to raw HID device events.
- *
- */
-
-/*
- * 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
- *
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to Paul Stewart <stewart@wetlogic.net>
- */
-
-#define HIDDEV_MINOR_BASE 96
-#define HIDDEV_MINORS 16
-#define HIDDEV_BUFFER_SIZE 64
-
-#include <linux/poll.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/smp_lock.h>
-#include <linux/input.h>
-#include <linux/usb.h>
-#include "hid.h"
-#include <linux/hiddev.h>
-
-struct hiddev {
- int exist;
- int open;
- int minor;
- wait_queue_head_t wait;
- devfs_handle_t devfs;
- struct hid_device *hid;
- struct hiddev_list *list;
-};
-
-struct hiddev_list {
- struct hiddev_usage_ref buffer[HIDDEV_BUFFER_SIZE];
- int head;
- int tail;
- unsigned flags;
- struct fasync_struct *fasync;
- struct hiddev *hiddev;
- struct hiddev_list *next;
-};
-
-static struct hiddev *hiddev_table[HIDDEV_MINORS];
-static devfs_handle_t hiddev_devfs_handle;
-
-/*
- * Find a report, given the report's type and ID. The ID can be specified
- * indirectly by REPORT_ID_FIRST (which returns the first report of the given
- * type) or by (REPORT_ID_NEXT | old_id), which returns the next report of the
- * given type which follows old_id.
- */
-static struct hid_report *
-hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo)
-{
- struct hid_report_enum *report_enum;
- struct list_head *list;
-
- if (rinfo->report_type < HID_REPORT_TYPE_MIN ||
- rinfo->report_type > HID_REPORT_TYPE_MAX) return NULL;
-
- report_enum = hid->report_enum +
- (rinfo->report_type - HID_REPORT_TYPE_MIN);
- if ((rinfo->report_id & ~HID_REPORT_ID_MASK) != 0) {
- switch (rinfo->report_id & ~HID_REPORT_ID_MASK) {
- case HID_REPORT_ID_FIRST:
- list = report_enum->report_list.next;
- if (list == &report_enum->report_list) return NULL;
- rinfo->report_id = ((struct hid_report *) list)->id;
- break;
-
- case HID_REPORT_ID_NEXT:
- list = (struct list_head *)
- report_enum->report_id_hash[rinfo->report_id &
- HID_REPORT_ID_MASK];
- if (list == NULL) return NULL;
- list = list->next;
- if (list == &report_enum->report_list) return NULL;
- rinfo->report_id = ((struct hid_report *) list)->id;
- break;
-
- default:
- return NULL;
- }
- }
-
- return report_enum->report_id_hash[rinfo->report_id];
-}
-
-/*
- * Perform an exhaustive search of the report table for a usage, given its
- * type and usage id.
- */
-static struct hid_field *
-hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref)
-{
- int i, j;
- struct hid_report *report;
- struct hid_report_enum *report_enum;
- struct list_head *list;
- struct hid_field *field;
-
- if (uref->report_type < HID_REPORT_TYPE_MIN ||
- uref->report_type > HID_REPORT_TYPE_MAX) return NULL;
-
- report_enum = hid->report_enum +
- (uref->report_type - HID_REPORT_TYPE_MIN);
- list = report_enum->report_list.next;
- while (list != &report_enum->report_list) {
- report = (struct hid_report *) list;
- for (i = 0; i < report->maxfield; i++) {
- field = report->field[i];
- for (j = 0; j < field->maxusage; j++) {
- if (field->usage[j].hid == uref->usage_code) {
- uref->report_id = report->id;
- uref->field_index = i;
- uref->usage_index = j;
- return field;
- }
- }
- }
- list = list->next;
- }
-
- return NULL;
-}
-
-/*
- * This is where hid.c calls into hiddev to pass an event that occurred over
- * the interrupt pipe
- */
-void hiddev_hid_event(struct hid_device *hid, struct hiddev_usage_ref *uref)
-{
- struct hiddev *hiddev = hid->hiddev;
- struct hiddev_list *list = hiddev->list;
-
- while (list) {
- if (uref->field_index != HID_FIELD_INDEX_NONE ||
- (list->flags & HIDDEV_FLAG_REPORT) != 0) {
- list->buffer[list->head] = *uref;
- list->head = (list->head + 1) &
- (HIDDEV_BUFFER_SIZE - 1);
- kill_fasync(&list->fasync, SIGIO, POLL_IN);
- }
-
- list = list->next;
- }
-
- wake_up_interruptible(&hiddev->wait);
-}
-
-/*
- * fasync file op
- */
-static int hiddev_fasync(int fd, struct file *file, int on)
-{
- int retval;
- struct hiddev_list *list = file->private_data;
- retval = fasync_helper(fd, file, on, &list->fasync);
- return retval < 0 ? retval : 0;
-}
-
-/*
- * De-allocate a hiddev structure
- */
-static void hiddev_cleanup(struct hiddev *hiddev)
-{
- devfs_unregister(hiddev->devfs);
- hiddev_table[hiddev->minor] = NULL;
- kfree(hiddev);
-}
-
-/*
- * release file op
- */
-static int hiddev_release(struct inode * inode, struct file * file)
-{
- struct hiddev_list *list = file->private_data;
- struct hiddev_list **listptr;
-
- listptr = &list->hiddev->list;
- hiddev_fasync(-1, file, 0);
-
- while (*listptr && (*listptr != list))
- listptr = &((*listptr)->next);
- *listptr = (*listptr)->next;
-
- if (!--list->hiddev->open) {
- if (list->hiddev->exist)
- hid_close(list->hiddev->hid);
- else
- hiddev_cleanup(list->hiddev);
- }
-
- kfree(list);
-
- return 0;
-}
-
-/*
- * open file op
- */
-static int hiddev_open(struct inode * inode, struct file * file) {
- struct hiddev_list *list;
-
- int i = minor(inode->i_rdev) - HIDDEV_MINOR_BASE;
-
- if (i >= HIDDEV_MINORS || !hiddev_table[i])
- return -ENODEV;
-
- if (!(list = kmalloc(sizeof(struct hiddev_list), GFP_KERNEL)))
- return -ENOMEM;
- memset(list, 0, sizeof(struct hiddev_list));
-
- list->hiddev = hiddev_table[i];
- list->next = hiddev_table[i]->list;
- hiddev_table[i]->list = list;
-
- file->private_data = list;
-
- if (!list->hiddev->open++)
- if (list->hiddev->exist)
- hid_open(hiddev_table[i]->hid);
-
- return 0;
-}
-
-/*
- * "write" file op
- */
-static ssize_t hiddev_write(struct file * file, const char * buffer,
- size_t count, loff_t *ppos)
-{
- return -EINVAL;
-}
-
-/*
- * "read" file op
- */
-static ssize_t hiddev_read(struct file * file, char * buffer, size_t count,
- loff_t *ppos)
-{
- DECLARE_WAITQUEUE(wait, current);
- struct hiddev_list *list = file->private_data;
- int event_size;
- int retval = 0;
-
- event_size = ((list->flags & HIDDEV_FLAG_UREF) != 0) ?
- sizeof(struct hiddev_usage_ref) : sizeof(struct hiddev_event);
-
- if (count < event_size) return 0;
-
- while (retval == 0) {
- if (list->head == list->tail) {
- add_wait_queue(&list->hiddev->wait, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
-
- while (list->head == list->tail) {
- if (file->f_flags & O_NONBLOCK) {
- retval = -EAGAIN;
- break;
- }
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
- if (!list->hiddev->exist) {
- retval = -EIO;
- break;
- }
-
- schedule();
- }
-
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&list->hiddev->wait, &wait);
- }
-
- if (retval)
- return retval;
-
-
- while (list->head != list->tail &&
- retval + event_size <= count) {
- if ((list->flags & HIDDEV_FLAG_UREF) == 0) {
- if (list->buffer[list->tail].field_index !=
- HID_FIELD_INDEX_NONE) {
- struct hiddev_event event;
- event.hid = list->buffer[list->tail].usage_code;
- event.value = list->buffer[list->tail].value;
- if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event)))
- return -EFAULT;
- retval += sizeof(struct hiddev_event);
- }
- } else {
- if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE ||
- (list->flags & HIDDEV_FLAG_REPORT) != 0) {
- if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref)))
- return -EFAULT;
- retval += sizeof(struct hiddev_usage_ref);
- }
- }
- list->tail = (list->tail + 1) & (HIDDEV_BUFFER_SIZE - 1);
- }
-
- }
-
- return retval;
-}
-
-/*
- * "poll" file op
- * No kernel lock - fine
- */
-static unsigned int hiddev_poll(struct file *file, poll_table *wait)
-{
- struct hiddev_list *list = file->private_data;
- poll_wait(file, &list->hiddev->wait, wait);
- if (list->head != list->tail)
- return POLLIN | POLLRDNORM;
- if (!list->hiddev->exist)
- return POLLERR | POLLHUP;
- return 0;
-}
-
-/*
- * "ioctl" file op
- */
-static int hiddev_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- struct hiddev_list *list = file->private_data;
- struct hiddev *hiddev = list->hiddev;
- struct hid_device *hid = hiddev->hid;
- struct usb_device *dev = hid->dev;
- struct hiddev_report_info rinfo;
- struct hiddev_usage_ref uref;
- struct hid_report *report;
- struct hid_field *field;
-
- if (!hiddev->exist) return -EIO;
-
- switch (cmd) {
-
- case HIDIOCGVERSION:
- return put_user(HID_VERSION, (int *) arg);
-
- case HIDIOCAPPLICATION:
- if (arg < 0 || arg >= hid->maxapplication)
- return -EINVAL;
- return hid->application[arg];
-
- case HIDIOCGDEVINFO:
- {
- struct hiddev_devinfo dinfo;
- dinfo.bustype = BUS_USB;
- dinfo.busnum = dev->bus->busnum;
- dinfo.devnum = dev->devnum;
- dinfo.ifnum = hid->ifnum;
- dinfo.vendor = dev->descriptor.idVendor;
- dinfo.product = dev->descriptor.idProduct;
- dinfo.version = dev->descriptor.bcdDevice;
- dinfo.num_applications = hid->maxapplication;
- return copy_to_user((void *) arg, &dinfo, sizeof(dinfo));
- }
-
- case HIDIOCGFLAG:
- return put_user(list->flags, (int *) arg);
-
- case HIDIOCSFLAG:
- {
- int newflags;
- if (get_user(newflags, (int *) arg))
- return -EFAULT;
-
- if ((newflags & ~HIDDEV_FLAGS) != 0 ||
- ((newflags & HIDDEV_FLAG_REPORT) != 0 &&
- (newflags & HIDDEV_FLAG_UREF) == 0))
- return -EINVAL;
-
- list->flags = newflags;
-
- return 0;
- }
-
- case HIDIOCGSTRING:
- {
- int idx, len;
- char *buf;
-
- if (get_user(idx, (int *) arg))
- return -EFAULT;
-
- if ((buf = kmalloc(HID_STRING_SIZE, GFP_KERNEL)) == NULL)
- return -ENOMEM;
-
- if ((len = usb_string(dev, idx, buf, HID_STRING_SIZE-1)) < 0) {
- kfree(buf);
- return -EINVAL;
- }
-
- if (copy_to_user((void *) (arg+sizeof(int)), buf, len+1)) {
- kfree(buf);
- return -EFAULT;
- }
-
- kfree(buf);
-
- return len;
- }
-
- case HIDIOCINITREPORT:
-
- hid_init_reports(hid);
-
- return 0;
-
- case HIDIOCGREPORT:
- if (copy_from_user(&rinfo, (void *) arg, sizeof(rinfo)))
- return -EFAULT;
-
- if (rinfo.report_type == HID_REPORT_TYPE_OUTPUT)
- return -EINVAL;
-
- if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
- return -EINVAL;
-
- hid_submit_report(hid, report, USB_DIR_IN);
-
- return 0;
-
- case HIDIOCSREPORT:
- if (copy_from_user(&rinfo, (void *) arg, sizeof(rinfo)))
- return -EFAULT;
-
- if (rinfo.report_type == HID_REPORT_TYPE_INPUT)
- return -EINVAL;
-
- if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
- return -EINVAL;
-
- hid_submit_report(hid, report, USB_DIR_OUT);
-
- return 0;
-
- case HIDIOCGREPORTINFO:
- if (copy_from_user(&rinfo, (void *) arg, sizeof(rinfo)))
- return -EFAULT;
-
- if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
- return -EINVAL;
-
- rinfo.num_fields = report->maxfield;
-
- return copy_to_user((void *) arg, &rinfo, sizeof(rinfo));
-
- case HIDIOCGFIELDINFO:
- {
- struct hiddev_field_info finfo;
- if (copy_from_user(&finfo, (void *) arg, sizeof(finfo)))
- return -EFAULT;
- rinfo.report_type = finfo.report_type;
- rinfo.report_id = finfo.report_id;
- if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
- return -EINVAL;
-
- if (finfo.field_index >= report->maxfield)
- return -EINVAL;
-
- field = report->field[finfo.field_index];
- memset(&finfo, 0, sizeof(finfo));
- finfo.report_type = rinfo.report_type;
- finfo.report_id = rinfo.report_id;
- finfo.field_index = field->report_count - 1;
- finfo.maxusage = field->maxusage;
- finfo.flags = field->flags;
- finfo.physical = field->physical;
- finfo.logical = field->logical;
- finfo.application = field->application;
- finfo.logical_minimum = field->logical_minimum;
- finfo.logical_maximum = field->logical_maximum;
- finfo.physical_minimum = field->physical_minimum;
- finfo.physical_maximum = field->physical_maximum;
- finfo.unit_exponent = field->unit_exponent;
- finfo.unit = field->unit;
-
- return copy_to_user((void *) arg, &finfo, sizeof(finfo));
- }
-
- case HIDIOCGUCODE:
- if (copy_from_user(&uref, (void *) arg, sizeof(uref)))
- return -EFAULT;
-
- rinfo.report_type = uref.report_type;
- rinfo.report_id = uref.report_id;
- if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
- return -EINVAL;
-
- if (uref.field_index >= report->maxfield)
- return -EINVAL;
-
- field = report->field[uref.field_index];
- if (uref.usage_index >= field->maxusage)
- return -EINVAL;
-
- uref.usage_code = field->usage[uref.usage_index].hid;
-
- return copy_to_user((void *) arg, &uref, sizeof(uref));
-
- case HIDIOCGUSAGE:
- case HIDIOCSUSAGE:
- if (copy_from_user(&uref, (void *) arg, sizeof(uref)))
- return -EFAULT;
-
- if (cmd == HIDIOCSUSAGE &&
- uref.report_type != HID_REPORT_TYPE_OUTPUT)
- return -EINVAL;
-
- if (uref.report_id == HID_REPORT_ID_UNKNOWN) {
- field = hiddev_lookup_usage(hid, &uref);
- if (field == NULL)
- return -EINVAL;
- } else {
- rinfo.report_type = uref.report_type;
- rinfo.report_id = uref.report_id;
- if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
- return -EINVAL;
-
- if (uref.field_index >= report->maxfield)
- return -EINVAL;
-
- field = report->field[uref.field_index];
- if (uref.usage_index >= field->maxusage)
- return -EINVAL;
- }
-
- if (cmd == HIDIOCGUSAGE) {
- uref.value = field->value[uref.usage_index];
- return copy_to_user((void *) arg, &uref, sizeof(uref));
- } else {
- field->value[uref.usage_index] = uref.value;
- }
-
- return 0;
-
- default:
-
- if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ)
- return -EINVAL;
-
- if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGNAME(0))) {
- int len;
- if (!hid->name) return 0;
- len = strlen(hid->name) + 1;
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user((char *) arg, hid->name, len) ?
- -EFAULT : len;
- }
- }
- return -EINVAL;
-}
-
-static struct file_operations hiddev_fops = {
- owner: THIS_MODULE,
- read: hiddev_read,
- write: hiddev_write,
- poll: hiddev_poll,
- open: hiddev_open,
- release: hiddev_release,
- ioctl: hiddev_ioctl,
- fasync: hiddev_fasync,
-};
-
-/*
- * This is where hid.c calls us to connect a hid device to the hiddev driver
- */
-int hiddev_connect(struct hid_device *hid)
-{
- struct hiddev *hiddev;
- int minor, i;
- char devfs_name[16];
-
- for (i = 0; i < hid->maxapplication; i++)
- if (!IS_INPUT_APPLICATION(hid->application[i]))
- break;
-
- if (i == hid->maxapplication)
- return -1;
-
- for (minor = 0; minor < HIDDEV_MINORS && hiddev_table[minor]; minor++);
- if (minor == HIDDEV_MINORS) {
- printk(KERN_ERR "hiddev: no more free hiddev devices\n");
- return -1;
- }
-
- if (!(hiddev = kmalloc(sizeof(struct hiddev), GFP_KERNEL)))
- return -1;
- memset(hiddev, 0, sizeof(struct hiddev));
-
- init_waitqueue_head(&hiddev->wait);
-
- hiddev->minor = minor;
- hiddev_table[minor] = hiddev;
-
- hiddev->hid = hid;
- hiddev->exist = 1;
-
- sprintf(devfs_name, "hiddev%d", minor);
- hiddev->devfs = devfs_register(hiddev_devfs_handle, devfs_name,
- DEVFS_FL_DEFAULT, USB_MAJOR,
- minor + HIDDEV_MINOR_BASE,
- S_IFCHR | S_IRUGO | S_IWUSR,
- &hiddev_fops, NULL);
- hid->minor = minor;
- hid->hiddev = hiddev;
-
- return 0;
-}
-
-/*
- * This is where hid.c calls us to disconnect a hiddev device from the
- * corresponding hid device (usually because the usb device has disconnected)
- */
-void hiddev_disconnect(struct hid_device *hid)
-{
- struct hiddev *hiddev = hid->hiddev;
-
- hiddev->exist = 0;
-
- if (hiddev->open) {
- hid_close(hiddev->hid);
- wake_up_interruptible(&hiddev->wait);
- } else {
- hiddev_cleanup(hiddev);
- }
-}
-
-/* Currently this driver is a USB driver. It's not a conventional one in
- * the sense that it doesn't probe at the USB level. Instead it waits to
- * be connected by HID through the hiddev_connect / hiddev_disconnect
- * routines. The reason to register as a USB device is to gain part of the
- * minor number space from the USB major.
- *
- * In theory, should the HID code be generalized to more than one physical
- * medium (say, IEEE 1384), this driver will probably need to register its
- * own major number, and in doing so, no longer need to register with USB.
- * At that point the probe routine and hiddev_driver struct below will no
- * longer be useful.
- */
-
-
-/* We never attach in this manner, and rely on HID to connect us. This
- * is why there is no disconnect routine defined in the usb_driver either.
- */
-static void *hiddev_usbd_probe(struct usb_device *dev, unsigned int ifnum,
- const struct usb_device_id *hiddev_info)
-{
- return NULL;
-}
-
-
-static /* const */ struct usb_driver hiddev_driver = {
- name: "hiddev",
- probe: hiddev_usbd_probe,
- fops: &hiddev_fops,
- minor: HIDDEV_MINOR_BASE
-};
-
-int __init hiddev_init(void)
-{
- hiddev_devfs_handle =
- devfs_mk_dir(devfs_find_handle(NULL, "usb", 0, 0, 0, 0), "hid", NULL);
- usb_register(&hiddev_driver);
- return 0;
-}
-
-void __exit hiddev_exit(void)
-{
- devfs_unregister(hiddev_devfs_handle);
- usb_deregister(&hiddev_driver);
-}
diff --git a/drivers/usb/class/storage/Makefile b/drivers/usb/class/storage/Makefile
deleted file mode 100644
index 0181d2e727ca..000000000000
--- a/drivers/usb/class/storage/Makefile
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# Makefile for the USB Mass Storage device drivers.
-#
-# 15 Aug 2000, Christoph Hellwig <hch@infradead.org>
-# Rewritten to use lists instead of if-statements.
-#
-
-O_TARGET := storage.o
-EXTRA_CFLAGS := -I../../../scsi/
-
-list-multi := usb-storage.o
-
-obj-$(CONFIG_USB_STORAGE) += usb-storage.o
-
-usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_HP8200e) += shuttle_usbat.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR09) += sddr09.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM) += freecom.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_SHUTTLE_SMARTMEDIA) += shuttle_sm.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_SHUTTLE_COMPACTFLASH) += shuttle_cf.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_DPCM) += dpcm.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_ISD200) += isd200.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o
-
-usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \
- initializers.o $(usb-storage-obj-y)
-
-include $(TOPDIR)/Rules.make
-
-usb-storage.o: $(usb-storage-objs)
- $(LD) -r -o $@ $(usb-storage-objs)
diff --git a/drivers/usb/class/storage/datafab.c b/drivers/usb/class/storage/datafab.c
deleted file mode 100644
index d1aca3be8627..000000000000
--- a/drivers/usb/class/storage/datafab.c
+++ /dev/null
@@ -1,806 +0,0 @@
-/* Driver for Datafab USB Compact Flash reader
- *
- * datafab driver v0.1:
- *
- * First release
- *
- * Current development and maintenance by:
- * (c) 2000 Jimmie Mayfield (mayfield+datafab@sackheads.org)
- * many thanks to Robert Baruch for the SanDisk SmartMedia reader driver
- * which I used as a template for this driver.
- * Some bugfixes and scatter-gather code by Gregory P. Smith
- * (greg-usb@electricrain.com)
- *
- * 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, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*
- * This driver attempts to support USB CompactFlash reader/writer devices
- * based on Datafab USB-to-ATA chips. It was specifically developed for the
- * Datafab MDCFE-B USB CompactFlash reader but has since been found to work
- * with a variety of Datafab-based devices from a number of manufacturers.
- * I've received a report of this driver working with a Datafab-based
- * SmartMedia device though please be aware that I'm personally unable to
- * test SmartMedia support.
- *
- * This driver supports reading and writing. If you're truly paranoid,
- * however, you can force the driver into a write-protected state by setting
- * the WP enable bits in datafab_handle_mode_sense(). Basically this means
- * setting mode_param_header[3] = 0x80.
- */
-
-#include "transport.h"
-#include "protocol.h"
-#include "usb.h"
-#include "debug.h"
-#include "datafab.h"
-
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-
-extern int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe,
- unsigned int len, unsigned int *act_len);
-
-static int datafab_determine_lun(struct us_data *us, struct datafab_info *info);
-
-
-static void datafab_dump_data(unsigned char *data, int len)
-{
- unsigned char buf[80];
- int sofar = 0;
-
- if (!data)
- return;
-
- memset(buf, 0, sizeof(buf));
-
- for (sofar = 0; sofar < len; sofar++) {
- sprintf(buf + strlen(buf), "%02x ",
- ((unsigned int) data[sofar]) & 0xFF);
-
- if (sofar % 16 == 15) {
- US_DEBUGP("datafab: %s\n", buf);
- memset(buf, 0, sizeof(buf));
- }
- }
-
- if (strlen(buf) != 0)
- US_DEBUGP("datafab: %s\n", buf);
-}
-
-
-static int datafab_raw_bulk(int direction,
- struct us_data *us,
- unsigned char *data,
- unsigned int len)
-{
- int result;
- int act_len;
- int pipe;
-
- if (direction == SCSI_DATA_READ)
- pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
- else
- pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
-
- result = usb_stor_bulk_msg(us, data, pipe, len, &act_len);
-
- // if we stall, we need to clear it before we go on
- if (result == -EPIPE) {
- US_DEBUGP("datafab_raw_bulk: EPIPE. clearing endpoint halt for"
- " pipe 0x%x, stalled at %d bytes\n", pipe, act_len);
- usb_clear_halt(us->pusb_dev, pipe);
- }
-
- if (result) {
- // NAK - that means we've retried a few times already
- if (result == -ETIMEDOUT) {
- US_DEBUGP("datafab_raw_bulk: device NAKed\n");
- return US_BULK_TRANSFER_FAILED;
- }
-
- // -ENOENT -- we canceled this transfer
- if (result == -ENOENT) {
- US_DEBUGP("datafab_raw_bulk: transfer aborted\n");
- return US_BULK_TRANSFER_ABORTED;
- }
-
- if (result == -EPIPE) {
- US_DEBUGP("datafab_raw_bulk: output pipe stalled\n");
- return USB_STOR_TRANSPORT_FAILED;
- }
-
- // the catch-all case
- US_DEBUGP("datafab_raw_bulk: unknown error\n");
- return US_BULK_TRANSFER_FAILED;
- }
-
- if (act_len != len) {
- US_DEBUGP("datafab_raw_bulk: Warning. Transferred only %d bytes\n", act_len);
- return US_BULK_TRANSFER_SHORT;
- }
-
- US_DEBUGP("datafab_raw_bulk: Transfered %d of %d bytes\n", act_len, len);
- return US_BULK_TRANSFER_GOOD;
-}
-
-static inline int datafab_bulk_read(struct us_data *us,
- unsigned char *data,
- unsigned int len)
-{
- if (len == 0)
- return USB_STOR_TRANSPORT_GOOD;
-
- US_DEBUGP("datafab_bulk_read: len = %d\n", len);
- return datafab_raw_bulk(SCSI_DATA_READ, us, data, len);
-}
-
-
-static inline int datafab_bulk_write(struct us_data *us,
- unsigned char *data,
- unsigned int len)
-{
- if (len == 0)
- return USB_STOR_TRANSPORT_GOOD;
-
- US_DEBUGP("datafab_bulk_write: len = %d\n", len);
- return datafab_raw_bulk(SCSI_DATA_WRITE, us, data, len);
-}
-
-
-static int datafab_read_data(struct us_data *us,
- struct datafab_info *info,
- u32 sector,
- u32 sectors,
- unsigned char *dest,
- int use_sg)
-{
- unsigned char command[8] = { 0, 0, 0, 0, 0, 0xE0, 0x20, 0x01 };
- unsigned char *buffer = NULL;
- unsigned char *ptr;
- unsigned char thistime;
- struct scatterlist *sg = NULL;
- int totallen, len, result;
- int sg_idx = 0, current_sg_offset = 0;
- int transferred, rc;
-
- // we're working in LBA mode. according to the ATA spec,
- // we can support up to 28-bit addressing. I don't know if Datafab
- // supports beyond 24-bit addressing. It's kind of hard to test
- // since it requires > 8GB CF card.
- //
- if (sectors > 0x0FFFFFFF)
- return USB_STOR_TRANSPORT_ERROR;
-
- if (info->lun == -1) {
- rc = datafab_determine_lun(us, info);
- if (rc != USB_STOR_TRANSPORT_GOOD)
- return rc;
- }
-
- command[5] += (info->lun << 4);
-
- // If we're using scatter-gather, we have to create a new
- // buffer to read all of the data in first, since a
- // scatter-gather buffer could in theory start in the middle
- // of a page, which would be bad. A developer who wants a
- // challenge might want to write a limited-buffer
- // version of this code.
-
- totallen = sectors * info->ssize;
-
- do {
- // loop, never allocate or transfer more than 64k at once (min(128k, 255*info->ssize) is the real limit)
- len = min_t(int, totallen, 65536);
-
- if (use_sg) {
- sg = (struct scatterlist *) dest;
- buffer = kmalloc(len, GFP_NOIO);
- if (buffer == NULL)
- return USB_STOR_TRANSPORT_ERROR;
- ptr = buffer;
- } else {
- ptr = dest;
- }
-
- thistime = (len / info->ssize) & 0xff;
-
- command[0] = 0;
- command[1] = thistime;
- command[2] = sector & 0xFF;
- command[3] = (sector >> 8) & 0xFF;
- command[4] = (sector >> 16) & 0xFF;
-
- command[5] |= (sector >> 24) & 0x0F;
-
- // send the command
- US_DEBUGP("datafab_read_data: sending following command\n");
- datafab_dump_data(command, sizeof(command));
-
- result = datafab_bulk_write(us, command, sizeof(command));
- if (result != USB_STOR_TRANSPORT_GOOD) {
- if (use_sg)
- kfree(buffer);
- return result;
- }
-
- // read the result
- result = datafab_bulk_read(us, ptr, len);
- if (result != USB_STOR_TRANSPORT_GOOD) {
- if (use_sg)
- kfree(buffer);
- return result;
- }
-
- US_DEBUGP("datafab_read_data results: %d bytes\n", len);
- // datafab_dump_data(ptr, len);
-
- sectors -= thistime;
- sector += thistime;
-
- if (use_sg) {
- transferred = 0;
- while (sg_idx < use_sg && transferred < len) {
- if (len - transferred >= sg[sg_idx].length - current_sg_offset) {
- US_DEBUGP("datafab_read_data: adding %d bytes to %d byte sg buffer\n", sg[sg_idx].length - current_sg_offset, sg[sg_idx].length);
- memcpy(sg[sg_idx].address + current_sg_offset,
- buffer + transferred,
- sg[sg_idx].length - current_sg_offset);
- transferred += sg[sg_idx].length - current_sg_offset;
- current_sg_offset = 0;
- // on to the next sg buffer
- ++sg_idx;
- } else {
- US_DEBUGP("datafab_read_data: adding %d bytes to %d byte sg buffer\n", len - transferred, sg[sg_idx].length);
- memcpy(sg[sg_idx].address + current_sg_offset,
- buffer + transferred,
- len - transferred);
- current_sg_offset += len - transferred;
- // this sg buffer is only partially full and we're out of data to copy in
- break;
- }
- }
- kfree(buffer);
- } else {
- dest += len;
- }
-
- totallen -= len;
- } while (totallen > 0);
-
- return USB_STOR_TRANSPORT_GOOD;
-}
-
-
-static int datafab_write_data(struct us_data *us,
- struct datafab_info *info,
- u32 sector,
- u32 sectors,
- unsigned char *src,
- int use_sg)
-{
- unsigned char command[8] = { 0, 0, 0, 0, 0, 0xE0, 0x30, 0x02 };
- unsigned char reply[2] = { 0, 0 };
- unsigned char *buffer = NULL;
- unsigned char *ptr;
- unsigned char thistime;
- struct scatterlist *sg = NULL;
- int totallen, len, result;
- int sg_idx = 0, current_sg_offset = 0;
- int transferred, rc;
-
- // we're working in LBA mode. according to the ATA spec,
- // we can support up to 28-bit addressing. I don't know if Datafab
- // supports beyond 24-bit addressing. It's kind of hard to test
- // since it requires > 8GB CF card.
- //
- if (sectors > 0x0FFFFFFF)
- return USB_STOR_TRANSPORT_ERROR;
-
- if (info->lun == -1) {
- rc = datafab_determine_lun(us, info);
- if (rc != USB_STOR_TRANSPORT_GOOD)
- return rc;
- }
-
- command[5] += (info->lun << 4);
-
- // If we're using scatter-gather, we have to create a new
- // buffer to read all of the data in first, since a
- // scatter-gather buffer could in theory start in the middle
- // of a page, which would be bad. A developer who wants a
- // challenge might want to write a limited-buffer
- // version of this code.
-
- totallen = sectors * info->ssize;
-
- do {
- // loop, never allocate or transfer more than 64k at once (min(128k, 255*info->ssize) is the real limit)
- len = min_t(int, totallen, 65536);
-
- if (use_sg) {
- sg = (struct scatterlist *) src;
- buffer = kmalloc(len, GFP_NOIO);
- if (buffer == NULL)
- return USB_STOR_TRANSPORT_ERROR;
- ptr = buffer;
-
- memset(buffer, 0, len);
-
- // copy the data from the sg bufs into the big contiguous buf
- //
- transferred = 0;
- while (transferred < len) {
- if (len - transferred >= sg[sg_idx].length - current_sg_offset) {
- US_DEBUGP("datafab_write_data: getting %d bytes from %d byte sg buffer\n", sg[sg_idx].length - current_sg_offset, sg[sg_idx].length);
- memcpy(ptr + transferred,
- sg[sg_idx].address + current_sg_offset,
- sg[sg_idx].length - current_sg_offset);
- transferred += sg[sg_idx].length - current_sg_offset;
- current_sg_offset = 0;
- // on to the next sg buffer
- ++sg_idx;
- } else {
- US_DEBUGP("datafab_write_data: getting %d bytes from %d byte sg buffer\n", len - transferred, sg[sg_idx].length);
- memcpy(ptr + transferred,
- sg[sg_idx].address + current_sg_offset,
- len - transferred);
- current_sg_offset += len - transferred;
- // we only copied part of this sg buffer
- break;
- }
- }
- } else {
- ptr = src;
- }
-
- thistime = (len / info->ssize) & 0xff;
-
- command[0] = 0;
- command[1] = thistime;
- command[2] = sector & 0xFF;
- command[3] = (sector >> 8) & 0xFF;
- command[4] = (sector >> 16) & 0xFF;
-
- command[5] |= (sector >> 24) & 0x0F;
-
- // send the command
- US_DEBUGP("datafab_write_data: sending following command\n");
- datafab_dump_data(command, sizeof(command));
-
- result = datafab_bulk_write(us, command, sizeof(command));
- if (result != USB_STOR_TRANSPORT_GOOD) {
- if (use_sg)
- kfree(buffer);
- return result;
- }
-
- // send the data
- result = datafab_bulk_write(us, ptr, len);
- if (result != USB_STOR_TRANSPORT_GOOD) {
- if (use_sg)
- kfree(buffer);
- return result;
- }
-
- // read the result
- result = datafab_bulk_read(us, reply, sizeof(reply));
- if (result != USB_STOR_TRANSPORT_GOOD) {
- if (use_sg)
- kfree(buffer);
- return result;
- }
-
- if (reply[0] != 0x50 && reply[1] != 0) {
- US_DEBUGP("datafab_write_data: Gah! write return code: %02x %02x\n", reply[0], reply[1]);
- if (use_sg)
- kfree(buffer);
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- sectors -= thistime;
- sector += thistime;
-
- if (use_sg) {
- kfree(buffer);
- } else {
- src += len;
- }
-
- totallen -= len;
- } while (totallen > 0);
-
- return USB_STOR_TRANSPORT_GOOD;
-}
-
-
-static int datafab_determine_lun(struct us_data *us,
- struct datafab_info *info)
-{
- // dual-slot readers can be thought of as dual-LUN devices. we need to
- // determine which card slot is being used. we'll send an IDENTIFY DEVICE
- // command and see which LUN responds...
- //
- // there might be a better way of doing this?
- //
- unsigned char command[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 };
- unsigned char buf[512];
- int count = 0, rc;
-
- if (!us || !info)
- return USB_STOR_TRANSPORT_ERROR;
-
- US_DEBUGP("datafab_determine_lun: locating...\n");
-
- // we'll try 10 times before giving up...
- //
- while (count++ < 10) {
- command[5] = 0xa0;
-
- rc = datafab_bulk_write(us, command, 8);
- if (rc != USB_STOR_TRANSPORT_GOOD)
- return rc;
-
- rc = datafab_bulk_read(us, buf, sizeof(buf));
- if (rc == USB_STOR_TRANSPORT_GOOD) {
- info->lun = 0;
- return USB_STOR_TRANSPORT_GOOD;
- }
-
- command[5] = 0xb0;
-
- rc = datafab_bulk_write(us, command, 8);
- if (rc != USB_STOR_TRANSPORT_GOOD)
- return rc;
-
- rc = datafab_bulk_read(us, buf, sizeof(buf));
- if (rc == USB_STOR_TRANSPORT_GOOD) {
- info->lun = 1;
- return USB_STOR_TRANSPORT_GOOD;
- }
-
- wait_ms(20);
- }
-
- return USB_STOR_TRANSPORT_FAILED;
-}
-
-static int datafab_id_device(struct us_data *us,
- struct datafab_info *info)
-{
- // this is a variation of the ATA "IDENTIFY DEVICE" command...according
- // to the ATA spec, 'Sector Count' isn't used but the Windows driver
- // sets this bit so we do too...
- //
- unsigned char command[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 };
- unsigned char reply[512];
- int rc;
-
- if (!us || !info)
- return USB_STOR_TRANSPORT_ERROR;
-
- if (info->lun == -1) {
- rc = datafab_determine_lun(us, info);
- if (rc != USB_STOR_TRANSPORT_GOOD)
- return rc;
- }
-
- command[5] += (info->lun << 4);
-
- rc = datafab_bulk_write(us, command, 8);
- if (rc != USB_STOR_TRANSPORT_GOOD)
- return rc;
-
- // we'll go ahead and extract the media capacity while we're here...
- //
- rc = datafab_bulk_read(us, reply, sizeof(reply));
- if (rc == USB_STOR_TRANSPORT_GOOD) {
- // capacity is at word offset 57-58
- //
- info->sectors = ((u32)(reply[117]) << 24) |
- ((u32)(reply[116]) << 16) |
- ((u32)(reply[115]) << 8) |
- ((u32)(reply[114]) );
- }
-
- return rc;
-}
-
-
-static int datafab_handle_mode_sense(struct us_data *us,
- Scsi_Cmnd * srb,
- unsigned char *ptr,
- int sense_6)
-{
- unsigned char mode_param_header[8] = {
- 0, 0, 0, 0, 0, 0, 0, 0
- };
- unsigned char rw_err_page[12] = {
- 0x1, 0xA, 0x21, 1, 0, 0, 0, 0, 1, 0, 0, 0
- };
- unsigned char cache_page[12] = {
- 0x8, 0xA, 0x1, 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
- unsigned char rbac_page[12] = {
- 0x1B, 0xA, 0, 0x81, 0, 0, 0, 0, 0, 0, 0, 0
- };
- unsigned char timer_page[8] = {
- 0x1C, 0x6, 0, 0, 0, 0
- };
- unsigned char pc, page_code;
- unsigned short total_len = 0;
- unsigned short param_len, i = 0;
-
- // most of this stuff is just a hack to get things working. the
- // datafab reader doesn't present a SCSI interface so we
- // fudge the SCSI commands...
- //
-
- if (sense_6)
- param_len = srb->cmnd[4];
- else
- param_len = ((u16) (srb->cmnd[7]) >> 8) | ((u16) (srb->cmnd[8]));
-
- pc = srb->cmnd[2] >> 6;
- page_code = srb->cmnd[2] & 0x3F;
-
- switch (pc) {
- case 0x0:
- US_DEBUGP("datafab_handle_mode_sense: Current values\n");
- break;
- case 0x1:
- US_DEBUGP("datafab_handle_mode_sense: Changeable values\n");
- break;
- case 0x2:
- US_DEBUGP("datafab_handle_mode_sense: Default values\n");
- break;
- case 0x3:
- US_DEBUGP("datafab_handle_mode_sense: Saves values\n");
- break;
- }
-
- mode_param_header[3] = 0x80; // write enable
-
- switch (page_code) {
- case 0x0:
- // vendor-specific mode
- return USB_STOR_TRANSPORT_ERROR;
-
- case 0x1:
- total_len = sizeof(rw_err_page);
- mode_param_header[0] = total_len >> 8;
- mode_param_header[1] = total_len & 0xFF;
- mode_param_header[3] = 0x00; // WP enable: 0x80
-
- memcpy(ptr, mode_param_header, sizeof(mode_param_header));
- i += sizeof(mode_param_header);
- memcpy(ptr + i, rw_err_page, sizeof(rw_err_page));
- break;
-
- case 0x8:
- total_len = sizeof(cache_page);
- mode_param_header[0] = total_len >> 8;
- mode_param_header[1] = total_len & 0xFF;
- mode_param_header[3] = 0x00; // WP enable: 0x80
-
- memcpy(ptr, mode_param_header, sizeof(mode_param_header));
- i += sizeof(mode_param_header);
- memcpy(ptr + i, cache_page, sizeof(cache_page));
- break;
-
- case 0x1B:
- total_len = sizeof(rbac_page);
- mode_param_header[0] = total_len >> 8;
- mode_param_header[1] = total_len & 0xFF;
- mode_param_header[3] = 0x00; // WP enable: 0x80
-
- memcpy(ptr, mode_param_header, sizeof(mode_param_header));
- i += sizeof(mode_param_header);
- memcpy(ptr + i, rbac_page, sizeof(rbac_page));
- break;
-
- case 0x1C:
- total_len = sizeof(timer_page);
- mode_param_header[0] = total_len >> 8;
- mode_param_header[1] = total_len & 0xFF;
- mode_param_header[3] = 0x00; // WP enable: 0x80
-
- memcpy(ptr, mode_param_header, sizeof(mode_param_header));
- i += sizeof(mode_param_header);
- memcpy(ptr + i, timer_page, sizeof(timer_page));
- break;
-
- case 0x3F: // retrieve all pages
- total_len = sizeof(timer_page) + sizeof(rbac_page) +
- sizeof(cache_page) + sizeof(rw_err_page);
- mode_param_header[0] = total_len >> 8;
- mode_param_header[1] = total_len & 0xFF;
- mode_param_header[3] = 0x00; // WP enable
-
- memcpy(ptr, mode_param_header, sizeof(mode_param_header));
- i += sizeof(mode_param_header);
- memcpy(ptr + i, timer_page, sizeof(timer_page));
- i += sizeof(timer_page);
- memcpy(ptr + i, rbac_page, sizeof(rbac_page));
- i += sizeof(rbac_page);
- memcpy(ptr + i, cache_page, sizeof(cache_page));
- i += sizeof(cache_page);
- memcpy(ptr + i, rw_err_page, sizeof(rw_err_page));
- break;
- }
-
- return USB_STOR_TRANSPORT_GOOD;
-}
-
-void datafab_info_destructor(void *extra)
-{
- // this routine is a placeholder...
- // currently, we don't allocate any extra memory so we're okay
-}
-
-
-// Transport for the Datafab MDCFE-B
-//
-int datafab_transport(Scsi_Cmnd * srb, struct us_data *us)
-{
- struct datafab_info *info;
- int rc;
- unsigned long block, blocks;
- unsigned char *ptr = NULL;
- unsigned char inquiry_reply[36] = {
- 0x00, 0x80, 0x00, 0x01, 0x1F, 0x00, 0x00, 0x00
- };
-
- if (!us->extra) {
- us->extra = kmalloc(sizeof(struct datafab_info), GFP_NOIO);
- if (!us->extra) {
- US_DEBUGP("datafab_transport: Gah! Can't allocate storage for Datafab info struct!\n");
- return USB_STOR_TRANSPORT_ERROR;
- }
- memset(us->extra, 0, sizeof(struct datafab_info));
- us->extra_destructor = datafab_info_destructor;
- ((struct datafab_info *)us->extra)->lun = -1;
- }
-
- info = (struct datafab_info *) (us->extra);
- ptr = (unsigned char *) srb->request_buffer;
-
- if (srb->cmnd[0] == INQUIRY) {
- US_DEBUGP("datafab_transport: INQUIRY. Returning bogus response");
- memset( inquiry_reply + 8, 0, 28 );
- fill_inquiry_response(us, inquiry_reply, 36);
- return USB_STOR_TRANSPORT_GOOD;
- }
-
- if (srb->cmnd[0] == READ_CAPACITY) {
- info->ssize = 0x200; // hard coded 512 byte sectors as per ATA spec
- rc = datafab_id_device(us, info);
- if (rc != USB_STOR_TRANSPORT_GOOD)
- return rc;
-
- US_DEBUGP("datafab_transport: READ_CAPACITY: %ld sectors, %ld bytes per sector\n",
- info->sectors, info->ssize);
-
- // build the reply
- //
- ptr[0] = (info->sectors >> 24) & 0xFF;
- ptr[1] = (info->sectors >> 16) & 0xFF;
- ptr[2] = (info->sectors >> 8) & 0xFF;
- ptr[3] = (info->sectors) & 0xFF;
-
- ptr[4] = (info->ssize >> 24) & 0xFF;
- ptr[5] = (info->ssize >> 16) & 0xFF;
- ptr[6] = (info->ssize >> 8) & 0xFF;
- ptr[7] = (info->ssize) & 0xFF;
-
- return USB_STOR_TRANSPORT_GOOD;
- }
-
- if (srb->cmnd[0] == MODE_SELECT_10) {
- US_DEBUGP("datafab_transport: Gah! MODE_SELECT_10.\n");
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- // don't bother implementing READ_6 or WRITE_6. Just set MODE_XLATE and
- // let the usb storage code convert to READ_10/WRITE_10
- //
- if (srb->cmnd[0] == READ_10) {
- block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
- ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5]));
-
- blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
-
- US_DEBUGP("datafab_transport: READ_10: read block 0x%04lx count %ld\n", block, blocks);
- return datafab_read_data(us, info, block, blocks, ptr, srb->use_sg);
- }
-
- if (srb->cmnd[0] == READ_12) {
- // we'll probably never see a READ_12 but we'll do it anyway...
- //
- block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
- ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5]));
-
- blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
- ((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9]));
-
- US_DEBUGP("datafab_transport: READ_12: read block 0x%04lx count %ld\n", block, blocks);
- return datafab_read_data(us, info, block, blocks, ptr, srb->use_sg);
- }
-
- if (srb->cmnd[0] == WRITE_10) {
- block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
- ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5]));
-
- blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
-
- US_DEBUGP("datafab_transport: WRITE_10: write block 0x%04lx count %ld\n", block, blocks);
- return datafab_write_data(us, info, block, blocks, ptr, srb->use_sg);
- }
-
- if (srb->cmnd[0] == WRITE_12) {
- // we'll probably never see a WRITE_12 but we'll do it anyway...
- //
- block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
- ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5]));
-
- blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
- ((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9]));
-
- US_DEBUGP("datafab_transport: WRITE_12: write block 0x%04lx count %ld\n", block, blocks);
- return datafab_write_data(us, info, block, blocks, ptr, srb->use_sg);
- }
-
- if (srb->cmnd[0] == TEST_UNIT_READY) {
- US_DEBUGP("datafab_transport: TEST_UNIT_READY.\n");
- return datafab_id_device(us, info);
- }
-
- if (srb->cmnd[0] == REQUEST_SENSE) {
- US_DEBUGP("datafab_transport: REQUEST_SENSE. Returning faked response\n");
-
- // this response is pretty bogus right now. eventually if necessary
- // we can set the correct sense data. so far though it hasn't been
- // necessary
- //
- ptr[0] = 0xF0;
- ptr[2] = info->sense_key;
- ptr[7] = 11;
- ptr[12] = info->sense_asc;
- ptr[13] = info->sense_ascq;
-
- return USB_STOR_TRANSPORT_GOOD;
- }
-
- if (srb->cmnd[0] == MODE_SENSE) {
- US_DEBUGP("datafab_transport: MODE_SENSE_6 detected\n");
- return datafab_handle_mode_sense(us, srb, ptr, TRUE);
- }
-
- if (srb->cmnd[0] == MODE_SENSE_10) {
- US_DEBUGP("datafab_transport: MODE_SENSE_10 detected\n");
- return datafab_handle_mode_sense(us, srb, ptr, FALSE);
- }
-
- if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
- // sure. whatever. not like we can stop the user from
- // popping the media out of the device (no locking doors, etc)
- //
- return USB_STOR_TRANSPORT_GOOD;
- }
-
- US_DEBUGP("datafab_transport: Gah! Unknown command: %d (0x%x)\n", srb->cmnd[0], srb->cmnd[0]);
- return USB_STOR_TRANSPORT_ERROR;
-}
diff --git a/drivers/usb/class/storage/datafab.h b/drivers/usb/class/storage/datafab.h
deleted file mode 100644
index 5515583ddce3..000000000000
--- a/drivers/usb/class/storage/datafab.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* Driver for Datafab MDCFE-B USB Compact Flash reader
- * Header File
- *
- * Current development and maintenance by:
- * (c) 2000 Jimmie Mayfield (mayfield+datafab@sackheads.org)
- *
- * See datafab.c for more explanation
- *
- * 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, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _USB_DATAFAB_MDCFE_B_H
-#define _USB_DATAFAB_MDCFE_B_H
-
-extern int datafab_transport(Scsi_Cmnd *srb, struct us_data *us);
-
-struct datafab_info {
- unsigned long sectors; // total sector count
- unsigned long ssize; // sector size in bytes
- char lun; // used for dual-slot readers
-
- // the following aren't used yet
- unsigned char sense_key;
- unsigned long sense_asc; // additional sense code
- unsigned long sense_ascq; // additional sense code qualifier
-};
-
-#endif
diff --git a/drivers/usb/class/storage/debug.c b/drivers/usb/class/storage/debug.c
deleted file mode 100644
index 3556bfd41500..000000000000
--- a/drivers/usb/class/storage/debug.c
+++ /dev/null
@@ -1,369 +0,0 @@
-/* Driver for USB Mass Storage compliant devices
- * Debugging Functions Source Code File
- *
- * $Id: debug.c,v 1.5 2001/06/27 23:20:45 mdharm Exp $
- *
- * Current development and maintenance by:
- * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
- *
- * Initial work by:
- * (c) 1999 Michael Gee (michael@linuxspecific.com)
- *
- * This driver is based on the 'USB Mass Storage Class' document. This
- * describes in detail the protocol used to communicate with such
- * devices. Clearly, the designers had SCSI and ATAPI commands in
- * mind when they created this document. The commands are all very
- * similar to commands in the SCSI-II and ATAPI specifications.
- *
- * It is important to note that in a number of cases this class
- * exhibits class-specific exemptions from the USB specification.
- * Notably the usage of NAK, STALL and ACK differs from the norm, in
- * that they are used to communicate wait, failed and OK on commands.
- *
- * Also, for certain devices, the interrupt endpoint is used to convey
- * status of a command.
- *
- * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more
- * information about this driver.
- *
- * 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, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include "debug.h"
-
-void usb_stor_show_command(Scsi_Cmnd *srb)
-{
- char *what = NULL;
-
- switch (srb->cmnd[0]) {
- case TEST_UNIT_READY: what = "TEST_UNIT_READY"; break;
- case REZERO_UNIT: what = "REZERO_UNIT"; break;
- case REQUEST_SENSE: what = "REQUEST_SENSE"; break;
- case FORMAT_UNIT: what = "FORMAT_UNIT"; break;
- case READ_BLOCK_LIMITS: what = "READ_BLOCK_LIMITS"; break;
- case REASSIGN_BLOCKS: what = "REASSIGN_BLOCKS"; break;
- case READ_6: what = "READ_6"; break;
- case WRITE_6: what = "WRITE_6"; break;
- case SEEK_6: what = "SEEK_6"; break;
- case READ_REVERSE: what = "READ_REVERSE"; break;
- case WRITE_FILEMARKS: what = "WRITE_FILEMARKS"; break;
- case SPACE: what = "SPACE"; break;
- case INQUIRY: what = "INQUIRY"; break;
- case RECOVER_BUFFERED_DATA: what = "RECOVER_BUFFERED_DATA"; break;
- case MODE_SELECT: what = "MODE_SELECT"; break;
- case RESERVE: what = "RESERVE"; break;
- case RELEASE: what = "RELEASE"; break;
- case COPY: what = "COPY"; break;
- case ERASE: what = "ERASE"; break;
- case MODE_SENSE: what = "MODE_SENSE"; break;
- case START_STOP: what = "START_STOP"; break;
- case RECEIVE_DIAGNOSTIC: what = "RECEIVE_DIAGNOSTIC"; break;
- case SEND_DIAGNOSTIC: what = "SEND_DIAGNOSTIC"; break;
- case ALLOW_MEDIUM_REMOVAL: what = "ALLOW_MEDIUM_REMOVAL"; break;
- case SET_WINDOW: what = "SET_WINDOW"; break;
- case READ_CAPACITY: what = "READ_CAPACITY"; break;
- case READ_10: what = "READ_10"; break;
- case WRITE_10: what = "WRITE_10"; break;
- case SEEK_10: what = "SEEK_10"; break;
- case WRITE_VERIFY: what = "WRITE_VERIFY"; break;
- case VERIFY: what = "VERIFY"; break;
- case SEARCH_HIGH: what = "SEARCH_HIGH"; break;
- case SEARCH_EQUAL: what = "SEARCH_EQUAL"; break;
- case SEARCH_LOW: what = "SEARCH_LOW"; break;
- case SET_LIMITS: what = "SET_LIMITS"; break;
- case READ_POSITION: what = "READ_POSITION"; break;
- case SYNCHRONIZE_CACHE: what = "SYNCHRONIZE_CACHE"; break;
- case LOCK_UNLOCK_CACHE: what = "LOCK_UNLOCK_CACHE"; break;
- case READ_DEFECT_DATA: what = "READ_DEFECT_DATA"; break;
- case MEDIUM_SCAN: what = "MEDIUM_SCAN"; break;
- case COMPARE: what = "COMPARE"; break;
- case COPY_VERIFY: what = "COPY_VERIFY"; break;
- case WRITE_BUFFER: what = "WRITE_BUFFER"; break;
- case READ_BUFFER: what = "READ_BUFFER"; break;
- case UPDATE_BLOCK: what = "UPDATE_BLOCK"; break;
- case READ_LONG: what = "READ_LONG"; break;
- case WRITE_LONG: what = "WRITE_LONG"; break;
- case CHANGE_DEFINITION: what = "CHANGE_DEFINITION"; break;
- case WRITE_SAME: what = "WRITE_SAME"; break;
- case GPCMD_READ_SUBCHANNEL: what = "READ SUBCHANNEL"; break;
- case READ_TOC: what = "READ_TOC"; break;
- case GPCMD_READ_HEADER: what = "READ HEADER"; break;
- case GPCMD_PLAY_AUDIO_10: what = "PLAY AUDIO (10)"; break;
- case GPCMD_PLAY_AUDIO_MSF: what = "PLAY AUDIO MSF"; break;
- case GPCMD_GET_EVENT_STATUS_NOTIFICATION:
- what = "GET EVENT/STATUS NOTIFICATION"; break;
- case GPCMD_PAUSE_RESUME: what = "PAUSE/RESUME"; break;
- case LOG_SELECT: what = "LOG_SELECT"; break;
- case LOG_SENSE: what = "LOG_SENSE"; break;
- case GPCMD_STOP_PLAY_SCAN: what = "STOP PLAY/SCAN"; break;
- case GPCMD_READ_DISC_INFO: what = "READ DISC INFORMATION"; break;
- case GPCMD_READ_TRACK_RZONE_INFO:
- what = "READ TRACK INFORMATION"; break;
- case GPCMD_RESERVE_RZONE_TRACK: what = "RESERVE TRACK"; break;
- case GPCMD_SEND_OPC: what = "SEND OPC"; break;
- case MODE_SELECT_10: what = "MODE_SELECT_10"; break;
- case GPCMD_REPAIR_RZONE_TRACK: what = "REPAIR TRACK"; break;
- case 0x59: what = "READ MASTER CUE"; break;
- case MODE_SENSE_10: what = "MODE_SENSE_10"; break;
- case GPCMD_CLOSE_TRACK: what = "CLOSE TRACK/SESSION"; break;
- case 0x5C: what = "READ BUFFER CAPACITY"; break;
- case 0x5D: what = "SEND CUE SHEET"; break;
- case GPCMD_BLANK: what = "BLANK"; break;
- case MOVE_MEDIUM: what = "MOVE_MEDIUM or PLAY AUDIO (12)"; break;
- case READ_12: what = "READ_12"; break;
- case WRITE_12: what = "WRITE_12"; break;
- case WRITE_VERIFY_12: what = "WRITE_VERIFY_12"; break;
- case SEARCH_HIGH_12: what = "SEARCH_HIGH_12"; break;
- case SEARCH_EQUAL_12: what = "SEARCH_EQUAL_12"; break;
- case SEARCH_LOW_12: what = "SEARCH_LOW_12"; break;
- case SEND_VOLUME_TAG: what = "SEND_VOLUME_TAG"; break;
- case READ_ELEMENT_STATUS: what = "READ_ELEMENT_STATUS"; break;
- case GPCMD_READ_CD_MSF: what = "READ CD MSF"; break;
- case GPCMD_SCAN: what = "SCAN"; break;
- case GPCMD_SET_SPEED: what = "SET CD SPEED"; break;
- case GPCMD_MECHANISM_STATUS: what = "MECHANISM STATUS"; break;
- case GPCMD_READ_CD: what = "READ CD"; break;
- case 0xE1: what = "WRITE CONTINUE"; break;
- case WRITE_LONG_2: what = "WRITE_LONG_2"; break;
- default: what = "(unknown command)"; break;
- }
- US_DEBUGP("Command %s (%d bytes)\n", what, srb->cmd_len);
- US_DEBUGP("%02x %02x %02x %02x "
- "%02x %02x %02x %02x "
- "%02x %02x %02x %02x\n",
- srb->cmnd[0], srb->cmnd[1], srb->cmnd[2], srb->cmnd[3],
- srb->cmnd[4], srb->cmnd[5], srb->cmnd[6], srb->cmnd[7],
- srb->cmnd[8], srb->cmnd[9], srb->cmnd[10],
- srb->cmnd[11]);
-}
-
-void usb_stor_print_Scsi_Cmnd( Scsi_Cmnd* cmd )
-{
- int i=0, bufferSize = cmd->request_bufflen;
- u8* buffer = cmd->request_buffer;
- struct scatterlist* sg = (struct scatterlist*)cmd->request_buffer;
-
- US_DEBUGP("Dumping information about %p.\n", cmd );
- US_DEBUGP("cmd->cmnd[0] value is %d.\n", cmd->cmnd[0] );
- US_DEBUGP("(MODE_SENSE is %d and MODE_SENSE_10 is %d)\n",
- MODE_SENSE, MODE_SENSE_10 );
-
- US_DEBUGP("buffer is %p with length %d.\n", buffer, bufferSize );
- for ( i=0; i<bufferSize; i+=16 )
- {
- US_DEBUGP("%02x %02x %02x %02x %02x %02x %02x %02x\n"
- "%02x %02x %02x %02x %02x %02x %02x %02x\n",
- buffer[i],
- buffer[i+1],
- buffer[i+2],
- buffer[i+3],
- buffer[i+4],
- buffer[i+5],
- buffer[i+6],
- buffer[i+7],
- buffer[i+8],
- buffer[i+9],
- buffer[i+10],
- buffer[i+11],
- buffer[i+12],
- buffer[i+13],
- buffer[i+14],
- buffer[i+15] );
- }
-
- US_DEBUGP("Buffer has %d scatterlists.\n", cmd->use_sg );
- for ( i=0; i<cmd->use_sg; i++ )
- {
- char *adr = page_address(sg[i].page) + sg[i].offset;
-
- US_DEBUGP("Length of scatterlist %d is %d.\n",i,sg[i].length);
- US_DEBUGP("%02x %02x %02x %02x %02x %02x %02x %02x\n"
- "%02x %02x %02x %02x %02x %02x %02x %02x\n",
- adr[0],
- adr[1],
- adr[2],
- adr[3],
- adr[4],
- adr[5],
- adr[6],
- adr[7],
- adr[8],
- adr[9],
- adr[10],
- adr[11],
- adr[12],
- adr[13],
- adr[14],
- adr[15]);
- }
-}
-
-void usb_stor_show_sense(
- unsigned char key,
- unsigned char asc,
- unsigned char ascq) {
-
- char *keys[] = {
- "No Sense",
- "Recovered Error",
- "Not Ready",
- "Medium Error",
- "Hardware Error",
- "Illegal Request",
- "Unit Attention",
- "Data Protect",
- "Blank Check",
- "Vendor Specific",
- "Copy Aborted",
- "Aborted Command",
- "(Obsolete)",
- "Volume Overflow",
- "Miscompare"
- };
-
- unsigned short qual = asc;
-
- char *what = 0;
- char *keystr = 0;
-
- qual <<= 8;
- qual |= ascq;
-
- if (key>0x0E)
- keystr = "(Unknown Key)";
- else
- keystr = keys[key];
-
- switch (qual) {
-
- case 0x0000: what="no additional sense information"; break;
- case 0x0001: what="filemark detected"; break;
- case 0x0002: what="end of partition/medium detected"; break;
- case 0x0003: what="setmark detected"; break;
- case 0x0004: what="beginning of partition/medium detected"; break;
- case 0x0005: what="end of data detected"; break;
- case 0x0006: what="I/O process terminated"; break;
- case 0x0011: what="audio play operation in progress"; break;
- case 0x0012: what="audio play operation paused"; break;
- case 0x0013: what="audio play operation stopped due to error"; break;
- case 0x0014: what="audio play operation successfully completed"; break;
- case 0x0015: what="no current audio status to return"; break;
- case 0x0016: what="operation in progress"; break;
- case 0x0017: what="cleaning requested"; break;
- case 0x0100: what="no index/sector signal"; break;
- case 0x0200: what="no seek complete"; break;
- case 0x0300: what="peripheral device write fault"; break;
- case 0x0301: what="no write current"; break;
- case 0x0302: what="excessive write errors"; break;
- case 0x0400: what="LUN not ready, cause not reportable"; break;
- case 0x0401: what="LUN in process of becoming ready"; break;
- case 0x0402: what="LUN not ready, initializing cmd. required"; break;
- case 0x0403: what="LUN not ready, manual intervention required"; break;
- case 0x0404: what="LUN not ready, format in progress"; break;
- case 0x0405: what="LUN not ready, rebuild in progress"; break;
- case 0x0406: what="LUN not ready, recalculation in progress"; break;
- case 0x0407: what="LUN not ready, operation in progress"; break;
- case 0x0408: what="LUN not ready, long write in progress"; break;
- case 0x0500: what="LUN doesn't respond to selection"; break;
- case 0x0A00: what="error log overflow"; break;
- case 0x0C04: what="compression check miscompare error"; break;
- case 0x0C05: what="data expansion occurred during compression"; break;
- case 0x0C06: what="block not compressible"; break;
- case 0x1102: what="error too long to correct"; break;
- case 0x1106: what="CIRC unrecovered error"; break;
- case 0x1107: what="data resynchronization error"; break;
- case 0x110D: what="decompression CRC error"; break;
- case 0x110E: what="can't decompress using declared algorithm"; break;
- case 0x110F: what="error reading UPC/EAN number"; break;
- case 0x1110: what="error reading ISRC number"; break;
- case 0x1200: what="address mark not found for ID field"; break;
- case 0x1300: what="address mark not found for data field"; break;
- case 0x1403: what="end of data not found"; break;
- case 0x1404: what="block sequence error"; break;
- case 0x1600: what="data sync mark error"; break;
- case 0x1601: what="data sync error: data rewritten"; break;
- case 0x1602: what="data sync error: recommend rewrite"; break;
- case 0x1603: what="data sync error: data auto-reallocated"; break;
- case 0x1604: what="data sync error: recommend reassignment"; break;
- case 0x1900: what="defect list error"; break;
- case 0x1901: what="defect list not available"; break;
- case 0x1902: what="defect list error in primary list"; break;
- case 0x1903: what="defect list error in grown list"; break;
- case 0x1C00: what="defect list not found"; break;
- case 0x2400: what="invalid field in CDB"; break;
- case 0x2703: what="associated write protect"; break;
- case 0x2800: what="not ready to ready transition"; break;
- case 0x2903: what="bus device reset function occurred"; break;
- case 0x2904: what="device internal reset"; break;
- case 0x2B00: what="copy can't execute / host can't disconnect"; break;
- case 0x2C00: what="command sequence error"; break;
- case 0x2C03: what="current program area is not empty"; break;
- case 0x2C04: what="current program area is empty"; break;
- case 0x2F00: what="commands cleared by another initiator"; break;
- case 0x3001: what="can't read medium: unknown format"; break;
- case 0x3002: what="can't read medium: incompatible format"; break;
- case 0x3003: what="cleaning cartridge installed"; break;
- case 0x3004: what="can't write medium: unknown format"; break;
- case 0x3005: what="can't write medium: incompatible format"; break;
- case 0x3006: what="can't format medium: incompatible medium"; break;
- case 0x3007: what="cleaning failure"; break;
- case 0x3008: what="can't write: application code mismatch"; break;
- case 0x3009: what="current session not fixated for append"; break;
- case 0x3201: what="defect list update failure"; break;
- case 0x3400: what="enclosure failure"; break;
- case 0x3500: what="enclosure services failure"; break;
- case 0x3502: what="enclosure services unavailable"; break;
- case 0x3503: what="enclosure services transfer failure"; break;
- case 0x3504: what="enclosure services transfer refused"; break;
- case 0x3B0F: what="end of medium reached"; break;
- case 0x3F02: what="changed operating definition"; break;
- case 0x4100: what="data path failure (should use 40 NN)"; break;
- case 0x4A00: what="command phase error"; break;
- case 0x4B00: what="data phase error"; break;
- case 0x5100: what="erase failure"; break;
- case 0x5200: what="cartridge fault"; break;
- case 0x6300: what="end of user area encountered on this track"; break;
- case 0x6600: what="automatic document feeder cover up"; break;
- case 0x6601: what="automatic document feeder lift up"; break;
- case 0x6602: what="document jam in auto doc feeder"; break;
- case 0x6603: what="document miss feed auto in doc feeder"; break;
- case 0x6700: what="configuration failure"; break;
- case 0x6701: what="configuration of incapable LUN's failed"; break;
- case 0x6702: what="add logical unit failed"; break;
- case 0x6706: what="attachment of logical unit failed"; break;
- case 0x6707: what="creation of logical unit failed"; break;
- case 0x6900: what="data loss on logical unit"; break;
- case 0x6E00: what="command to logical unit failed"; break;
- case 0x7100: what="decompression exception long algorithm ID"; break;
- case 0x7204: what="empty or partially written reserved track"; break;
- case 0x7300: what="CD control error"; break;
-
- default:
- if (asc==0x40) {
- US_DEBUGP("%s: diagnostic failure on component"
- " %02X\n", keystr, ascq);
- return;
- }
- if (asc==0x70) {
- US_DEBUGP("%s: decompression exception short"
- " algorithm ID of %02X\n", keystr, ascq);
- return;
- }
- what = "(unknown ASC/ASCQ)";
- }
-
- US_DEBUGP("%s: %s\n", keystr, what);
-}
-
diff --git a/drivers/usb/class/storage/debug.h b/drivers/usb/class/storage/debug.h
deleted file mode 100644
index c5477dcaf55d..000000000000
--- a/drivers/usb/class/storage/debug.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* Driver for USB Mass Storage compliant devices
- * Debugging Functions Header File
- *
- * $Id: debug.h,v 1.6 2001/01/12 23:51:04 mdharm Exp $
- *
- * Current development and maintenance by:
- * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
- *
- * Initial work by:
- * (c) 1999 Michael Gee (michael@linuxspecific.com)
- *
- * This driver is based on the 'USB Mass Storage Class' document. This
- * describes in detail the protocol used to communicate with such
- * devices. Clearly, the designers had SCSI and ATAPI commands in
- * mind when they created this document. The commands are all very
- * similar to commands in the SCSI-II and ATAPI specifications.
- *
- * It is important to note that in a number of cases this class
- * exhibits class-specific exemptions from the USB specification.
- * Notably the usage of NAK, STALL and ACK differs from the norm, in
- * that they are used to communicate wait, failed and OK on commands.
- *
- * Also, for certain devices, the interrupt endpoint is used to convey
- * status of a command.
- *
- * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more
- * information about this driver.
- *
- * 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, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _DEBUG_H_
-#define _DEBUG_H_
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/blk.h>
-#include <linux/cdrom.h>
-#include "scsi.h"
-
-#define USB_STORAGE "usb-storage: "
-
-#ifdef CONFIG_USB_STORAGE_DEBUG
-void usb_stor_show_command(Scsi_Cmnd *srb);
-void usb_stor_print_Scsi_Cmnd( Scsi_Cmnd* cmd );
-void usb_stor_show_sense( unsigned char key,
- unsigned char asc, unsigned char ascq );
-#define US_DEBUGP(x...) printk( KERN_DEBUG USB_STORAGE x )
-#define US_DEBUGPX(x...) printk( x )
-#define US_DEBUG(x) x
-#else
-#define US_DEBUGP(x...)
-#define US_DEBUGPX(x...)
-#define US_DEBUG(x)
-#endif
-
-#endif
diff --git a/drivers/usb/class/storage/dpcm.c b/drivers/usb/class/storage/dpcm.c
deleted file mode 100644
index 5f7e8d4673a6..000000000000
--- a/drivers/usb/class/storage/dpcm.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/* Driver for Microtech DPCM-USB CompactFlash/SmartMedia reader
- *
- * $Id: dpcm.c,v 1.4 2001/06/11 02:54:25 mdharm Exp $
- *
- * DPCM driver v0.1:
- *
- * First release
- *
- * Current development and maintenance by:
- * (c) 2000 Brian Webb (webbb@earthlink.net)
- *
- * This device contains both a CompactFlash card reader, which
- * uses the Control/Bulk w/o Interrupt protocol and
- * a SmartMedia card reader that uses the same protocol
- * as the SDDR09.
- *
- * 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, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/config.h>
-#include "transport.h"
-#include "protocol.h"
-#include "usb.h"
-#include "debug.h"
-#include "dpcm.h"
-#include "sddr09.h"
-
-/*
- * Transport for the Microtech DPCM-USB
- *
- */
-int dpcm_transport(Scsi_Cmnd *srb, struct us_data *us)
-{
- int ret;
-
- if(srb == NULL)
- return USB_STOR_TRANSPORT_ERROR;
-
- US_DEBUGP("dpcm_transport: LUN=%d\n", srb->lun);
-
- switch(srb->lun) {
- case 0:
-
- /*
- * LUN 0 corresponds to the CompactFlash card reader.
- */
- return usb_stor_CB_transport(srb, us);
-
-#ifdef CONFIG_USB_STORAGE_SDDR09
- case 1:
-
- /*
- * LUN 1 corresponds to the SmartMedia card reader.
- */
-
- /*
- * Set the LUN to 0 (just in case).
- */
- srb->lun = 0; us->srb->lun = 0;
- ret = sddr09_transport(srb, us);
- srb->lun = 1; us->srb->lun = 1;
-
- return ret;
-#endif
-
- default:
- US_DEBUGP("dpcm_transport: Invalid LUN %d\n", srb->lun);
- return USB_STOR_TRANSPORT_ERROR;
- }
-}
diff --git a/drivers/usb/class/storage/dpcm.h b/drivers/usb/class/storage/dpcm.h
deleted file mode 100644
index e6e5637d65a9..000000000000
--- a/drivers/usb/class/storage/dpcm.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Driver for Microtech DPCM-USB CompactFlash/SmartMedia reader
- *
- * $Id: dpcm.h,v 1.2 2000/08/25 00:13:51 mdharm Exp $
- *
- * DPCM driver v0.1:
- *
- * First release
- *
- * Current development and maintenance by:
- * (c) 2000 Brian Webb (webbb@earthlink.net)
- *
- * See dpcm.c for more explanation
- *
- * 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, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _MICROTECH_DPCM_USB_H
-#define _MICROTECH_DPCM_USB_H
-
-extern int dpcm_transport(Scsi_Cmnd *srb, struct us_data *us);
-
-#endif
diff --git a/drivers/usb/class/storage/freecom.c b/drivers/usb/class/storage/freecom.c
deleted file mode 100644
index f273ea54f635..000000000000
--- a/drivers/usb/class/storage/freecom.c
+++ /dev/null
@@ -1,707 +0,0 @@
-/* Driver for Freecom USB/IDE adaptor
- *
- * $Id: freecom.c,v 1.21 2001/12/29 03:47:33 mdharm Exp $
- *
- * Freecom v0.1:
- *
- * First release
- *
- * Current development and maintenance by:
- * (C) 2000 David Brown <usb-storage@davidb.org>
- *
- * 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, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * This driver was developed with information provided in FREECOM's USB
- * Programmers Reference Guide. For further information contact Freecom
- * (http://www.freecom.de/)
- */
-
-#include <linux/config.h>
-#include "transport.h"
-#include "protocol.h"
-#include "usb.h"
-#include "debug.h"
-#include "freecom.h"
-#include "linux/hdreg.h"
-
-#ifdef CONFIG_USB_STORAGE_DEBUG
-static void pdump (void *, int);
-#endif
-
-struct freecom_udata {
- __u8 buffer[64]; /* Common command block. */
-};
-typedef struct freecom_udata *freecom_udata_t;
-
-/* All of the outgoing packets are 64 bytes long. */
-struct freecom_cb_wrap {
- __u8 Type; /* Command type. */
- __u8 Timeout; /* Timeout in seconds. */
- __u8 Atapi[12]; /* An ATAPI packet. */
- __u8 Filler[50]; /* Padding Data. */
-};
-
-struct freecom_xfer_wrap {
- __u8 Type; /* Command type. */
- __u8 Timeout; /* Timeout in seconds. */
- __u32 Count; /* Number of bytes to transfer. */
- __u8 Pad[58];
-} __attribute__ ((packed));
-
-struct freecom_ide_out {
- __u8 Type; /* Type + IDE register. */
- __u8 Pad;
- __u16 Value; /* Value to write. */
- __u8 Pad2[60];
-};
-
-struct freecom_ide_in {
- __u8 Type; /* Type | IDE register. */
- __u8 Pad[63];
-};
-
-struct freecom_status {
- __u8 Status;
- __u8 Reason;
- __u16 Count;
- __u8 Pad[60];
-};
-
-/* Freecom stuffs the interrupt status in the INDEX_STAT bit of the ide
- * register. */
-#define FCM_INT_STATUS 0x02 /* INDEX_STAT */
-#define FCM_STATUS_BUSY 0x80
-
-/* These are the packet types. The low bit indicates that this command
- * should wait for an interrupt. */
-#define FCM_PACKET_ATAPI 0x21
-#define FCM_PACKET_STATUS 0x20
-
-/* Receive data from the IDE interface. The ATAPI packet has already
- * waited, so the data should be immediately available. */
-#define FCM_PACKET_INPUT 0x81
-
-/* Send data to the IDE interface. */
-#define FCM_PACKET_OUTPUT 0x01
-
-/* Write a value to an ide register. Or the ide register to write after
- * munging the address a bit. */
-#define FCM_PACKET_IDE_WRITE 0x40
-#define FCM_PACKET_IDE_READ 0xC0
-
-/* All packets (except for status) are 64 bytes long. */
-#define FCM_PACKET_LENGTH 64
-
-/*
- * Transfer an entire SCSI command's worth of data payload over the bulk
- * pipe.
- *
- * Note that this uses usb_stor_transfer_partial to achieve it's goals -- this
- * function simply determines if we're going to use scatter-gather or not,
- * and acts appropriately. For now, it also re-interprets the error codes.
- */
-static void us_transfer_freecom(Scsi_Cmnd *srb, struct us_data* us, int transfer_amount)
-{
- int i;
- int result = -1;
- struct scatterlist *sg;
- unsigned int total_transferred = 0;
-
- /* was someone foolish enough to request more data than available
- * buffer space? */
- if (transfer_amount > srb->request_bufflen)
- transfer_amount = srb->request_bufflen;
-
- /* are we scatter-gathering? */
- if (srb->use_sg) {
-
- /* loop over all the scatter gather structures and
- * make the appropriate requests for each, until done
- */
- sg = (struct scatterlist *) srb->request_buffer;
- for (i = 0; i < srb->use_sg; i++) {
-
- US_DEBUGP("transfer_amount: %d and total_transferred: %d\n", transfer_amount, total_transferred);
-
- /* End this if we're done */
- if (transfer_amount == total_transferred)
- break;
-
- /* transfer the lesser of the next buffer or the
- * remaining data */
- if (transfer_amount - total_transferred >=
- sg[i].length) {
- result = usb_stor_transfer_partial(us,
- page_address(sg[i].page) + sg[i].offset, sg[i].length);
- total_transferred += sg[i].length;
- } else {
- result = usb_stor_transfer_partial(us,
- page_address(sg[i].page) + sg[i].offset,
- transfer_amount - total_transferred);
- total_transferred += transfer_amount - total_transferred;
- }
-
- /* if we get an error, end the loop here */
- if (result)
- break;
- }
- }
- else
- /* no scatter-gather, just make the request */
- result = usb_stor_transfer_partial(us, srb->request_buffer,
- transfer_amount);
-
- /* return the result in the data structure itself */
- srb->result = result;
-}
-
-#if 0
-/* Write a value to an ide register. */
-static int
-freecom_ide_write (struct us_data *us, int reg, int value)
-{
- freecom_udata_t extra = (freecom_udata_t) us->extra;
- struct freecom_ide_out *ideout =
- (struct freecom_ide_out *) extra->buffer;
- int opipe;
- int result, partial;
-
- US_DEBUGP("IDE out 0x%02x <- 0x%02x\n", reg, value);
-
- /* Get handles for both transports. */
- opipe = usb_sndbulkpipe (us->pusb_dev, us->ep_out);
-
- if (reg < 0 || reg > 8)
- return USB_STOR_TRANSPORT_ERROR;
- if (reg < 8)
- reg |= 0x20;
- else
- reg = 0x0e;
-
- ideout->Type = FCM_PACKET_IDE_WRITE | reg;
- ideout->Pad = 0;
- ideout->Value = cpu_to_le16 (value);
- memset (ideout->Pad2, 0, sizeof (ideout->Pad2));
-
- result = usb_stor_bulk_msg (us, ideout, opipe,
- FCM_PACKET_LENGTH, &partial);
- if (result != 0) {
- if (result == -ENOENT)
- return US_BULK_TRANSFER_ABORTED;
- else
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- return USB_STOR_TRANSPORT_GOOD;
-}
-
-/* Read a value from an ide register. */
-static int
-freecom_ide_read (struct us_data *us, int reg, int *value)
-{
- freecom_udata_t extra = (freecom_udata_t) us->extra;
- struct freecom_ide_in *idein =
- (struct freecom_ide_in *) extra->buffer;
- __u8 *buffer = extra->buffer;
- int ipipe, opipe;
- int result, partial;
- int desired_length;
-
- /* Get handles for both transports. */
- opipe = usb_sndbulkpipe (us->pusb_dev, us->ep_out);
- ipipe = usb_rcvbulkpipe (us->pusb_dev, us->ep_in);
-
- if (reg < 0 || reg > 8)
- return USB_STOR_TRANSPORT_ERROR;
- if (reg < 8)
- reg |= 0x10;
- else
- reg = 0x0e;
-
- US_DEBUGP("IDE in request for register 0x%02x\n", reg);
-
- idein->Type = FCM_PACKET_IDE_READ | reg;
- memset (idein->Pad, 0, sizeof (idein->Pad));
-
- result = usb_stor_bulk_msg (us, idein, opipe,
- FCM_PACKET_LENGTH, &partial);
- if (result != 0) {
- if (result == -ENOENT)
- return US_BULK_TRANSFER_ABORTED;
- else
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- desired_length = 1;
- if (reg == 0x10)
- desired_length = 2;
-
- result = usb_stor_bulk_msg (us, buffer, ipipe,
- desired_length, &partial);
- if (result != 0) {
- if (result == -ENOENT)
- return US_BULK_TRANSFER_ABORTED;
- else
- return USB_STOR_TRANSPORT_ERROR;
- }
- US_DEBUGP("IDE in partial is %d\n", partial);
-
- if (desired_length == 1)
- *value = buffer[0];
- else
- *value = le16_to_cpu (*(__u16 *) buffer);
-
- US_DEBUGP("IDE in 0x%02x -> 0x%02x\n", reg, *value);
-
- return USB_STOR_TRANSPORT_GOOD;
-}
-#endif
-
-static int
-freecom_readdata (Scsi_Cmnd *srb, struct us_data *us,
- int ipipe, int opipe, int count)
-{
- freecom_udata_t extra = (freecom_udata_t) us->extra;
- struct freecom_xfer_wrap *fxfr =
- (struct freecom_xfer_wrap *) extra->buffer;
- int result, partial;
-
- fxfr->Type = FCM_PACKET_INPUT | 0x00;
- fxfr->Timeout = 0; /* Short timeout for debugging. */
- fxfr->Count = cpu_to_le32 (count);
- memset (fxfr->Pad, 0, sizeof (fxfr->Pad));
-
- US_DEBUGP("Read data Freecom! (c=%d)\n", count);
-
- /* Issue the transfer command. */
- result = usb_stor_bulk_msg (us, fxfr, opipe,
- FCM_PACKET_LENGTH, &partial);
- if (result != 0) {
- US_DEBUGP ("Freecom readdata xpot failure: r=%d, p=%d\n",
- result, partial);
-
- /* -ENOENT -- we canceled this transfer */
- if (result == -ENOENT) {
- US_DEBUGP("freecom_readdata(): transfer aborted\n");
- return US_BULK_TRANSFER_ABORTED;
- }
-
- return USB_STOR_TRANSPORT_ERROR;
- }
- US_DEBUGP("Done issuing read request: %d %d\n", result, partial);
-
- /* Now transfer all of our blocks. */
- US_DEBUGP("Start of read\n");
- us_transfer_freecom(srb, us, count);
- US_DEBUGP("freecom_readdata done!\n");
-
- return USB_STOR_TRANSPORT_GOOD;
-}
-
-static int
-freecom_writedata (Scsi_Cmnd *srb, struct us_data *us,
- int ipipe, int opipe, int count)
-{
- freecom_udata_t extra = (freecom_udata_t) us->extra;
- struct freecom_xfer_wrap *fxfr =
- (struct freecom_xfer_wrap *) extra->buffer;
- int result, partial;
-
- fxfr->Type = FCM_PACKET_OUTPUT | 0x00;
- fxfr->Timeout = 0; /* Short timeout for debugging. */
- fxfr->Count = cpu_to_le32 (count);
- memset (fxfr->Pad, 0, sizeof (fxfr->Pad));
-
- US_DEBUGP("Write data Freecom! (c=%d)\n", count);
-
- /* Issue the transfer command. */
- result = usb_stor_bulk_msg (us, fxfr, opipe,
- FCM_PACKET_LENGTH, &partial);
- if (result != 0) {
- US_DEBUGP ("Freecom writedata xpot failure: r=%d, p=%d\n",
- result, partial);
-
- /* -ENOENT -- we canceled this transfer */
- if (result == -ENOENT) {
- US_DEBUGP("freecom_writedata(): transfer aborted\n");
- return US_BULK_TRANSFER_ABORTED;
- }
-
- return USB_STOR_TRANSPORT_ERROR;
- }
- US_DEBUGP("Done issuing write request: %d %d\n",
- result, partial);
-
- /* Now transfer all of our blocks. */
- US_DEBUGP("Start of write\n");
- us_transfer_freecom(srb, us, count);
-
- US_DEBUGP("freecom_writedata done!\n");
- return USB_STOR_TRANSPORT_GOOD;
-}
-
-/*
- * Transport for the Freecom USB/IDE adaptor.
- *
- */
-int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
-{
- struct freecom_cb_wrap *fcb;
- struct freecom_status *fst;
- int ipipe, opipe; /* We need both pipes. */
- int result;
- int partial;
- int length;
- freecom_udata_t extra;
-
- extra = (freecom_udata_t) us->extra;
-
- fcb = (struct freecom_cb_wrap *) extra->buffer;
- fst = (struct freecom_status *) extra->buffer;
-
- US_DEBUGP("Freecom TRANSPORT STARTED\n");
-
- /* Get handles for both transports. */
- opipe = usb_sndbulkpipe (us->pusb_dev, us->ep_out);
- ipipe = usb_rcvbulkpipe (us->pusb_dev, us->ep_in);
-
- /* The ATAPI Command always goes out first. */
- fcb->Type = FCM_PACKET_ATAPI | 0x00;
- fcb->Timeout = 0;
- memcpy (fcb->Atapi, srb->cmnd, 12);
- memset (fcb->Filler, 0, sizeof (fcb->Filler));
-
- US_DEBUG(pdump (srb->cmnd, 12));
-
- /* Send it out. */
- result = usb_stor_bulk_msg (us, fcb, opipe,
- FCM_PACKET_LENGTH, &partial);
-
- /* The Freecom device will only fail if there is something wrong in
- * USB land. It returns the status in its own registers, which
- * come back in the bulk pipe. */
- if (result != 0) {
- US_DEBUGP ("freecom xport failure: r=%d, p=%d\n",
- result, partial);
-
- /* -ENOENT -- we canceled this transfer */
- if (result == -ENOENT) {
- US_DEBUGP("freecom_transport(): transfer aborted\n");
- return US_BULK_TRANSFER_ABORTED;
- }
-
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- /* There are times we can optimize out this status read, but it
- * doesn't hurt us to always do it now. */
- result = usb_stor_bulk_msg (us, fst, ipipe,
- FCM_PACKET_LENGTH, &partial);
- US_DEBUGP("foo Status result %d %d\n", result, partial);
- /* -ENOENT -- we canceled this transfer */
- if (result == -ENOENT) {
- US_DEBUGP("freecom_transport(): transfer aborted\n");
- return US_BULK_TRANSFER_ABORTED;
- }
-
- US_DEBUG(pdump ((void *) fst, partial));
-
- /* The firmware will time-out commands after 20 seconds. Some commands
- * can legitimately take longer than this, so we use a different
- * command that only waits for the interrupt and then sends status,
- * without having to send a new ATAPI command to the device.
- *
- * NOTE: There is some indication that a data transfer after a timeout
- * may not work, but that is a condition that should never happen.
- */
- while (fst->Status & FCM_STATUS_BUSY) {
- US_DEBUGP("20 second USB/ATAPI bridge TIMEOUT occured!\n");
- US_DEBUGP("fst->Status is %x\n", fst->Status);
-
- /* Get the status again */
- fcb->Type = FCM_PACKET_STATUS;
- fcb->Timeout = 0;
- memset (fcb->Atapi, 0, sizeof(fcb->Atapi));
- memset (fcb->Filler, 0, sizeof (fcb->Filler));
-
- /* Send it out. */
- result = usb_stor_bulk_msg (us, fcb, opipe,
- FCM_PACKET_LENGTH, &partial);
-
- /* The Freecom device will only fail if there is something
- * wrong in USB land. It returns the status in its own
- * registers, which come back in the bulk pipe.
- */
- if (result != 0) {
- US_DEBUGP ("freecom xport failure: r=%d, p=%d\n",
- result, partial);
-
- /* -ENOENT -- we canceled this transfer */
- if (result == -ENOENT) {
- US_DEBUGP("freecom_transport(): transfer aborted\n");
- return US_BULK_TRANSFER_ABORTED;
- }
-
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- /* get the data */
- result = usb_stor_bulk_msg (us, fst, ipipe,
- FCM_PACKET_LENGTH, &partial);
-
- US_DEBUGP("bar Status result %d %d\n", result, partial);
-
- /* -ENOENT -- we canceled this transfer */
- if (result == -ENOENT) {
- US_DEBUGP("freecom_transport(): transfer aborted\n");
- return US_BULK_TRANSFER_ABORTED;
- }
-
- US_DEBUG(pdump ((void *) fst, partial));
- }
-
- if (partial != 4 || result != 0) {
- return USB_STOR_TRANSPORT_ERROR;
- }
- if ((fst->Status & 1) != 0) {
- US_DEBUGP("operation failed\n");
- return USB_STOR_TRANSPORT_FAILED;
- }
-
- /* The device might not have as much data available as we
- * requested. If you ask for more than the device has, this reads
- * and such will hang. */
- US_DEBUGP("Device indicates that it has %d bytes available\n",
- le16_to_cpu (fst->Count));
- US_DEBUGP("SCSI requested %d\n", usb_stor_transfer_length(srb));
-
- /* Find the length we desire to read. */
- switch (srb->cmnd[0]) {
- case INQUIRY:
- case REQUEST_SENSE: /* 16 or 18 bytes? spec says 18, lots of devices only have 16 */
- case MODE_SENSE:
- case MODE_SENSE_10:
- length = fst->Count;
- break;
- default:
- length = usb_stor_transfer_length (srb);
- }
-
- /* verify that this amount is legal */
- if (length > srb->request_bufflen) {
- length = srb->request_bufflen;
- US_DEBUGP("Truncating request to match buffer length: %d\n", length);
- }
-
- /* What we do now depends on what direction the data is supposed to
- * move in. */
-
- switch (us->srb->sc_data_direction) {
- case SCSI_DATA_READ:
- /* Make sure that the status indicates that the device
- * wants data as well. */
- if ((fst->Status & DRQ_STAT) == 0 || (fst->Reason & 3) != 2) {
- US_DEBUGP("SCSI wants data, drive doesn't have any\n");
- return USB_STOR_TRANSPORT_FAILED;
- }
- result = freecom_readdata (srb, us, ipipe, opipe, length);
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- US_DEBUGP("FCM: Waiting for status\n");
- result = usb_stor_bulk_msg (us, fst, ipipe,
- FCM_PACKET_LENGTH, &partial);
- US_DEBUG(pdump ((void *) fst, partial));
- if (result == -ENOENT) {
- US_DEBUGP ("freecom_transport: transfer aborted\n");
- return US_BULK_TRANSFER_ABORTED;
- }
- if (partial != 4 || result != 0)
- return USB_STOR_TRANSPORT_ERROR;
- if ((fst->Status & ERR_STAT) != 0) {
- US_DEBUGP("operation failed\n");
- return USB_STOR_TRANSPORT_FAILED;
- }
- if ((fst->Reason & 3) != 3) {
- US_DEBUGP("Drive seems still hungry\n");
- return USB_STOR_TRANSPORT_FAILED;
- }
- US_DEBUGP("Transfer happy\n");
- break;
-
- case SCSI_DATA_WRITE:
- /* Make sure the status indicates that the device wants to
- * send us data. */
- /* !!IMPLEMENT!! */
- result = freecom_writedata (srb, us, ipipe, opipe, length);
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- US_DEBUGP("FCM: Waiting for status\n");
- result = usb_stor_bulk_msg (us, fst, ipipe,
- FCM_PACKET_LENGTH, &partial);
- if (result == -ENOENT) {
- US_DEBUGP ("freecom_transport: transfer aborted\n");
- return US_BULK_TRANSFER_ABORTED;
- }
- if (partial != 4 || result != 0)
- return USB_STOR_TRANSPORT_ERROR;
- if ((fst->Status & ERR_STAT) != 0) {
- US_DEBUGP("operation failed\n");
- return USB_STOR_TRANSPORT_FAILED;
- }
- if ((fst->Reason & 3) != 3) {
- US_DEBUGP("Drive seems still hungry\n");
- return USB_STOR_TRANSPORT_FAILED;
- }
-
- US_DEBUGP("Transfer happy\n");
- break;
-
-
- case SCSI_DATA_NONE:
- /* Easy, do nothing. */
- break;
-
- default:
- US_DEBUGP ("freecom unimplemented direction: %d\n",
- us->srb->sc_data_direction);
- // Return fail, SCSI seems to handle this better.
- return USB_STOR_TRANSPORT_FAILED;
- break;
- }
-
- return USB_STOR_TRANSPORT_GOOD;
-
- US_DEBUGP("Freecom: transfer_length = %d\n",
- usb_stor_transfer_length (srb));
-
- US_DEBUGP("Freecom: direction = %d\n", srb->sc_data_direction);
-
- return USB_STOR_TRANSPORT_ERROR;
-}
-
-int
-freecom_init (struct us_data *us)
-{
- int result;
- char buffer[33];
-
- /* Allocate a buffer for us. The upper usb transport code will
- * free this for us when cleaning up. */
- if (us->extra == NULL) {
- us->extra = kmalloc (sizeof (struct freecom_udata),
- GFP_KERNEL);
- if (us->extra == NULL) {
- US_DEBUGP("Out of memory\n");
- return USB_STOR_TRANSPORT_ERROR;
- }
- }
-
- result = usb_control_msg(us->pusb_dev,
- usb_rcvctrlpipe(us->pusb_dev, 0),
- 0x4c, 0xc0, 0x4346, 0x0, buffer, 0x20, 3*HZ);
- buffer[32] = '\0';
- US_DEBUGP("String returned from FC init is: %s\n", buffer);
-
- /* Special thanks to the people at Freecom for providing me with
- * this "magic sequence", which they use in their Windows and MacOS
- * drivers to make sure that all the attached perhiperals are
- * properly reset.
- */
-
- /* send reset */
- result = usb_control_msg(us->pusb_dev,
- usb_sndctrlpipe(us->pusb_dev, 0),
- 0x4d, 0x40, 0x24d8, 0x0, NULL, 0x0, 3*HZ);
- US_DEBUGP("result from activate reset is %d\n", result);
-
- /* wait 250ms */
- mdelay(250);
-
- /* clear reset */
- result = usb_control_msg(us->pusb_dev,
- usb_sndctrlpipe(us->pusb_dev, 0),
- 0x4d, 0x40, 0x24f8, 0x0, NULL, 0x0, 3*HZ);
- US_DEBUGP("result from clear reset is %d\n", result);
-
- /* wait 3 seconds */
- mdelay(3 * 1000);
-
- return USB_STOR_TRANSPORT_GOOD;
-}
-
-int usb_stor_freecom_reset(struct us_data *us)
-{
- printk (KERN_CRIT "freecom reset called\n");
-
- /* We don't really have this feature. */
- return FAILED;
-}
-
-#ifdef CONFIG_USB_STORAGE_DEBUG
-static void pdump (void *ibuffer, int length)
-{
- static char line[80];
- int offset = 0;
- unsigned char *buffer = (unsigned char *) ibuffer;
- int i, j;
- int from, base;
-
- offset = 0;
- for (i = 0; i < length; i++) {
- if ((i & 15) == 0) {
- if (i > 0) {
- offset += sprintf (line+offset, " - ");
- for (j = i - 16; j < i; j++) {
- if (buffer[j] >= 32 && buffer[j] <= 126)
- line[offset++] = buffer[j];
- else
- line[offset++] = '.';
- }
- line[offset] = 0;
- US_DEBUGP("%s\n", line);
- offset = 0;
- }
- offset += sprintf (line+offset, "%08x:", i);
- }
- else if ((i & 7) == 0) {
- offset += sprintf (line+offset, " -");
- }
- offset += sprintf (line+offset, " %02x", buffer[i] & 0xff);
- }
-
- /* Add the last "chunk" of data. */
- from = (length - 1) % 16;
- base = ((length - 1) / 16) * 16;
-
- for (i = from + 1; i < 16; i++)
- offset += sprintf (line+offset, " ");
- if (from < 8)
- offset += sprintf (line+offset, " ");
- offset += sprintf (line+offset, " - ");
-
- for (i = 0; i <= from; i++) {
- if (buffer[base+i] >= 32 && buffer[base+i] <= 126)
- line[offset++] = buffer[base+i];
- else
- line[offset++] = '.';
- }
- line[offset] = 0;
- US_DEBUGP("%s\n", line);
- offset = 0;
-}
-#endif
-
diff --git a/drivers/usb/class/storage/freecom.h b/drivers/usb/class/storage/freecom.h
deleted file mode 100644
index 8c0ada8bbeb6..000000000000
--- a/drivers/usb/class/storage/freecom.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Driver for Freecom USB/IDE adaptor
- *
- * $Id: freecom.h,v 1.4 2000/08/29 14:49:15 dlbrown Exp $
- *
- * Freecom v0.1:
- *
- * First release
- *
- * Current development and maintenance by:
- * (c) 2000 David Brown <usb-storage@davidb.org>
- *
- * See freecom.c for more explanation
- *
- * 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, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _FREECOM_USB_H
-#define _FREECOM_USB_H
-
-extern int freecom_transport(Scsi_Cmnd *srb, struct us_data *us);
-extern int usb_stor_freecom_reset(struct us_data *us);
-extern int freecom_init (struct us_data *us);
-
-#endif
diff --git a/drivers/usb/class/storage/initializers.c b/drivers/usb/class/storage/initializers.c
deleted file mode 100644
index dd03ef7ae3ce..000000000000
--- a/drivers/usb/class/storage/initializers.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/* Special Initializers for certain USB Mass Storage devices
- *
- * $Id: initializers.c,v 1.2 2000/09/06 22:35:57 mdharm Exp $
- *
- * Current development and maintenance by:
- * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
- *
- * This driver is based on the 'USB Mass Storage Class' document. This
- * describes in detail the protocol used to communicate with such
- * devices. Clearly, the designers had SCSI and ATAPI commands in
- * mind when they created this document. The commands are all very
- * similar to commands in the SCSI-II and ATAPI specifications.
- *
- * It is important to note that in a number of cases this class
- * exhibits class-specific exemptions from the USB specification.
- * Notably the usage of NAK, STALL and ACK differs from the norm, in
- * that they are used to communicate wait, failed and OK on commands.
- *
- * Also, for certain devices, the interrupt endpoint is used to convey
- * status of a command.
- *
- * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more
- * information about this driver.
- *
- * 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, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include "initializers.h"
-#include "debug.h"
-
-/* This places the Shuttle/SCM USB<->SCSI bridge devices in multi-target
- * mode */
-int usb_stor_euscsi_init(struct us_data *us)
-{
- unsigned char data = 0x1;
- int result;
-
- US_DEBUGP("Attempting to init eUSCSI bridge...\n");
- result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
- 0x0C, USB_RECIP_INTERFACE | USB_TYPE_VENDOR,
- 0x01, 0x0, &data, 0x1, 5*HZ);
- US_DEBUGP("-- result is %d\n", result);
- US_DEBUGP("-- data afterwards is %d\n", data);
-
- return 0;
-}
-
-
diff --git a/drivers/usb/class/storage/initializers.h b/drivers/usb/class/storage/initializers.h
deleted file mode 100644
index 51bb0241e161..000000000000
--- a/drivers/usb/class/storage/initializers.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* Header file for Special Initializers for certain USB Mass Storage devices
- *
- * $Id: initializers.h,v 1.1 2000/08/29 23:07:02 mdharm Exp $
- *
- * Current development and maintenance by:
- * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
- *
- * This driver is based on the 'USB Mass Storage Class' document. This
- * describes in detail the protocol used to communicate with such
- * devices. Clearly, the designers had SCSI and ATAPI commands in
- * mind when they created this document. The commands are all very
- * similar to commands in the SCSI-II and ATAPI specifications.
- *
- * It is important to note that in a number of cases this class
- * exhibits class-specific exemptions from the USB specification.
- * Notably the usage of NAK, STALL and ACK differs from the norm, in
- * that they are used to communicate wait, failed and OK on commands.
- *
- * Also, for certain devices, the interrupt endpoint is used to convey
- * status of a command.
- *
- * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more
- * information about this driver.
- *
- * 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, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include "usb.h"
-
-/* This places the Shuttle/SCM USB<->SCSI bridge devices in multi-target
- * mode */
-int usb_stor_euscsi_init(struct us_data *us);
diff --git a/drivers/usb/class/storage/isd200.c b/drivers/usb/class/storage/isd200.c
deleted file mode 100644
index f43f4a5d8f24..000000000000
--- a/drivers/usb/class/storage/isd200.c
+++ /dev/null
@@ -1,1749 +0,0 @@
-/* Transport & Protocol Driver for In-System Design, Inc. ISD200 ASIC
- *
- * First release
- *
- * Current development and maintenance by:
- * (c) 2000 In-System Design, Inc. (support@in-system.com)
- *
- * The ISD200 ASIC does not natively support ATA devices. The chip
- * does implement an interface, the ATA Command Block (ATACB) which provides
- * a means of passing ATA commands and ATA register accesses to a device.
- *
- * 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, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * History:
- *
- * 2001-02-24: Removed lots of duplicate code and simplified the structure.
- * (bjorn@haxx.se)
- */
-
-
-/* Include files */
-
-#include "transport.h"
-#include "protocol.h"
-#include "usb.h"
-#include "debug.h"
-#include "scsiglue.h"
-#include "isd200.h"
-
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/hdreg.h>
-#include <linux/ide.h>
-
-/*
- * Inquiry defines. Used to interpret data returned from target as result
- * of inquiry command.
- *
- * DeviceType field
- */
-
-#define DIRECT_ACCESS_DEVICE 0x00 /* disks */
-
-/* Timeout defines (in Seconds) */
-
-#define ISD200_ENUM_BSY_TIMEOUT 35
-#define ISD200_ENUM_DETECT_TIMEOUT 30
-#define ISD200_DEFAULT_TIMEOUT 30
-
-/* device flags */
-#define DF_ATA_DEVICE 0x0001
-#define DF_MEDIA_STATUS_ENABLED 0x0002
-#define DF_REMOVABLE_MEDIA 0x0004
-
-/* capability bit definitions */
-#define CAPABILITY_DMA 0x01
-#define CAPABILITY_LBA 0x02
-
-/* command_setX bit definitions */
-#define COMMANDSET_REMOVABLE 0x02
-#define COMMANDSET_MEDIA_STATUS 0x10
-
-/* ATA Vendor Specific defines */
-#define ATA_ADDRESS_DEVHEAD_STD 0xa0
-#define ATA_ADDRESS_DEVHEAD_LBA_MODE 0x40
-#define ATA_ADDRESS_DEVHEAD_SLAVE 0x10
-
-/* Action Select bits */
-#define ACTION_SELECT_0 0x01
-#define ACTION_SELECT_1 0x02
-#define ACTION_SELECT_2 0x04
-#define ACTION_SELECT_3 0x08
-#define ACTION_SELECT_4 0x10
-#define ACTION_SELECT_5 0x20
-#define ACTION_SELECT_6 0x40
-#define ACTION_SELECT_7 0x80
-
-/* ATA error definitions not in <linux/hdreg.h> */
-#define ATA_ERROR_MEDIA_CHANGE 0x20
-
-/* ATA command definitions not in <linux/hdreg.h> */
-#define ATA_COMMAND_GET_MEDIA_STATUS 0xDA
-#define ATA_COMMAND_MEDIA_EJECT 0xED
-
-/* ATA drive control definitions */
-#define ATA_DC_DISABLE_INTERRUPTS 0x02
-#define ATA_DC_RESET_CONTROLLER 0x04
-#define ATA_DC_REENABLE_CONTROLLER 0x00
-
-/*
- * General purpose return codes
- */
-
-#define ISD200_ERROR -1
-#define ISD200_GOOD 0
-
-/*
- * Transport return codes
- */
-
-#define ISD200_TRANSPORT_GOOD 0 /* Transport good, command good */
-#define ISD200_TRANSPORT_FAILED 1 /* Transport good, command failed */
-#define ISD200_TRANSPORT_ERROR 2 /* Transport bad (i.e. device dead) */
-#define ISD200_TRANSPORT_ABORTED 3 /* Transport aborted */
-#define ISD200_TRANSPORT_SHORT 4 /* Transport short */
-
-/* driver action codes */
-#define ACTION_READ_STATUS 0
-#define ACTION_RESET 1
-#define ACTION_REENABLE 2
-#define ACTION_SOFT_RESET 3
-#define ACTION_ENUM 4
-#define ACTION_IDENTIFY 5
-
-
-/*
- * ata_cdb struct
- */
-
-
-union ata_cdb {
- struct {
- unsigned char SignatureByte0;
- unsigned char SignatureByte1;
- unsigned char ActionSelect;
- unsigned char RegisterSelect;
- unsigned char TransferBlockSize;
- unsigned char WriteData3F6;
- unsigned char WriteData1F1;
- unsigned char WriteData1F2;
- unsigned char WriteData1F3;
- unsigned char WriteData1F4;
- unsigned char WriteData1F5;
- unsigned char WriteData1F6;
- unsigned char WriteData1F7;
- unsigned char Reserved[3];
- } generic;
-
- struct {
- unsigned char SignatureByte0;
- unsigned char SignatureByte1;
- unsigned char ReadRegisterAccessBit : 1;
- unsigned char NoDeviceSelectionBit : 1;
- unsigned char NoBSYPollBit : 1;
- unsigned char IgnorePhaseErrorBit : 1;
- unsigned char IgnoreDeviceErrorBit : 1;
- unsigned char Reserved0Bit : 3;
- unsigned char SelectAlternateStatus : 1;
- unsigned char SelectError : 1;
- unsigned char SelectSectorCount : 1;
- unsigned char SelectSectorNumber : 1;
- unsigned char SelectCylinderLow : 1;
- unsigned char SelectCylinderHigh : 1;
- unsigned char SelectDeviceHead : 1;
- unsigned char SelectStatus : 1;
- unsigned char TransferBlockSize;
- unsigned char AlternateStatusByte;
- unsigned char ErrorByte;
- unsigned char SectorCountByte;
- unsigned char SectorNumberByte;
- unsigned char CylinderLowByte;
- unsigned char CylinderHighByte;
- unsigned char DeviceHeadByte;
- unsigned char StatusByte;
- unsigned char Reserved[3];
- } read;
-
- struct {
- unsigned char SignatureByte0;
- unsigned char SignatureByte1;
- unsigned char ReadRegisterAccessBit : 1;
- unsigned char NoDeviceSelectionBit : 1;
- unsigned char NoBSYPollBit : 1;
- unsigned char IgnorePhaseErrorBit : 1;
- unsigned char IgnoreDeviceErrorBit : 1;
- unsigned char Reserved0Bit : 3;
- unsigned char SelectDeviceControl : 1;
- unsigned char SelectFeatures : 1;
- unsigned char SelectSectorCount : 1;
- unsigned char SelectSectorNumber : 1;
- unsigned char SelectCylinderLow : 1;
- unsigned char SelectCylinderHigh : 1;
- unsigned char SelectDeviceHead : 1;
- unsigned char SelectCommand : 1;
- unsigned char TransferBlockSize;
- unsigned char DeviceControlByte;
- unsigned char FeaturesByte;
- unsigned char SectorCountByte;
- unsigned char SectorNumberByte;
- unsigned char CylinderLowByte;
- unsigned char CylinderHighByte;
- unsigned char DeviceHeadByte;
- unsigned char CommandByte;
- unsigned char Reserved[3];
- } write;
-};
-
-
-/*
- * Inquiry data structure. This is the data returned from the target
- * after it receives an inquiry.
- *
- * This structure may be extended by the number of bytes specified
- * in the field AdditionalLength. The defined size constant only
- * includes fields through ProductRevisionLevel.
- */
-
-struct inquiry_data {
- unsigned char DeviceType : 5;
- unsigned char DeviceTypeQualifier : 3;
- unsigned char DeviceTypeModifier : 7;
- unsigned char RemovableMedia : 1;
- unsigned char Versions;
- unsigned char ResponseDataFormat : 4;
- unsigned char HiSupport : 1;
- unsigned char NormACA : 1;
- unsigned char ReservedBit : 1;
- unsigned char AERC : 1;
- unsigned char AdditionalLength;
- unsigned char Reserved[2];
- unsigned char SoftReset : 1;
- unsigned char CommandQueue : 1;
- unsigned char Reserved2 : 1;
- unsigned char LinkedCommands : 1;
- unsigned char Synchronous : 1;
- unsigned char Wide16Bit : 1;
- unsigned char Wide32Bit : 1;
- unsigned char RelativeAddressing : 1;
- unsigned char VendorId[8];
- unsigned char ProductId[16];
- unsigned char ProductRevisionLevel[4];
- unsigned char VendorSpecific[20];
- unsigned char Reserved3[40];
-} __attribute__ ((packed));
-
-/*
- * INQUIRY data buffer size
- */
-
-#define INQUIRYDATABUFFERSIZE 36
-
-
-/*
- * ISD200 CONFIG data struct
- */
-
-struct isd200_config {
- unsigned char EventNotification;
- unsigned char ExternalClock;
- unsigned char ATAInitTimeout;
- unsigned char ATATiming : 4;
- unsigned char ATAPIReset : 1;
- unsigned char MasterSlaveSelection : 1;
- unsigned char ATAPICommandBlockSize : 2;
- unsigned char ATAMajorCommand;
- unsigned char ATAMinorCommand;
- unsigned char LastLUNIdentifier : 3;
- unsigned char DescriptOverride : 1;
- unsigned char ATA3StateSuspend : 1;
- unsigned char SkipDeviceBoot : 1;
- unsigned char ConfigDescriptor2 : 1;
- unsigned char InitStatus : 1;
- unsigned char SRSTEnable : 1;
- unsigned char Reserved0 : 7;
-};
-
-
-/*
- * ISD200 driver information struct
- */
-
-struct isd200_info {
- struct inquiry_data InquiryData;
- struct hd_driveid drive;
- struct isd200_config ConfigData;
- unsigned char ATARegs[8];
- unsigned char DeviceHead;
- unsigned char DeviceFlags;
-
- /* maximum number of LUNs supported */
- unsigned char MaxLUNs;
-};
-
-
-/*
- * Read Capacity Data - returned in Big Endian format
- */
-
-struct read_capacity_data {
- unsigned long LogicalBlockAddress;
- unsigned long BytesPerBlock;
-};
-
-/*
- * Read Block Limits Data - returned in Big Endian format
- * This structure returns the maximum and minimum block
- * size for a TAPE device.
- */
-
-struct read_block_limits {
- unsigned char Reserved;
- unsigned char BlockMaximumSize[3];
- unsigned char BlockMinimumSize[2];
-};
-
-
-/*
- * Sense Data Format
- */
-
-struct sense_data {
- unsigned char ErrorCode:7;
- unsigned char Valid:1;
- unsigned char SegmentNumber;
- unsigned char SenseKey:4;
- unsigned char Reserved:1;
- unsigned char IncorrectLength:1;
- unsigned char EndOfMedia:1;
- unsigned char FileMark:1;
- unsigned char Information[4];
- unsigned char AdditionalSenseLength;
- unsigned char CommandSpecificInformation[4];
- unsigned char AdditionalSenseCode;
- unsigned char AdditionalSenseCodeQualifier;
- unsigned char FieldReplaceableUnitCode;
- unsigned char SenseKeySpecific[3];
-} __attribute__ ((packed));
-
-/*
- * Default request sense buffer size
- */
-
-#define SENSE_BUFFER_SIZE 18
-
-/***********************************************************************
- * Helper routines
- ***********************************************************************/
-
-
-/**************************************************************************
- * isd200_build_sense
- *
- * Builds an artificial sense buffer to report the results of a
- * failed command.
- *
- * RETURNS:
- * void
- */
-void isd200_build_sense(struct us_data *us, Scsi_Cmnd *srb)
-{
- struct isd200_info *info = (struct isd200_info *)us->extra;
- struct sense_data *buf = (struct sense_data *) &srb->sense_buffer[0];
- unsigned char error = info->ATARegs[IDE_ERROR_OFFSET];
-
- if(error & ATA_ERROR_MEDIA_CHANGE) {
- buf->ErrorCode = 0x70;
- buf->Valid = 1;
- buf->AdditionalSenseLength = 0xb;
- buf->SenseKey = UNIT_ATTENTION;
- buf->AdditionalSenseCode = 0;
- buf->AdditionalSenseCodeQualifier = 0;
- } else if(error & MCR_ERR) {
- buf->ErrorCode = 0x70;
- buf->Valid = 1;
- buf->AdditionalSenseLength = 0xb;
- buf->SenseKey = UNIT_ATTENTION;
- buf->AdditionalSenseCode = 0;
- buf->AdditionalSenseCodeQualifier = 0;
- } else if(error & TRK0_ERR) {
- buf->ErrorCode = 0x70;
- buf->Valid = 1;
- buf->AdditionalSenseLength = 0xb;
- buf->SenseKey = NOT_READY;
- buf->AdditionalSenseCode = 0;
- buf->AdditionalSenseCodeQualifier = 0;
- } else if(error & ECC_ERR) {
- buf->ErrorCode = 0x70;
- buf->Valid = 1;
- buf->AdditionalSenseLength = 0xb;
- buf->SenseKey = DATA_PROTECT;
- buf->AdditionalSenseCode = 0;
- buf->AdditionalSenseCodeQualifier = 0;
- } else {
- buf->ErrorCode = 0;
- buf->Valid = 0;
- buf->AdditionalSenseLength = 0;
- buf->SenseKey = 0;
- buf->AdditionalSenseCode = 0;
- buf->AdditionalSenseCodeQualifier = 0;
- }
-}
-
-/***********************************************************************
- * Data transfer routines
- ***********************************************************************/
-
-
-/**************************************************************************
- * Transfer one SCSI scatter-gather buffer via bulk transfer
- *
- * Note that this function is necessary because we want the ability to
- * use scatter-gather memory. Good performance is achieved by a combination
- * of scatter-gather and clustering (which makes each chunk bigger).
- *
- * Note that the lower layer will always retry when a NAK occurs, up to the
- * timeout limit. Thus we don't have to worry about it for individual
- * packets.
- */
-static int isd200_transfer_partial( struct us_data *us,
- unsigned char dataDirection,
- char *buf, int length )
-{
- int result;
- int partial;
- int pipe;
-
- /* calculate the appropriate pipe information */
- if (dataDirection == SCSI_DATA_READ)
- pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
- else
- pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
-
- /* transfer the data */
- US_DEBUGP("isd200_transfer_partial(): xfer %d bytes\n", length);
- result = usb_stor_bulk_msg(us, buf, pipe, length, &partial);
- US_DEBUGP("usb_stor_bulk_msg() returned %d xferred %d/%d\n",
- result, partial, length);
-
- /* if we stall, we need to clear it before we go on */
- if (result == -EPIPE) {
- US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
- usb_stor_clear_halt(us->pusb_dev, pipe);
- }
-
- /* did we send all the data? */
- if (partial == length) {
- US_DEBUGP("isd200_transfer_partial(): transfer complete\n");
- return ISD200_TRANSPORT_GOOD;
- }
-
- /* uh oh... we have an error code, so something went wrong. */
- if (result) {
- /* NAK - that means we've retried a few times already */
- if (result == -ETIMEDOUT) {
- US_DEBUGP("isd200_transfer_partial(): device NAKed\n");
- return ISD200_TRANSPORT_FAILED;
- }
-
- /* -ENOENT -- we canceled this transfer */
- if (result == -ENOENT) {
- US_DEBUGP("isd200_transfer_partial(): transfer aborted\n");
- return ISD200_TRANSPORT_ABORTED;
- }
-
- /* the catch-all case */
- US_DEBUGP("isd200_transfer_partial(): unknown error\n");
- return ISD200_TRANSPORT_FAILED;
- }
-
- /* no error code, so we must have transferred some data,
- * just not all of it */
- return ISD200_TRANSPORT_SHORT;
-}
-
-
-/**************************************************************************
- * Transfer an entire SCSI command's worth of data payload over the bulk
- * pipe.
- *
- * Note that this uses us_transfer_partial to achieve it's goals -- this
- * function simply determines if we're going to use scatter-gather or not,
- * and acts appropriately. For now, it also re-interprets the error codes.
- */
-static void isd200_transfer( struct us_data *us, Scsi_Cmnd *srb )
-{
- int i;
- int result = -1;
- struct scatterlist *sg;
- unsigned int total_transferred = 0;
- unsigned int transfer_amount;
-
- /* calculate how much we want to transfer */
- int dir = srb->sc_data_direction;
- srb->sc_data_direction = SCSI_DATA_WRITE;
- transfer_amount = usb_stor_transfer_length(srb);
- srb->sc_data_direction = dir;
-
- /* was someone foolish enough to request more data than available
- * buffer space? */
- if (transfer_amount > srb->request_bufflen)
- transfer_amount = srb->request_bufflen;
-
- /* are we scatter-gathering? */
- if (srb->use_sg) {
-
- /* loop over all the scatter gather structures and
- * make the appropriate requests for each, until done
- */
- sg = (struct scatterlist *) srb->request_buffer;
- for (i = 0; i < srb->use_sg; i++) {
-
- /* transfer the lesser of the next buffer or the
- * remaining data */
- if (transfer_amount - total_transferred >=
- sg[i].length) {
- result = isd200_transfer_partial(us,
- srb->sc_data_direction,
- page_address(sg[i].page) + sg[i].offset,
- sg[i].length);
- total_transferred += sg[i].length;
- } else
- result = isd200_transfer_partial(us,
- srb->sc_data_direction,
- page_address(sg[i].page) + sg[i].offset,
- transfer_amount - total_transferred);
-
- /* if we get an error, end the loop here */
- if (result)
- break;
- }
- }
- else
- /* no scatter-gather, just make the request */
- result = isd200_transfer_partial(us,
- srb->sc_data_direction,
- srb->request_buffer,
- transfer_amount);
-
- /* return the result in the data structure itself */
- srb->result = result;
-}
-
-
-/***********************************************************************
- * Transport routines
- ***********************************************************************/
-
-
-/**************************************************************************
- * ISD200 Bulk Transport
- *
- * Note: This routine was copied from the usb_stor_Bulk_transport routine
- * located in the transport.c source file. The scsi command is limited to
- * only 12 bytes while the CDB for the ISD200 must be 16 bytes.
- */
-int isd200_Bulk_transport( struct us_data *us, Scsi_Cmnd *srb,
- union ata_cdb *AtaCdb, unsigned char AtaCdbLength )
-{
- struct bulk_cb_wrap bcb;
- struct bulk_cs_wrap bcs;
- int result;
- int pipe;
- int partial;
- unsigned int transfer_amount;
-
- int dir = srb->sc_data_direction;
- srb->sc_data_direction = SCSI_DATA_WRITE;
- transfer_amount = usb_stor_transfer_length(srb);
- srb->sc_data_direction = dir;
-
- /* set up the command wrapper */
- bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN);
- bcb.DataTransferLength = cpu_to_le32(transfer_amount);
- bcb.Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;
- bcb.Tag = srb->serial_number;
- bcb.Lun = srb->cmnd[1] >> 5;
- if (us->flags & US_FL_SCM_MULT_TARG)
- bcb.Lun |= srb->target << 4;
-
- bcb.Length = AtaCdbLength;
-
- /* construct the pipe handle */
- pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
-
- /* copy the command payload */
- memset(bcb.CDB, 0, sizeof(bcb.CDB));
- memcpy(bcb.CDB, AtaCdb, bcb.Length);
-
- /* send it to out endpoint */
- US_DEBUGP("Bulk command S 0x%x T 0x%x Trg %d LUN %d L %d F %d CL %d\n",
- le32_to_cpu(bcb.Signature), bcb.Tag,
- (bcb.Lun >> 4), (bcb.Lun & 0xFF),
- bcb.DataTransferLength, bcb.Flags, bcb.Length);
- result = usb_stor_bulk_msg(us, &bcb, pipe, US_BULK_CB_WRAP_LEN,
- &partial);
- US_DEBUGP("Bulk command transfer result=%d\n", result);
-
- if (result == -ENOENT)
- return ISD200_TRANSPORT_ABORTED;
- else if (result == -EPIPE) {
- /* if we stall, we need to clear it before we go on */
- US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
- usb_stor_clear_halt(us->pusb_dev, pipe);
- } else if (result)
- return ISD200_TRANSPORT_ERROR;
-
- /* if the command transfered well, then we go to the data stage */
- if (!result && bcb.DataTransferLength) {
- isd200_transfer(us, srb);
- US_DEBUGP("Bulk data transfer result 0x%x\n", srb->result);
-
- if (srb->result == ISD200_TRANSPORT_ABORTED)
- return ISD200_TRANSPORT_ABORTED;
- }
-
- /* See flow chart on pg 15 of the Bulk Only Transport spec for
- * an explanation of how this code works.
- */
-
- /* construct the pipe handle */
- pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
-
- /* get CSW for device status */
- US_DEBUGP("Attempting to get CSW...\n");
- result = usb_stor_bulk_msg(us, &bcs, pipe, US_BULK_CS_WRAP_LEN,
- &partial);
- if (result == -ENOENT)
- return ISD200_TRANSPORT_ABORTED;
-
- /* did the attempt to read the CSW fail? */
- if (result == -EPIPE) {
- US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
- usb_stor_clear_halt(us->pusb_dev, pipe);
-
- /* get the status again */
- US_DEBUGP("Attempting to get CSW (2nd try)...\n");
- result = usb_stor_bulk_msg(us, &bcs, pipe,
- US_BULK_CS_WRAP_LEN, &partial);
-
- /* if the command was aborted, indicate that */
- if (result == -ENOENT)
- return ISD200_TRANSPORT_ABORTED;
-
- /* if it fails again, we need a reset and return an error*/
- if (result == -EPIPE) {
- US_DEBUGP("clearing halt for pipe 0x%x\n", pipe);
- usb_stor_clear_halt(us->pusb_dev, pipe);
- return ISD200_TRANSPORT_ERROR;
- }
- }
-
- /* if we still have a failure at this point, we're in trouble */
- US_DEBUGP("Bulk status result = %d\n", result);
- if (result)
- return ISD200_TRANSPORT_ERROR;
-
- /* check bulk status */
- US_DEBUGP("Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x\n",
- le32_to_cpu(bcs.Signature), bcs.Tag,
- bcs.Residue, bcs.Status);
- if (bcs.Signature != cpu_to_le32(US_BULK_CS_SIGN) ||
- bcs.Tag != bcb.Tag ||
- bcs.Status > US_BULK_STAT_PHASE || partial != 13) {
- US_DEBUGP("Bulk logical error\n");
- return ISD200_TRANSPORT_ERROR;
- }
-
- /* based on the status code, we report good or bad */
- switch (bcs.Status) {
- case US_BULK_STAT_OK:
- /* command good -- note that we could be short on data */
- return ISD200_TRANSPORT_GOOD;
-
- case US_BULK_STAT_FAIL:
- /* command failed */
- return ISD200_TRANSPORT_FAILED;
-
- case US_BULK_STAT_PHASE:
- /* phase error */
- usb_stor_Bulk_reset(us);
- return ISD200_TRANSPORT_ERROR;
- }
-
- /* we should never get here, but if we do, we're in trouble */
- return ISD200_TRANSPORT_ERROR;
-}
-
-
-/**************************************************************************
- * isd200_action
- *
- * Routine for sending commands to the isd200
- *
- * RETURNS:
- * ISD status code
- */
-static int isd200_action( struct us_data *us, int action,
- void* pointer, int value )
-{
- union ata_cdb ata;
- struct scsi_cmnd srb;
- struct isd200_info *info = (struct isd200_info *)us->extra;
- int status;
-
- memset(&ata, 0, sizeof(ata));
- memset(&srb, 0, sizeof(srb));
-
- ata.generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
- ata.generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
- ata.generic.TransferBlockSize = 1;
-
- switch ( action ) {
- case ACTION_READ_STATUS:
- US_DEBUGP(" isd200_action(READ_STATUS)\n");
- ata.generic.ActionSelect = ACTION_SELECT_0|ACTION_SELECT_2;
- ata.read.SelectStatus = 1;
- ata.read.SelectError = 1;
- ata.read.SelectCylinderHigh = 1;
- ata.read.SelectCylinderLow = 1;
- srb.sc_data_direction = SCSI_DATA_READ;
- srb.request_buffer = pointer;
- srb.request_bufflen = value;
- break;
-
- case ACTION_ENUM:
- US_DEBUGP(" isd200_action(ENUM,0x%02x)\n",value);
- ata.generic.ActionSelect = ACTION_SELECT_1|ACTION_SELECT_2|
- ACTION_SELECT_3|ACTION_SELECT_4|
- ACTION_SELECT_5;
- ata.write.SelectDeviceHead = 1;
- ata.write.DeviceHeadByte = value;
- srb.sc_data_direction = SCSI_DATA_NONE;
- break;
-
- case ACTION_RESET:
- US_DEBUGP(" isd200_action(RESET)\n");
- ata.generic.ActionSelect = ACTION_SELECT_1|ACTION_SELECT_2|
- ACTION_SELECT_3|ACTION_SELECT_4;
- ata.write.SelectDeviceControl = 1;
- ata.write.DeviceControlByte = ATA_DC_RESET_CONTROLLER;
- srb.sc_data_direction = SCSI_DATA_NONE;
- break;
-
- case ACTION_REENABLE:
- US_DEBUGP(" isd200_action(REENABLE)\n");
- ata.generic.ActionSelect = ACTION_SELECT_1|ACTION_SELECT_2|
- ACTION_SELECT_3|ACTION_SELECT_4;
- ata.write.SelectDeviceControl = 1;
- ata.write.DeviceControlByte = ATA_DC_REENABLE_CONTROLLER;
- srb.sc_data_direction = SCSI_DATA_NONE;
- break;
-
- case ACTION_SOFT_RESET:
- US_DEBUGP(" isd200_action(SOFT_RESET)\n");
- ata.generic.ActionSelect = ACTION_SELECT_1|ACTION_SELECT_5;
- ata.write.SelectDeviceHead = 1;
- ata.write.DeviceHeadByte = info->DeviceHead;
- ata.write.SelectCommand = 1;
- ata.write.CommandByte = WIN_SRST;
- srb.sc_data_direction = SCSI_DATA_NONE;
- break;
-
- case ACTION_IDENTIFY:
- US_DEBUGP(" isd200_action(IDENTIFY)\n");
- ata.write.SelectCommand = 1;
- ata.write.CommandByte = WIN_IDENTIFY;
- srb.sc_data_direction = SCSI_DATA_READ;
- srb.request_buffer = (void *)&info->drive;
- srb.request_bufflen = sizeof(struct hd_driveid);
- break;
-
- default:
- US_DEBUGP("Error: Undefined action %d\n",action);
- break;
- }
-
- status = isd200_Bulk_transport(us, &srb, &ata, sizeof(ata.generic));
- if (status != ISD200_TRANSPORT_GOOD) {
- US_DEBUGP(" isd200_action(0x%02x) error: %d\n",action,status);
- status = ISD200_ERROR;
- /* need to reset device here */
- }
-
- return status;
-}
-
-/**************************************************************************
- * isd200_read_regs
- *
- * Read ATA Registers
- *
- * RETURNS:
- * ISD status code
- */
-int isd200_read_regs( struct us_data *us )
-{
- struct isd200_info *info = (struct isd200_info *)us->extra;
- int retStatus = ISD200_GOOD;
- int transferStatus;
-
- US_DEBUGP("Entering isd200_IssueATAReadRegs\n");
-
- transferStatus = isd200_action( us, ACTION_READ_STATUS,
- info->ATARegs, sizeof(info->ATARegs) );
- if (transferStatus != ISD200_TRANSPORT_GOOD) {
- US_DEBUGP(" Error reading ATA registers\n");
- retStatus = ISD200_ERROR;
- } else {
- US_DEBUGP(" Got ATA Register[IDE_ERROR_OFFSET] = 0x%x\n",
- info->ATARegs[IDE_ERROR_OFFSET]);
- }
-
- return retStatus;
-}
-
-
-/**************************************************************************
- * Invoke the transport and basic error-handling/recovery methods
- *
- * This is used by the protocol layers to actually send the message to
- * the device and receive the response.
- */
-void isd200_invoke_transport( struct us_data *us,
- Scsi_Cmnd *srb,
- union ata_cdb *ataCdb )
-{
- int need_auto_sense = 0;
- int transferStatus;
-
- /* send the command to the transport layer */
- transferStatus = isd200_Bulk_transport(us, srb, ataCdb,
- sizeof(ataCdb->generic));
- switch (transferStatus) {
-
- case ISD200_TRANSPORT_GOOD:
- /* Indicate a good result */
- srb->result = GOOD;
- break;
-
- case ISD200_TRANSPORT_ABORTED:
- /* if the command gets aborted by the higher layers, we need to
- * short-circuit all other processing
- */
- US_DEBUGP("-- transport indicates command was aborted\n");
- srb->result = DID_ABORT << 16;
- break;
-
- case ISD200_TRANSPORT_FAILED:
- US_DEBUGP("-- transport indicates command failure\n");
- need_auto_sense = 1;
- break;
-
- case ISD200_TRANSPORT_ERROR:
- US_DEBUGP("-- transport indicates transport failure\n");
- srb->result = DID_ERROR << 16;
- break;
-
- case ISD200_TRANSPORT_SHORT:
- if (!((srb->cmnd[0] == REQUEST_SENSE) ||
- (srb->cmnd[0] == INQUIRY) ||
- (srb->cmnd[0] == MODE_SENSE) ||
- (srb->cmnd[0] == LOG_SENSE) ||
- (srb->cmnd[0] == MODE_SENSE_10))) {
- US_DEBUGP("-- unexpectedly short transfer\n");
- need_auto_sense = 1;
- }
- break;
-
- default:
- US_DEBUGP("-- transport indicates unknown failure\n");
- srb->result = DID_ERROR << 16;
-
- }
-
- if (need_auto_sense)
- if (isd200_read_regs(us) == ISD200_GOOD)
- isd200_build_sense(us, srb);
-
- /* Regardless of auto-sense, if we _know_ we have an error
- * condition, show that in the result code
- */
- if (transferStatus == ISD200_TRANSPORT_FAILED)
- srb->result = CHECK_CONDITION;
-}
-
-
-/**************************************************************************
- * isd200_write_config
- *
- * Write the ISD200 Configuraton data
- *
- * RETURNS:
- * ISD status code
- */
-int isd200_write_config( struct us_data *us )
-{
- struct isd200_info *info = (struct isd200_info *)us->extra;
- int retStatus = ISD200_GOOD;
- int result;
-
-
- US_DEBUGP("Entering isd200_write_config\n");
-
- US_DEBUGP(" Writing the following ISD200 Config Data:\n");
- US_DEBUGP(" Event Notification: 0x%x\n", info->ConfigData.EventNotification);
- US_DEBUGP(" External Clock: 0x%x\n", info->ConfigData.ExternalClock);
- US_DEBUGP(" ATA Init Timeout: 0x%x\n", info->ConfigData.ATAInitTimeout);
- US_DEBUGP(" ATAPI Command Block Size: 0x%x\n", info->ConfigData.ATAPICommandBlockSize);
- US_DEBUGP(" Master/Slave Selection: 0x%x\n", info->ConfigData.MasterSlaveSelection);
- US_DEBUGP(" ATAPI Reset: 0x%x\n", info->ConfigData.ATAPIReset);
- US_DEBUGP(" ATA Timing: 0x%x\n", info->ConfigData.ATATiming);
- US_DEBUGP(" ATA Major Command: 0x%x\n", info->ConfigData.ATAMajorCommand);
- US_DEBUGP(" ATA Minor Command: 0x%x\n", info->ConfigData.ATAMinorCommand);
- US_DEBUGP(" Init Status: 0x%x\n", info->ConfigData.InitStatus);
- US_DEBUGP(" Config Descriptor 2: 0x%x\n", info->ConfigData.ConfigDescriptor2);
- US_DEBUGP(" Skip Device Boot: 0x%x\n", info->ConfigData.SkipDeviceBoot);
- US_DEBUGP(" ATA 3 State Supsend: 0x%x\n", info->ConfigData.ATA3StateSuspend);
- US_DEBUGP(" Descriptor Override: 0x%x\n", info->ConfigData.DescriptOverride);
- US_DEBUGP(" Last LUN Identifier: 0x%x\n", info->ConfigData.LastLUNIdentifier);
- US_DEBUGP(" SRST Enable: 0x%x\n", info->ConfigData.SRSTEnable);
-
- /* let's send the command via the control pipe */
- result = usb_stor_control_msg(
- us,
- usb_sndctrlpipe(us->pusb_dev,0),
- 0x01,
- USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
- 0x0000,
- 0x0002,
- (void *) &info->ConfigData,
- sizeof(info->ConfigData));
-
- if (result >= 0) {
- US_DEBUGP(" ISD200 Config Data was written successfully\n");
- } else {
- US_DEBUGP(" Request to write ISD200 Config Data failed!\n");
-
- /* STALL must be cleared when they are detected */
- if (result == -EPIPE) {
- US_DEBUGP("-- Stall on control pipe. Clearing\n");
- result = usb_stor_clear_halt(us->pusb_dev,
- usb_sndctrlpipe(us->pusb_dev, 0));
- US_DEBUGP("-- usb_stor_clear_halt() returns %d\n", result);
-
- }
- retStatus = ISD200_ERROR;
- }
-
- US_DEBUGP("Leaving isd200_write_config %08X\n", retStatus);
- return retStatus;
-}
-
-
-/**************************************************************************
- * isd200_read_config
- *
- * Reads the ISD200 Configuraton data
- *
- * RETURNS:
- * ISD status code
- */
-int isd200_read_config( struct us_data *us )
-{
- struct isd200_info *info = (struct isd200_info *)us->extra;
- int retStatus = ISD200_GOOD;
- int result;
-
- US_DEBUGP("Entering isd200_read_config\n");
-
- /* read the configuration information from ISD200. Use this to */
- /* determine what the special ATA CDB bytes are. */
-
- result = usb_stor_control_msg(
- us,
- usb_rcvctrlpipe(us->pusb_dev,0),
- 0x02,
- USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
- 0x0000,
- 0x0002,
- (void *) &info->ConfigData,
- sizeof(info->ConfigData));
-
-
- if (result >= 0) {
- US_DEBUGP(" Retrieved the following ISD200 Config Data:\n");
- US_DEBUGP(" Event Notification: 0x%x\n", info->ConfigData.EventNotification);
- US_DEBUGP(" External Clock: 0x%x\n", info->ConfigData.ExternalClock);
- US_DEBUGP(" ATA Init Timeout: 0x%x\n", info->ConfigData.ATAInitTimeout);
- US_DEBUGP(" ATAPI Command Block Size: 0x%x\n", info->ConfigData.ATAPICommandBlockSize);
- US_DEBUGP(" Master/Slave Selection: 0x%x\n", info->ConfigData.MasterSlaveSelection);
- US_DEBUGP(" ATAPI Reset: 0x%x\n", info->ConfigData.ATAPIReset);
- US_DEBUGP(" ATA Timing: 0x%x\n", info->ConfigData.ATATiming);
- US_DEBUGP(" ATA Major Command: 0x%x\n", info->ConfigData.ATAMajorCommand);
- US_DEBUGP(" ATA Minor Command: 0x%x\n", info->ConfigData.ATAMinorCommand);
- US_DEBUGP(" Init Status: 0x%x\n", info->ConfigData.InitStatus);
- US_DEBUGP(" Config Descriptor 2: 0x%x\n", info->ConfigData.ConfigDescriptor2);
- US_DEBUGP(" Skip Device Boot: 0x%x\n", info->ConfigData.SkipDeviceBoot);
- US_DEBUGP(" ATA 3 State Supsend: 0x%x\n", info->ConfigData.ATA3StateSuspend);
- US_DEBUGP(" Descriptor Override: 0x%x\n", info->ConfigData.DescriptOverride);
- US_DEBUGP(" Last LUN Identifier: 0x%x\n", info->ConfigData.LastLUNIdentifier);
- US_DEBUGP(" SRST Enable: 0x%x\n", info->ConfigData.SRSTEnable);
- } else {
- US_DEBUGP(" Request to get ISD200 Config Data failed!\n");
-
- /* STALL must be cleared when they are detected */
- if (result == -EPIPE) {
- US_DEBUGP("-- Stall on control pipe. Clearing\n");
- result = usb_stor_clear_halt(us->pusb_dev,
- usb_sndctrlpipe(us->pusb_dev, 0));
- US_DEBUGP("-- usb_stor_clear_halt() returns %d\n", result);
-
- }
- retStatus = ISD200_ERROR;
- }
-
- US_DEBUGP("Leaving isd200_read_config %08X\n", retStatus);
- return retStatus;
-}
-
-
-/**************************************************************************
- * isd200_atapi_soft_reset
- *
- * Perform an Atapi Soft Reset on the device
- *
- * RETURNS:
- * NT status code
- */
-int isd200_atapi_soft_reset( struct us_data *us )
-{
- int retStatus = ISD200_GOOD;
- int transferStatus;
-
- US_DEBUGP("Entering isd200_atapi_soft_reset\n");
-
- transferStatus = isd200_action( us, ACTION_SOFT_RESET, NULL, 0 );
- if (transferStatus != ISD200_TRANSPORT_GOOD) {
- US_DEBUGP(" Error issuing Atapi Soft Reset\n");
- retStatus = ISD200_ERROR;
- }
-
- US_DEBUGP("Leaving isd200_atapi_soft_reset %08X\n", retStatus);
- return retStatus;
-}
-
-
-/**************************************************************************
- * isd200_srst
- *
- * Perform an SRST on the device
- *
- * RETURNS:
- * ISD status code
- */
-int isd200_srst( struct us_data *us )
-{
- int retStatus = ISD200_GOOD;
- int transferStatus;
-
- US_DEBUGP("Entering isd200_SRST\n");
-
- transferStatus = isd200_action( us, ACTION_RESET, NULL, 0 );
-
- /* check to see if this request failed */
- if (transferStatus != ISD200_TRANSPORT_GOOD) {
- US_DEBUGP(" Error issuing SRST\n");
- retStatus = ISD200_ERROR;
- } else {
- /* delay 10ms to give the drive a chance to see it */
- wait_ms(10);
-
- transferStatus = isd200_action( us, ACTION_REENABLE, NULL, 0 );
- if (transferStatus != ISD200_TRANSPORT_GOOD) {
- US_DEBUGP(" Error taking drive out of reset\n");
- retStatus = ISD200_ERROR;
- } else {
- /* delay 50ms to give the drive a chance to recover after SRST */
- wait_ms(50);
- }
- }
-
- US_DEBUGP("Leaving isd200_srst %08X\n", retStatus);
- return retStatus;
-}
-
-
-/**************************************************************************
- * isd200_try_enum
- *
- * Helper function for isd200_manual_enum(). Does ENUM and READ_STATUS
- * and tries to analyze the status registers
- *
- * RETURNS:
- * ISD status code
- */
-static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
- int detect )
-{
- int status = ISD200_GOOD;
- unsigned char regs[8];
- unsigned long endTime;
- struct isd200_info *info = (struct isd200_info *)us->extra;
- int recheckAsMaster = FALSE;
-
- if ( detect )
- endTime = jiffies + ISD200_ENUM_DETECT_TIMEOUT * HZ;
- else
- endTime = jiffies + ISD200_ENUM_BSY_TIMEOUT * HZ;
-
- /* loop until we detect !BSY or timeout */
- while(TRUE) {
-#ifdef CONFIG_USB_STORAGE_DEBUG
- char* mstr = master_slave == ATA_ADDRESS_DEVHEAD_STD ?
- "Master" : "Slave";
-#endif
-
- status = isd200_action( us, ACTION_ENUM, NULL, master_slave );
- if ( status != ISD200_GOOD )
- break;
-
- status = isd200_action( us, ACTION_READ_STATUS,
- regs, sizeof(regs) );
- if ( status != ISD200_GOOD )
- break;
-
- if (!detect) {
- if (regs[IDE_STATUS_OFFSET] & BUSY_STAT ) {
- US_DEBUGP(" %s status is still BSY, try again...\n",mstr);
- } else {
- US_DEBUGP(" %s status !BSY, continue with next operation\n",mstr);
- break;
- }
- }
- /* check for BUSY_STAT and */
- /* WRERR_STAT (workaround ATA Zip drive) and */
- /* ERR_STAT (workaround for Archos CD-ROM) */
- else if (regs[IDE_STATUS_OFFSET] &
- (BUSY_STAT | WRERR_STAT | ERR_STAT )) {
- US_DEBUGP(" Status indicates it is not ready, try again...\n");
- }
- /* check for DRDY, ATA devices set DRDY after SRST */
- else if (regs[IDE_STATUS_OFFSET] & READY_STAT) {
- US_DEBUGP(" Identified ATA device\n");
- info->DeviceFlags |= DF_ATA_DEVICE;
- info->DeviceHead = master_slave;
- break;
- }
- /* check Cylinder High/Low to
- determine if it is an ATAPI device
- */
- else if ((regs[IDE_HCYL_OFFSET] == 0xEB) &&
- (regs[IDE_LCYL_OFFSET] == 0x14)) {
- /* It seems that the RICOH
- MP6200A CD/RW drive will
- report itself okay as a
- slave when it is really a
- master. So this check again
- as a master device just to
- make sure it doesn't report
- itself okay as a master also
- */
- if ((master_slave & ATA_ADDRESS_DEVHEAD_SLAVE) &&
- (recheckAsMaster == FALSE)) {
- US_DEBUGP(" Identified ATAPI device as slave. Rechecking again as master\n");
- recheckAsMaster = TRUE;
- master_slave = ATA_ADDRESS_DEVHEAD_STD;
- } else {
- US_DEBUGP(" Identified ATAPI device\n");
- info->DeviceHead = master_slave;
-
- status = isd200_atapi_soft_reset(us);
- break;
- }
- } else {
- US_DEBUGP(" Not ATA, not ATAPI. Weird.\n");
- }
-
- /* check for timeout on this request */
- if (jiffies >= endTime) {
- if (!detect)
- US_DEBUGP(" BSY check timeout, just continue with next operation...\n");
- else
- US_DEBUGP(" Device detect timeout!\n");
- break;
- }
- }
-
- return status;
-}
-
-/**************************************************************************
- * isd200_manual_enum
- *
- * Determines if the drive attached is an ATA or ATAPI and if it is a
- * master or slave.
- *
- * RETURNS:
- * ISD status code
- */
-int isd200_manual_enum(struct us_data *us)
-{
- struct isd200_info *info = (struct isd200_info *)us->extra;
- int retStatus = ISD200_GOOD;
-
- US_DEBUGP("Entering isd200_manual_enum\n");
-
- retStatus = isd200_read_config(us);
- if (retStatus == ISD200_GOOD) {
- int isslave;
- /* master or slave? */
- retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_STD, FALSE );
- if (retStatus == ISD200_GOOD)
- retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_SLAVE, FALSE );
-
- if (retStatus == ISD200_GOOD) {
- retStatus = isd200_srst(us);
- if (retStatus == ISD200_GOOD)
- /* ata or atapi? */
- retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_STD, TRUE );
- }
-
- isslave = (info->DeviceHead & ATA_ADDRESS_DEVHEAD_SLAVE) ? 1 : 0;
- if (info->ConfigData.MasterSlaveSelection != isslave) {
- US_DEBUGP(" Setting Master/Slave selection to %d\n", isslave);
- info->ConfigData.MasterSlaveSelection = isslave;
- retStatus = isd200_write_config(us);
- }
- }
-
- US_DEBUGP("Leaving isd200_manual_enum %08X\n", retStatus);
- return(retStatus);
-}
-
-
-/**************************************************************************
- * isd200_get_inquiry_data
- *
- * Get inquiry data
- *
- * RETURNS:
- * ISD status code
- */
-int isd200_get_inquiry_data( struct us_data *us )
-{
- struct isd200_info *info = (struct isd200_info *)us->extra;
- int retStatus = ISD200_GOOD;
-
- US_DEBUGP("Entering isd200_get_inquiry_data\n");
-
- /* set default to Master */
- info->DeviceHead = ATA_ADDRESS_DEVHEAD_STD;
-
- /* attempt to manually enumerate this device */
- retStatus = isd200_manual_enum(us);
- if (retStatus == ISD200_GOOD) {
- int transferStatus;
-
- /* check for an ATA device */
- if (info->DeviceFlags & DF_ATA_DEVICE) {
- /* this must be an ATA device */
- /* perform an ATA Commmand Identify */
- transferStatus = isd200_action( us, ACTION_IDENTIFY,
- &info->drive,
- sizeof(struct hd_driveid) );
- if (transferStatus != ISD200_TRANSPORT_GOOD) {
- /* Error issuing ATA Command Identify */
- US_DEBUGP(" Error issuing ATA Command Identify\n");
- retStatus = ISD200_ERROR;
- } else {
- /* ATA Command Identify successful */
- int i;
-
- US_DEBUGP(" Identify Data Structure:\n");
- US_DEBUGP(" config = 0x%x\n", info->drive.config);
- US_DEBUGP(" cyls = 0x%x\n", info->drive.cyls);
- US_DEBUGP(" heads = 0x%x\n", info->drive.heads);
- US_DEBUGP(" track_bytes = 0x%x\n", info->drive.track_bytes);
- US_DEBUGP(" sector_bytes = 0x%x\n", info->drive.sector_bytes);
- US_DEBUGP(" sectors = 0x%x\n", info->drive.sectors);
- US_DEBUGP(" serial_no[0] = 0x%x\n", info->drive.serial_no[0]);
- US_DEBUGP(" buf_type = 0x%x\n", info->drive.buf_type);
- US_DEBUGP(" buf_size = 0x%x\n", info->drive.buf_size);
- US_DEBUGP(" ecc_bytes = 0x%x\n", info->drive.ecc_bytes);
- US_DEBUGP(" fw_rev[0] = 0x%x\n", info->drive.fw_rev[0]);
- US_DEBUGP(" model[0] = 0x%x\n", info->drive.model[0]);
- US_DEBUGP(" max_multsect = 0x%x\n", info->drive.max_multsect);
- US_DEBUGP(" dword_io = 0x%x\n", info->drive.dword_io);
- US_DEBUGP(" capability = 0x%x\n", info->drive.capability);
- US_DEBUGP(" tPIO = 0x%x\n", info->drive.tPIO);
- US_DEBUGP(" tDMA = 0x%x\n", info->drive.tDMA);
- US_DEBUGP(" field_valid = 0x%x\n", info->drive.field_valid);
- US_DEBUGP(" cur_cyls = 0x%x\n", info->drive.cur_cyls);
- US_DEBUGP(" cur_heads = 0x%x\n", info->drive.cur_heads);
- US_DEBUGP(" cur_sectors = 0x%x\n", info->drive.cur_sectors);
- US_DEBUGP(" cur_capacity = 0x%x\n", (info->drive.cur_capacity1 << 16) + info->drive.cur_capacity0 );
- US_DEBUGP(" multsect = 0x%x\n", info->drive.multsect);
- US_DEBUGP(" lba_capacity = 0x%x\n", info->drive.lba_capacity);
- US_DEBUGP(" command_set_1 = 0x%x\n", info->drive.command_set_1);
- US_DEBUGP(" command_set_2 = 0x%x\n", info->drive.command_set_2);
-
- memset(&info->InquiryData, 0, sizeof(info->InquiryData));
-
- /* Standard IDE interface only supports disks */
- info->InquiryData.DeviceType = DIRECT_ACCESS_DEVICE;
-
- /* Fix-up the return data from an INQUIRY command to show
- * ANSI SCSI rev 2 so we don't confuse the SCSI layers above us
- * in Linux.
- */
- info->InquiryData.Versions = 0x2;
-
- /* The length must be at least 36 (5 + 31) */
- info->InquiryData.AdditionalLength = 0x1F;
-
- if (info->drive.command_set_1 & COMMANDSET_MEDIA_STATUS) {
- /* set the removable bit */
- info->InquiryData.RemovableMedia = 1;
- info->DeviceFlags |= DF_REMOVABLE_MEDIA;
- }
-
- /* Fill in vendor identification fields */
- for (i = 0; i < 20; i += 2) {
- info->InquiryData.VendorId[i] =
- info->drive.model[i + 1];
- info->InquiryData.VendorId[i+1] =
- info->drive.model[i];
- }
-
- /* Initialize unused portion of product id */
- for (i = 0; i < 4; i++) {
- info->InquiryData.ProductId[12+i] = ' ';
- }
-
- /* Move firmware revision from IDENTIFY data to */
- /* product revision in INQUIRY data */
- for (i = 0; i < 4; i += 2) {
- info->InquiryData.ProductRevisionLevel[i] =
- info->drive.fw_rev[i+1];
- info->InquiryData.ProductRevisionLevel[i+1] =
- info->drive.fw_rev[i];
- }
-
- /* determine if it supports Media Status Notification */
- if (info->drive.command_set_2 & COMMANDSET_MEDIA_STATUS) {
- US_DEBUGP(" Device supports Media Status Notification\n");
-
- /* Indicate that it is enabled, even though it is not
- * This allows the lock/unlock of the media to work
- * correctly.
- */
- info->DeviceFlags |= DF_MEDIA_STATUS_ENABLED;
- }
- else
- info->DeviceFlags &= ~DF_MEDIA_STATUS_ENABLED;
-
- }
- } else {
- /*
- * this must be an ATAPI device
- * use an ATAPI protocol (Transparent SCSI)
- */
- us->protocol_name = "Transparent SCSI";
- us->proto_handler = usb_stor_transparent_scsi_command;
-
- US_DEBUGP("Protocol changed to: %s\n", us->protocol_name);
-
- /* Free driver structure */
- if (us->extra != NULL) {
- kfree(us->extra);
- us->extra = NULL;
- us->extra_destructor = NULL;
- }
- }
- }
-
- US_DEBUGP("Leaving isd200_get_inquiry_data %08X\n", retStatus);
-
- return(retStatus);
-}
-
-
-/**************************************************************************
- * isd200_data_copy
- *
- * Copy data into the srb request buffer. Use scatter gather if required.
- *
- * RETURNS:
- * void
- */
-void isd200_data_copy(Scsi_Cmnd *srb, char * src, int length)
-{
- unsigned int len = length;
- struct scatterlist *sg;
-
- if (srb->use_sg) {
- int i;
- unsigned int total = 0;
-
- /* Add up the sizes of all the sg segments */
- sg = (struct scatterlist *) srb->request_buffer;
- for (i = 0; i < srb->use_sg; i++)
- total += sg[i].length;
-
- if (length > total)
- len = total;
-
- total = 0;
-
- /* Copy data into sg buffer(s) */
- for (i = 0; i < srb->use_sg; i++) {
- if ((len > total) && (len > 0)) {
- /* transfer the lesser of the next buffer or the
- * remaining data */
- if (len - total >= sg[i].length) {
- memcpy(page_address(sg[i].page) + sg[i].offset, src + total, sg[i].length);
- total += sg[i].length;
- } else {
- memcpy(page_address(sg[i].page) + sg[i].offset, src + total, len - total);
- total = len;
- }
- }
- else
- break;
- }
- } else {
- /* Make sure length does not exceed buffer length */
- if (length > srb->request_bufflen)
- len = srb->request_bufflen;
-
- if (len > 0)
- memcpy(srb->request_buffer, src, len);
- }
-}
-
-
-/**************************************************************************
- * isd200_scsi_to_ata
- *
- * Translate SCSI commands to ATA commands.
- *
- * RETURNS:
- * TRUE if the command needs to be sent to the transport layer
- * FALSE otherwise
- */
-int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
- union ata_cdb * ataCdb)
-{
- struct isd200_info *info = (struct isd200_info *)us->extra;
- int sendToTransport = TRUE;
- unsigned char sectnum, head;
- unsigned short cylinder;
- unsigned long lba;
- unsigned long blockCount;
- unsigned char senseData[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
-
- memset(ataCdb, 0, sizeof(union ata_cdb));
-
- /* SCSI Command */
- switch (srb->cmnd[0]) {
- case INQUIRY:
- US_DEBUGP(" ATA OUT - INQUIRY\n");
-
- if (srb->request_bufflen > sizeof(struct inquiry_data))
- srb->request_bufflen = sizeof(struct inquiry_data);
-
- /* copy InquiryData */
- isd200_data_copy(srb, (char *) &info->InquiryData, srb->request_bufflen);
- srb->result = GOOD;
- sendToTransport = FALSE;
- break;
-
- case MODE_SENSE:
- US_DEBUGP(" ATA OUT - SCSIOP_MODE_SENSE\n");
-
- /* Initialize the return buffer */
- isd200_data_copy(srb, (char *) &senseData, 8);
-
- if (info->DeviceFlags & DF_MEDIA_STATUS_ENABLED)
- {
- ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
- ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
- ataCdb->generic.TransferBlockSize = 1;
- ataCdb->write.SelectCommand = 1;
- ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS;
- srb->request_bufflen = 0;
- } else {
- US_DEBUGP(" Media Status not supported, just report okay\n");
- srb->result = GOOD;
- sendToTransport = FALSE;
- }
- break;
-
- case TEST_UNIT_READY:
- US_DEBUGP(" ATA OUT - SCSIOP_TEST_UNIT_READY\n");
-
- /* Initialize the return buffer */
- isd200_data_copy(srb, (char *) &senseData, 8);
-
- if (info->DeviceFlags & DF_MEDIA_STATUS_ENABLED)
- {
- ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
- ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
- ataCdb->generic.TransferBlockSize = 1;
- ataCdb->write.SelectCommand = 1;
- ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS;
- srb->request_bufflen = 0;
- } else {
- US_DEBUGP(" Media Status not supported, just report okay\n");
- srb->result = GOOD;
- sendToTransport = FALSE;
- }
- break;
-
- case READ_CAPACITY:
- {
- unsigned long capacity;
- struct read_capacity_data readCapacityData;
-
- US_DEBUGP(" ATA OUT - SCSIOP_READ_CAPACITY\n");
-
- if (info->drive.capability & CAPABILITY_LBA ) {
- capacity = info->drive.lba_capacity - 1;
- } else {
- capacity = (info->drive.heads *
- info->drive.cyls *
- info->drive.sectors) - 1;
- }
- readCapacityData.LogicalBlockAddress = cpu_to_be32(capacity);
- readCapacityData.BytesPerBlock = cpu_to_be32(0x200);
-
- if (srb->request_bufflen > sizeof(struct read_capacity_data))
- srb->request_bufflen = sizeof(struct read_capacity_data);
-
- isd200_data_copy(srb, (char *) &readCapacityData, srb->request_bufflen);
- srb->result = GOOD;
- sendToTransport = FALSE;
- }
- break;
-
- case READ_10:
- US_DEBUGP(" ATA OUT - SCSIOP_READ\n");
-
- lba = *(unsigned long *)&srb->cmnd[2];
- lba = cpu_to_be32(lba);
- blockCount = (unsigned long)srb->cmnd[7]<<8 | (unsigned long)srb->cmnd[8];
-
- if (info->drive.capability & CAPABILITY_LBA) {
- sectnum = (unsigned char)(lba);
- cylinder = (unsigned short)(lba>>8);
- head = ATA_ADDRESS_DEVHEAD_LBA_MODE | (unsigned char)(lba>>24 & 0x0F);
- } else {
- sectnum = (unsigned char)((lba % info->drive.sectors) + 1);
- cylinder = (unsigned short)(lba / (info->drive.sectors *
- info->drive.heads));
- head = (unsigned char)((lba / info->drive.sectors) %
- info->drive.heads);
- }
- ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
- ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
- ataCdb->generic.TransferBlockSize = 1;
- ataCdb->write.SelectSectorCount = 1;
- ataCdb->write.SectorCountByte = (unsigned char)blockCount;
- ataCdb->write.SelectSectorNumber = 1;
- ataCdb->write.SectorNumberByte = sectnum;
- ataCdb->write.SelectCylinderHigh = 1;
- ataCdb->write.CylinderHighByte = (unsigned char)(cylinder>>8);
- ataCdb->write.SelectCylinderLow = 1;
- ataCdb->write.CylinderLowByte = (unsigned char)cylinder;
- ataCdb->write.SelectDeviceHead = 1;
- ataCdb->write.DeviceHeadByte = (head | ATA_ADDRESS_DEVHEAD_STD);
- ataCdb->write.SelectCommand = 1;
- ataCdb->write.CommandByte = WIN_READ;
- break;
-
- case WRITE_10:
- US_DEBUGP(" ATA OUT - SCSIOP_WRITE\n");
-
- lba = *(unsigned long *)&srb->cmnd[2];
- lba = cpu_to_be32(lba);
- blockCount = (unsigned long)srb->cmnd[7]<<8 | (unsigned long)srb->cmnd[8];
-
- if (info->drive.capability & CAPABILITY_LBA) {
- sectnum = (unsigned char)(lba);
- cylinder = (unsigned short)(lba>>8);
- head = ATA_ADDRESS_DEVHEAD_LBA_MODE | (unsigned char)(lba>>24 & 0x0F);
- } else {
- sectnum = (unsigned char)((lba % info->drive.sectors) + 1);
- cylinder = (unsigned short)(lba / (info->drive.sectors * info->drive.heads));
- head = (unsigned char)((lba / info->drive.sectors) % info->drive.heads);
- }
- ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
- ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
- ataCdb->generic.TransferBlockSize = 1;
- ataCdb->write.SelectSectorCount = 1;
- ataCdb->write.SectorCountByte = (unsigned char)blockCount;
- ataCdb->write.SelectSectorNumber = 1;
- ataCdb->write.SectorNumberByte = sectnum;
- ataCdb->write.SelectCylinderHigh = 1;
- ataCdb->write.CylinderHighByte = (unsigned char)(cylinder>>8);
- ataCdb->write.SelectCylinderLow = 1;
- ataCdb->write.CylinderLowByte = (unsigned char)cylinder;
- ataCdb->write.SelectDeviceHead = 1;
- ataCdb->write.DeviceHeadByte = (head | ATA_ADDRESS_DEVHEAD_STD);
- ataCdb->write.SelectCommand = 1;
- ataCdb->write.CommandByte = WIN_WRITE;
- break;
-
- case ALLOW_MEDIUM_REMOVAL:
- US_DEBUGP(" ATA OUT - SCSIOP_MEDIUM_REMOVAL\n");
-
- if (info->DeviceFlags & DF_REMOVABLE_MEDIA) {
- US_DEBUGP(" srb->cmnd[4] = 0x%X\n", srb->cmnd[4]);
-
- ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
- ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
- ataCdb->generic.TransferBlockSize = 1;
- ataCdb->write.SelectCommand = 1;
- ataCdb->write.CommandByte = (srb->cmnd[4] & 0x1) ?
- WIN_DOORLOCK : WIN_DOORUNLOCK;
- srb->request_bufflen = 0;
- } else {
- US_DEBUGP(" Not removeable media, just report okay\n");
- srb->result = GOOD;
- sendToTransport = FALSE;
- }
- break;
-
- case START_STOP:
- US_DEBUGP(" ATA OUT - SCSIOP_START_STOP_UNIT\n");
- US_DEBUGP(" srb->cmnd[4] = 0x%X\n", srb->cmnd[4]);
-
- /* Initialize the return buffer */
- isd200_data_copy(srb, (char *) &senseData, 8);
-
- if ((srb->cmnd[4] & 0x3) == 0x2) {
- US_DEBUGP(" Media Eject\n");
- ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
- ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
- ataCdb->generic.TransferBlockSize = 0;
- ataCdb->write.SelectCommand = 1;
- ataCdb->write.CommandByte = ATA_COMMAND_MEDIA_EJECT;
- } else if ((srb->cmnd[4] & 0x3) == 0x1) {
- US_DEBUGP(" Get Media Status\n");
- ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
- ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
- ataCdb->generic.TransferBlockSize = 1;
- ataCdb->write.SelectCommand = 1;
- ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS;
- srb->request_bufflen = 0;
- } else {
- US_DEBUGP(" Nothing to do, just report okay\n");
- srb->result = GOOD;
- sendToTransport = FALSE;
- }
- break;
-
- default:
- US_DEBUGP("Unsupported SCSI command - 0x%X\n", srb->cmnd[0]);
- srb->result = DID_ERROR << 16;
- sendToTransport = FALSE;
- break;
- }
-
- return(sendToTransport);
-}
-
-
-/**************************************************************************
- * isd200_init_info
- *
- * Allocates (if necessary) and initializes the driver structure.
- *
- * RETURNS:
- * ISD status code
- */
-int isd200_init_info(struct us_data *us)
-{
- int retStatus = ISD200_GOOD;
-
- if (!us->extra) {
- us->extra = (void *) kmalloc(sizeof(struct isd200_info), GFP_KERNEL);
- if (!us->extra) {
- US_DEBUGP("ERROR - kmalloc failure\n");
- retStatus = ISD200_ERROR;
- }
- }
-
- if (retStatus == ISD200_GOOD) {
- memset(us->extra, 0, sizeof(struct isd200_info));
- }
-
- return(retStatus);
-}
-
-/**************************************************************************
- * Initialization for the ISD200
- */
-
-int isd200_Initialization(struct us_data *us)
-{
- US_DEBUGP("ISD200 Initialization...\n");
-
- /* Initialize ISD200 info struct */
-
- if (isd200_init_info(us) == ISD200_ERROR) {
- US_DEBUGP("ERROR Initializing ISD200 Info struct\n");
- } else {
- /* Get device specific data */
-
- if (isd200_get_inquiry_data(us) != ISD200_GOOD)
- US_DEBUGP("ISD200 Initialization Failure\n");
- else
- US_DEBUGP("ISD200 Initialization complete\n");
- }
-
- return 0;
-}
-
-
-/**************************************************************************
- * Protocol and Transport for the ISD200 ASIC
- *
- * This protocol and transport are for ATA devices connected to an ISD200
- * ASIC. An ATAPI device that is conected as a slave device will be
- * detected in the driver initialization function and the protocol will
- * be changed to an ATAPI protocol (Transparent SCSI).
- *
- */
-
-void isd200_ata_command(Scsi_Cmnd *srb, struct us_data *us)
-{
- int sendToTransport = TRUE;
- union ata_cdb ataCdb;
-
- /* Make sure driver was initialized */
-
- if (us->extra == NULL)
- US_DEBUGP("ERROR Driver not initialized\n");
-
- /* Convert command */
- sendToTransport = isd200_scsi_to_ata(srb, us, &ataCdb);
-
- /* send the command to the transport layer */
- if (sendToTransport)
- isd200_invoke_transport(us, srb, &ataCdb);
-}
diff --git a/drivers/usb/class/storage/isd200.h b/drivers/usb/class/storage/isd200.h
deleted file mode 100644
index 70ebe1c39a86..000000000000
--- a/drivers/usb/class/storage/isd200.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Header File for In-System Design, Inc. ISD200 ASIC
- *
- * First release
- *
- * Current development and maintenance by:
- * (c) 2000 In-System Design, Inc. (support@in-system.com)
- *
- * See isd200.c for more information.
- *
- * 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, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _USB_ISD200_H
-#define _USB_ISD200_H
-
-extern void isd200_ata_command(Scsi_Cmnd *srb, struct us_data *us);
-extern int isd200_Initialization(struct us_data *us);
-
-#endif
diff --git a/drivers/usb/class/storage/jumpshot.c b/drivers/usb/class/storage/jumpshot.c
deleted file mode 100644
index 94b9941cff01..000000000000
--- a/drivers/usb/class/storage/jumpshot.c
+++ /dev/null
@@ -1,804 +0,0 @@
-/* Driver for Lexar "Jumpshot" Compact Flash reader
- *
- * jumpshot driver v0.1:
- *
- * First release
- *
- * Current development and maintenance by:
- * (c) 2000 Jimmie Mayfield (mayfield+usb@sackheads.org)
- * many thanks to Robert Baruch for the SanDisk SmartMedia reader driver
- * which I used as a template for this driver.
- * Some bugfixes and scatter-gather code by Gregory P. Smith
- * (greg-usb@electricrain.com)
- *
- * 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, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- /*
- * This driver attempts to support the Lexar Jumpshot USB CompactFlash
- * reader. Like many other USB CompactFlash readers, the Jumpshot contains
- * a USB-to-ATA chip.
- *
- * This driver supports reading and writing. If you're truly paranoid,
- * however, you can force the driver into a write-protected state by setting
- * the WP enable bits in jumpshot_handle_mode_sense. Basically this means
- * setting mode_param_header[3] = 0x80.
- */
-
-#include "transport.h"
-#include "protocol.h"
-#include "usb.h"
-#include "debug.h"
-#include "jumpshot.h"
-
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-
-extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
- u8 request, u8 requesttype, u16 value,
- u16 index, void *data, u16 size);
-extern int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe,
- unsigned int len, unsigned int *act_len);
-
-#if 0
-static void jumpshot_dump_data(unsigned char *data, int len)
-{
- unsigned char buf[80];
- int sofar = 0;
-
- if (!data)
- return;
-
- memset(buf, 0, sizeof(buf));
-
- for (sofar = 0; sofar < len; sofar++) {
- sprintf(buf + strlen(buf), "%02x ",
- ((unsigned int) data[sofar]) & 0xFF);
-
- if (sofar % 16 == 15) {
- US_DEBUGP("jumpshot: %s\n", buf);
- memset(buf, 0, sizeof(buf));
- }
- }
-
- if (strlen(buf) != 0)
- US_DEBUGP("jumpshot: %s\n", buf);
-}
-#endif
-
-/*
- * Send a control message and wait for the response.
- *
- * us - the pointer to the us_data structure for the device to use
- *
- * request - the URB Setup Packet's first 6 bytes. The first byte always
- * corresponds to the request type, and the second byte always corresponds
- * to the request. The other 4 bytes do not correspond to value and index,
- * since they are used in a custom way by the SCM protocol.
- *
- * xfer_data - a buffer from which to get, or to which to store, any data
- * that gets send or received, respectively, with the URB. Even though
- * it looks like we allocate a buffer in this code for the data, xfer_data
- * must contain enough allocated space.
- *
- * xfer_len - the number of bytes to send or receive with the URB.
- *
- * This routine snarfed from the SanDisk SDDR-09 driver
- *
- */
-static int jumpshot_send_control(struct us_data *us,
- int pipe,
- unsigned char request,
- unsigned char requesttype,
- unsigned short value,
- unsigned short index,
- unsigned char *xfer_data,
- unsigned int xfer_len)
-{
- int result;
-
- // Send the URB to the device and wait for a response.
-
- /* Why are request and request type reversed in this call? */
-
- result = usb_stor_control_msg(us, pipe,
- request, requesttype,
- value, index, xfer_data, xfer_len);
-
- // Check the return code for the command.
-
- if (result < 0) {
- /* if the command was aborted, indicate that */
- if (result == -ENOENT)
- return USB_STOR_TRANSPORT_ABORTED;
-
- /* a stall is a fatal condition from the device */
- if (result == -EPIPE) {
- US_DEBUGP("jumpshot_send_control: -- Stall on control pipe. Clearing\n");
- result = usb_clear_halt(us->pusb_dev, pipe);
- US_DEBUGP("jumpshot_send_control: -- usb_clear_halt() returns %d\n", result);
- return USB_STOR_TRANSPORT_FAILED;
- }
-
- /* Uh oh... serious problem here */
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- return USB_STOR_TRANSPORT_GOOD;
-}
-
-
-static int jumpshot_raw_bulk(int direction,
- struct us_data *us,
- unsigned char *data,
- unsigned int len)
-{
- int result;
- int act_len;
- int pipe;
-
- if (direction == SCSI_DATA_READ)
- pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
- else
- pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
-
- result = usb_stor_bulk_msg(us, data, pipe, len, &act_len);
-
- // if we stall, we need to clear it before we go on
- if (result == -EPIPE) {
- US_DEBUGP("jumpshot_raw_bulk: EPIPE. clearing endpoint halt for"
- " pipe 0x%x, stalled at %d bytes\n", pipe, act_len);
- usb_clear_halt(us->pusb_dev, pipe);
- }
-
- if (result) {
- // NAK - that means we've retried a few times already
- if (result == -ETIMEDOUT) {
- US_DEBUGP("jumpshot_raw_bulk: device NAKed\n");
- return US_BULK_TRANSFER_FAILED;
- }
-
- // -ENOENT -- we canceled this transfer
- if (result == -ENOENT) {
- US_DEBUGP("jumpshot_raw_bulk: transfer aborted\n");
- return US_BULK_TRANSFER_ABORTED;
- }
-
- if (result == -EPIPE) {
- US_DEBUGP("jumpshot_raw_bulk: output pipe stalled\n");
- return USB_STOR_TRANSPORT_FAILED;
- }
-
- // the catch-all case
- US_DEBUGP("jumpshot_raw_bulk: unknown error\n");
- return US_BULK_TRANSFER_FAILED;
- }
-
- if (act_len != len) {
- US_DEBUGP("jumpshot_raw_bulk: Warning. Transferred only %d bytes\n", act_len);
- return US_BULK_TRANSFER_SHORT;
- }
-
- US_DEBUGP("jumpshot_raw_bulk: Transfered %d of %d bytes\n", act_len, len);
- return US_BULK_TRANSFER_GOOD;
-}
-
-static inline int jumpshot_bulk_read(struct us_data *us,
- unsigned char *data,
- unsigned int len)
-{
- if (len == 0)
- return USB_STOR_TRANSPORT_GOOD;
-
- US_DEBUGP("jumpshot_bulk_read: len = %d\n", len);
- return jumpshot_raw_bulk(SCSI_DATA_READ, us, data, len);
-}
-
-
-static inline int jumpshot_bulk_write(struct us_data *us,
- unsigned char *data,
- unsigned int len)
-{
- if (len == 0)
- return USB_STOR_TRANSPORT_GOOD;
-
- US_DEBUGP("jumpshot_bulk_write: len = %d\n", len);
- return jumpshot_raw_bulk(SCSI_DATA_WRITE, us, data, len);
-}
-
-
-static int jumpshot_get_status(struct us_data *us)
-{
- unsigned char reply;
- int rc;
-
- if (!us)
- return USB_STOR_TRANSPORT_ERROR;
-
- // send the setup
- rc = jumpshot_send_control(us,
- usb_rcvctrlpipe(us->pusb_dev, 0),
- 0, 0xA0, 0, 7, &reply, 1);
-
- if (rc != USB_STOR_TRANSPORT_GOOD)
- return rc;
-
- if (reply != 0x50) {
- US_DEBUGP("jumpshot_get_status: 0x%2x\n",
- (unsigned short) (reply));
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- return USB_STOR_TRANSPORT_GOOD;
-}
-
-static int jumpshot_read_data(struct us_data *us,
- struct jumpshot_info *info,
- u32 sector,
- u32 sectors,
- unsigned char *dest,
- int use_sg)
-{
- unsigned char command[] = { 0, 0, 0, 0, 0, 0xe0, 0x20 };
- unsigned char *buffer = NULL;
- unsigned char *ptr;
- unsigned char thistime;
- struct scatterlist *sg = NULL;
- int totallen, len, result;
- int sg_idx = 0, current_sg_offset = 0;
- int transferred;
-
- // we're working in LBA mode. according to the ATA spec,
- // we can support up to 28-bit addressing. I don't know if Jumpshot
- // supports beyond 24-bit addressing. It's kind of hard to test
- // since it requires > 8GB CF card.
- //
- if (sector > 0x0FFFFFFF)
- return USB_STOR_TRANSPORT_ERROR;
-
- // If we're using scatter-gather, we have to create a new
- // buffer to read all of the data in first, since a
- // scatter-gather buffer could in theory start in the middle
- // of a page, which would be bad. A developer who wants a
- // challenge might want to write a limited-buffer
- // version of this code.
-
- totallen = sectors * info->ssize;
-
- do {
- // loop, never allocate or transfer more than 64k at once (min(128k, 255*info->ssize) is the real limit)
- len = min_t(int, totallen, 65536);
-
- if (use_sg) {
- sg = (struct scatterlist *) dest;
- buffer = kmalloc(len, GFP_NOIO);
- if (buffer == NULL)
- return USB_STOR_TRANSPORT_ERROR;
- ptr = buffer;
- } else {
- ptr = dest;
- }
-
- thistime = (len / info->ssize) & 0xff;
-
- command[0] = 0;
- command[1] = thistime;
- command[2] = sector & 0xFF;
- command[3] = (sector >> 8) & 0xFF;
- command[4] = (sector >> 16) & 0xFF;
-
- command[5] |= (sector >> 24) & 0x0F;
-
- // send the setup + command
- result = jumpshot_send_control(us,
- usb_sndctrlpipe(us->pusb_dev, 0),
- 0, 0x20, 0, 1, command, 7);
- if (result != USB_STOR_TRANSPORT_GOOD) {
- if (use_sg)
- kfree(buffer);
- return result;
- }
-
- // read the result
- result = jumpshot_bulk_read(us, ptr, len);
- if (result != USB_STOR_TRANSPORT_GOOD) {
- if (use_sg)
- kfree(buffer);
- return result;
- }
-
- US_DEBUGP("jumpshot_read_data: %d bytes\n", len);
- //jumpshot_dump_data(ptr, len);
-
- sectors -= thistime;
- sector += thistime;
-
- if (use_sg) {
- transferred = 0;
- while (sg_idx < use_sg && transferred < len) {
- if (len - transferred >= sg[sg_idx].length - current_sg_offset) {
- US_DEBUGP("jumpshot_read_data: adding %d bytes to %d byte sg buffer\n", sg[sg_idx].length - current_sg_offset, sg[sg_idx].length);
- memcpy(sg[sg_idx].address + current_sg_offset,
- buffer + transferred,
- sg[sg_idx].length - current_sg_offset);
- transferred += sg[sg_idx].length - current_sg_offset;
- current_sg_offset = 0;
- // on to the next sg buffer
- ++sg_idx;
- } else {
- US_DEBUGP("jumpshot_read_data: adding %d bytes to %d byte sg buffer\n", len - transferred, sg[sg_idx].length);
- memcpy(sg[sg_idx].address + current_sg_offset,
- buffer + transferred,
- len - transferred);
- current_sg_offset += len - transferred;
- // this sg buffer is only partially full and we're out of data to copy in
- break;
- }
- }
- kfree(buffer);
- } else {
- dest += len;
- }
-
- totallen -= len;
- } while (totallen > 0);
-
- return USB_STOR_TRANSPORT_GOOD;
-}
-
-
-static int jumpshot_write_data(struct us_data *us,
- struct jumpshot_info *info,
- u32 sector,
- u32 sectors,
- unsigned char *src,
- int use_sg)
-{
- unsigned char command[7] = { 0, 0, 0, 0, 0, 0xE0, 0x30 };
- unsigned char *buffer = NULL;
- unsigned char *ptr;
- unsigned char thistime;
- struct scatterlist *sg = NULL;
- int totallen, len, result, waitcount;
- int sg_idx = 0, current_sg_offset = 0;
- int transferred;
-
- // we're working in LBA mode. according to the ATA spec,
- // we can support up to 28-bit addressing. I don't know if Jumpshot
- // supports beyond 24-bit addressing. It's kind of hard to test
- // since it requires > 8GB CF card.
- //
- if (sector > 0x0FFFFFFF)
- return USB_STOR_TRANSPORT_ERROR;
-
- // If we're using scatter-gather, we have to create a new
- // buffer to read all of the data in first, since a
- // scatter-gather buffer could in theory start in the middle
- // of a page, which would be bad. A developer who wants a
- // challenge might want to write a limited-buffer
- // version of this code.
-
- totallen = sectors * info->ssize;
-
- do {
- // loop, never allocate or transfer more than 64k at once (min(128k, 255*info->ssize) is the real limit)
- len = min_t(int, totallen, 65536);
-
- if (use_sg) {
- sg = (struct scatterlist *) src;
- buffer = kmalloc(len, GFP_NOIO);
- if (buffer == NULL)
- return USB_STOR_TRANSPORT_ERROR;
- ptr = buffer;
-
- memset(buffer, 0, len);
-
- // copy the data from the sg bufs into the big contiguous buf
- //
- transferred = 0;
- while (transferred < len) {
- if (len - transferred >= sg[sg_idx].length - current_sg_offset) {
- US_DEBUGP("jumpshot_write_data: getting %d bytes from %d byte sg buffer\n", sg[sg_idx].length - current_sg_offset, sg[sg_idx].length);
- memcpy(ptr + transferred,
- sg[sg_idx].address + current_sg_offset,
- sg[sg_idx].length - current_sg_offset);
- transferred += sg[sg_idx].length - current_sg_offset;
- current_sg_offset = 0;
- // on to the next sg buffer
- ++sg_idx;
- } else {
- US_DEBUGP("jumpshot_write_data: getting %d bytes from %d byte sg buffer\n", len - transferred, sg[sg_idx].length);
- memcpy(ptr + transferred,
- sg[sg_idx].address + current_sg_offset,
- len - transferred);
- current_sg_offset += len - transferred;
- // we only copied part of this sg buffer
- break;
- }
- }
- } else {
- ptr = src;
- }
-
- thistime = (len / info->ssize) & 0xff;
-
- command[0] = 0;
- command[1] = thistime;
- command[2] = sector & 0xFF;
- command[3] = (sector >> 8) & 0xFF;
- command[4] = (sector >> 16) & 0xFF;
-
- command[5] |= (sector >> 24) & 0x0F;
-
- // send the setup + command
- result = jumpshot_send_control(us,
- usb_sndctrlpipe(us->pusb_dev, 0),
- 0, 0x20, 0, 1, command, 7);
-
- // send the data
- result = jumpshot_bulk_write(us, ptr, len);
- if (result != USB_STOR_TRANSPORT_GOOD) {
- if (use_sg)
- kfree(buffer);
- return result;
- }
-
- // read the result. apparently the bulk write can complete before the
- // jumpshot drive is finished writing. so we loop here until we
- // get a good return code
- waitcount = 0;
- do {
- result = jumpshot_get_status(us);
- if (result != USB_STOR_TRANSPORT_GOOD) {
- // I have not experimented to find the smallest value.
- //
- wait_ms(50);
- }
- } while ((result != USB_STOR_TRANSPORT_GOOD) && (waitcount < 10));
-
- if (result != USB_STOR_TRANSPORT_GOOD)
- US_DEBUGP("jumpshot_write_data: Gah! Waitcount = 10. Bad write!?\n");
-
- sectors -= thistime;
- sector += thistime;
-
- if (use_sg) {
- kfree(buffer);
- } else {
- src += len;
- }
-
- totallen -= len;
- } while (totallen > 0);
-
- return result;
-}
-
-static int jumpshot_id_device(struct us_data *us,
- struct jumpshot_info *info)
-{
- unsigned char command[2] = { 0xe0, 0xec };
- unsigned char reply[512];
- int rc;
-
- if (!us || !info)
- return USB_STOR_TRANSPORT_ERROR;
-
- // send the setup
- rc = jumpshot_send_control(us,
- usb_sndctrlpipe(us->pusb_dev, 0),
- 0, 0x20, 0, 6, command, 2);
-
- if (rc != USB_STOR_TRANSPORT_GOOD) {
- US_DEBUGP("jumpshot_id_device: Gah! send_control for read_capacity failed\n");
- return rc;
- }
-
- // read the reply
- rc = jumpshot_bulk_read(us, reply, sizeof(reply));
- if (rc != USB_STOR_TRANSPORT_GOOD)
- return rc;
-
- info->sectors = ((u32)(reply[117]) << 24) |
- ((u32)(reply[116]) << 16) |
- ((u32)(reply[115]) << 8) |
- ((u32)(reply[114]) );
-
- return USB_STOR_TRANSPORT_GOOD;
-}
-
-static int jumpshot_handle_mode_sense(struct us_data *us,
- Scsi_Cmnd * srb,
- unsigned char *ptr,
- int sense_6)
-{
- unsigned char mode_param_header[8] = {
- 0, 0, 0, 0, 0, 0, 0, 0
- };
- unsigned char rw_err_page[12] = {
- 0x1, 0xA, 0x21, 1, 0, 0, 0, 0, 1, 0, 0, 0
- };
- unsigned char cache_page[12] = {
- 0x8, 0xA, 0x1, 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
- unsigned char rbac_page[12] = {
- 0x1B, 0xA, 0, 0x81, 0, 0, 0, 0, 0, 0, 0, 0
- };
- unsigned char timer_page[8] = {
- 0x1C, 0x6, 0, 0, 0, 0
- };
- unsigned char pc, page_code;
- unsigned short total_len = 0;
- unsigned short param_len, i = 0;
-
-
- if (sense_6)
- param_len = srb->cmnd[4];
- else
- param_len = ((u32) (srb->cmnd[7]) >> 8) | ((u32) (srb->cmnd[8]));
-
-
- pc = srb->cmnd[2] >> 6;
- page_code = srb->cmnd[2] & 0x3F;
-
- switch (pc) {
- case 0x0:
- US_DEBUGP("jumpshot_handle_mode_sense: Current values\n");
- break;
- case 0x1:
- US_DEBUGP("jumpshot_handle_mode_sense: Changeable values\n");
- break;
- case 0x2:
- US_DEBUGP("jumpshot_handle_mode_sense: Default values\n");
- break;
- case 0x3:
- US_DEBUGP("jumpshot_handle_mode_sense: Saves values\n");
- break;
- }
-
- mode_param_header[3] = 0x80; // write enable
-
- switch (page_code) {
- case 0x0:
- // vendor-specific mode
- return USB_STOR_TRANSPORT_ERROR;
-
- case 0x1:
- total_len = sizeof(rw_err_page);
- mode_param_header[0] = total_len >> 8;
- mode_param_header[1] = total_len & 0xFF;
- mode_param_header[3] = 0x00; // WP enable: 0x80
-
- memcpy(ptr, mode_param_header, sizeof(mode_param_header));
- i += sizeof(mode_param_header);
- memcpy(ptr + i, rw_err_page, sizeof(rw_err_page));
- break;
-
- case 0x8:
- total_len = sizeof(cache_page);
- mode_param_header[0] = total_len >> 8;
- mode_param_header[1] = total_len & 0xFF;
- mode_param_header[3] = 0x00; // WP enable: 0x80
-
- memcpy(ptr, mode_param_header, sizeof(mode_param_header));
- i += sizeof(mode_param_header);
- memcpy(ptr + i, cache_page, sizeof(cache_page));
- break;
-
- case 0x1B:
- total_len = sizeof(rbac_page);
- mode_param_header[0] = total_len >> 8;
- mode_param_header[1] = total_len & 0xFF;
- mode_param_header[3] = 0x00; // WP enable: 0x80
-
- memcpy(ptr, mode_param_header, sizeof(mode_param_header));
- i += sizeof(mode_param_header);
- memcpy(ptr + i, rbac_page, sizeof(rbac_page));
- break;
-
- case 0x1C:
- total_len = sizeof(timer_page);
- mode_param_header[0] = total_len >> 8;
- mode_param_header[1] = total_len & 0xFF;
- mode_param_header[3] = 0x00; // WP enable: 0x80
-
- memcpy(ptr, mode_param_header, sizeof(mode_param_header));
- i += sizeof(mode_param_header);
- memcpy(ptr + i, timer_page, sizeof(timer_page));
- break;
-
- case 0x3F:
- total_len = sizeof(timer_page) + sizeof(rbac_page) +
- sizeof(cache_page) + sizeof(rw_err_page);
- mode_param_header[0] = total_len >> 8;
- mode_param_header[1] = total_len & 0xFF;
- mode_param_header[3] = 0x00; // WP enable: 0x80
-
- memcpy(ptr, mode_param_header, sizeof(mode_param_header));
- i += sizeof(mode_param_header);
- memcpy(ptr + i, timer_page, sizeof(timer_page));
- i += sizeof(timer_page);
- memcpy(ptr + i, rbac_page, sizeof(rbac_page));
- i += sizeof(rbac_page);
- memcpy(ptr + i, cache_page, sizeof(cache_page));
- i += sizeof(cache_page);
- memcpy(ptr + i, rw_err_page, sizeof(rw_err_page));
- break;
- }
-
- return USB_STOR_TRANSPORT_GOOD;
-}
-
-
-void jumpshot_info_destructor(void *extra)
-{
- // this routine is a placeholder...
- // currently, we don't allocate any extra blocks so we're okay
-}
-
-
-
-// Transport for the Lexar 'Jumpshot'
-//
-int jumpshot_transport(Scsi_Cmnd * srb, struct us_data *us)
-{
- struct jumpshot_info *info;
- int rc;
- unsigned long block, blocks;
- unsigned char *ptr = NULL;
- unsigned char inquiry_response[36] = {
- 0x00, 0x80, 0x00, 0x01, 0x1F, 0x00, 0x00, 0x00
- };
-
-
- if (!us->extra) {
- us->extra = kmalloc(sizeof(struct jumpshot_info), GFP_NOIO);
- if (!us->extra) {
- US_DEBUGP("jumpshot_transport: Gah! Can't allocate storage for jumpshot info struct!\n");
- return USB_STOR_TRANSPORT_ERROR;
- }
- memset(us->extra, 0, sizeof(struct jumpshot_info));
- us->extra_destructor = jumpshot_info_destructor;
- }
-
- info = (struct jumpshot_info *) (us->extra);
- ptr = (unsigned char *) srb->request_buffer;
-
- if (srb->cmnd[0] == INQUIRY) {
- US_DEBUGP("jumpshot_transport: INQUIRY. Returning bogus response.\n");
- memset(inquiry_response + 8, 0, 28);
- fill_inquiry_response(us, inquiry_response, 36);
- return USB_STOR_TRANSPORT_GOOD;
- }
-
- if (srb->cmnd[0] == READ_CAPACITY) {
- info->ssize = 0x200; // hard coded 512 byte sectors as per ATA spec
-
- rc = jumpshot_get_status(us);
- if (rc != USB_STOR_TRANSPORT_GOOD)
- return rc;
-
- rc = jumpshot_id_device(us, info);
- if (rc != USB_STOR_TRANSPORT_GOOD)
- return rc;
-
- US_DEBUGP("jumpshot_transport: READ_CAPACITY: %ld sectors, %ld bytes per sector\n",
- info->sectors, info->ssize);
-
- // build the reply
- //
- ptr[0] = (info->sectors >> 24) & 0xFF;
- ptr[1] = (info->sectors >> 16) & 0xFF;
- ptr[2] = (info->sectors >> 8) & 0xFF;
- ptr[3] = (info->sectors) & 0xFF;
-
- ptr[4] = (info->ssize >> 24) & 0xFF;
- ptr[5] = (info->ssize >> 16) & 0xFF;
- ptr[6] = (info->ssize >> 8) & 0xFF;
- ptr[7] = (info->ssize) & 0xFF;
-
- return USB_STOR_TRANSPORT_GOOD;
- }
-
- if (srb->cmnd[0] == MODE_SELECT_10) {
- US_DEBUGP("jumpshot_transport: Gah! MODE_SELECT_10.\n");
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- if (srb->cmnd[0] == READ_10) {
- block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
- ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5]));
-
- blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
-
- US_DEBUGP("jumpshot_transport: READ_10: read block 0x%04lx count %ld\n", block, blocks);
- return jumpshot_read_data(us, info, block, blocks, ptr, srb->use_sg);
- }
-
- if (srb->cmnd[0] == READ_12) {
- // I don't think we'll ever see a READ_12 but support it anyway...
- //
- block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
- ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5]));
-
- blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
- ((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9]));
-
- US_DEBUGP("jumpshot_transport: READ_12: read block 0x%04lx count %ld\n", block, blocks);
- return jumpshot_read_data(us, info, block, blocks, ptr, srb->use_sg);
- }
-
- if (srb->cmnd[0] == WRITE_10) {
- block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
- ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5]));
-
- blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
-
- US_DEBUGP("jumpshot_transport: WRITE_10: write block 0x%04lx count %ld\n", block, blocks);
- return jumpshot_write_data(us, info, block, blocks, ptr, srb->use_sg);
- }
-
- if (srb->cmnd[0] == WRITE_12) {
- // I don't think we'll ever see a WRITE_12 but support it anyway...
- //
- block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
- ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5]));
-
- blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
- ((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9]));
-
- US_DEBUGP("jumpshot_transport: WRITE_12: write block 0x%04lx count %ld\n", block, blocks);
- return jumpshot_write_data(us, info, block, blocks, ptr, srb->use_sg);
- }
-
-
- if (srb->cmnd[0] == TEST_UNIT_READY) {
- US_DEBUGP("jumpshot_transport: TEST_UNIT_READY.\n");
- return jumpshot_get_status(us);
- }
-
- if (srb->cmnd[0] == REQUEST_SENSE) {
- US_DEBUGP("jumpshot_transport: REQUEST_SENSE. Returning NO SENSE for now\n");
-
- ptr[0] = 0xF0;
- ptr[2] = info->sense_key;
- ptr[7] = 11;
- ptr[12] = info->sense_asc;
- ptr[13] = info->sense_ascq;
-
- return USB_STOR_TRANSPORT_GOOD;
- }
-
- if (srb->cmnd[0] == MODE_SENSE) {
- US_DEBUGP("jumpshot_transport: MODE_SENSE_6 detected\n");
- return jumpshot_handle_mode_sense(us, srb, ptr, TRUE);
- }
-
- if (srb->cmnd[0] == MODE_SENSE_10) {
- US_DEBUGP("jumpshot_transport: MODE_SENSE_10 detected\n");
- return jumpshot_handle_mode_sense(us, srb, ptr, FALSE);
- }
-
- if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
- // sure. whatever. not like we can stop the user from popping
- // the media out of the device (no locking doors, etc)
- //
- return USB_STOR_TRANSPORT_GOOD;
- }
-
- US_DEBUGP("jumpshot_transport: Gah! Unknown command: %d (0x%x)\n", srb->cmnd[0], srb->cmnd[0]);
- return USB_STOR_TRANSPORT_ERROR;
-}
diff --git a/drivers/usb/class/storage/jumpshot.h b/drivers/usb/class/storage/jumpshot.h
deleted file mode 100644
index 8147197cd4fc..000000000000
--- a/drivers/usb/class/storage/jumpshot.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Driver for Lexar "Jumpshot" USB Compact Flash reader
- * Header File
- *
- * Current development and maintenance by:
- * (c) 2000 Jimmie Mayfield (mayfield+usb@sackheads.org)
- *
- * See jumpshot.c for more explanation
- *
- * 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, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _USB_JUMPSHOT_H
-#define _USB_JUMPSHOT_H
-
-extern int jumpshot_transport(Scsi_Cmnd *srb, struct us_data *us);
-
-struct jumpshot_info {
- unsigned long sectors; // total sector count
- unsigned long ssize; // sector size in bytes
-
- // the following aren't used yet
- unsigned char sense_key;
- unsigned long sense_asc; // additional sense code
- unsigned long sense_ascq; // additional sense code qualifier
-};
-
-#endif
diff --git a/drivers/usb/class/storage/protocol.c b/drivers/usb/class/storage/protocol.c
deleted file mode 100644
index c2bc41be7357..000000000000
--- a/drivers/usb/class/storage/protocol.c
+++ /dev/null
@@ -1,339 +0,0 @@
-/* Driver for USB Mass Storage compliant devices
- *
- * $Id: protocol.c,v 1.11 2002/01/13 06:40:25 mdharm Exp $
- *
- * Current development and maintenance by:
- * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
- *
- * Developed with the assistance of:
- * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
- *
- * Initial work by:
- * (c) 1999 Michael Gee (michael@linuxspecific.com)
- *
- * This driver is based on the 'USB Mass Storage Class' document. This
- * describes in detail the protocol used to communicate with such
- * devices. Clearly, the designers had SCSI and ATAPI commands in
- * mind when they created this document. The commands are all very
- * similar to commands in the SCSI-II and ATAPI specifications.
- *
- * It is important to note that in a number of cases this class
- * exhibits class-specific exemptions from the USB specification.
- * Notably the usage of NAK, STALL and ACK differs from the norm, in
- * that they are used to communicate wait, failed and OK on commands.
- *
- * Also, for certain devices, the interrupt endpoint is used to convey
- * status of a command.
- *
- * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more
- * information about this driver.
- *
- * 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, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include "protocol.h"
-#include "usb.h"
-#include "debug.h"
-#include "scsiglue.h"
-#include "transport.h"
-
-/***********************************************************************
- * Helper routines
- ***********************************************************************/
-
-/* Fix-up the return data from an INQUIRY command to show
- * ANSI SCSI rev 2 so we don't confuse the SCSI layers above us
- */
-void fix_inquiry_data(Scsi_Cmnd *srb)
-{
- unsigned char *data_ptr;
-
- /* verify that it's an INQUIRY command */
- if (srb->cmnd[0] != INQUIRY)
- return;
-
- US_DEBUGP("Fixing INQUIRY data to show SCSI rev 2\n");
-
- /* find the location of the data */
- if (srb->use_sg)
- BUG();
-
- data_ptr = (unsigned char *) srb->request_buffer;
-
- /* Change the SCSI revision number */
- data_ptr[2] = (data_ptr[2] & ~7) | 2;
-}
-
-/***********************************************************************
- * Protocol routines
- ***********************************************************************/
-
-void usb_stor_qic157_command(Scsi_Cmnd *srb, struct us_data *us)
-{
- /* Pad the ATAPI command with zeros
- * NOTE: This only works because a Scsi_Cmnd struct field contains
- * a unsigned char cmnd[12], so we know we have storage available
- */
- for (; srb->cmd_len<12; srb->cmd_len++)
- srb->cmnd[srb->cmd_len] = 0;
-
- /* set command length to 12 bytes */
- srb->cmd_len = 12;
-
- /* send the command to the transport layer */
- usb_stor_invoke_transport(srb, us);
-
- /* fix the INQUIRY data if necessary */
- fix_inquiry_data(srb);
-}
-
-void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us)
-{
- int old_cmnd = 0;
-
- /* Fix some commands -- this is a form of mode translation
- * ATAPI devices only accept 12 byte long commands
- *
- * NOTE: This only works because a Scsi_Cmnd struct field contains
- * a unsigned char cmnd[12], so we know we have storage available
- */
-
- /* Pad the ATAPI command with zeros */
- for (; srb->cmd_len<12; srb->cmd_len++)
- srb->cmnd[srb->cmd_len] = 0;
-
- /* set command length to 12 bytes */
- srb->cmd_len = 12;
-
- /* determine the correct (or minimum) data length for these commands */
- switch (srb->cmnd[0]) {
-
- /* change MODE_SENSE/MODE_SELECT from 6 to 10 byte commands */
- case MODE_SENSE:
- case MODE_SELECT:
- /* save the command so we can tell what it was */
- old_cmnd = srb->cmnd[0];
-
- srb->cmnd[11] = 0;
- srb->cmnd[10] = 0;
- srb->cmnd[9] = 0;
- srb->cmnd[8] = srb->cmnd[4];
- srb->cmnd[7] = 0;
- srb->cmnd[6] = 0;
- srb->cmnd[5] = 0;
- srb->cmnd[4] = 0;
- srb->cmnd[3] = 0;
- srb->cmnd[2] = srb->cmnd[2];
- srb->cmnd[1] = srb->cmnd[1];
- srb->cmnd[0] = srb->cmnd[0] | 0x40;
- break;
-
- /* change READ_6/WRITE_6 to READ_10/WRITE_10, which
- * are ATAPI commands */
- case WRITE_6:
- case READ_6:
- srb->cmnd[11] = 0;
- srb->cmnd[10] = 0;
- srb->cmnd[9] = 0;
- srb->cmnd[8] = srb->cmnd[4];
- srb->cmnd[7] = 0;
- srb->cmnd[6] = 0;
- srb->cmnd[5] = srb->cmnd[3];
- srb->cmnd[4] = srb->cmnd[2];
- srb->cmnd[3] = srb->cmnd[1] & 0x1F;
- srb->cmnd[2] = 0;
- srb->cmnd[1] = srb->cmnd[1] & 0xE0;
- srb->cmnd[0] = srb->cmnd[0] | 0x20;
- break;
- } /* end switch on cmnd[0] */
-
- /* convert MODE_SELECT data here */
- if (old_cmnd == MODE_SELECT)
- usb_stor_scsiSense6to10(srb);
-
- /* send the command to the transport layer */
- usb_stor_invoke_transport(srb, us);
-
- /* Fix the MODE_SENSE data if we translated the command */
- if ((old_cmnd == MODE_SENSE) && (status_byte(srb->result) == GOOD))
- usb_stor_scsiSense10to6(srb);
-
- /* fix the INQUIRY data if necessary */
- fix_inquiry_data(srb);
-}
-
-
-void usb_stor_ufi_command(Scsi_Cmnd *srb, struct us_data *us)
-{
- int old_cmnd = 0;
-
- /* fix some commands -- this is a form of mode translation
- * UFI devices only accept 12 byte long commands
- *
- * NOTE: This only works because a Scsi_Cmnd struct field contains
- * a unsigned char cmnd[12], so we know we have storage available
- */
-
- /* set command length to 12 bytes (this affects the transport layer) */
- srb->cmd_len = 12;
-
- /* determine the correct (or minimum) data length for these commands */
- switch (srb->cmnd[0]) {
-
- /* for INQUIRY, UFI devices only ever return 36 bytes */
- case INQUIRY:
- srb->cmnd[4] = 36;
- break;
-
- /* change MODE_SENSE/MODE_SELECT from 6 to 10 byte commands */
- case MODE_SENSE:
- case MODE_SELECT:
- /* save the command so we can tell what it was */
- old_cmnd = srb->cmnd[0];
-
- srb->cmnd[11] = 0;
- srb->cmnd[10] = 0;
- srb->cmnd[9] = 0;
-
- /* if we're sending data, we send all. If getting data,
- * get the minimum */
- if (srb->cmnd[0] == MODE_SELECT)
- srb->cmnd[8] = srb->cmnd[4];
- else
- srb->cmnd[8] = 8;
-
- srb->cmnd[7] = 0;
- srb->cmnd[6] = 0;
- srb->cmnd[5] = 0;
- srb->cmnd[4] = 0;
- srb->cmnd[3] = 0;
- srb->cmnd[2] = srb->cmnd[2];
- srb->cmnd[1] = srb->cmnd[1];
- srb->cmnd[0] = srb->cmnd[0] | 0x40;
- break;
-
- /* again, for MODE_SENSE_10, we get the minimum (8) */
- case MODE_SENSE_10:
- srb->cmnd[7] = 0;
- srb->cmnd[8] = 8;
- break;
-
- /* for REQUEST_SENSE, UFI devices only ever return 18 bytes */
- case REQUEST_SENSE:
- srb->cmnd[4] = 18;
- break;
-
- /* change READ_6/WRITE_6 to READ_10/WRITE_10, which
- * are UFI commands */
- case WRITE_6:
- case READ_6:
- srb->cmnd[11] = 0;
- srb->cmnd[10] = 0;
- srb->cmnd[9] = 0;
- srb->cmnd[8] = srb->cmnd[4];
- srb->cmnd[7] = 0;
- srb->cmnd[6] = 0;
- srb->cmnd[5] = srb->cmnd[3];
- srb->cmnd[4] = srb->cmnd[2];
- srb->cmnd[3] = srb->cmnd[1] & 0x1F;
- srb->cmnd[2] = 0;
- srb->cmnd[1] = srb->cmnd[1] & 0xE0;
- srb->cmnd[0] = srb->cmnd[0] | 0x20;
- break;
- } /* end switch on cmnd[0] */
-
- /* convert MODE_SELECT data here */
- if (old_cmnd == MODE_SELECT)
- usb_stor_scsiSense6to10(srb);
-
- /* send the command to the transport layer */
- usb_stor_invoke_transport(srb, us);
-
- /* Fix the MODE_SENSE data if we translated the command */
- if ((old_cmnd == MODE_SENSE) && (status_byte(srb->result) == GOOD))
- usb_stor_scsiSense10to6(srb);
-
- /* Fix the data for an INQUIRY, if necessary */
- fix_inquiry_data(srb);
-}
-
-void usb_stor_transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us)
-{
- int old_cmnd = 0;
-
- /* This code supports devices which do not support {READ|WRITE}_6
- * Apparently, neither Windows or MacOS will use these commands,
- * so some devices do not support them
- */
- if (us->flags & US_FL_MODE_XLATE) {
- US_DEBUGP("Invoking Mode Translation\n");
- /* save the old command for later */
- old_cmnd = srb->cmnd[0];
-
- switch (srb->cmnd[0]) {
- /* change READ_6/WRITE_6 to READ_10/WRITE_10 */
- case WRITE_6:
- case READ_6:
- srb->cmd_len = 12;
- srb->cmnd[11] = 0;
- srb->cmnd[10] = 0;
- srb->cmnd[9] = 0;
- srb->cmnd[8] = srb->cmnd[4];
- srb->cmnd[7] = 0;
- srb->cmnd[6] = 0;
- srb->cmnd[5] = srb->cmnd[3];
- srb->cmnd[4] = srb->cmnd[2];
- srb->cmnd[3] = srb->cmnd[1] & 0x1F;
- srb->cmnd[2] = 0;
- srb->cmnd[1] = srb->cmnd[1] & 0xE0;
- srb->cmnd[0] = srb->cmnd[0] | 0x20;
- break;
-
- /* convert MODE_SELECT data here */
- case MODE_SENSE:
- case MODE_SELECT:
- srb->cmd_len = 12;
- srb->cmnd[11] = 0;
- srb->cmnd[10] = 0;
- srb->cmnd[9] = 0;
- srb->cmnd[8] = srb->cmnd[4];
- srb->cmnd[7] = 0;
- srb->cmnd[6] = 0;
- srb->cmnd[5] = 0;
- srb->cmnd[4] = 0;
- srb->cmnd[3] = 0;
- srb->cmnd[2] = srb->cmnd[2];
- srb->cmnd[1] = srb->cmnd[1];
- srb->cmnd[0] = srb->cmnd[0] | 0x40;
- break;
- } /* switch (srb->cmnd[0]) */
- } /* if (us->flags & US_FL_MODE_XLATE) */
-
- /* convert MODE_SELECT data here */
- if ((us->flags & US_FL_MODE_XLATE) && (old_cmnd == MODE_SELECT))
- usb_stor_scsiSense6to10(srb);
-
- /* send the command to the transport layer */
- usb_stor_invoke_transport(srb, us);
-
- /* Fix the MODE_SENSE data if we translated the command */
- if ((us->flags & US_FL_MODE_XLATE) && (old_cmnd == MODE_SENSE)
- && (status_byte(srb->result) == GOOD))
- usb_stor_scsiSense10to6(srb);
-
- /* fix the INQUIRY data if necessary */
- fix_inquiry_data(srb);
-}
-
diff --git a/drivers/usb/class/storage/protocol.h b/drivers/usb/class/storage/protocol.h
deleted file mode 100644
index 4153a6c7144b..000000000000
--- a/drivers/usb/class/storage/protocol.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/* Driver for USB Mass Storage compliant devices
- * Protocol Functions Header File
- *
- * $Id: protocol.h,v 1.4 2001/02/13 07:10:03 mdharm Exp $
- *
- * Current development and maintenance by:
- * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
- *
- * This driver is based on the 'USB Mass Storage Class' document. This
- * describes in detail the protocol used to communicate with such
- * devices. Clearly, the designers had SCSI and ATAPI commands in
- * mind when they created this document. The commands are all very
- * similar to commands in the SCSI-II and ATAPI specifications.
- *
- * It is important to note that in a number of cases this class
- * exhibits class-specific exemptions from the USB specification.
- * Notably the usage of NAK, STALL and ACK differs from the norm, in
- * that they are used to communicate wait, failed and OK on commands.
- *
- * Also, for certain devices, the interrupt endpoint is used to convey
- * status of a command.
- *
- * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more
- * information about this driver.
- *
- * 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, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _PROTOCOL_H_
-#define _PROTOCOL_H_
-
-#include <linux/blk.h>
-#include "scsi.h"
-#include "usb.h"
-
-/* Sub Classes */
-
-#define US_SC_RBC 0x01 /* Typically, flash devices */
-#define US_SC_8020 0x02 /* CD-ROM */
-#define US_SC_QIC 0x03 /* QIC-157 Tapes */
-#define US_SC_UFI 0x04 /* Floppy */
-#define US_SC_8070 0x05 /* Removable media */
-#define US_SC_SCSI 0x06 /* Transparent */
-#define US_SC_ISD200 0x07 /* ISD200 ATA */
-#define US_SC_MIN US_SC_RBC
-#define US_SC_MAX US_SC_ISD200
-
-extern void usb_stor_ATAPI_command(Scsi_Cmnd*, struct us_data*);
-extern void usb_stor_qic157_command(Scsi_Cmnd*, struct us_data*);
-extern void usb_stor_ufi_command(Scsi_Cmnd*, struct us_data*);
-extern void usb_stor_transparent_scsi_command(Scsi_Cmnd*, struct us_data*);
-
-#endif
diff --git a/drivers/usb/class/storage/scsiglue.c b/drivers/usb/class/storage/scsiglue.c
deleted file mode 100644
index 596aa799adf1..000000000000
--- a/drivers/usb/class/storage/scsiglue.c
+++ /dev/null
@@ -1,900 +0,0 @@
-/* Driver for USB Mass Storage compliant devices
- * SCSI layer glue code
- *
- * $Id: scsiglue.c,v 1.24 2001/11/11 03:33:58 mdharm Exp $
- *
- * Current development and maintenance by:
- * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
- *
- * Developed with the assistance of:
- * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
- * (c) 2000 Stephen J. Gowdy (SGowdy@lbl.gov)
- *
- * Initial work by:
- * (c) 1999 Michael Gee (michael@linuxspecific.com)
- *
- * This driver is based on the 'USB Mass Storage Class' document. This
- * describes in detail the protocol used to communicate with such
- * devices. Clearly, the designers had SCSI and ATAPI commands in
- * mind when they created this document. The commands are all very
- * similar to commands in the SCSI-II and ATAPI specifications.
- *
- * It is important to note that in a number of cases this class
- * exhibits class-specific exemptions from the USB specification.
- * Notably the usage of NAK, STALL and ACK differs from the norm, in
- * that they are used to communicate wait, failed and OK on commands.
- *
- * Also, for certain devices, the interrupt endpoint is used to convey
- * status of a command.
- *
- * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more
- * information about this driver.
- *
- * 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, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include "scsiglue.h"
-#include "usb.h"
-#include "debug.h"
-#include "transport.h"
-
-#include <linux/slab.h>
-
-/*
- * kernel thread actions
- */
-
-#define US_ACT_COMMAND 1
-#define US_ACT_DEVICE_RESET 2
-#define US_ACT_BUS_RESET 3
-#define US_ACT_HOST_RESET 4
-#define US_ACT_EXIT 5
-
-/***********************************************************************
- * Host functions
- ***********************************************************************/
-
-static const char* host_info(struct Scsi_Host *host)
-{
- return "SCSI emulation for USB Mass Storage devices";
-}
-
-/* detect a virtual adapter (always works) */
-static int detect(struct SHT *sht)
-{
- struct us_data *us;
- char local_name[32];
-
- /* This is not nice at all, but how else are we to get the
- * data here? */
- us = (struct us_data *)sht->proc_dir;
-
- /* set up the name of our subdirectory under /proc/scsi/ */
- sprintf(local_name, "usb-storage-%d", us->host_number);
- sht->proc_name = kmalloc (strlen(local_name) + 1, GFP_KERNEL);
- if (!sht->proc_name)
- return 0;
- strcpy(sht->proc_name, local_name);
-
- /* we start with no /proc directory entry */
- sht->proc_dir = NULL;
-
- /* register the host */
- us->host = scsi_register(sht, sizeof(us));
- if (us->host) {
- us->host->hostdata[0] = (unsigned long)us;
- us->host_no = us->host->host_no;
- return 1;
- }
-
- /* odd... didn't register properly. Abort and free pointers */
- kfree(sht->proc_name);
- sht->proc_name = NULL;
- return 0;
-}
-
-/* Release all resources used by the virtual host
- *
- * NOTE: There is no contention here, because we're already deregistered
- * the driver and we're doing each virtual host in turn, not in parallel
- */
-static int release(struct Scsi_Host *psh)
-{
- struct us_data *us = (struct us_data *)psh->hostdata[0];
-
- US_DEBUGP("release() called for host %s\n", us->htmplt.name);
-
- /* Kill the control threads
- *
- * Enqueue the command, wake up the thread, and wait for
- * notification that it's exited.
- */
- US_DEBUGP("-- sending US_ACT_EXIT command to thread\n");
- us->action = US_ACT_EXIT;
-
- up(&(us->sema));
- wait_for_completion(&(us->notify));
-
- /* remove the pointer to the data structure we were using */
- (struct us_data*)psh->hostdata[0] = NULL;
-
- /* we always have a successful release */
- return 0;
-}
-
-/* run command */
-static int command( Scsi_Cmnd *srb )
-{
- US_DEBUGP("Bad use of us_command\n");
-
- return DID_BAD_TARGET << 16;
-}
-
-/* run command */
-static int queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *))
-{
- struct us_data *us = (struct us_data *)srb->host->hostdata[0];
-
- US_DEBUGP("queuecommand() called\n");
- srb->host_scribble = (unsigned char *)us;
-
- /* get exclusive access to the structures we want */
- down(&(us->queue_exclusion));
-
- /* enqueue the command */
- us->queue_srb = srb;
- srb->scsi_done = done;
- us->action = US_ACT_COMMAND;
-
- /* release the lock on the structure */
- up(&(us->queue_exclusion));
-
- /* wake up the process task */
- up(&(us->sema));
-
- return 0;
-}
-
-/***********************************************************************
- * Error handling functions
- ***********************************************************************/
-
-/* Command abort */
-static int command_abort( Scsi_Cmnd *srb )
-{
- struct us_data *us = (struct us_data *)srb->host->hostdata[0];
-
- US_DEBUGP("command_abort() called\n");
-
- /* if we're stuck waiting for an IRQ, simulate it */
- if (atomic_read(us->ip_wanted)) {
- US_DEBUGP("-- simulating missing IRQ\n");
- up(&(us->ip_waitq));
- }
-
- /* if the device has been removed, this worked */
- if (!us->pusb_dev) {
- US_DEBUGP("-- device removed already\n");
- return SUCCESS;
- }
-
- /* if we have an urb pending, let's wake the control thread up */
- if (us->current_urb->status == -EINPROGRESS) {
- /* cancel the URB -- this will automatically wake the thread */
- usb_unlink_urb(us->current_urb);
-
- /* wait for us to be done */
- wait_for_completion(&(us->notify));
- return SUCCESS;
- }
-
- US_DEBUGP ("-- nothing to abort\n");
- return FAILED;
-}
-
-/* This invokes the transport reset mechanism to reset the state of the
- * device */
-static int device_reset( Scsi_Cmnd *srb )
-{
- struct us_data *us = (struct us_data *)srb->host->hostdata[0];
-
- US_DEBUGP("device_reset() called\n" );
- return us->transport_reset(us);
-}
-
-/* This resets the device port, and simulates the device
- * disconnect/reconnect for all drivers which have claimed other
- * interfaces. */
-static int bus_reset( Scsi_Cmnd *srb )
-{
- struct us_data *us = (struct us_data *)srb->host->hostdata[0];
- int i;
- int result;
-
- /* we use the usb_reset_device() function to handle this for us */
- US_DEBUGP("bus_reset() called\n");
-
- /* if the device has been removed, this worked */
- if (!us->pusb_dev) {
- US_DEBUGP("-- device removed already\n");
- return SUCCESS;
- }
-
- /* release the IRQ, if we have one */
- down(&(us->irq_urb_sem));
- if (us->irq_urb) {
- US_DEBUGP("-- releasing irq URB\n");
- result = usb_unlink_urb(us->irq_urb);
- US_DEBUGP("-- usb_unlink_urb() returned %d\n", result);
- }
- up(&(us->irq_urb_sem));
-
- /* attempt to reset the port */
- if (usb_reset_device(us->pusb_dev) < 0)
- return FAILED;
-
- /* FIXME: This needs to lock out driver probing while it's working
- * or we can have race conditions */
- for (i = 0; i < us->pusb_dev->actconfig->bNumInterfaces; i++) {
- struct usb_interface *intf =
- &us->pusb_dev->actconfig->interface[i];
- const struct usb_device_id *id;
-
- /* if this is an unclaimed interface, skip it */
- if (!intf->driver) {
- continue;
- }
-
- US_DEBUGP("Examinging driver %s...", intf->driver->name);
- /* skip interfaces which we've claimed */
- if (intf->driver == &usb_storage_driver) {
- US_DEBUGPX("skipping ourselves.\n");
- continue;
- }
-
- /* simulate a disconnect and reconnect for all interfaces */
- US_DEBUGPX("simulating disconnect/reconnect.\n");
- down(&intf->driver->serialize);
- intf->driver->disconnect(us->pusb_dev, intf->private_data);
- id = usb_match_id(us->pusb_dev, intf, intf->driver->id_table);
- intf->driver->probe(us->pusb_dev, i, id);
- up(&intf->driver->serialize);
- }
-
- /* re-allocate the IRQ URB and submit it to restore connectivity
- * for CBI devices
- */
- if (us->protocol == US_PR_CBI) {
- down(&(us->irq_urb_sem));
- us->irq_urb->dev = us->pusb_dev;
- result = usb_submit_urb(us->irq_urb, GFP_NOIO);
- US_DEBUGP("usb_submit_urb() returns %d\n", result);
- up(&(us->irq_urb_sem));
- }
-
- US_DEBUGP("bus_reset() complete\n");
- return SUCCESS;
-}
-
-/* FIXME: This doesn't do anything right now */
-static int host_reset( Scsi_Cmnd *srb )
-{
- printk(KERN_CRIT "usb-storage: host_reset() requested but not implemented\n" );
- return FAILED;
-}
-
-/***********************************************************************
- * /proc/scsi/ functions
- ***********************************************************************/
-
-/* we use this macro to help us write into the buffer */
-#undef SPRINTF
-#define SPRINTF(args...) \
- do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0)
-
-static int proc_info (char *buffer, char **start, off_t offset, int length,
- int hostno, int inout)
-{
- struct us_data *us;
- char *pos = buffer;
-
- /* if someone is sending us data, just throw it away */
- if (inout)
- return length;
-
- /* lock the data structures */
- down(&us_list_semaphore);
-
- /* find our data from hostno */
- us = us_list;
- while (us) {
- if (us->host_no == hostno)
- break;
- us = us->next;
- }
-
- /* release our lock on the data structures */
- up(&us_list_semaphore);
-
- /* if we couldn't find it, we return an error */
- if (!us) {
- return -ESRCH;
- }
-
- /* print the controller name */
- SPRINTF(" Host scsi%d: usb-storage\n", hostno);
-
- /* print product, vendor, and serial number strings */
- SPRINTF(" Vendor: %s\n", us->vendor);
- SPRINTF(" Product: %s\n", us->product);
- SPRINTF("Serial Number: %s\n", us->serial);
-
- /* show the protocol and transport */
- SPRINTF(" Protocol: %s\n", us->protocol_name);
- SPRINTF(" Transport: %s\n", us->transport_name);
-
- /* show the GUID of the device */
- SPRINTF(" GUID: " GUID_FORMAT "\n", GUID_ARGS(us->guid));
- SPRINTF(" Attached: %s\n", us->pusb_dev ? "Yes" : "No");
-
- /*
- * Calculate start of next buffer, and return value.
- */
- *start = buffer + offset;
-
- if ((pos - buffer) < offset)
- return (0);
- else if ((pos - buffer - offset) < length)
- return (pos - buffer - offset);
- else
- return (length);
-}
-
-/*
- * this defines our 'host'
- */
-
-Scsi_Host_Template usb_stor_host_template = {
- name: "usb-storage",
- proc_info: proc_info,
- info: host_info,
-
- detect: detect,
- release: release,
- command: command,
- queuecommand: queuecommand,
-
- eh_abort_handler: command_abort,
- eh_device_reset_handler:device_reset,
- eh_bus_reset_handler: bus_reset,
- eh_host_reset_handler: host_reset,
-
- can_queue: 1,
- this_id: -1,
-
- sg_tablesize: SG_ALL,
- cmd_per_lun: 1,
- present: 0,
- unchecked_isa_dma: FALSE,
- use_clustering: TRUE,
- emulated: TRUE
-};
-
-unsigned char usb_stor_sense_notready[18] = {
- [0] = 0x70, /* current error */
- [2] = 0x02, /* not ready */
- [5] = 0x0a, /* additional length */
- [10] = 0x04, /* not ready */
- [11] = 0x03 /* manual intervention */
-};
-
-#define USB_STOR_SCSI_SENSE_HDRSZ 4
-#define USB_STOR_SCSI_SENSE_10_HDRSZ 8
-
-struct usb_stor_scsi_sense_hdr
-{
- __u8* dataLength;
- __u8* mediumType;
- __u8* devSpecParms;
- __u8* blkDescLength;
-};
-
-typedef struct usb_stor_scsi_sense_hdr Usb_Stor_Scsi_Sense_Hdr;
-
-union usb_stor_scsi_sense_hdr_u
-{
- Usb_Stor_Scsi_Sense_Hdr hdr;
- __u8* array[USB_STOR_SCSI_SENSE_HDRSZ];
-};
-
-typedef union usb_stor_scsi_sense_hdr_u Usb_Stor_Scsi_Sense_Hdr_u;
-
-struct usb_stor_scsi_sense_hdr_10
-{
- __u8* dataLengthMSB;
- __u8* dataLengthLSB;
- __u8* mediumType;
- __u8* devSpecParms;
- __u8* reserved1;
- __u8* reserved2;
- __u8* blkDescLengthMSB;
- __u8* blkDescLengthLSB;
-};
-
-typedef struct usb_stor_scsi_sense_hdr_10 Usb_Stor_Scsi_Sense_Hdr_10;
-
-union usb_stor_scsi_sense_hdr_10_u
-{
- Usb_Stor_Scsi_Sense_Hdr_10 hdr;
- __u8* array[USB_STOR_SCSI_SENSE_10_HDRSZ];
-};
-
-typedef union usb_stor_scsi_sense_hdr_10_u Usb_Stor_Scsi_Sense_Hdr_10_u;
-
-void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* , Usb_Stor_Scsi_Sense_Hdr_u*,
- Usb_Stor_Scsi_Sense_Hdr_10_u*, int* );
-
-int usb_stor_scsiSense10to6( Scsi_Cmnd* the10 )
-{
- __u8 *buffer=0;
- int outputBufferSize = 0;
- int length=0;
- struct scatterlist *sg = 0;
- int i=0, j=0, element=0;
- Usb_Stor_Scsi_Sense_Hdr_u the6Locations;
- Usb_Stor_Scsi_Sense_Hdr_10_u the10Locations;
- int sb=0,si=0,db=0,di=0;
- int sgLength=0;
-
- US_DEBUGP("-- converting 10 byte sense data to 6 byte\n");
- the10->cmnd[0] = the10->cmnd[0] & 0xBF;
-
- /* Determine buffer locations */
- usb_stor_scsiSenseParseBuffer( the10, &the6Locations, &the10Locations,
- &length );
-
- /* Work out minimum buffer to output */
- outputBufferSize = *the10Locations.hdr.dataLengthLSB;
- outputBufferSize += USB_STOR_SCSI_SENSE_HDRSZ;
-
- /* Check to see if we need to trucate the output */
- if ( outputBufferSize > length )
- {
- printk( KERN_WARNING USB_STORAGE
- "Had to truncate MODE_SENSE_10 buffer into MODE_SENSE.\n" );
- printk( KERN_WARNING USB_STORAGE
- "outputBufferSize is %d and length is %d.\n",
- outputBufferSize, length );
- }
- outputBufferSize = length;
-
- /* Data length */
- if ( *the10Locations.hdr.dataLengthMSB != 0 ) /* MSB must be zero */
- {
- printk( KERN_WARNING USB_STORAGE
- "Command will be truncated to fit in SENSE6 buffer.\n" );
- *the6Locations.hdr.dataLength = 0xff;
- }
- else
- {
- *the6Locations.hdr.dataLength = *the10Locations.hdr.dataLengthLSB;
- }
-
- /* Medium type and DevSpecific parms */
- *the6Locations.hdr.mediumType = *the10Locations.hdr.mediumType;
- *the6Locations.hdr.devSpecParms = *the10Locations.hdr.devSpecParms;
-
- /* Block descriptor length */
- if ( *the10Locations.hdr.blkDescLengthMSB != 0 ) /* MSB must be zero */
- {
- printk( KERN_WARNING USB_STORAGE
- "Command will be truncated to fit in SENSE6 buffer.\n" );
- *the6Locations.hdr.blkDescLength = 0xff;
- }
- else
- {
- *the6Locations.hdr.blkDescLength = *the10Locations.hdr.blkDescLengthLSB;
- }
-
- if ( the10->use_sg == 0 )
- {
- buffer = the10->request_buffer;
- /* Copy the rest of the data */
- memmove( &(buffer[USB_STOR_SCSI_SENSE_HDRSZ]),
- &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]),
- outputBufferSize - USB_STOR_SCSI_SENSE_HDRSZ );
- /* initialise last bytes left in buffer due to smaller header */
- memset( &(buffer[outputBufferSize
- -(USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ)]),
- 0,
- USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ );
- }
- else
- {
- sg = (struct scatterlist *) the10->request_buffer;
- /* scan through this scatterlist and figure out starting positions */
- for ( i=0; i < the10->use_sg; i++)
- {
- sgLength = sg[i].length;
- for ( j=0; j<sgLength; j++ )
- {
- /* get to end of header */
- if ( element == USB_STOR_SCSI_SENSE_HDRSZ )
- {
- db=i;
- di=j;
- }
- if ( element == USB_STOR_SCSI_SENSE_10_HDRSZ )
- {
- sb=i;
- si=j;
- /* we've found both sets now, exit loops */
- j=sgLength;
- i=the10->use_sg;
- }
- element++;
- }
- }
-
- /* Now we know where to start the copy from */
- element = USB_STOR_SCSI_SENSE_HDRSZ;
- while ( element < outputBufferSize
- -(USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ) )
- {
- /* check limits */
- if ( sb >= the10->use_sg ||
- si >= sg[sb].length ||
- db >= the10->use_sg ||
- di >= sg[db].length )
- {
- printk( KERN_ERR USB_STORAGE
- "Buffer overrun averted, this shouldn't happen!\n" );
- break;
- }
-
- /* copy one byte */
- {
- char *src = page_address(sg[sb].page) + sg[sb].offset + si;
- char *dst = page_address(sg[db].page) + sg[db].offset + di;
-
- *dst = *src;
- }
-
- /* get next destination */
- if ( sg[db].length-1 == di )
- {
- db++;
- di=0;
- }
- else
- {
- di++;
- }
-
- /* get next source */
- if ( sg[sb].length-1 == si )
- {
- sb++;
- si=0;
- }
- else
- {
- si++;
- }
-
- element++;
- }
- /* zero the remaining bytes */
- while ( element < outputBufferSize )
- {
- /* check limits */
- if ( db >= the10->use_sg ||
- di >= sg[db].length )
- {
- printk( KERN_ERR USB_STORAGE
- "Buffer overrun averted, this shouldn't happen!\n" );
- break;
- }
-
- *(char *)(page_address(sg[db].page) + sg[db].offset) = 0;
-
- /* get next destination */
- if ( sg[db].length-1 == di )
- {
- db++;
- di=0;
- }
- else
- {
- di++;
- }
- element++;
- }
- }
-
- /* All done any everything was fine */
- return 0;
-}
-
-int usb_stor_scsiSense6to10( Scsi_Cmnd* the6 )
-{
- /* will be used to store part of buffer */
- __u8 tempBuffer[USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ],
- *buffer=0;
- int outputBufferSize = 0;
- int length=0;
- struct scatterlist *sg = 0;
- int i=0, j=0, element=0;
- Usb_Stor_Scsi_Sense_Hdr_u the6Locations;
- Usb_Stor_Scsi_Sense_Hdr_10_u the10Locations;
- int sb=0,si=0,db=0,di=0;
- int lsb=0,lsi=0,ldb=0,ldi=0;
-
- US_DEBUGP("-- converting 6 byte sense data to 10 byte\n");
- the6->cmnd[0] = the6->cmnd[0] | 0x40;
-
- /* Determine buffer locations */
- usb_stor_scsiSenseParseBuffer( the6, &the6Locations, &the10Locations,
- &length );
-
- /* Work out minimum buffer to output */
- outputBufferSize = *the6Locations.hdr.dataLength;
- outputBufferSize += USB_STOR_SCSI_SENSE_10_HDRSZ;
-
- /* Check to see if we need to trucate the output */
- if ( outputBufferSize > length )
- {
- printk( KERN_WARNING USB_STORAGE
- "Had to truncate MODE_SENSE into MODE_SENSE_10 buffer.\n" );
- printk( KERN_WARNING USB_STORAGE
- "outputBufferSize is %d and length is %d.\n",
- outputBufferSize, length );
- }
- outputBufferSize = length;
-
- /* Block descriptor length - save these before overwriting */
- tempBuffer[2] = *the10Locations.hdr.blkDescLengthMSB;
- tempBuffer[3] = *the10Locations.hdr.blkDescLengthLSB;
- *the10Locations.hdr.blkDescLengthLSB = *the6Locations.hdr.blkDescLength;
- *the10Locations.hdr.blkDescLengthMSB = 0;
-
- /* reserved - save these before overwriting */
- tempBuffer[0] = *the10Locations.hdr.reserved1;
- tempBuffer[1] = *the10Locations.hdr.reserved2;
- *the10Locations.hdr.reserved1 = *the10Locations.hdr.reserved2 = 0;
-
- /* Medium type and DevSpecific parms */
- *the10Locations.hdr.devSpecParms = *the6Locations.hdr.devSpecParms;
- *the10Locations.hdr.mediumType = *the6Locations.hdr.mediumType;
-
- /* Data length */
- *the10Locations.hdr.dataLengthLSB = *the6Locations.hdr.dataLength;
- *the10Locations.hdr.dataLengthMSB = 0;
-
- if ( !the6->use_sg )
- {
- buffer = the6->request_buffer;
- /* Copy the rest of the data */
- memmove( &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]),
- &(buffer[USB_STOR_SCSI_SENSE_HDRSZ]),
- outputBufferSize-USB_STOR_SCSI_SENSE_10_HDRSZ );
- /* Put the first four bytes (after header) in place */
- memcpy( &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]),
- tempBuffer,
- USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ );
- }
- else
- {
- sg = (struct scatterlist *) the6->request_buffer;
- /* scan through this scatterlist and figure out ending positions */
- for ( i=0; i < the6->use_sg; i++)
- {
- for ( j=0; j<sg[i].length; j++ )
- {
- /* get to end of header */
- if ( element == USB_STOR_SCSI_SENSE_HDRSZ )
- {
- ldb=i;
- ldi=j;
- }
- if ( element == USB_STOR_SCSI_SENSE_10_HDRSZ )
- {
- lsb=i;
- lsi=j;
- /* we've found both sets now, exit loops */
- j=sg[i].length;
- i=the6->use_sg;
- break;
- }
- element++;
- }
- }
- /* scan through this scatterlist and figure out starting positions */
- element = length-1;
- /* destination is the last element */
- db=the6->use_sg-1;
- di=sg[db].length-1;
- for ( i=the6->use_sg-1; i >= 0; i--)
- {
- for ( j=sg[i].length-1; j>=0; j-- )
- {
- /* get to end of header and find source for copy */
- if ( element == length - 1
- - (USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ) )
- {
- sb=i;
- si=j;
- /* we've found both sets now, exit loops */
- j=-1;
- i=-1;
- }
- element--;
- }
- }
- /* Now we know where to start the copy from */
- element = length-1
- - (USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ);
- while ( element >= USB_STOR_SCSI_SENSE_10_HDRSZ )
- {
- /* check limits */
- if ( ( sb <= lsb && si < lsi ) ||
- ( db <= ldb && di < ldi ) )
- {
- printk( KERN_ERR USB_STORAGE
- "Buffer overrun averted, this shouldn't happen!\n" );
- break;
- }
-
- /* copy one byte */
- {
- char *src = page_address(sg[sb].page) + sg[sb].offset + si;
- char *dst = page_address(sg[db].page) + sg[db].offset + di;
-
- *dst = *src;
- }
-
- /* get next destination */
- if ( di == 0 )
- {
- db--;
- di=sg[db].length-1;
- }
- else
- {
- di--;
- }
-
- /* get next source */
- if ( si == 0 )
- {
- sb--;
- si=sg[sb].length-1;
- }
- else
- {
- si--;
- }
-
- element--;
- }
- /* copy the remaining four bytes */
- while ( element >= USB_STOR_SCSI_SENSE_HDRSZ )
- {
- /* check limits */
- if ( db <= ldb && di < ldi )
- {
- printk( KERN_ERR USB_STORAGE
- "Buffer overrun averted, this shouldn't happen!\n" );
- break;
- }
-
- {
- char *dst = page_address(sg[db].page) + sg[db].offset + di;
-
- *dst = tempBuffer[element-USB_STOR_SCSI_SENSE_HDRSZ];
- }
-
- /* get next destination */
- if ( di == 0 )
- {
- db--;
- di=sg[db].length-1;
- }
- else
- {
- di--;
- }
- element--;
- }
- }
-
- /* All done and everything was fine */
- return 0;
-}
-
-void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* srb, Usb_Stor_Scsi_Sense_Hdr_u* the6,
- Usb_Stor_Scsi_Sense_Hdr_10_u* the10,
- int* length_p )
-
-{
- int i = 0, j=0, element=0;
- struct scatterlist *sg = 0;
- int length = 0;
- __u8* buffer=0;
-
- /* are we scatter-gathering? */
- if ( srb->use_sg != 0 )
- {
- /* loop over all the scatter gather structures and
- * get pointer to the data members in the headers
- * (also work out the length while we're here)
- */
- sg = (struct scatterlist *) srb->request_buffer;
- for (i = 0; i < srb->use_sg; i++)
- {
- length += sg[i].length;
- /* We only do the inner loop for the headers */
- if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ )
- {
- /* scan through this scatterlist */
- for ( j=0; j<sg[i].length; j++ )
- {
- if ( element < USB_STOR_SCSI_SENSE_HDRSZ )
- {
- /* fill in the pointers for both header types */
- the6->array[element] =
- page_address(sg[i].page) +
- sg[i].offset + j;
- the10->array[element] =
- page_address(sg[i].page) +
- sg[i].offset + j;
- }
- else if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ )
- {
- /* only the longer headers still cares now */
- the10->array[element] =
- page_address(sg[i].page) +
- sg[i].offset + j;
- }
- /* increase element counter */
- element++;
- }
- }
- }
- }
- else
- {
- length = srb->request_bufflen;
- buffer = srb->request_buffer;
- if ( length < USB_STOR_SCSI_SENSE_10_HDRSZ )
- printk( KERN_ERR USB_STORAGE
- "Buffer length smaller than header!!" );
- for( i=0; i<USB_STOR_SCSI_SENSE_10_HDRSZ; i++ )
- {
- if ( i < USB_STOR_SCSI_SENSE_HDRSZ )
- {
- the6->array[i] = &(buffer[i]);
- the10->array[i] = &(buffer[i]);
- }
- else
- {
- the10->array[i] = &(buffer[i]);
- }
- }
- }
-
- /* Set value of length passed in */
- *length_p = length;
-}
-
diff --git a/drivers/usb/class/storage/scsiglue.h b/drivers/usb/class/storage/scsiglue.h
deleted file mode 100644
index 13b9f3bec266..000000000000
--- a/drivers/usb/class/storage/scsiglue.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* Driver for USB Mass Storage compliant devices
- * SCSI Connecting Glue Header File
- *
- * $Id: scsiglue.h,v 1.4 2000/08/25 00:13:51 mdharm Exp $
- *
- * Current development and maintenance by:
- * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
- *
- * This driver is based on the 'USB Mass Storage Class' document. This
- * describes in detail the protocol used to communicate with such
- * devices. Clearly, the designers had SCSI and ATAPI commands in
- * mind when they created this document. The commands are all very
- * similar to commands in the SCSI-II and ATAPI specifications.
- *
- * It is important to note that in a number of cases this class
- * exhibits class-specific exemptions from the USB specification.
- * Notably the usage of NAK, STALL and ACK differs from the norm, in
- * that they are used to communicate wait, failed and OK on commands.
- *
- * Also, for certain devices, the interrupt endpoint is used to convey
- * status of a command.
- *
- * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more
- * information about this driver.
- *
- * 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, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _SCSIGLUE_H_
-#define _SCSIGLUE_H_
-
-#include <linux/blk.h>
-#include "scsi.h"
-#include "hosts.h"
-
-extern unsigned char usb_stor_sense_notready[18];
-extern Scsi_Host_Template usb_stor_host_template;
-extern int usb_stor_scsiSense10to6(Scsi_Cmnd*);
-extern int usb_stor_scsiSense6to10(Scsi_Cmnd*);
-
-#endif
diff --git a/drivers/usb/class/storage/sddr09.c b/drivers/usb/class/storage/sddr09.c
deleted file mode 100644
index bc14015ae97f..000000000000
--- a/drivers/usb/class/storage/sddr09.c
+++ /dev/null
@@ -1,1058 +0,0 @@
-/* Driver for SanDisk SDDR-09 SmartMedia reader
- *
- * $Id: sddr09.c,v 1.22 2001/12/08 23:32:48 mdharm Exp $
- *
- * SDDR09 driver v0.1:
- *
- * First release
- *
- * Current development and maintenance by:
- * (c) 2000, 2001 Robert Baruch (autophile@starband.net)
- *
- * The SanDisk SDDR-09 SmartMedia reader uses the Shuttle EUSB-01 chip.
- * This chip is a programmable USB controller. In the SDDR-09, it has
- * been programmed to obey a certain limited set of SCSI commands. This
- * driver translates the "real" SCSI commands to the SDDR-09 SCSI
- * commands.
- *
- * 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, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include "transport.h"
-#include "protocol.h"
-#include "usb.h"
-#include "debug.h"
-#include "sddr09.h"
-
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-
-#define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) )
-#define LSB_of(s) ((s)&0xFF)
-#define MSB_of(s) ((s)>>8)
-
-/*
- * Send a control message and wait for the response.
- *
- * us - the pointer to the us_data structure for the device to use
- *
- * request - the URB Setup Packet's first 6 bytes. The first byte always
- * corresponds to the request type, and the second byte always corresponds
- * to the request. The other 4 bytes do not correspond to value and index,
- * since they are used in a custom way by the SCM protocol.
- *
- * xfer_data - a buffer from which to get, or to which to store, any data
- * that gets send or received, respectively, with the URB. Even though
- * it looks like we allocate a buffer in this code for the data, xfer_data
- * must contain enough allocated space.
- *
- * xfer_len - the number of bytes to send or receive with the URB.
- *
- */
-
-static int sddr09_send_control(struct us_data *us,
- int pipe,
- unsigned char request,
- unsigned char requesttype,
- unsigned short value,
- unsigned short index,
- unsigned char *xfer_data,
- unsigned int xfer_len) {
-
- int result;
-
- // If data is going to be sent or received with the URB,
- // then allocate a buffer for it. If data is to be sent,
- // copy the data into the buffer.
-/*
- if (xfer_len > 0) {
- buffer = kmalloc(xfer_len, GFP_NOIO);
- if (!(command[0] & USB_DIR_IN))
- memcpy(buffer, xfer_data, xfer_len);
- }
-*/
- // Send the URB to the device and wait for a response.
-
- /* Why are request and request type reversed in this call? */
-
- result = usb_stor_control_msg(us, pipe,
- request, requesttype, value, index,
- xfer_data, xfer_len);
-
-
- // If data was sent or received with the URB, free the buffer we
- // allocated earlier, but not before reading the data out of the
- // buffer if we wanted to receive data.
-/*
- if (xfer_len > 0) {
- if (command[0] & USB_DIR_IN)
- memcpy(xfer_data, buffer, xfer_len);
- kfree(buffer);
- }
-*/
- // Check the return code for the command.
-
- if (result < 0) {
- /* if the command was aborted, indicate that */
- if (result == -ENOENT)
- return USB_STOR_TRANSPORT_ABORTED;
-
- /* a stall is a fatal condition from the device */
- if (result == -EPIPE) {
- US_DEBUGP("-- Stall on control pipe. Clearing\n");
- result = usb_clear_halt(us->pusb_dev, pipe);
- US_DEBUGP("-- usb_clear_halt() returns %d\n", result);
- return USB_STOR_TRANSPORT_FAILED;
- }
-
- /* Uh oh... serious problem here */
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- return USB_STOR_TRANSPORT_GOOD;
-}
-
-static int sddr09_raw_bulk(struct us_data *us,
- int direction,
- unsigned char *data,
- unsigned int len) {
-
- int result;
- int act_len;
- int pipe;
-
- if (direction == SCSI_DATA_READ)
- pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
- else
- pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
-
- result = usb_stor_bulk_msg(us, data, pipe, len, &act_len);
-
- /* if we stall, we need to clear it before we go on */
- if (result == -EPIPE) {
- US_DEBUGP("EPIPE: clearing endpoint halt for"
- " pipe 0x%x, stalled at %d bytes\n",
- pipe, act_len);
- usb_clear_halt(us->pusb_dev, pipe);
- }
-
- if (result) {
-
- /* NAK - that means we've retried a few times already */
- if (result == -ETIMEDOUT) {
- US_DEBUGP("usbat_raw_bulk():"
- " device NAKed\n");
- return US_BULK_TRANSFER_FAILED;
- }
-
- /* -ENOENT -- we canceled this transfer */
- if (result == -ENOENT) {
- US_DEBUGP("usbat_raw_bulk():"
- " transfer aborted\n");
- return US_BULK_TRANSFER_ABORTED;
- }
-
- if (result == -EPIPE) {
- US_DEBUGP("usbat_raw_bulk():"
- " output pipe stalled\n");
- return USB_STOR_TRANSPORT_FAILED;
- }
-
- /* the catch-all case */
- US_DEBUGP("us_transfer_partial(): unknown error\n");
- return US_BULK_TRANSFER_FAILED;
- }
-
- if (act_len != len) {
- US_DEBUGP("Warning: Transferred only %d bytes\n",
- act_len);
- return US_BULK_TRANSFER_SHORT;
- }
-
- US_DEBUGP("Transferred %d of %d bytes\n", act_len, len);
-
- return US_BULK_TRANSFER_GOOD;
-}
-
-/*
- * Note: direction must be set if command_len == 0.
- */
-
-static int sddr09_bulk_transport(struct us_data *us,
- int direction,
- unsigned char *data,
- unsigned int len,
- int use_sg) {
-
- int result = USB_STOR_TRANSPORT_GOOD;
- int transferred = 0;
- int i;
- struct scatterlist *sg;
- char string[64];
-
- if (len==0)
- return USB_STOR_TRANSPORT_GOOD;
-
-
- /* transfer the data */
-
- if (direction == SCSI_DATA_WRITE) {
-
- /* Debug-print the first 48 bytes of the write transfer */
-
- if (!use_sg) {
- strcpy(string, "wr: ");
- for (i=0; i<len && i<48; i++) {
- sprintf(string+strlen(string), "%02X ",
- data[i]);
- if ((i%16)==15) {
- US_DEBUGP("%s\n", string);
- strcpy(string, "wr: ");
- }
- }
- if ((i%16)!=0)
- US_DEBUGP("%s\n", string);
- }
- }
-
-
- US_DEBUGP("SCM data %s transfer %d sg buffers %d\n",
- ( direction==SCSI_DATA_READ ? "in" : "out"),
- len, use_sg);
-
- if (!use_sg)
- result = sddr09_raw_bulk(us, direction, data, len);
- else {
- sg = (struct scatterlist *)data;
- for (i=0; i<use_sg && transferred<len; i++) {
- result = sddr09_raw_bulk(us, direction,
- page_address(sg[i].page) + sg[i].offset,
- len-transferred > sg[i].length ?
- sg[i].length : len-transferred);
- if (result!=US_BULK_TRANSFER_GOOD)
- break;
- transferred += sg[i].length;
- }
- }
-
- if (direction == SCSI_DATA_READ) {
-
- /* Debug-print the first 48 bytes of the read transfer */
-
- if (!use_sg) {
- strcpy(string, "rd: ");
- for (i=0; i<len && i<48; i++) {
- sprintf(string+strlen(string), "%02X ",
- data[i]);
- if ((i%16)==15) {
- US_DEBUGP("%s\n", string);
- strcpy(string, "rd: ");
- }
- }
- if ((i%16)!=0)
- US_DEBUGP("%s\n", string);
- }
- }
-
- return result;
-}
-
-int sddr09_read_data(struct us_data *us,
- unsigned long address,
- unsigned short sectors,
- unsigned char *content,
- int use_sg) {
-
- int result;
- unsigned char command[12] = {
- 0xe8, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
- struct sddr09_card_info *info = (struct sddr09_card_info *)us->extra;
- unsigned int lba;
- unsigned int pba;
- unsigned short page;
- unsigned short pages;
- unsigned char *buffer = NULL;
- unsigned char *ptr;
- struct scatterlist *sg = NULL;
- int i;
- int len;
- int transferred;
-
- // If we're using scatter-gather, we have to create a new
- // buffer to read all of the data in first, since a
- // scatter-gather buffer could in theory start in the middle
- // of a page, which would be bad. A developer who wants a
- // challenge might want to write a limited-buffer
- // version of this code.
-
- len = sectors*info->pagesize;
-
- if (use_sg) {
- sg = (struct scatterlist *)content;
- buffer = kmalloc(len, GFP_NOIO);
- if (buffer == NULL)
- return USB_STOR_TRANSPORT_ERROR;
- ptr = buffer;
- } else
- ptr = content;
-
- // Figure out the initial LBA and page
-
- pba = address >> (info->pageshift + info->blockshift);
- lba = info->pba_to_lba[pba];
- page = (address >> info->pageshift) & info->blockmask;
-
- // This could be made much more efficient by checking for
- // contiguous LBA's. Another exercise left to the student.
-
- while (sectors>0) {
-
- pba = info->lba_to_pba[lba];
-
- // Read as many sectors as possible in this block
-
- pages = info->blocksize - page;
- if (pages > sectors)
- pages = sectors;
-
- US_DEBUGP("Read %02X pages, from PBA %04X"
- " (LBA %04X) page %02X\n",
- pages, pba, lba, page);
-
- address = ( (pba << info->blockshift) + page ) <<
- info->pageshift;
-
- // Unlike in the documentation, the address is in
- // words of 2 bytes.
-
- command[2] = MSB_of(address>>17);
- command[3] = LSB_of(address>>17);
- command[4] = MSB_of((address>>1)&0xFFFF);
- command[5] = LSB_of((address>>1)&0xFFFF);
-
- command[10] = MSB_of(pages);
- command[11] = LSB_of(pages);
-
- result = sddr09_send_control(us,
- usb_sndctrlpipe(us->pusb_dev,0),
- 0,
- 0x41,
- 0,
- 0,
- command,
- 12);
-
- US_DEBUGP("Result for send_control in read_data %d\n",
- result);
-
- if (result != USB_STOR_TRANSPORT_GOOD) {
- if (use_sg)
- kfree(buffer);
- return result;
- }
-
- result = sddr09_bulk_transport(us,
- SCSI_DATA_READ, ptr,
- pages<<info->pageshift, 0);
-
- if (result != USB_STOR_TRANSPORT_GOOD) {
- if (use_sg)
- kfree(buffer);
- return result;
- }
-
- page = 0;
- lba++;
- sectors -= pages;
- ptr += (pages << info->pageshift);
- }
-
- if (use_sg) {
- transferred = 0;
- for (i=0; i<use_sg && transferred<len; i++) {
- memcpy(page_address(sg[i].page) + sg[i].offset, buffer+transferred,
- len-transferred > sg[i].length ?
- sg[i].length : len-transferred);
- transferred += sg[i].length;
- }
- kfree(buffer);
- }
-
- return USB_STOR_TRANSPORT_GOOD;
-}
-
-int sddr09_read_control(struct us_data *us,
- unsigned long address,
- unsigned short blocks,
- unsigned char *content,
- int use_sg) {
-
- // Unlike in the documentation, the last two bytes are the
- // number of blocks, not sectors.
-
- int result;
- unsigned char command[12] = {
- 0xe8, 0x21, MSB_of(address>>16),
- LSB_of(address>>16), MSB_of(address&0xFFFF),
- LSB_of(address&0xFFFF), 0, 0, 0, 0,
- MSB_of(blocks), LSB_of(blocks)
- };
-
- US_DEBUGP("Read control address %08lX blocks %04X\n",
- address, blocks);
-
- result = sddr09_send_control(us,
- usb_sndctrlpipe(us->pusb_dev,0),
- 0,
- 0x41,
- 0,
- 0,
- command,
- 12);
-
- US_DEBUGP("Result for send_control in read_control %d\n",
- result);
-
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- result = sddr09_bulk_transport(us,
- SCSI_DATA_READ, content,
- blocks<<6, use_sg); // 0x40 bytes per block
-
- US_DEBUGP("Result for bulk read in read_control %d\n",
- result);
-
- return result;
-}
-
-int sddr09_read_deviceID(struct us_data *us,
- unsigned char *manufacturerID,
- unsigned char *deviceID) {
-
- int result;
- unsigned char command[12] = {
- 0xed, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
- unsigned char content[64];
-
- result = sddr09_send_control(us,
- usb_sndctrlpipe(us->pusb_dev,0),
- 0,
- 0x41,
- 0,
- 0,
- command,
- 12);
-
- US_DEBUGP("Result of send_control for device ID is %d\n",
- result);
-
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- result = sddr09_bulk_transport(us,
- SCSI_DATA_READ, content,
- 64, 0);
-
- *manufacturerID = content[0];
- *deviceID = content[1];
-
- return result;
-}
-
-int sddr09_read_status(struct us_data *us,
- unsigned char *status) {
-
- int result;
- unsigned char command[12] = {
- 0xec, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
-
- result = sddr09_send_control(us,
- usb_sndctrlpipe(us->pusb_dev,0),
- 0,
- 0x41,
- 0,
- 0,
- command,
- 12);
-
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- result = sddr09_bulk_transport(us,
- SCSI_DATA_READ, status,
- 1, 0);
-
- return result;
-}
-
-int sddr09_reset(struct us_data *us) {
-
- int result;
- unsigned char command[12] = {
- 0xeb, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
-
- result = sddr09_send_control(us,
- usb_sndctrlpipe(us->pusb_dev,0),
- 0,
- 0x41,
- 0,
- 0,
- command,
- 12);
-
- return result;
-}
-
-unsigned long sddr09_get_capacity(struct us_data *us,
- unsigned int *pagesize, unsigned int *blocksize) {
-
- unsigned char manufacturerID;
- unsigned char deviceID;
- int result;
-
- US_DEBUGP("Reading capacity...\n");
-
- result = sddr09_read_deviceID(us,
- &manufacturerID,
- &deviceID);
-
- US_DEBUGP("Result of read_deviceID is %d\n",
- result);
-
- if (result != USB_STOR_TRANSPORT_GOOD)
- return 0;
-
- US_DEBUGP("Device ID = %02X\n", deviceID);
- US_DEBUGP("Manuf ID = %02X\n", manufacturerID);
-
- *pagesize = 512;
- *blocksize = 16;
-
- switch (deviceID) {
-
- case 0x6e: // 1MB
- case 0xe8:
- case 0xec:
- *pagesize = 256;
- return 0x00100000;
-
- case 0xea: // 2MB
- case 0x5d: // 5d is a ROM card with pagesize 512.
- case 0x64:
- if (deviceID!=0x5D)
- *pagesize = 256;
- return 0x00200000;
-
- case 0xe3: // 4MB
- case 0xe5:
- case 0x6b:
- case 0xd5:
- return 0x00400000;
-
- case 0xe6: // 8MB
- case 0xd6:
- return 0x00800000;
-
- case 0x73: // 16MB
- *blocksize = 32;
- return 0x01000000;
-
- case 0x75: // 32MB
- *blocksize = 32;
- return 0x02000000;
-
- case 0x76: // 64MB
- *blocksize = 32;
- return 0x04000000;
-
- case 0x79: // 128MB
- *blocksize = 32;
- return 0x08000000;
-
- default: // unknown
- return 0;
-
- }
-}
-
-int sddr09_read_map(struct us_data *us) {
-
- struct scatterlist *sg;
- struct sddr09_card_info *info = (struct sddr09_card_info *)(us->extra);
- int numblocks;
- int i;
- unsigned char *ptr;
- unsigned short lba;
- unsigned char parity;
- unsigned char fast_parity[16] = {
- 0, 1, 1, 0, 1, 0, 0, 1,
- 1, 0, 0, 1, 0, 1, 1, 0
- };
- int result;
- int alloc_len;
- int alloc_blocks;
-
- if (!info->capacity)
- return -1;
-
- // read 64 (1<<6) bytes for every block
- // ( 1 << ( blockshift + pageshift ) bytes)
- // of capacity:
- // (1<<6)*capacity/(1<<(b+p)) =
- // ((1<<6)*capacity)>>(b+p) =
- // capacity>>(b+p-6)
-
- alloc_len = info->capacity >>
- (info->blockshift + info->pageshift - 6);
-
- // Allocate a number of scatterlist structures according to
- // the number of 128k blocks in the alloc_len. Adding 128k-1
- // and then dividing by 128k gives the correct number of blocks.
- // 128k = 1<<17
-
- alloc_blocks = (alloc_len + (1<<17) - 1) >> 17;
- sg = kmalloc(alloc_blocks*sizeof(struct scatterlist),
- GFP_NOIO);
- if (sg == NULL)
- return 0;
-
- for (i=0; i<alloc_blocks; i++) {
- if (i<alloc_blocks-1) {
- char *vaddr = kmalloc(1 << 17, GFP_NOIO);
- sg[i].page = virt_to_page(vaddr);
- sg[i].offset = ((unsigned long)vaddr & ~PAGE_MASK);
- sg[i].length = (1<<17);
- } else {
- char *vaddr = kmalloc(alloc_len, GFP_NOIO);
- sg[i].page = virt_to_page(vaddr);
- sg[i].offset = ((unsigned long)vaddr & ~PAGE_MASK);
- sg[i].length = alloc_len;
- }
- alloc_len -= sg[i].length;
- }
-
- for (i=0; i<alloc_blocks; i++)
- if (sg[i].page == NULL) {
- for (i=0; i<alloc_blocks; i++)
- if (sg[i].page != NULL)
- kfree(page_address(sg[i].page) + sg[i].offset);
- kfree(sg);
- return 0;
- }
-
- numblocks = info->capacity >> (info->blockshift + info->pageshift);
-
- if ( (result = sddr09_read_control(us, 0, numblocks,
- (unsigned char *)sg, alloc_blocks)) !=
- USB_STOR_TRANSPORT_GOOD) {
- for (i=0; i<alloc_blocks; i++)
- kfree(page_address(sg[i].page) + sg[i].offset);
- kfree(sg);
- return -1;
- }
-
-
-
- if (info->lba_to_pba)
- kfree(info->lba_to_pba);
- if (info->pba_to_lba)
- kfree(info->pba_to_lba);
- info->lba_to_pba = kmalloc(numblocks*sizeof(int), GFP_NOIO);
- info->pba_to_lba = kmalloc(numblocks*sizeof(int), GFP_NOIO);
-
- if (info->lba_to_pba == NULL || info->pba_to_lba == NULL) {
- if (info->lba_to_pba != NULL)
- kfree(info->lba_to_pba);
- if (info->pba_to_lba != NULL)
- kfree(info->pba_to_lba);
- info->lba_to_pba = NULL;
- info->pba_to_lba = NULL;
- for (i=0; i<alloc_blocks; i++)
- kfree(page_address(sg[i].page) + sg[i].offset);
- kfree(sg);
- return 0;
- }
-
- memset(info->lba_to_pba, 0, numblocks*sizeof(int));
- memset(info->pba_to_lba, 0, numblocks*sizeof(int));
-
- // Each block is 64 bytes of control data, so block i is located in
- // scatterlist block i*64/128k = i*(2^6)*(2^-17) = i*(2^-11)
-
- for (i=0; i<numblocks; i++) {
- ptr = page_address(sg[i>>11].page)+sg[i>>11].offset+((i&0x7ff)<<6);
- if (ptr[0]!=0xFF || ptr[1]!=0xFF || ptr[2]!=0xFF ||
- ptr[3]!=0xFF || ptr[4]!=0xFF || ptr[5]!=0xFF) {
- US_DEBUGP("PBA %04X has no logical mapping: reserved area = "
- "%02X%02X%02X%02X data status %02X block status %02X\n",
- i, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]);
- continue;
- }
- if ((ptr[6]>>4)!=0x01) {
- US_DEBUGP("PBA %04X has invalid address field %02X%02X/%02X%02X\n",
- i, ptr[6], ptr[7], ptr[11], ptr[12]);
- continue;
- }
-
- /* ensure even parity */
-
- lba = short_pack(ptr[7], ptr[6]);
- parity = 1; // the parity of 0x1000
- parity ^= fast_parity[lba & 0x000F];
- parity ^= fast_parity[(lba>>4) & 0x000F];
- parity ^= fast_parity[(lba>>8) & 0x000F];
-
- if (parity) { /* bad parity bit */
- US_DEBUGP("Bad parity in LBA for block %04X\n", i);
- continue;
- }
-
- lba = (lba&0x07FF)>>1;
-
- /* Every 1024 physical blocks ("zone"), the LBA numbers
- * go back to zero, but are within a higher
- * block of LBA's. Also, there is a maximum of
- * 1000 LBA's per zone. In other words, in PBA
- * 1024-2047 you will find LBA 0-999 which are
- * really LBA 1000-1999. Yes, this wastes 24
- * physical blocks per zone. Go figure.
- */
-
- lba += 1000*(i/0x400);
-
- if (lba>=numblocks) {
- US_DEBUGP("Bad LBA %04X for block %04X\n", lba, i);
- continue;
- }
-
- if (lba<0x10 || (lba>=0x3E0 && lba<0x3EF))
- US_DEBUGP("LBA %04X <-> PBA %04X\n", lba, i);
-
- info->pba_to_lba[i] = lba;
- info->lba_to_pba[lba] = i;
- }
-
- for (i=0; i<alloc_blocks; i++)
- kfree(page_address(sg[i].page)+sg[i].offset);
- kfree(sg);
- return 0;
-}
-
-/*
-static int init_sddr09(struct us_data *us) {
-
- int result;
- unsigned char data[14];
- unsigned char command[8] = {
- 0xc1, 0x01, 0, 0, 0, 0, 0, 0
- };
- unsigned char command2[8] = {
- 0x41, 0, 0, 0, 0, 0, 0, 0
- };
- unsigned char tur[12] = {
- 0x03, 0x20, 0, 0, 0x0e, 0, 0, 0, 0, 0, 0, 0
- };
-
- // What the hey is all this for? Doesn't seem to
- // affect the device, so we won't do device inits.
-
- if ( (result = sddr09_send_control(us, command, data, 2)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- US_DEBUGP("SDDR09: %02X %02X\n", data[0], data[1]);
-
- command[1] = 0x08;
-
- if ( (result = sddr09_send_control(us, command, data, 2)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- US_DEBUGP("SDDR09: %02X %02X\n", data[0], data[1]);
-
- if ( (result = sddr09_send_control(us, command2, tur, 12)) !=
- USB_STOR_TRANSPORT_GOOD) {
- US_DEBUGP("SDDR09: request sense failed\n");
- return result;
- }
-
- if ( (result = sddr09_raw_bulk(
- us, SCSI_DATA_READ, data, 14)) !=
- USB_STOR_TRANSPORT_GOOD) {
- US_DEBUGP("SDDR09: request sense bulk in failed\n");
- return result;
- }
-
- US_DEBUGP("SDDR09: request sense worked\n");
-
- return result;
-}
-*/
-
-void sddr09_card_info_destructor(void *extra) {
- struct sddr09_card_info *info = (struct sddr09_card_info *)extra;
-
- if (!extra)
- return;
-
- if (info->lba_to_pba)
- kfree(info->lba_to_pba);
- if (info->pba_to_lba)
- kfree(info->pba_to_lba);
-}
-
-/*
- * Transport for the Sandisk SDDR-09
- */
-int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us)
-{
- int result;
- int i;
- char string[64];
- unsigned char inquiry_response[36] = {
- 0x00, 0x80, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x00
- };
- unsigned char mode_page_01[16] = { // write-protected for now
- 0x03, 0x00, 0x80, 0x00,
- 0x01, 0x0A,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
- unsigned char *ptr;
- unsigned long capacity;
- unsigned int lba;
- unsigned int pba;
- unsigned int page;
- unsigned short pages;
- struct sddr09_card_info *info = (struct sddr09_card_info *)(us->extra);
-
- if (!us->extra) {
- us->extra = kmalloc(
- sizeof(struct sddr09_card_info), GFP_NOIO);
- if (!us->extra)
- return USB_STOR_TRANSPORT_ERROR;
- memset(us->extra, 0, sizeof(struct sddr09_card_info));
- us->extra_destructor = sddr09_card_info_destructor;
- }
-
- ptr = (unsigned char *)srb->request_buffer;
-
- /* Dummy up a response for INQUIRY since SDDR09 doesn't
- respond to INQUIRY commands */
-
- if (srb->cmnd[0] == INQUIRY) {
- memset(inquiry_response+8, 0, 28);
- fill_inquiry_response(us, inquiry_response, 36);
- return USB_STOR_TRANSPORT_GOOD;
- }
-
- if (srb->cmnd[0] == READ_CAPACITY) {
-
- capacity = sddr09_get_capacity(us, &info->pagesize,
- &info->blocksize);
-
- if (!capacity)
- return USB_STOR_TRANSPORT_FAILED;
-
- info->capacity = capacity;
- for (info->pageshift=1;
- (info->pagesize>>info->pageshift);
- info->pageshift++);
- info->pageshift--;
- for (info->blockshift=1;
- (info->blocksize>>info->blockshift);
- info->blockshift++);
- info->blockshift--;
- info->blockmask = (1<<info->blockshift)-1;
-
- // Last page in the card
-
- capacity /= info->pagesize;
- capacity--;
-
- ptr[0] = MSB_of(capacity>>16);
- ptr[1] = LSB_of(capacity>>16);
- ptr[2] = MSB_of(capacity&0xFFFF);
- ptr[3] = LSB_of(capacity&0xFFFF);
-
- // The page size
-
- ptr[4] = MSB_of(info->pagesize>>16);
- ptr[5] = LSB_of(info->pagesize>>16);
- ptr[6] = MSB_of(info->pagesize&0xFFFF);
- ptr[7] = LSB_of(info->pagesize&0xFFFF);
-
- sddr09_read_map(us);
-
- return USB_STOR_TRANSPORT_GOOD;
- }
-
- if (srb->cmnd[0] == MODE_SENSE) {
-
- // Read-write error recovery page: there needs to
- // be a check for write-protect here
-
- if ( (srb->cmnd[2] & 0x3F) == 0x01 ) {
-
- US_DEBUGP(
- "SDDR09: Dummy up request for mode page 1\n");
-
- if (ptr==NULL ||
- srb->request_bufflen<sizeof(mode_page_01))
- return USB_STOR_TRANSPORT_ERROR;
-
- memcpy(ptr, mode_page_01, sizeof(mode_page_01));
- return USB_STOR_TRANSPORT_GOOD;
-
- } else if ( (srb->cmnd[2] & 0x3F) == 0x3F ) {
-
- US_DEBUGP(
- "SDDR09: Dummy up request for all mode pages\n");
-
- if (ptr==NULL ||
- srb->request_bufflen<sizeof(mode_page_01))
- return USB_STOR_TRANSPORT_ERROR;
-
- memcpy(ptr, mode_page_01, sizeof(mode_page_01));
- return USB_STOR_TRANSPORT_GOOD;
-
- }
-
- // FIXME: sense buffer?
-
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
-
- US_DEBUGP(
- "SDDR09: %s medium removal. Not that I can do"
- " anything about it...\n",
- (srb->cmnd[4]&0x03) ? "Prevent" : "Allow");
-
- return USB_STOR_TRANSPORT_GOOD;
-
- }
-
- if (srb->cmnd[0] == READ_10) {
-
- page = short_pack(srb->cmnd[3], srb->cmnd[2]);
- page <<= 16;
- page |= short_pack(srb->cmnd[5], srb->cmnd[4]);
- pages = short_pack(srb->cmnd[8], srb->cmnd[7]);
-
- // convert page to block and page-within-block
-
- lba = page >> info->blockshift;
- page = page & info->blockmask;
-
- // locate physical block corresponding to logical block
-
- if (lba >=
- (info->capacity >>
- (info->pageshift + info->blockshift) ) ) {
-
- US_DEBUGP("Error: Requested LBA %04X exceeds maximum "
- "block %04lX\n", lba,
- (info->capacity >> (info->pageshift + info->blockshift))-1);
-
- // FIXME: sense buffer?
-
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- pba = info->lba_to_pba[lba];
-
- // if pba is 0, either it's really 0, in which case
- // the pba-to-lba map for pba 0 will be the lba,
- // or that lba doesn't exist.
-
- if (pba==0 && info->pba_to_lba[0] != lba) {
-
- // FIXME: sense buffer?
-
- US_DEBUGP("Error: Requested LBA %04X has no physical block "
- "mapping.\n", lba);
-
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- US_DEBUGP("READ_10: read block %04X (LBA %04X) page %01X"
- " pages %d\n",
- pba, lba, page, pages);
-
- return sddr09_read_data(us,
- ( (pba << info->blockshift) + page) << info->pageshift,
- pages, ptr, srb->use_sg);
- }
-
- // Pass TEST_UNIT_READY and REQUEST_SENSE through
-
- if (srb->cmnd[0] != TEST_UNIT_READY &&
- srb->cmnd[0] != REQUEST_SENSE)
- return USB_STOR_TRANSPORT_ERROR; // FIXME: sense buffer?
-
- for (; srb->cmd_len<12; srb->cmd_len++)
- srb->cmnd[srb->cmd_len] = 0;
-
- srb->cmnd[1] = 0x20;
-
- string[0] = 0;
- for (i=0; i<12; i++)
- sprintf(string+strlen(string), "%02X ", srb->cmnd[i]);
-
- US_DEBUGP("SDDR09: Send control for command %s\n",
- string);
-
- if ( (result = sddr09_send_control(us,
- usb_sndctrlpipe(us->pusb_dev,0),
- 0,
- 0x41,
- 0,
- 0,
- srb->cmnd,
- 12)) != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- US_DEBUGP("SDDR09: Control for command OK\n");
-
- if (srb->request_bufflen == 0)
- return USB_STOR_TRANSPORT_GOOD;
-
- if (srb->sc_data_direction == SCSI_DATA_WRITE ||
- srb->sc_data_direction == SCSI_DATA_READ) {
-
- US_DEBUGP("SDDR09: %s %d bytes\n",
- srb->sc_data_direction==SCSI_DATA_WRITE ?
- "sending" : "receiving",
- srb->request_bufflen);
-
- result = sddr09_bulk_transport(us,
- srb->sc_data_direction,
- srb->request_buffer,
- srb->request_bufflen, srb->use_sg);
-
- return result;
-
- }
-
- return USB_STOR_TRANSPORT_GOOD;
-}
-
diff --git a/drivers/usb/class/storage/sddr09.h b/drivers/usb/class/storage/sddr09.h
deleted file mode 100644
index ac984469f157..000000000000
--- a/drivers/usb/class/storage/sddr09.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* Driver for SanDisk SDDR-09 SmartMedia reader
- * Header File
- *
- * $Id: sddr09.h,v 1.5 2000/08/25 00:13:51 mdharm Exp $
- *
- * Current development and maintenance by:
- * (c) 2000 Robert Baruch (autophile@dol.net)
- *
- * See sddr09.c for more explanation
- *
- * 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, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _USB_SHUTTLE_EUSB_SDDR09_H
-#define _USB_SHUTTLE_EUSB_SDDR09_H
-
-/* Sandisk SDDR-09 stuff */
-
-extern int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us);
-
-struct sddr09_card_info {
- unsigned long capacity; /* Size of card in bytes */
- int pagesize; /* Size of page in bytes */
- int pageshift; /* log2 of pagesize */
- int blocksize; /* Size of block in pages */
- int blockshift; /* log2 of blocksize */
- int blockmask; /* 2^blockshift - 1 */
- int *lba_to_pba; /* logical to physical map */
- int *pba_to_lba; /* physical to logical map */
-};
-
-#endif
diff --git a/drivers/usb/class/storage/shuttle_usbat.c b/drivers/usb/class/storage/shuttle_usbat.c
deleted file mode 100644
index 9770f9103210..000000000000
--- a/drivers/usb/class/storage/shuttle_usbat.c
+++ /dev/null
@@ -1,1083 +0,0 @@
-/* Driver for SCM Microsystems USB-ATAPI cable
- *
- * $Id: shuttle_usbat.c,v 1.15 2001/12/08 23:32:48 mdharm Exp $
- *
- * Current development and maintenance by:
- * (c) 2000, 2001 Robert Baruch (autophile@starband.net)
- *
- * Many originally ATAPI devices were slightly modified to meet the USB
- * market by using some kind of translation from ATAPI to USB on the host,
- * and the peripheral would translate from USB back to ATAPI.
- *
- * SCM Microsystems (www.scmmicro.com) makes a device, sold to OEM's only,
- * which does the USB-to-ATAPI conversion. By obtaining the data sheet on
- * their device under nondisclosure agreement, I have been able to write
- * this driver for Linux.
- *
- * The chip used in the device can also be used for EPP and ISA translation
- * as well. This driver is only guaranteed to work with the ATAPI
- * translation.
- *
- * The only peripheral that I know of (as of 27 Mar 2001) that uses this
- * device is the Hewlett-Packard 8200e/8210e/8230e CD-Writer Plus.
- *
- * 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, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include "transport.h"
-#include "protocol.h"
-#include "usb.h"
-#include "debug.h"
-#include "shuttle_usbat.h"
-
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-
-extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
- u8 request, u8 requesttype, u16 value, u16 index,
- void *data, u16 size);
-extern int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe,
- unsigned int len, unsigned int *act_len);
-
-#define short_pack(LSB,MSB) ( ((u16)(LSB)) | ( ((u16)(MSB))<<8 ) )
-#define LSB_of(s) ((s)&0xFF)
-#define MSB_of(s) ((s)>>8)
-
-int transferred = 0;
-
-/*
- * Send a control message and wait for the response.
- *
- * us - the pointer to the us_data structure for the device to use
- *
- * request - the URB Setup Packet's first 6 bytes. The first byte always
- * corresponds to the request type, and the second byte always corresponds
- * to the request. The other 4 bytes do not correspond to value and index,
- * since they are used in a custom way by the SCM protocol.
- *
- * xfer_data - a buffer from which to get, or to which to store, any data
- * that gets send or received, respectively, with the URB. Even though
- * it looks like we allocate a buffer in this code for the data, xfer_data
- * must contain enough allocated space.
- *
- * xfer_len - the number of bytes to send or receive with the URB.
- *
- */
-
-static int usbat_send_control(struct us_data *us,
- int pipe,
- unsigned char request,
- unsigned char requesttype,
- unsigned short value,
- unsigned short index,
- unsigned char *xfer_data,
- unsigned int xfer_len) {
-
- int result;
-
- // Send the URB to the device and wait for a response.
-
- /* Why are request and request type reversed in this call? */
-
- result = usb_stor_control_msg(us, pipe,
- request, requesttype, value, index,
- xfer_data, xfer_len);
-
-
- // Check the return code for the command.
-
- if (result < 0) {
- /* if the command was aborted, indicate that */
- if (result == -ENOENT)
- return USB_STOR_TRANSPORT_ABORTED;
-
- /* a stall is a fatal condition from the device */
- if (result == -EPIPE) {
- US_DEBUGP("-- Stall on control pipe. Clearing\n");
- result = usb_clear_halt(us->pusb_dev, pipe);
- US_DEBUGP("-- usb_clear_halt() returns %d\n", result);
- return USB_STOR_TRANSPORT_FAILED;
- }
-
- /* Uh oh... serious problem here */
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- return USB_STOR_TRANSPORT_GOOD;
-}
-
-static int usbat_raw_bulk(struct us_data *us,
- int direction,
- unsigned char *data,
- unsigned short len) {
-
- int result;
- int act_len;
- int pipe;
-
- if (direction == SCSI_DATA_READ)
- pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
- else
- pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
-
- result = usb_stor_bulk_msg(us, data, pipe, len, &act_len);
-
- /* if we stall, we need to clear it before we go on */
- if (result == -EPIPE) {
- US_DEBUGP("EPIPE: clearing endpoint halt for"
- " pipe 0x%x, stalled at %d bytes\n",
- pipe, act_len);
- usb_clear_halt(us->pusb_dev, pipe);
- }
-
- if (result) {
-
- /* NAK - that means we've retried a few times already */
- if (result == -ETIMEDOUT) {
- US_DEBUGP("usbat_raw_bulk():"
- " device NAKed\n");
- return US_BULK_TRANSFER_FAILED;
- }
-
- /* -ENOENT -- we canceled this transfer */
- if (result == -ENOENT) {
- US_DEBUGP("usbat_raw_bulk():"
- " transfer aborted\n");
- return US_BULK_TRANSFER_ABORTED;
- }
-
- if (result == -EPIPE) {
- US_DEBUGP("usbat_raw_bulk():"
- " output pipe stalled\n");
- return US_BULK_TRANSFER_SHORT;
- }
-
- /* the catch-all case */
- US_DEBUGP("us_transfer_partial(): unknown error\n");
- return US_BULK_TRANSFER_FAILED;
- }
-
- if (act_len != len) {
- US_DEBUGP("Warning: Transferred only %d bytes\n",
- act_len);
- return US_BULK_TRANSFER_SHORT;
- }
-
- US_DEBUGP("Transferred %s %d of %d bytes\n",
- direction==SCSI_DATA_READ ? "in" : "out", act_len, len);
-
- return US_BULK_TRANSFER_GOOD;
-}
-
-/*
- * Note: direction must be set if command_len == 0.
- */
-
-static int usbat_bulk_transport(struct us_data *us,
- unsigned char *command,
- unsigned short command_len,
- int direction,
- unsigned char *data,
- unsigned short len,
- int use_sg) {
-
- int result = USB_STOR_TRANSPORT_GOOD;
- int transferred = 0;
- int i;
- struct scatterlist *sg;
-
- if (len==0)
- return USB_STOR_TRANSPORT_GOOD;
-
- /* transfer the data payload for the command, if there is any */
-
- if (command_len != 0)
- direction = (command[0]&0x80) ? SCSI_DATA_READ :
- SCSI_DATA_WRITE;
-
- if (!use_sg)
- result = usbat_raw_bulk(us, direction, data, len);
- else {
- sg = (struct scatterlist *)data;
- for (i=0; i<use_sg && transferred<len; i++) {
- result = usbat_raw_bulk(us, direction,
- page_address(sg[i].page) + sg[i].offset,
- len-transferred > sg[i].length ?
- sg[i].length : len-transferred);
- if (result!=US_BULK_TRANSFER_GOOD)
- break;
- transferred += sg[i].length;
- }
- }
-
- return result;
-}
-
-int usbat_read(struct us_data *us,
- unsigned char access,
- unsigned char reg,
- unsigned char *content) {
-
- int result;
-
- result = usbat_send_control(us,
- usb_rcvctrlpipe(us->pusb_dev,0),
- access,
- 0xC0,
- (u16)reg,
- 0,
- content,
- 1);
-
- return result;
-}
-
-int usbat_write(struct us_data *us,
- unsigned char access,
- unsigned char reg,
- unsigned char content) {
-
- int result;
-
- result = usbat_send_control(us,
- usb_sndctrlpipe(us->pusb_dev,0),
- access|0x01,
- 0x40,
- short_pack(reg, content),
- 0,
- NULL,
- 0);
-
- return result;
-}
-
-int usbat_set_shuttle_features(struct us_data *us,
- unsigned char external_trigger,
- unsigned char epp_control,
- unsigned char mask_byte,
- unsigned char test_pattern,
- unsigned char subcountH,
- unsigned char subcountL) {
-
- int result;
- unsigned char command[8] = {
- 0x40, 0x81, epp_control, external_trigger,
- test_pattern, mask_byte, subcountL, subcountH
- };
-
- result = usbat_send_control(us,
- usb_sndctrlpipe(us->pusb_dev,0),
- 0x80,
- 0x40,
- 0,
- 0,
- command,
- 8);
-
- return result;
-}
-
-int usbat_read_block(struct us_data *us,
- unsigned char access,
- unsigned char reg,
- unsigned char *content,
- unsigned short len,
- int use_sg) {
-
- int result;
- unsigned char command[8] = {
- 0xC0, access|0x02, reg, 0x00, 0x00, 0x00,
- LSB_of(len), MSB_of(len)
- };
-
- result = usbat_send_control(us,
- usb_sndctrlpipe(us->pusb_dev,0),
- 0x80,
- 0x40,
- 0,
- 0,
- command,
- 8);
-
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- result = usbat_bulk_transport(us,
- NULL, 0, SCSI_DATA_READ, content, len, use_sg);
-
- return result;
-}
-
-/*
- * Block, waiting for an ATA device to become not busy or to report
- * an error condition.
- */
-
-int usbat_wait_not_busy(struct us_data *us, int minutes) {
-
- int i;
- int result;
- unsigned char status;
-
- /* Synchronizing cache on a CDR could take a heck of a long time,
- * but probably not more than 10 minutes or so. On the other hand,
- * doing a full blank on a CDRW at speed 1 will take about 75
- * minutes!
- */
-
- for (i=0; i<1200+minutes*60; i++) {
-
- result = usbat_read(us, USBAT_ATA, 0x17, &status);
-
- if (result!=USB_STOR_TRANSPORT_GOOD)
- return result;
- if (status&0x01) { // check condition
- result = usbat_read(us, USBAT_ATA, 0x10, &status);
- return USB_STOR_TRANSPORT_FAILED;
- }
- if (status&0x20) // device fault
- return USB_STOR_TRANSPORT_FAILED;
-
- if ((status&0x80)==0x00) { // not busy
- US_DEBUGP("Waited not busy for %d steps\n", i);
- return USB_STOR_TRANSPORT_GOOD;
- }
-
- if (i<500)
- wait_ms(10); // 5 seconds
- else if (i<700)
- wait_ms(50); // 10 seconds
- else if (i<1200)
- wait_ms(100); // 50 seconds
- else
- wait_ms(1000); // X minutes
- }
-
- US_DEBUGP("Waited not busy for %d minutes, timing out.\n",
- minutes);
- return USB_STOR_TRANSPORT_FAILED;
-}
-
-int usbat_write_block(struct us_data *us,
- unsigned char access,
- unsigned char reg,
- unsigned char *content,
- unsigned short len,
- int use_sg,
- int minutes) {
-
- int result;
- unsigned char command[8] = {
- 0x40, access|0x03, reg, 0x00, 0x00, 0x00,
- LSB_of(len), MSB_of(len)
- };
-
- result = usbat_send_control(us,
- usb_sndctrlpipe(us->pusb_dev,0),
- 0x80,
- 0x40,
- 0,
- 0,
- command,
- 8);
-
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- result = usbat_bulk_transport(us,
- NULL, 0, SCSI_DATA_WRITE, content, len, use_sg);
-
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- return usbat_wait_not_busy(us, minutes);
-}
-
-int usbat_rw_block_test(struct us_data *us,
- unsigned char access,
- unsigned char *registers,
- unsigned char *data_out,
- unsigned short num_registers,
- unsigned char data_reg,
- unsigned char status_reg,
- unsigned char timeout,
- unsigned char qualifier,
- int direction,
- unsigned char *content,
- unsigned short len,
- int use_sg,
- int minutes) {
-
- int result;
-
- // Not really sure the 0x07, 0x17, 0xfc, 0xe7 is necessary here,
- // but that's what came out of the trace every single time.
-
- unsigned char command[16] = {
- 0x40, access|0x07, 0x07, 0x17, 0xfc, 0xe7,
- LSB_of(num_registers*2), MSB_of(num_registers*2),
- (direction==SCSI_DATA_WRITE ? 0x40 : 0xC0),
- access|(direction==SCSI_DATA_WRITE ? 0x05 : 0x04),
- data_reg, status_reg,
- timeout, qualifier, LSB_of(len), MSB_of(len)
- };
-
- int i;
- unsigned char data[num_registers*2];
- unsigned char status;
-
- for (i=0; i<num_registers; i++) {
- data[i<<1] = registers[i];
- data[1+(i<<1)] = data_out[i];
- }
-
- for (i=0; i<20; i++) {
-
- /*
- * The first time we send the full command, which consists
- * of downloading the SCSI command followed by downloading
- * the data via a write-and-test. Any other time we only
- * send the command to download the data -- the SCSI command
- * is still 'active' in some sense in the device.
- *
- * We're only going to try sending the data 10 times. After
- * that, we just return a failure.
- */
-
- result = usbat_send_control(us,
- usb_sndctrlpipe(us->pusb_dev,0),
- 0x80,
- 0x40,
- 0,
- 0,
- (i==0 ? command : command+8),
- (i==0 ? 16 : 8));
-
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- if (i==0) {
-
- result = usbat_bulk_transport(us,
- NULL, 0, SCSI_DATA_WRITE,
- data, num_registers*2, 0);
-
- if (result!=USB_STOR_TRANSPORT_GOOD)
- return result;
-
- }
-
-
- //US_DEBUGP("Transfer %s %d bytes, sg buffers %d\n",
- // direction == SCSI_DATA_WRITE ? "out" : "in",
- // len, use_sg);
-
- result = usbat_bulk_transport(us,
- NULL, 0, direction, content, len, use_sg);
-
- /*
- * If we get a stall on the bulk download, we'll retry
- * the bulk download -- but not the SCSI command because
- * in some sense the SCSI command is still 'active' and
- * waiting for the data. Don't ask me why this should be;
- * I'm only following what the Windoze driver did.
- *
- * Note that a stall for the test-and-read/write command means
- * that the test failed. In this case we're testing to make
- * sure that the device is error-free
- * (i.e. bit 0 -- CHK -- of status is 0). The most likely
- * hypothesis is that the USBAT chip somehow knows what
- * the device will accept, but doesn't give the device any
- * data until all data is received. Thus, the device would
- * still be waiting for the first byte of data if a stall
- * occurs, even if the stall implies that some data was
- * transferred.
- */
-
- if (result == US_BULK_TRANSFER_SHORT) {
-
- /*
- * If we're reading and we stalled, then clear
- * the bulk output pipe only the first time.
- */
-
- if (direction==SCSI_DATA_READ && i==0)
- usb_clear_halt(us->pusb_dev,
- usb_sndbulkpipe(us->pusb_dev,
- us->ep_out));
- /*
- * Read status: is the device angry, or just busy?
- */
-
- result = usbat_read(us, USBAT_ATA,
- direction==SCSI_DATA_WRITE ? 0x17 : 0x0E,
- &status);
-
- if (result!=USB_STOR_TRANSPORT_GOOD)
- return result;
- if (status&0x01) // check condition
- return USB_STOR_TRANSPORT_FAILED;
- if (status&0x20) // device fault
- return USB_STOR_TRANSPORT_FAILED;
-
- US_DEBUGP("Redoing %s\n",
- direction==SCSI_DATA_WRITE ? "write" : "read");
-
- } else if (result != US_BULK_TRANSFER_GOOD)
- return result;
- else
- return usbat_wait_not_busy(us, minutes);
-
- }
-
- US_DEBUGP("Bummer! %s bulk data 20 times failed.\n",
- direction==SCSI_DATA_WRITE ? "Writing" : "Reading");
-
- return USB_STOR_TRANSPORT_FAILED;
-}
-
-/*
- * Write data to multiple registers at once. Not meant for large
- * transfers of data!
- */
-
-int usbat_multiple_write(struct us_data *us,
- unsigned char access,
- unsigned char *registers,
- unsigned char *data_out,
- unsigned short num_registers) {
-
- int result;
- unsigned char data[num_registers*2];
- int i;
- unsigned char command[8] = {
- 0x40, access|0x07, 0x00, 0x00, 0x00, 0x00,
- LSB_of(num_registers*2), MSB_of(num_registers*2)
- };
-
- for (i=0; i<num_registers; i++) {
- data[i<<1] = registers[i];
- data[1+(i<<1)] = data_out[i];
- }
-
- result = usbat_send_control(us,
- usb_sndctrlpipe(us->pusb_dev,0),
- 0x80,
- 0x40,
- 0,
- 0,
- command,
- 8);
-
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- result = usbat_bulk_transport(us,
- NULL, 0, SCSI_DATA_WRITE, data, num_registers*2, 0);
-
- if (result!=USB_STOR_TRANSPORT_GOOD)
- return result;
-
- return usbat_wait_not_busy(us, 0);
-}
-
-int usbat_read_user_io(struct us_data *us,
- unsigned char *data_flags) {
-
- int result;
-
- result = usbat_send_control(us,
- usb_rcvctrlpipe(us->pusb_dev,0),
- 0x82,
- 0xC0,
- 0,
- 0,
- data_flags,
- 1);
-
- return result;
-}
-
-int usbat_write_user_io(struct us_data *us,
- unsigned char enable_flags,
- unsigned char data_flags) {
-
- int result;
-
- result = usbat_send_control(us,
- usb_sndctrlpipe(us->pusb_dev,0),
- 0x82,
- 0x40,
- short_pack(enable_flags, data_flags),
- 0,
- NULL,
- 0);
-
- return result;
-}
-
-/*
- * Squeeze a potentially huge (> 65535 byte) read10 command into
- * a little ( <= 65535 byte) ATAPI pipe
- */
-
-int usbat_handle_read10(struct us_data *us,
- unsigned char *registers,
- unsigned char *data,
- Scsi_Cmnd *srb) {
-
- int result = USB_STOR_TRANSPORT_GOOD;
- unsigned char *buffer;
- unsigned int len;
- unsigned int sector;
- unsigned int amount;
- struct scatterlist *sg = NULL;
- int sg_segment = 0;
- int sg_offset = 0;
-
- US_DEBUGP("handle_read10: transfersize %d\n",
- srb->transfersize);
-
- if (srb->request_bufflen < 0x10000) {
-
- result = usbat_rw_block_test(us, USBAT_ATA,
- registers, data, 19,
- 0x10, 0x17, 0xFD, 0x30,
- SCSI_DATA_READ,
- srb->request_buffer,
- srb->request_bufflen, srb->use_sg, 1);
-
- return result;
- }
-
- /*
- * Since we're requesting more data than we can handle in
- * a single read command (max is 64k-1), we will perform
- * multiple reads, but each read must be in multiples of
- * a sector. Luckily the sector size is in srb->transfersize
- * (see linux/drivers/scsi/sr.c).
- */
-
- if (data[7+0] == GPCMD_READ_CD) {
- len = short_pack(data[7+9], data[7+8]);
- len <<= 16;
- len |= data[7+7];
- srb->transfersize = srb->request_bufflen/len;
- }
-
-
- len = (65535/srb->transfersize) * srb->transfersize;
- US_DEBUGP("Max read is %d bytes\n", len);
- buffer = kmalloc(len, GFP_NOIO);
- if (buffer == NULL) // bloody hell!
- return USB_STOR_TRANSPORT_FAILED;
- sector = short_pack(data[7+3], data[7+2]);
- sector <<= 16;
- sector |= short_pack(data[7+5], data[7+4]);
- transferred = 0;
-
- if (srb->use_sg) {
- sg = (struct scatterlist *)srb->request_buffer;
- sg_segment = 0; // for keeping track of where we are in
- sg_offset = 0; // the scatter/gather list
- }
-
- while (transferred != srb->request_bufflen) {
-
- if (len > srb->request_bufflen - transferred)
- len = srb->request_bufflen - transferred;
-
- data[3] = len&0xFF; // (cylL) = expected length (L)
- data[4] = (len>>8)&0xFF; // (cylH) = expected length (H)
-
- // Fix up the SCSI command sector and num sectors
-
- data[7+2] = MSB_of(sector>>16); // SCSI command sector
- data[7+3] = LSB_of(sector>>16);
- data[7+4] = MSB_of(sector&0xFFFF);
- data[7+5] = LSB_of(sector&0xFFFF);
- if (data[7+0] == GPCMD_READ_CD)
- data[7+6] = 0;
- data[7+7] = MSB_of(len / srb->transfersize); // SCSI command
- data[7+8] = LSB_of(len / srb->transfersize); // num sectors
-
- result = usbat_rw_block_test(us, USBAT_ATA,
- registers, data, 19,
- 0x10, 0x17, 0xFD, 0x30,
- SCSI_DATA_READ,
- buffer,
- len, 0, 1);
-
- if (result != USB_STOR_TRANSPORT_GOOD)
- break;
-
- // Transfer the received data into the srb buffer
-
- if (!srb->use_sg) {
- memcpy(srb->request_buffer+transferred, buffer, len);
- } else {
- amount = 0;
- while (amount<len) {
- if (len - amount >=
- sg[sg_segment].length-sg_offset) {
- memcpy(page_address(sg[sg_segment].page) +
- sg[sg_segment].offset + sg_offset,
- buffer + amount,
- sg[sg_segment].length - sg_offset);
- amount +=
- sg[sg_segment].length-sg_offset;
- sg_segment++;
- sg_offset=0;
- } else {
- memcpy(page_address(sg[sg_segment].page) +
- sg[sg_segment].offset + sg_offset,
- buffer + amount,
- len - amount);
- sg_offset += (len - amount);
- amount = len;
- }
- }
- }
-
- // Update the amount transferred and the sector number
-
- transferred += len;
- sector += len / srb->transfersize;
-
- } // while transferred != srb->request_bufflen
-
- kfree(buffer);
- return result;
-}
-
-static int hp_8200e_select_and_test_registers(struct us_data *us) {
-
- int result;
- int selector;
- unsigned char status;
-
- // try device = master, then device = slave.
-
- for (selector = 0xA0; selector <= 0xB0; selector += 0x10) {
-
- if ( (result = usbat_write(us, USBAT_ATA, 0x16, selector)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- if ( (result = usbat_read(us, USBAT_ATA, 0x17, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- if ( (result = usbat_read(us, USBAT_ATA, 0x16, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- if ( (result = usbat_read(us, USBAT_ATA, 0x14, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- if ( (result = usbat_read(us, USBAT_ATA, 0x15, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- if ( (result = usbat_write(us, USBAT_ATA, 0x14, 0x55)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- if ( (result = usbat_write(us, USBAT_ATA, 0x15, 0xAA)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- if ( (result = usbat_read(us, USBAT_ATA, 0x14, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- if ( (result = usbat_read(us, USBAT_ATA, 0x15, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
- }
-
- return result;
-}
-
-int init_8200e(struct us_data *us) {
-
- int result;
- unsigned char status;
-
- // Enable peripheral control signals
-
- if ( (result = usbat_write_user_io(us,
- USBAT_UIO_OE1 | USBAT_UIO_OE0,
- USBAT_UIO_EPAD | USBAT_UIO_1)) != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- US_DEBUGP("INIT 1\n");
-
- wait_ms(2000);
-
- if ( (result = usbat_read_user_io(us, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- US_DEBUGP("INIT 2\n");
-
- if ( (result = usbat_read_user_io(us, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- US_DEBUGP("INIT 3\n");
-
- // Reset peripheral, enable periph control signals
- // (bring reset signal up)
-
- if ( (result = usbat_write_user_io(us,
- USBAT_UIO_DRVRST | USBAT_UIO_OE1 | USBAT_UIO_OE0,
- USBAT_UIO_EPAD | USBAT_UIO_1)) != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- US_DEBUGP("INIT 4\n");
-
- // Enable periph control signals
- // (bring reset signal down)
-
- if ( (result = usbat_write_user_io(us,
- USBAT_UIO_OE1 | USBAT_UIO_OE0,
- USBAT_UIO_EPAD | USBAT_UIO_1)) != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- US_DEBUGP("INIT 5\n");
-
- wait_ms(250);
-
- // Write 0x80 to ISA port 0x3F
-
- if ( (result = usbat_write(us, USBAT_ISA, 0x3F, 0x80)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- US_DEBUGP("INIT 6\n");
-
- // Read ISA port 0x27
-
- if ( (result = usbat_read(us, USBAT_ISA, 0x27, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- US_DEBUGP("INIT 7\n");
-
- if ( (result = usbat_read_user_io(us, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- US_DEBUGP("INIT 8\n");
-
- if ( (result = hp_8200e_select_and_test_registers(us)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- US_DEBUGP("INIT 9\n");
-
- if ( (result = usbat_read_user_io(us, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- US_DEBUGP("INIT 10\n");
-
- // Enable periph control signals and card detect
-
- if ( (result = usbat_write_user_io(us,
- USBAT_UIO_ACKD |USBAT_UIO_OE1 | USBAT_UIO_OE0,
- USBAT_UIO_EPAD | USBAT_UIO_1)) != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- US_DEBUGP("INIT 11\n");
-
- if ( (result = usbat_read_user_io(us, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- US_DEBUGP("INIT 12\n");
-
- wait_ms(1400);
-
- if ( (result = usbat_read_user_io(us, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- US_DEBUGP("INIT 13\n");
-
- if ( (result = hp_8200e_select_and_test_registers(us)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- US_DEBUGP("INIT 14\n");
-
- if ( (result = usbat_set_shuttle_features(us,
- 0x83, 0x00, 0x88, 0x08, 0x15, 0x14)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- US_DEBUGP("INIT 15\n");
-
- return result;
-}
-
-/*
- * Transport for the HP 8200e
- */
-int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us)
-{
- int result;
- unsigned char status;
- unsigned char registers[32];
- unsigned char data[32];
- unsigned int len;
- int i;
- char string[64];
-
- len = srb->request_bufflen;
-
- /* Send A0 (ATA PACKET COMMAND).
- Note: I guess we're never going to get any of the ATA
- commands... just ATA Packet Commands.
- */
-
- registers[0] = 0x11;
- registers[1] = 0x12;
- registers[2] = 0x13;
- registers[3] = 0x14;
- registers[4] = 0x15;
- registers[5] = 0x16;
- registers[6] = 0x17;
- data[0] = 0x00;
- data[1] = 0x00;
- data[2] = 0x00;
- data[3] = len&0xFF; // (cylL) = expected length (L)
- data[4] = (len>>8)&0xFF; // (cylH) = expected length (H)
- data[5] = 0xB0; // (device sel) = slave
- data[6] = 0xA0; // (command) = ATA PACKET COMMAND
-
- for (i=7; i<19; i++) {
- registers[i] = 0x10;
- data[i] = (i-7 >= srb->cmd_len) ? 0 : srb->cmnd[i-7];
- }
-
- result = usbat_read(us, USBAT_ATA, 0x17, &status);
- US_DEBUGP("Status = %02X\n", status);
-
- if (srb->cmnd[0] == TEST_UNIT_READY)
- transferred = 0;
-
- if (srb->sc_data_direction == SCSI_DATA_WRITE) {
-
- result = usbat_rw_block_test(us, USBAT_ATA,
- registers, data, 19,
- 0x10, 0x17, 0xFD, 0x30,
- SCSI_DATA_WRITE,
- srb->request_buffer,
- len, srb->use_sg, 10);
-
- if (result == USB_STOR_TRANSPORT_GOOD) {
- transferred += len;
- US_DEBUGP("Wrote %08X bytes\n", transferred);
- }
-
- return result;
-
- } else if (srb->cmnd[0] == READ_10 ||
- srb->cmnd[0] == GPCMD_READ_CD) {
-
- return usbat_handle_read10(us, registers, data, srb);
-
- }
-
- if (len > 0xFFFF) {
- US_DEBUGP("Error: len = %08X... what do I do now?\n",
- len);
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- if ( (result = usbat_multiple_write(us,
- USBAT_ATA,
- registers, data, 7)) != USB_STOR_TRANSPORT_GOOD) {
- return result;
- }
-
- // Write the 12-byte command header.
-
- // If the command is BLANK then set the timer for 75 minutes.
- // Otherwise set it for 10 minutes.
-
- // NOTE: THE 8200 DOCUMENTATION STATES THAT BLANKING A CDRW
- // AT SPEED 4 IS UNRELIABLE!!!
-
- if ( (result = usbat_write_block(us,
- USBAT_ATA, 0x10, srb->cmnd, 12, 0,
- srb->cmnd[0]==GPCMD_BLANK ? 75 : 10)) !=
- USB_STOR_TRANSPORT_GOOD) {
- return result;
- }
-
- // If there is response data to be read in
- // then do it here.
-
- if (len != 0 && (srb->sc_data_direction == SCSI_DATA_READ)) {
-
- // How many bytes to read in? Check cylL register
-
- if ( (result = usbat_read(us, USBAT_ATA, 0x14, &status)) !=
- USB_STOR_TRANSPORT_GOOD) {
- return result;
- }
-
- if (len>0xFF) { // need to read cylH also
- len = status;
- if ( (result = usbat_read(us, USBAT_ATA, 0x15,
- &status)) !=
- USB_STOR_TRANSPORT_GOOD) {
- return result;
- }
- len += ((unsigned int)status)<<8;
- }
- else
- len = status;
-
-
- result = usbat_read_block(us, USBAT_ATA, 0x10,
- srb->request_buffer, len, srb->use_sg);
-
- /* Debug-print the first 32 bytes of the transfer */
-
- if (!srb->use_sg) {
- string[0] = 0;
- for (i=0; i<len && i<32; i++) {
- sprintf(string+strlen(string), "%02X ",
- ((unsigned char *)srb->request_buffer)[i]);
- if ((i%16)==15) {
- US_DEBUGP("%s\n", string);
- string[0] = 0;
- }
- }
- if (string[0]!=0)
- US_DEBUGP("%s\n", string);
- }
- }
-
- return result;
-}
-
-
diff --git a/drivers/usb/class/storage/shuttle_usbat.h b/drivers/usb/class/storage/shuttle_usbat.h
deleted file mode 100644
index ad5078f16aa7..000000000000
--- a/drivers/usb/class/storage/shuttle_usbat.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* Driver for SCM Microsystems USB-ATAPI cable
- * Header File
- *
- * $Id: shuttle_usbat.h,v 1.5 2000/09/17 14:44:52 groovyjava Exp $
- *
- * Current development and maintenance by:
- * (c) 2000 Robert Baruch (autophile@dol.net)
- *
- * See scm.c for more explanation
- *
- * 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, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _USB_SHUTTLE_USBAT_H
-#define _USB_SHUTTLE_USBAT_H
-
-#define USBAT_EPP_PORT 0x10
-#define USBAT_EPP_REGISTER 0x30
-#define USBAT_ATA 0x40
-#define USBAT_ISA 0x50
-
-/* SCM User I/O Data registers */
-
-#define USBAT_UIO_EPAD 0x80 // Enable Peripheral Control Signals
-#define USBAT_UIO_CDT 0x40 // Card Detect (Read Only)
- // CDT = ACKD & !UI1 & !UI0
-#define USBAT_UIO_1 0x20 // I/O 1
-#define USBAT_UIO_0 0x10 // I/O 0
-#define USBAT_UIO_EPP_ATA 0x08 // 1=EPP mode, 0=ATA mode
-#define USBAT_UIO_UI1 0x04 // Input 1
-#define USBAT_UIO_UI0 0x02 // Input 0
-#define USBAT_UIO_INTR_ACK 0x01 // Interrupt (ATA & ISA)/Acknowledge (EPP)
-
-/* SCM User I/O Enable registers */
-
-#define USBAT_UIO_DRVRST 0x80 // Reset Peripheral
-#define USBAT_UIO_ACKD 0x40 // Enable Card Detect
-#define USBAT_UIO_OE1 0x20 // I/O 1 set=output/clr=input
- // If ACKD=1, set OE1 to 1 also.
-#define USBAT_UIO_OE0 0x10 // I/O 0 set=output/clr=input
-#define USBAT_UIO_ADPRST 0x01 // Reset SCM chip
-
-/* USBAT-specific commands */
-
-extern int usbat_read(struct us_data *us, unsigned char access,
- unsigned char reg, unsigned char *content);
-extern int usbat_write(struct us_data *us, unsigned char access,
- unsigned char reg, unsigned char content);
-extern int usbat_read_block(struct us_data *us, unsigned char access,
- unsigned char reg, unsigned char *content, unsigned short len,
- int use_sg);
-extern int usbat_write_block(struct us_data *us, unsigned char access,
- unsigned char reg, unsigned char *content, unsigned short len,
- int use_sg, int minutes);
-extern int usbat_multiple_write(struct us_data *us, unsigned char access,
- unsigned char *registers, unsigned char *data_out,
- unsigned short num_registers);
-extern int usbat_read_user_io(struct us_data *us, unsigned char *data_flags);
-extern int usbat_write_user_io(struct us_data *us,
- unsigned char enable_flags, unsigned char data_flags);
-
-/* HP 8200e stuff */
-
-extern int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us);
-extern int init_8200e(struct us_data *us);
-
-#endif
diff --git a/drivers/usb/class/storage/transport.c b/drivers/usb/class/storage/transport.c
deleted file mode 100644
index 04ba81c47102..000000000000
--- a/drivers/usb/class/storage/transport.c
+++ /dev/null
@@ -1,1268 +0,0 @@
-/* Driver for USB Mass Storage compliant devices
- *
- * $Id: transport.c,v 1.42 2001/12/08 23:32:48 mdharm Exp $
- *
- * Current development and maintenance by:
- * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
- *
- * Developed with the assistance of:
- * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
- * (c) 2000 Stephen J. Gowdy (SGowdy@lbl.gov)
- *
- * Initial work by:
- * (c) 1999 Michael Gee (michael@linuxspecific.com)
- *
- * This driver is based on the 'USB Mass Storage Class' document. This
- * describes in detail the protocol used to communicate with such
- * devices. Clearly, the designers had SCSI and ATAPI commands in
- * mind when they created this document. The commands are all very
- * similar to commands in the SCSI-II and ATAPI specifications.
- *
- * It is important to note that in a number of cases this class
- * exhibits class-specific exemptions from the USB specification.
- * Notably the usage of NAK, STALL and ACK differs from the norm, in
- * that they are used to communicate wait, failed and OK on commands.
- *
- * Also, for certain devices, the interrupt endpoint is used to convey
- * status of a command.
- *
- * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more
- * information about this driver.
- *
- * 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, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/config.h>
-#include "transport.h"
-#include "protocol.h"
-#include "usb.h"
-#include "debug.h"
-
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-
-/***********************************************************************
- * Helper routines
- ***********************************************************************/
-
-/* Calculate the length of the data transfer (not the command) for any
- * given SCSI command
- */
-unsigned int usb_stor_transfer_length(Scsi_Cmnd *srb)
-{
- int i;
- int doDefault = 0;
- unsigned int len = 0;
- unsigned int total = 0;
- struct scatterlist *sg;
-
- /* This table tells us:
- X = command not supported
- L = return length in cmnd[4] (8 bits).
- M = return length in cmnd[8] (8 bits).
- G = return length in cmnd[3] and cmnd[4] (16 bits)
- H = return length in cmnd[7] and cmnd[8] (16 bits)
- I = return length in cmnd[8] and cmnd[9] (16 bits)
- C = return length in cmnd[2] to cmnd[5] (32 bits)
- D = return length in cmnd[6] to cmnd[9] (32 bits)
- B = return length in blocksize so we use buff_len
- R = return length in cmnd[2] to cmnd[4] (24 bits)
- S = return length in cmnd[3] to cmnd[5] (24 bits)
- T = return length in cmnd[6] to cmnd[8] (24 bits)
- U = return length in cmnd[7] to cmnd[9] (24 bits)
- 0-9 = fixed return length
- V = 20 bytes
- W = 24 bytes
- Z = return length is mode dependant or not in command, use buff_len
- */
-
- static char *lengths =
-
- /* 0123456789ABCDEF 0123456789ABCDEF */
-
- "00XLZ6XZBXBBXXXB" "00LBBLG0R0L0GG0X" /* 00-1F */
- "XXXXT8XXB4B0BBBB" "ZZZ0B00HCSSZTBHH" /* 20-3F */
- "M0HHB0X000H0HH0X" "XHH0HHXX0TH0H0XX" /* 40-5F */
- "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* 60-7F */
- "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* 80-9F */
- "X0XXX00XB0BXBXBB" "ZZZ0XUIDU000XHBX" /* A0-BF */
- "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* C0-DF */
- "XDXXXXXXXXXXXXXX" "XXW00HXXXXXXXXXX"; /* E0-FF */
-
- /* Commands checked in table:
-
- CHANGE_DEFINITION 40
- COMPARE 39
- COPY 18
- COPY_AND_VERIFY 3a
- ERASE 19
- ERASE_10 2c
- ERASE_12 ac
- EXCHANGE_MEDIUM a6
- FORMAT_UNIT 04
- GET_DATA_BUFFER_STATUS 34
- GET_MESSAGE_10 28
- GET_MESSAGE_12 a8
- GET_WINDOW 25 !!! Has more data than READ_CAPACITY, need to fix table
- INITIALIZE_ELEMENT_STATUS 07 !!! REASSIGN_BLOCKS luckily uses buff_len
- INQUIRY 12
- LOAD_UNLOAD 1b
- LOCATE 2b
- LOCK_UNLOCK_CACHE 36
- LOG_SELECT 4c
- LOG_SENSE 4d
- MEDIUM_SCAN 38 !!! This was M
- MODE_SELECT6 15
- MODE_SELECT_10 55
- MODE_SENSE_6 1a
- MODE_SENSE_10 5a
- MOVE_MEDIUM a5
- OBJECT_POSITION 31 !!! Same as SEARCH_DATA_EQUAL
- PAUSE_RESUME 4b
- PLAY_AUDIO_10 45
- PLAY_AUDIO_12 a5
- PLAY_AUDIO_MSF 47
- PLAY_AUDIO_TRACK_INDEX 48
- PLAY_AUDIO_TRACK_RELATIVE_10 49
- PLAY_AUDIO_TRACK_RELATIVE_12 a9
- POSITION_TO_ELEMENT 2b
- PRE-FETCH 34
- PREVENT_ALLOW_MEDIUM_REMOVAL 1e
- PRINT 0a !!! Same as WRITE_6 but is always in bytes
- READ_6 08
- READ_10 28
- READ_12 a8
- READ_BLOCK_LIMITS 05
- READ_BUFFER 3c
- READ_CAPACITY 25
- READ_CDROM_CAPACITY 25
- READ_DEFECT_DATA 37
- READ_DEFECT_DATA_12 b7
- READ_ELEMENT_STATUS b8 !!! Think this is in bytes
- READ_GENERATION 29 !!! Could also be M?
- READ_HEADER 44 !!! This was L
- READ_LONG 3e
- READ_POSITION 34 !!! This should be V but conflicts with PRE-FETCH
- READ_REVERSE 0f
- READ_SUB-CHANNEL 42 !!! Is this in bytes?
- READ_TOC 43 !!! Is this in bytes?
- READ_UPDATED_BLOCK 2d
- REASSIGN_BLOCKS 07
- RECEIVE 08 !!! Same as READ_6 probably in bytes though
- RECEIVE_DIAGNOSTIC_RESULTS 1c
- RECOVER_BUFFERED_DATA 14 !!! For PRINTERs this is bytes
- RELEASE_UNIT 17
- REQUEST_SENSE 03
- REQUEST_VOLUME_ELEMENT_ADDRESS b5 !!! Think this is in bytes
- RESERVE_UNIT 16
- REWIND 01
- REZERO_UNIT 01
- SCAN 1b !!! Conflicts with various commands, should be L
- SEARCH_DATA_EQUAL 31
- SEARCH_DATA_EQUAL_12 b1
- SEARCH_DATA_LOW 30
- SEARCH_DATA_LOW_12 b0
- SEARCH_DATA_HIGH 32
- SEARCH_DATA_HIGH_12 b2
- SEEK_6 0b !!! Conflicts with SLEW_AND_PRINT
- SEEK_10 2b
- SEND 0a !!! Same as WRITE_6, probably in bytes though
- SEND 2a !!! Similar to WRITE_10 but for scanners
- SEND_DIAGNOSTIC 1d
- SEND_MESSAGE_6 0a !!! Same as WRITE_6 - is in bytes
- SEND_MESSAGE_10 2a !!! Same as WRITE_10 - is in bytes
- SEND_MESSAGE_12 aa !!! Same as WRITE_12 - is in bytes
- SEND_OPC 54
- SEND_VOLUME_TAG b6 !!! Think this is in bytes
- SET_LIMITS 33
- SET_LIMITS_12 b3
- SET_WINDOW 24
- SLEW_AND_PRINT 0b !!! Conflicts with SEEK_6
- SPACE 11
- START_STOP_UNIT 1b
- STOP_PRINT 1b
- SYNCHRONIZE_BUFFER 10
- SYNCHRONIZE_CACHE 35
- TEST_UNIT_READY 00
- UPDATE_BLOCK 3d
- VERIFY 13
- VERIFY 2f
- VERIFY_12 af
- WRITE_6 0a
- WRITE_10 2a
- WRITE_12 aa
- WRITE_AND_VERIFY 2e
- WRITE_AND_VERIFY_12 ae
- WRITE_BUFFER 3b
- WRITE_FILEMARKS 10
- WRITE_LONG 3f
- WRITE_SAME 41
- */
-
- if (srb->sc_data_direction == SCSI_DATA_WRITE) {
- doDefault = 1;
- }
- else
- switch (lengths[srb->cmnd[0]]) {
- case 'L':
- len = srb->cmnd[4];
- break;
-
- case 'M':
- len = srb->cmnd[8];
- break;
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- len = lengths[srb->cmnd[0]]-'0';
- break;
-
- case 'G':
- len = (((unsigned int)srb->cmnd[3])<<8) |
- srb->cmnd[4];
- break;
-
- case 'H':
- len = (((unsigned int)srb->cmnd[7])<<8) |
- srb->cmnd[8];
- break;
-
- case 'I':
- len = (((unsigned int)srb->cmnd[8])<<8) |
- srb->cmnd[9];
- break;
-
- case 'R':
- len = (((unsigned int)srb->cmnd[2])<<16) |
- (((unsigned int)srb->cmnd[3])<<8) |
- srb->cmnd[4];
- break;
-
- case 'S':
- len = (((unsigned int)srb->cmnd[3])<<16) |
- (((unsigned int)srb->cmnd[4])<<8) |
- srb->cmnd[5];
- break;
-
- case 'T':
- len = (((unsigned int)srb->cmnd[6])<<16) |
- (((unsigned int)srb->cmnd[7])<<8) |
- srb->cmnd[8];
- break;
-
- case 'U':
- len = (((unsigned int)srb->cmnd[7])<<16) |
- (((unsigned int)srb->cmnd[8])<<8) |
- srb->cmnd[9];
- break;
-
- case 'C':
- len = (((unsigned int)srb->cmnd[2])<<24) |
- (((unsigned int)srb->cmnd[3])<<16) |
- (((unsigned int)srb->cmnd[4])<<8) |
- srb->cmnd[5];
- break;
-
- case 'D':
- len = (((unsigned int)srb->cmnd[6])<<24) |
- (((unsigned int)srb->cmnd[7])<<16) |
- (((unsigned int)srb->cmnd[8])<<8) |
- srb->cmnd[9];
- break;
-
- case 'V':
- len = 20;
- break;
-
- case 'W':
- len = 24;
- break;
-
- case 'B':
- /* Use buffer size due to different block sizes */
- doDefault = 1;
- break;
-
- case 'X':
- US_DEBUGP("Error: UNSUPPORTED COMMAND %02X\n",
- srb->cmnd[0]);
- doDefault = 1;
- break;
-
- case 'Z':
- /* Use buffer size due to mode dependence */
- doDefault = 1;
- break;
-
- default:
- US_DEBUGP("Error: COMMAND %02X out of range or table inconsistent (%c).\n",
- srb->cmnd[0], lengths[srb->cmnd[0]] );
- doDefault = 1;
- }
-
- if ( doDefault == 1 ) {
- /* Are we going to scatter gather? */
- if (srb->use_sg) {
- /* Add up the sizes of all the sg segments */
- sg = (struct scatterlist *) srb->request_buffer;
- for (i = 0; i < srb->use_sg; i++)
- total += sg[i].length;
- len = total;
- }
- else
- /* Just return the length of the buffer */
- len = srb->request_bufflen;
- }
-
-return len;
-}
-
-/* This is a version of usb_clear_halt() that doesn't read the status from
- * the device -- this is because some devices crash their internal firmware
- * when the status is requested after a halt
- */
-int usb_stor_clear_halt(struct usb_device *dev, int pipe)
-{
- int result;
- int endp = usb_pipeendpoint(pipe) | (usb_pipein(pipe) << 7);
-
- result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0,
- endp, NULL, 0, HZ * 3);
-
- /* this is a failure case */
- if (result < 0)
- return result;
-
- /* reset the toggles and endpoint flags */
- usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
- usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);
-
- return 0;
-}
-
-/***********************************************************************
- * Data transfer routines
- ***********************************************************************/
-
-/* This is the completion handler which will wake us up when an URB
- * completes.
- */
-static void usb_stor_blocking_completion(struct urb *urb)
-{
- struct completion *urb_done_ptr = (struct completion *)urb->context;
-
- complete(urb_done_ptr);
-}
-
-/* This is our function to emulate usb_control_msg() but give us enough
- * access to make aborts/resets work
- */
-int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
- u8 request, u8 requesttype, u16 value, u16 index,
- void *data, u16 size)
-{
- struct completion urb_done;
- int status;
- struct usb_ctrlrequest *dr;
-
- /* allocate the device request structure */
- dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
- if (!dr)
- return -ENOMEM;
-
- /* fill in the structure */
- dr->bRequestType = requesttype;
- dr->bRequest = request;
- dr->wValue = cpu_to_le16(value);
- dr->wIndex = cpu_to_le16(index);
- dr->wLength = cpu_to_le16(size);
-
- /* set up data structures for the wakeup system */
- init_completion(&urb_done);
-
- /* lock the URB */
- down(&(us->current_urb_sem));
-
- /* fill the URB */
- FILL_CONTROL_URB(us->current_urb, us->pusb_dev, pipe,
- (unsigned char*) dr, data, size,
- usb_stor_blocking_completion, &urb_done);
- us->current_urb->actual_length = 0;
- us->current_urb->error_count = 0;
- us->current_urb->transfer_flags = USB_ASYNC_UNLINK;
-
- /* submit the URB */
- status = usb_submit_urb(us->current_urb, GFP_NOIO);
- if (status) {
- /* something went wrong */
- up(&(us->current_urb_sem));
- kfree(dr);
- return status;
- }
-
- /* wait for the completion of the URB */
- up(&(us->current_urb_sem));
- wait_for_completion(&urb_done);
- down(&(us->current_urb_sem));
-
- /* return the actual length of the data transferred if no error*/
- status = us->current_urb->status;
- if (status >= 0)
- status = us->current_urb->actual_length;
-
- /* release the lock and return status */
- up(&(us->current_urb_sem));
- kfree(dr);
- return status;
-}
-
-/* This is our function to emulate usb_bulk_msg() but give us enough
- * access to make aborts/resets work
- */
-int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe,
- unsigned int len, unsigned int *act_len)
-{
- struct completion urb_done;
- int status;
-
- /* set up data structures for the wakeup system */
- init_completion(&urb_done);
-
- /* lock the URB */
- down(&(us->current_urb_sem));
-
- /* fill the URB */
- FILL_BULK_URB(us->current_urb, us->pusb_dev, pipe, data, len,
- usb_stor_blocking_completion, &urb_done);
- us->current_urb->actual_length = 0;
- us->current_urb->error_count = 0;
- us->current_urb->transfer_flags = USB_ASYNC_UNLINK;
-
- /* submit the URB */
- status = usb_submit_urb(us->current_urb, GFP_NOIO);
- if (status) {
- /* something went wrong */
- up(&(us->current_urb_sem));
- return status;
- }
-
- /* wait for the completion of the URB */
- up(&(us->current_urb_sem));
- wait_for_completion(&urb_done);
- down(&(us->current_urb_sem));
-
- /* return the actual length of the data transferred */
- *act_len = us->current_urb->actual_length;
-
- /* release the lock and return status */
- up(&(us->current_urb_sem));
- return us->current_urb->status;
-}
-
-/*
- * Transfer one SCSI scatter-gather buffer via bulk transfer
- *
- * Note that this function is necessary because we want the ability to
- * use scatter-gather memory. Good performance is achieved by a combination
- * of scatter-gather and clustering (which makes each chunk bigger).
- *
- * Note that the lower layer will always retry when a NAK occurs, up to the
- * timeout limit. Thus we don't have to worry about it for individual
- * packets.
- */
-int usb_stor_transfer_partial(struct us_data *us, char *buf, int length)
-{
- int result;
- int partial;
- int pipe;
-
- /* calculate the appropriate pipe information */
- if (us->srb->sc_data_direction == SCSI_DATA_READ)
- pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
- else
- pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
-
- /* transfer the data */
- US_DEBUGP("usb_stor_transfer_partial(): xfer %d bytes\n", length);
- result = usb_stor_bulk_msg(us, buf, pipe, length, &partial);
- US_DEBUGP("usb_stor_bulk_msg() returned %d xferred %d/%d\n",
- result, partial, length);
-
- /* if we stall, we need to clear it before we go on */
- if (result == -EPIPE) {
- US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
- usb_stor_clear_halt(us->pusb_dev, pipe);
- }
-
- /* did we send all the data? */
- if (partial == length) {
- US_DEBUGP("usb_stor_transfer_partial(): transfer complete\n");
- return US_BULK_TRANSFER_GOOD;
- }
-
- /* uh oh... we have an error code, so something went wrong. */
- if (result) {
- /* NAK - that means we've retried a few times already */
- if (result == -ETIMEDOUT) {
- US_DEBUGP("usb_stor_transfer_partial(): device NAKed\n");
- return US_BULK_TRANSFER_FAILED;
- }
-
- /* -ENOENT -- we canceled this transfer */
- if (result == -ENOENT) {
- US_DEBUGP("usb_stor_transfer_partial(): transfer aborted\n");
- return US_BULK_TRANSFER_ABORTED;
- }
-
- /* the catch-all case */
- US_DEBUGP("usb_stor_transfer_partial(): unknown error\n");
- return US_BULK_TRANSFER_FAILED;
- }
-
- /* no error code, so we must have transferred some data,
- * just not all of it */
- return US_BULK_TRANSFER_SHORT;
-}
-
-/*
- * Transfer an entire SCSI command's worth of data payload over the bulk
- * pipe.
- *
- * Note that this uses usb_stor_transfer_partial to achieve it's goals -- this
- * function simply determines if we're going to use scatter-gather or not,
- * and acts appropriately. For now, it also re-interprets the error codes.
- */
-void usb_stor_transfer(Scsi_Cmnd *srb, struct us_data* us)
-{
- int i;
- int result = -1;
- struct scatterlist *sg;
- unsigned int total_transferred = 0;
- unsigned int transfer_amount;
-
- /* calculate how much we want to transfer */
- transfer_amount = usb_stor_transfer_length(srb);
-
- /* was someone foolish enough to request more data than available
- * buffer space? */
- if (transfer_amount > srb->request_bufflen)
- transfer_amount = srb->request_bufflen;
-
- /* are we scatter-gathering? */
- if (srb->use_sg) {
-
- /* loop over all the scatter gather structures and
- * make the appropriate requests for each, until done
- */
- sg = (struct scatterlist *) srb->request_buffer;
- for (i = 0; i < srb->use_sg; i++) {
-
- /* transfer the lesser of the next buffer or the
- * remaining data */
- if (transfer_amount - total_transferred >=
- sg[i].length) {
- result = usb_stor_transfer_partial(us,
- page_address(sg[i].page) + sg[i].offset, sg[i].length);
- total_transferred += sg[i].length;
- } else
- result = usb_stor_transfer_partial(us,
- page_address(sg[i].page) + sg[i].offset,
- transfer_amount - total_transferred);
-
- /* if we get an error, end the loop here */
- if (result)
- break;
- }
- }
- else
- /* no scatter-gather, just make the request */
- result = usb_stor_transfer_partial(us, srb->request_buffer,
- transfer_amount);
-
- /* return the result in the data structure itself */
- srb->result = result;
-}
-
-/***********************************************************************
- * Transport routines
- ***********************************************************************/
-
-/* Invoke the transport and basic error-handling/recovery methods
- *
- * This is used by the protocol layers to actually send the message to
- * the device and receive the response.
- */
-void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
-{
- int need_auto_sense;
- int result;
-
- /* send the command to the transport layer */
- result = us->transport(srb, us);
-
- /* if the command gets aborted by the higher layers, we need to
- * short-circuit all other processing
- */
- if (result == USB_STOR_TRANSPORT_ABORTED) {
- US_DEBUGP("-- transport indicates command was aborted\n");
- srb->result = DID_ABORT << 16;
- return;
- }
-
- /* Determine if we need to auto-sense
- *
- * I normally don't use a flag like this, but it's almost impossible
- * to understand what's going on here if I don't.
- */
- need_auto_sense = 0;
-
- /*
- * If we're running the CB transport, which is incapable
- * of determining status on it's own, we need to auto-sense almost
- * every time.
- */
- if (us->protocol == US_PR_CB || us->protocol == US_PR_DPCM_USB) {
- US_DEBUGP("-- CB transport device requiring auto-sense\n");
- need_auto_sense = 1;
-
- /* There are some exceptions to this. Notably, if this is
- * a UFI device and the command is REQUEST_SENSE or INQUIRY,
- * then it is impossible to truly determine status.
- */
- if (us->subclass == US_SC_UFI &&
- ((srb->cmnd[0] == REQUEST_SENSE) ||
- (srb->cmnd[0] == INQUIRY))) {
- US_DEBUGP("** no auto-sense for a special command\n");
- need_auto_sense = 0;
- }
- }
-
- /*
- * If we have an error, we're going to do a REQUEST_SENSE
- * automatically. Note that we differentiate between a command
- * "failure" and an "error" in the transport mechanism.
- */
- if (result == USB_STOR_TRANSPORT_FAILED) {
- US_DEBUGP("-- transport indicates command failure\n");
- need_auto_sense = 1;
- }
- if (result == USB_STOR_TRANSPORT_ERROR) {
- us->transport_reset(us);
- US_DEBUGP("-- transport indicates transport failure\n");
- need_auto_sense = 0;
- srb->result = DID_ERROR << 16;
- return;
- }
-
- /*
- * Also, if we have a short transfer on a command that can't have
- * a short transfer, we're going to do this.
- */
- if ((srb->result == US_BULK_TRANSFER_SHORT) &&
- !((srb->cmnd[0] == REQUEST_SENSE) ||
- (srb->cmnd[0] == INQUIRY) ||
- (srb->cmnd[0] == MODE_SENSE) ||
- (srb->cmnd[0] == LOG_SENSE) ||
- (srb->cmnd[0] == MODE_SENSE_10))) {
- US_DEBUGP("-- unexpectedly short transfer\n");
- need_auto_sense = 1;
- }
-
- /* Now, if we need to do the auto-sense, let's do it */
- if (need_auto_sense) {
- int temp_result;
- void* old_request_buffer;
- unsigned short old_sg;
- unsigned old_request_bufflen;
- unsigned char old_sc_data_direction;
- unsigned char old_cmnd[MAX_COMMAND_SIZE];
-
- US_DEBUGP("Issuing auto-REQUEST_SENSE\n");
-
- /* save the old command */
- memcpy(old_cmnd, srb->cmnd, MAX_COMMAND_SIZE);
-
- /* set the command and the LUN */
- srb->cmnd[0] = REQUEST_SENSE;
- srb->cmnd[1] = old_cmnd[1] & 0xE0;
- srb->cmnd[2] = 0;
- srb->cmnd[3] = 0;
- srb->cmnd[4] = 18;
- srb->cmnd[5] = 0;
-
- /* set the transfer direction */
- old_sc_data_direction = srb->sc_data_direction;
- srb->sc_data_direction = SCSI_DATA_READ;
-
- /* use the new buffer we have */
- old_request_buffer = srb->request_buffer;
- srb->request_buffer = srb->sense_buffer;
-
- /* set the buffer length for transfer */
- old_request_bufflen = srb->request_bufflen;
- srb->request_bufflen = 18;
-
- /* set up for no scatter-gather use */
- old_sg = srb->use_sg;
- srb->use_sg = 0;
-
- /* issue the auto-sense command */
- temp_result = us->transport(us->srb, us);
- if (temp_result != USB_STOR_TRANSPORT_GOOD) {
- US_DEBUGP("-- auto-sense failure\n");
-
- /* we skip the reset if this happens to be a
- * multi-target device, since failure of an
- * auto-sense is perfectly valid
- */
- if (!(us->flags & US_FL_SCM_MULT_TARG)) {
- us->transport_reset(us);
- }
- srb->result = DID_ERROR << 16;
- return;
- }
-
- US_DEBUGP("-- Result from auto-sense is %d\n", temp_result);
- US_DEBUGP("-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n",
- srb->sense_buffer[0],
- srb->sense_buffer[2] & 0xf,
- srb->sense_buffer[12],
- srb->sense_buffer[13]);
-#ifdef CONFIG_USB_STORAGE_DEBUG
- usb_stor_show_sense(
- srb->sense_buffer[2] & 0xf,
- srb->sense_buffer[12],
- srb->sense_buffer[13]);
-#endif
-
- /* set the result so the higher layers expect this data */
- srb->result = CHECK_CONDITION << 1;
-
- /* we're done here, let's clean up */
- srb->request_buffer = old_request_buffer;
- srb->request_bufflen = old_request_bufflen;
- srb->use_sg = old_sg;
- srb->sc_data_direction = old_sc_data_direction;
- memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE);
-
- /* If things are really okay, then let's show that */
- if ((srb->sense_buffer[2] & 0xf) == 0x0)
- srb->result = GOOD << 1;
- } else /* if (need_auto_sense) */
- srb->result = GOOD << 1;
-
- /* Regardless of auto-sense, if we _know_ we have an error
- * condition, show that in the result code
- */
- if (result == USB_STOR_TRANSPORT_FAILED)
- srb->result = CHECK_CONDITION << 1;
-
- /* If we think we're good, then make sure the sense data shows it.
- * This is necessary because the auto-sense for some devices always
- * sets byte 0 == 0x70, even if there is no error
- */
- if ((us->protocol == US_PR_CB || us->protocol == US_PR_DPCM_USB) &&
- (result == USB_STOR_TRANSPORT_GOOD) &&
- ((srb->sense_buffer[2] & 0xf) == 0x0))
- srb->sense_buffer[0] = 0x0;
-}
-
-/*
- * Control/Bulk/Interrupt transport
- */
-
-/* The interrupt handler for CBI devices */
-void usb_stor_CBI_irq(struct urb *urb)
-{
- struct us_data *us = (struct us_data *)urb->context;
-
- US_DEBUGP("USB IRQ received for device on host %d\n", us->host_no);
- US_DEBUGP("-- IRQ data length is %d\n", urb->actual_length);
- US_DEBUGP("-- IRQ state is %d\n", urb->status);
- US_DEBUGP("-- Interrupt Status (0x%x, 0x%x)\n",
- us->irqbuf[0], us->irqbuf[1]);
-
- /* reject improper IRQs */
- if (urb->actual_length != 2) {
- US_DEBUGP("-- IRQ too short\n");
- return;
- }
-
- /* is the device removed? */
- if (urb->status == -ENOENT) {
- US_DEBUGP("-- device has been removed\n");
- return;
- }
-
- /* was this a command-completion interrupt? */
- if (us->irqbuf[0] && (us->subclass != US_SC_UFI)) {
- US_DEBUGP("-- not a command-completion IRQ\n");
- return;
- }
-
- /* was this a wanted interrupt? */
- if (!atomic_read(us->ip_wanted)) {
- US_DEBUGP("ERROR: Unwanted interrupt received!\n");
- return;
- }
-
- /* adjust the flag */
- atomic_set(us->ip_wanted, 0);
-
- /* copy the valid data */
- us->irqdata[0] = us->irqbuf[0];
- us->irqdata[1] = us->irqbuf[1];
-
- /* wake up the command thread */
- US_DEBUGP("-- Current value of ip_waitq is: %d\n",
- atomic_read(&us->ip_waitq.count));
- up(&(us->ip_waitq));
-}
-
-int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
-{
- int result;
-
- /* Set up for status notification */
- atomic_set(us->ip_wanted, 1);
-
- /* re-initialize the mutex so that we avoid any races with
- * early/late IRQs from previous commands */
- init_MUTEX_LOCKED(&(us->ip_waitq));
-
- /* COMMAND STAGE */
- /* let's send the command via the control pipe */
- result = usb_stor_control_msg(us, usb_sndctrlpipe(us->pusb_dev,0),
- US_CBI_ADSC,
- USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0,
- us->ifnum, srb->cmnd, srb->cmd_len);
-
- /* check the return code for the command */
- US_DEBUGP("Call to usb_stor_control_msg() returned %d\n", result);
- if (result < 0) {
- /* Reset flag for status notification */
- atomic_set(us->ip_wanted, 0);
-
- /* if the command was aborted, indicate that */
- if (result == -ENOENT)
- return USB_STOR_TRANSPORT_ABORTED;
-
- /* STALL must be cleared when they are detected */
- if (result == -EPIPE) {
- US_DEBUGP("-- Stall on control pipe. Clearing\n");
- result = usb_stor_clear_halt(us->pusb_dev,
- usb_sndctrlpipe(us->pusb_dev,
- 0));
- US_DEBUGP("-- usb_stor_clear_halt() returns %d\n", result);
- return USB_STOR_TRANSPORT_FAILED;
- }
-
- /* Uh oh... serious problem here */
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- /* DATA STAGE */
- /* transfer the data payload for this command, if one exists*/
- if (usb_stor_transfer_length(srb)) {
- usb_stor_transfer(srb, us);
- US_DEBUGP("CBI data stage result is 0x%x\n", srb->result);
-
- /* if it was aborted, we need to indicate that */
- if (srb->result == USB_STOR_TRANSPORT_ABORTED) {
- return USB_STOR_TRANSPORT_ABORTED;
- }
- }
-
- /* STATUS STAGE */
-
- /* go to sleep until we get this interrupt */
- US_DEBUGP("Current value of ip_waitq is: %d\n", atomic_read(&us->ip_waitq.count));
- down(&(us->ip_waitq));
-
- /* if we were woken up by an abort instead of the actual interrupt */
- if (atomic_read(us->ip_wanted)) {
- US_DEBUGP("Did not get interrupt on CBI\n");
- atomic_set(us->ip_wanted, 0);
- return USB_STOR_TRANSPORT_ABORTED;
- }
-
- US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n",
- us->irqdata[0], us->irqdata[1]);
-
- /* UFI gives us ASC and ASCQ, like a request sense
- *
- * REQUEST_SENSE and INQUIRY don't affect the sense data on UFI
- * devices, so we ignore the information for those commands. Note
- * that this means we could be ignoring a real error on these
- * commands, but that can't be helped.
- */
- if (us->subclass == US_SC_UFI) {
- if (srb->cmnd[0] == REQUEST_SENSE ||
- srb->cmnd[0] == INQUIRY)
- return USB_STOR_TRANSPORT_GOOD;
- else
- if (((unsigned char*)us->irq_urb->transfer_buffer)[0])
- return USB_STOR_TRANSPORT_FAILED;
- else
- return USB_STOR_TRANSPORT_GOOD;
- }
-
- /* If not UFI, we interpret the data as a result code
- * The first byte should always be a 0x0
- * The second byte & 0x0F should be 0x0 for good, otherwise error
- */
- if (us->irqdata[0]) {
- US_DEBUGP("CBI IRQ data showed reserved bType %d\n",
- us->irqdata[0]);
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- switch (us->irqdata[1] & 0x0F) {
- case 0x00:
- return USB_STOR_TRANSPORT_GOOD;
- case 0x01:
- return USB_STOR_TRANSPORT_FAILED;
- default:
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- /* we should never get here, but if we do, we're in trouble */
- return USB_STOR_TRANSPORT_ERROR;
-}
-
-/*
- * Control/Bulk transport
- */
-int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
-{
- int result;
-
- /* COMMAND STAGE */
- /* let's send the command via the control pipe */
- result = usb_stor_control_msg(us, usb_sndctrlpipe(us->pusb_dev,0),
- US_CBI_ADSC,
- USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0,
- us->ifnum, srb->cmnd, srb->cmd_len);
-
- /* check the return code for the command */
- US_DEBUGP("Call to usb_stor_control_msg() returned %d\n", result);
- if (result < 0) {
- /* if the command was aborted, indicate that */
- if (result == -ENOENT)
- return USB_STOR_TRANSPORT_ABORTED;
-
- /* a stall is a fatal condition from the device */
- if (result == -EPIPE) {
- US_DEBUGP("-- Stall on control pipe. Clearing\n");
- result = usb_stor_clear_halt(us->pusb_dev,
- usb_sndctrlpipe(us->pusb_dev,
- 0));
- US_DEBUGP("-- usb_stor_clear_halt() returns %d\n", result);
- return USB_STOR_TRANSPORT_FAILED;
- }
-
- /* Uh oh... serious problem here */
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- /* DATA STAGE */
- /* transfer the data payload for this command, if one exists*/
- if (usb_stor_transfer_length(srb)) {
- usb_stor_transfer(srb, us);
- US_DEBUGP("CB data stage result is 0x%x\n", srb->result);
-
- /* if it was aborted, we need to indicate that */
- if (srb->result == USB_STOR_TRANSPORT_ABORTED)
- return USB_STOR_TRANSPORT_ABORTED;
- }
-
- /* STATUS STAGE */
- /* NOTE: CB does not have a status stage. Silly, I know. So
- * we have to catch this at a higher level.
- */
- return USB_STOR_TRANSPORT_GOOD;
-}
-
-/*
- * Bulk only transport
- */
-
-/* Determine what the maximum LUN supported is */
-int usb_stor_Bulk_max_lun(struct us_data *us)
-{
- unsigned char data;
- int result;
- int pipe;
-
- /* issue the command */
- pipe = usb_rcvctrlpipe(us->pusb_dev, 0);
- result = usb_control_msg(us->pusb_dev, pipe,
- US_BULK_GET_MAX_LUN,
- USB_DIR_IN | USB_TYPE_CLASS |
- USB_RECIP_INTERFACE,
- 0, us->ifnum, &data, sizeof(data), HZ);
-
- US_DEBUGP("GetMaxLUN command result is %d, data is %d\n",
- result, data);
-
- /* if we have a successful request, return the result */
- if (result == 1)
- return data;
-
- /* if we get a STALL, clear the stall */
- if (result == -EPIPE) {
- US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
- usb_stor_clear_halt(us->pusb_dev, pipe);
- }
-
- /* return the default -- no LUNs */
- return 0;
-}
-
-int usb_stor_Bulk_reset(struct us_data *us);
-
-int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
-{
- struct bulk_cb_wrap bcb;
- struct bulk_cs_wrap bcs;
- int result;
- int pipe;
- int partial;
-
- /* if the device was removed, then we're already reset */
- if (!us->pusb_dev)
- return SUCCESS;
-
- /* set up the command wrapper */
- bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN);
- bcb.DataTransferLength = cpu_to_le32(usb_stor_transfer_length(srb));
- bcb.Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;
- bcb.Tag = srb->serial_number;
- bcb.Lun = srb->cmnd[1] >> 5;
- if (us->flags & US_FL_SCM_MULT_TARG)
- bcb.Lun |= srb->target << 4;
- bcb.Length = srb->cmd_len;
-
- /* construct the pipe handle */
- pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
-
- /* copy the command payload */
- memset(bcb.CDB, 0, sizeof(bcb.CDB));
- memcpy(bcb.CDB, srb->cmnd, bcb.Length);
-
- /* send it to out endpoint */
- US_DEBUGP("Bulk command S 0x%x T 0x%x Trg %d LUN %d L %d F %d CL %d\n",
- le32_to_cpu(bcb.Signature), bcb.Tag,
- (bcb.Lun >> 4), (bcb.Lun & 0x0F),
- bcb.DataTransferLength, bcb.Flags, bcb.Length);
- result = usb_stor_bulk_msg(us, &bcb, pipe, US_BULK_CB_WRAP_LEN,
- &partial);
- US_DEBUGP("Bulk command transfer result=%d\n", result);
-
- /* if the command was aborted, indicate that */
- if (result == -ENOENT)
- return USB_STOR_TRANSPORT_ABORTED;
-
- /* if we stall, we need to clear it before we go on */
- if (result == -EPIPE) {
- US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
- usb_stor_clear_halt(us->pusb_dev, pipe);
- } else if (result) {
- /* unknown error -- we've got a problem */
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- /* if the command transfered well, then we go to the data stage */
- if (result == 0) {
- /* send/receive data payload, if there is any */
- if (bcb.DataTransferLength) {
- usb_stor_transfer(srb, us);
- US_DEBUGP("Bulk data transfer result 0x%x\n",
- srb->result);
-
- /* if it was aborted, we need to indicate that */
- if (srb->result == USB_STOR_TRANSPORT_ABORTED)
- return USB_STOR_TRANSPORT_ABORTED;
- }
- }
-
- /* See flow chart on pg 15 of the Bulk Only Transport spec for
- * an explanation of how this code works.
- */
-
- /* construct the pipe handle */
- pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
-
- /* get CSW for device status */
- US_DEBUGP("Attempting to get CSW...\n");
- result = usb_stor_bulk_msg(us, &bcs, pipe, US_BULK_CS_WRAP_LEN,
- &partial);
-
- /* if the command was aborted, indicate that */
- if (result == -ENOENT)
- return USB_STOR_TRANSPORT_ABORTED;
-
- /* did the attempt to read the CSW fail? */
- if (result == -EPIPE) {
- US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
- usb_stor_clear_halt(us->pusb_dev, pipe);
-
- /* get the status again */
- US_DEBUGP("Attempting to get CSW (2nd try)...\n");
- result = usb_stor_bulk_msg(us, &bcs, pipe,
- US_BULK_CS_WRAP_LEN, &partial);
-
- /* if the command was aborted, indicate that */
- if (result == -ENOENT)
- return USB_STOR_TRANSPORT_ABORTED;
-
- /* if it fails again, we need a reset and return an error*/
- if (result == -EPIPE) {
- US_DEBUGP("clearing halt for pipe 0x%x\n", pipe);
- usb_stor_clear_halt(us->pusb_dev, pipe);
- return USB_STOR_TRANSPORT_ERROR;
- }
- }
-
- /* if we still have a failure at this point, we're in trouble */
- US_DEBUGP("Bulk status result = %d\n", result);
- if (result) {
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- /* check bulk status */
- US_DEBUGP("Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x\n",
- le32_to_cpu(bcs.Signature), bcs.Tag,
- bcs.Residue, bcs.Status);
- if (bcs.Signature != cpu_to_le32(US_BULK_CS_SIGN) ||
- bcs.Tag != bcb.Tag ||
- bcs.Status > US_BULK_STAT_PHASE || partial != 13) {
- US_DEBUGP("Bulk logical error\n");
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- /* based on the status code, we report good or bad */
- switch (bcs.Status) {
- case US_BULK_STAT_OK:
- /* command good -- note that data could be short */
- return USB_STOR_TRANSPORT_GOOD;
-
- case US_BULK_STAT_FAIL:
- /* command failed */
- return USB_STOR_TRANSPORT_FAILED;
-
- case US_BULK_STAT_PHASE:
- /* phase error -- note that a transport reset will be
- * invoked by the invoke_transport() function
- */
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- /* we should never get here, but if we do, we're in trouble */
- return USB_STOR_TRANSPORT_ERROR;
-}
-
-/***********************************************************************
- * Reset routines
- ***********************************************************************/
-
-/* This issues a CB[I] Reset to the device in question
- */
-int usb_stor_CB_reset(struct us_data *us)
-{
- unsigned char cmd[12];
- int result;
-
- US_DEBUGP("CB_reset() called\n");
-
- /* if the device was removed, then we're already reset */
- if (!us->pusb_dev)
- return SUCCESS;
-
- memset(cmd, 0xFF, sizeof(cmd));
- cmd[0] = SEND_DIAGNOSTIC;
- cmd[1] = 4;
- result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
- US_CBI_ADSC,
- USB_TYPE_CLASS | USB_RECIP_INTERFACE,
- 0, us->ifnum, cmd, sizeof(cmd), HZ*5);
-
- if (result < 0) {
- US_DEBUGP("CB[I] soft reset failed %d\n", result);
- return FAILED;
- }
-
- /* long wait for reset */
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ*6);
- set_current_state(TASK_RUNNING);
-
- US_DEBUGP("CB_reset: clearing endpoint halt\n");
- usb_stor_clear_halt(us->pusb_dev,
- usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
- usb_stor_clear_halt(us->pusb_dev,
- usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
-
- US_DEBUGP("CB_reset done\n");
- /* return a result code based on the result of the control message */
- return SUCCESS;
-}
-
-/* This issues a Bulk-only Reset to the device in question, including
- * clearing the subsequent endpoint halts that may occur.
- */
-int usb_stor_Bulk_reset(struct us_data *us)
-{
- int result;
-
- US_DEBUGP("Bulk reset requested\n");
-
- /* if the device was removed, then we're already reset */
- if (!us->pusb_dev)
- return SUCCESS;
-
- result = usb_control_msg(us->pusb_dev,
- usb_sndctrlpipe(us->pusb_dev,0),
- US_BULK_RESET_REQUEST,
- USB_TYPE_CLASS | USB_RECIP_INTERFACE,
- 0, us->ifnum, NULL, 0, HZ*5);
-
- if (result < 0) {
- US_DEBUGP("Bulk soft reset failed %d\n", result);
- return FAILED;
- }
-
- /* long wait for reset */
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ*6);
- set_current_state(TASK_RUNNING);
-
- usb_stor_clear_halt(us->pusb_dev,
- usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
- usb_stor_clear_halt(us->pusb_dev,
- usb_sndbulkpipe(us->pusb_dev, us->ep_out));
- US_DEBUGP("Bulk soft reset completed\n");
- return SUCCESS;
-}
diff --git a/drivers/usb/class/storage/transport.h b/drivers/usb/class/storage/transport.h
deleted file mode 100644
index 2dc2ac1a3e0a..000000000000
--- a/drivers/usb/class/storage/transport.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/* Driver for USB Mass Storage compliant devices
- * Transport Functions Header File
- *
- * $Id: transport.h,v 1.15 2001/03/17 20:06:23 jrmayfield Exp $
- *
- * Current development and maintenance by:
- * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
- *
- * This driver is based on the 'USB Mass Storage Class' document. This
- * describes in detail the protocol used to communicate with such
- * devices. Clearly, the designers had SCSI and ATAPI commands in
- * mind when they created this document. The commands are all very
- * similar to commands in the SCSI-II and ATAPI specifications.
- *
- * It is important to note that in a number of cases this class
- * exhibits class-specific exemptions from the USB specification.
- * Notably the usage of NAK, STALL and ACK differs from the norm, in
- * that they are used to communicate wait, failed and OK on commands.
- *
- * Also, for certain devices, the interrupt endpoint is used to convey
- * status of a command.
- *
- * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more
- * information about this driver.
- *
- * 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, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _TRANSPORT_H_
-#define _TRANSPORT_H_
-
-#include <linux/config.h>
-#include <linux/blk.h>
-#include "usb.h"
-#include "scsi.h"
-
-/* Protocols */
-
-#define US_PR_CBI 0x00 /* Control/Bulk/Interrupt */
-#define US_PR_CB 0x01 /* Control/Bulk w/o interrupt */
-#define US_PR_BULK 0x50 /* bulk only */
-#ifdef CONFIG_USB_STORAGE_HP8200e
-#define US_PR_SCM_ATAPI 0x80 /* SCM-ATAPI bridge */
-#endif
-#ifdef CONFIG_USB_STORAGE_SDDR09
-#define US_PR_EUSB_SDDR09 0x81 /* SCM-SCSI bridge for
- SDDR-09 */
-#endif
-#define US_PR_DPCM_USB 0xf0 /* Combination CB/SDDR09 */
-
-#ifdef CONFIG_USB_STORAGE_FREECOM
-#define US_PR_FREECOM 0xf1 /* Freecom */
-#endif
-
-#ifdef CONFIG_USB_STORAGE_DATAFAB
-#define US_PR_DATAFAB 0xf2 /* Datafab chipsets */
-#endif
-
-#ifdef CONFIG_USB_STORAGE_JUMPSHOT
-#define US_PR_JUMPSHOT 0xf3 /* Lexar Jumpshot */
-#endif
-
-/*
- * 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 data */
- __u8 Flags; /* direction in bit 0 */
- __u8 Lun; /* LUN normally 0 */
- __u8 Length; /* of of the CDB */
- __u8 CDB[16]; /* max command */
-};
-
-#define US_BULK_CB_WRAP_LEN 31
-#define US_BULK_CB_SIGN 0x43425355 /*spells out USBC */
-#define US_BULK_FLAG_IN 1
-#define US_BULK_FLAG_OUT 0
-
-/* 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 */
- __u8 Filler[18];
-};
-
-#define US_BULK_CS_WRAP_LEN 13
-#define US_BULK_CS_SIGN 0x53425355 /* spells out 'USBS' */
-#define US_BULK_STAT_OK 0
-#define US_BULK_STAT_FAIL 1
-#define US_BULK_STAT_PHASE 2
-
-/* bulk-only class specific requests */
-#define US_BULK_RESET_REQUEST 0xff
-#define US_BULK_GET_MAX_LUN 0xfe
-
-/*
- * usb_stor_transfer() return codes
- */
-#define US_BULK_TRANSFER_GOOD 0 /* good transfer */
-#define US_BULK_TRANSFER_SHORT 1 /* transfered less than expected */
-#define US_BULK_TRANSFER_FAILED 2 /* transfer died in the middle */
-#define US_BULK_TRANSFER_ABORTED 3 /* transfer canceled */
-
-/*
- * Transport return codes
- */
-
-#define USB_STOR_TRANSPORT_GOOD 0 /* Transport good, command good */
-#define USB_STOR_TRANSPORT_FAILED 1 /* Transport good, command failed */
-#define USB_STOR_TRANSPORT_ERROR 2 /* Transport bad (i.e. device dead) */
-#define USB_STOR_TRANSPORT_ABORTED 3 /* Transport aborted */
-
-/*
- * CBI accept device specific command
- */
-
-#define US_CBI_ADSC 0
-
-extern void usb_stor_CBI_irq(struct urb*);
-extern int usb_stor_CBI_transport(Scsi_Cmnd*, struct us_data*);
-
-extern int usb_stor_CB_transport(Scsi_Cmnd*, struct us_data*);
-extern int usb_stor_CB_reset(struct us_data*);
-
-extern int usb_stor_Bulk_transport(Scsi_Cmnd*, struct us_data*);
-extern int usb_stor_Bulk_max_lun(struct us_data*);
-extern int usb_stor_Bulk_reset(struct us_data*);
-
-extern unsigned int usb_stor_transfer_length(Scsi_Cmnd*);
-extern void usb_stor_invoke_transport(Scsi_Cmnd*, struct us_data*);
-extern int usb_stor_transfer_partial(struct us_data*, char*, int);
-extern int usb_stor_bulk_msg(struct us_data*, void*, int, unsigned int,
- unsigned int*);
-extern int usb_stor_control_msg(struct us_data*, unsigned int, u8, u8,
- u16, u16, void*, u16);
-extern void usb_stor_transfer(Scsi_Cmnd*, struct us_data*);
-extern int usb_stor_clear_halt(struct usb_device*, int );
-#endif
diff --git a/drivers/usb/class/storage/unusual_devs.h b/drivers/usb/class/storage/unusual_devs.h
deleted file mode 100644
index 87ba0ccb0d30..000000000000
--- a/drivers/usb/class/storage/unusual_devs.h
+++ /dev/null
@@ -1,477 +0,0 @@
-/* Driver for USB Mass Storage compliant devices
- * Ununsual Devices File
- *
- * $Id: unusual_devs.h,v 1.25 2002/01/13 06:39:17 mdharm Exp $
- *
- * Current development and maintenance by:
- * (c) 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
- *
- * Initial work by:
- * (c) 2000 Adam J. Richter (adam@yggdrasil.com), Yggdrasil Computing, Inc.
- *
- * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more
- * information about this driver.
- *
- * 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, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/* IMPORTANT NOTE: This file must be included in another file which does
- * the following thing for it to work:
- * The macro UNUSUAL_DEV() must be defined before this file is included
- */
-#include <linux/config.h>
-
-/* If you edit this file, please try to keep it sorted first by VendorID,
- * then by ProductID.
- */
-
-UNUSUAL_DEV( 0x03ee, 0x0000, 0x0000, 0x0245,
- "Mitsumi",
- "CD-R/RW Drive",
- US_SC_8020, US_PR_CBI, NULL, 0),
-
-UNUSUAL_DEV( 0x03ee, 0x6901, 0x0000, 0x0100,
- "Mitsumi",
- "USB FDD",
- US_SC_UFI, US_PR_CBI, NULL,
- US_FL_SINGLE_LUN ),
-
-UNUSUAL_DEV( 0x03f0, 0x0107, 0x0200, 0x0200,
- "HP",
- "CD-Writer+",
- US_SC_8070, US_PR_CB, NULL, 0),
-
-#ifdef CONFIG_USB_STORAGE_HP8200e
-UNUSUAL_DEV( 0x03f0, 0x0207, 0x0001, 0x0001,
- "HP",
- "CD-Writer+ 8200e",
- US_SC_8070, US_PR_SCM_ATAPI, init_8200e, 0),
-
-UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001,
- "HP",
- "CD-Writer+ CD-4e",
- US_SC_8070, US_PR_SCM_ATAPI, init_8200e, 0),
-#endif
-
-#ifdef CONFIG_USB_STORAGE_DPCM
-UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100,
- "Microtech",
- "CameraMate (DPCM_USB)",
- US_SC_SCSI, US_PR_DPCM_USB, NULL,
- US_FL_START_STOP ),
-#endif
-
-/* Made with the help of Edd Dumbill <edd@usefulinc.com> */
-UNUSUAL_DEV( 0x0451, 0x5409, 0x0001, 0x0001,
- "Frontier Labs",
- "Nex II Digital",
- US_SC_SCSI, US_PR_BULK, NULL, US_FL_START_STOP),
-
-/* Reported by Paul Stewart <stewart@wetlogic.net>
- * This entry is needed because the device reports Sub=ff */
-UNUSUAL_DEV( 0x04a4, 0x0004, 0x0001, 0x0001,
- "Hitachi",
- "DVD-CAM DZ-MV100A Camcorder",
- US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN),
-
-UNUSUAL_DEV( 0x04cb, 0x0100, 0x0000, 0x2210,
- "Fujifilm",
- "FinePix 1400Zoom",
- US_SC_8070, US_PR_CBI, NULL, US_FL_FIX_INQUIRY),
-
-/* Reported by Peter Wächtler <pwaechtler@loewe-komp.de>
- * The device needs the flags only.
- */
-UNUSUAL_DEV( 0x04ce, 0x0002, 0x0074, 0x0074,
- "ScanLogic",
- "SL11R-IDE",
- US_SC_SCSI, US_PR_BULK, NULL,
- US_FL_FIX_INQUIRY),
-
-/* Reported by Kriston Fincher <kriston@airmail.net>
- * Patch submitted by Sean Millichamp <sean@bruenor.org>
- * This is to support the Panasonic PalmCam PV-SD4090
- * This entry is needed because the device reports Sub=ff
- */
-UNUSUAL_DEV( 0x04da, 0x0901, 0x0100, 0x0200,
- "Panasonic",
- "LS-120 Camera",
- US_SC_UFI, US_PR_CBI, NULL, 0),
-
-/* Most of the following entries were developed with the help of
- * Shuttle/SCM directly.
- */
-UNUSUAL_DEV( 0x04e6, 0x0001, 0x0200, 0x0200,
- "Matshita",
- "LS-120",
- US_SC_8020, US_PR_CB, NULL, 0),
-
-UNUSUAL_DEV( 0x04e6, 0x0002, 0x0100, 0x0100,
- "Shuttle",
- "eUSCSI Bridge",
- US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
- US_FL_SCM_MULT_TARG ),
-
-#ifdef CONFIG_USB_STORAGE_SDDR09
-UNUSUAL_DEV( 0x04e6, 0x0003, 0x0000, 0x9999,
- "Sandisk",
- "ImageMate SDDR09",
- US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
- US_FL_SINGLE_LUN | US_FL_START_STOP ),
-#endif
-
-/* This entry is from Andries.Brouwer@cwi.nl */
-UNUSUAL_DEV( 0x04e6, 0x0005, 0x0100, 0x0208,
- "SCM Microsystems",
- "eUSB SmartMedia / CompactFlash Adapter",
- US_SC_SCSI, US_PR_DPCM_USB, NULL,
- US_FL_START_STOP),
-
-UNUSUAL_DEV( 0x04e6, 0x0006, 0x0100, 0x0205,
- "Shuttle",
- "eUSB MMC Adapter",
- US_SC_SCSI, US_PR_CB, NULL,
- US_FL_SINGLE_LUN),
-
-UNUSUAL_DEV( 0x04e6, 0x0007, 0x0100, 0x0200,
- "Sony",
- "Hifd",
- US_SC_SCSI, US_PR_CB, NULL,
- US_FL_SINGLE_LUN),
-
-UNUSUAL_DEV( 0x04e6, 0x0009, 0x0200, 0x0200,
- "Shuttle",
- "eUSB ATA/ATAPI Adapter",
- US_SC_8020, US_PR_CB, NULL, 0),
-
-UNUSUAL_DEV( 0x04e6, 0x000a, 0x0200, 0x0200,
- "Shuttle",
- "eUSB CompactFlash Adapter",
- US_SC_8020, US_PR_CB, NULL, 0),
-
-UNUSUAL_DEV( 0x04e6, 0x000B, 0x0100, 0x0100,
- "Shuttle",
- "eUSCSI Bridge",
- US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
- US_FL_SCM_MULT_TARG ),
-
-UNUSUAL_DEV( 0x04e6, 0x000C, 0x0100, 0x0100,
- "Shuttle",
- "eUSCSI Bridge",
- US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
- US_FL_SCM_MULT_TARG ),
-
-UNUSUAL_DEV( 0x04e6, 0x0101, 0x0200, 0x0200,
- "Shuttle",
- "CD-RW Device",
- US_SC_8020, US_PR_CB, NULL, 0),
-
-/* Reported by Bob Sass <rls@vectordb.com> -- only rev 1.33 tested */
-UNUSUAL_DEV( 0x050d, 0x0115, 0x0133, 0x0133,
- "Belkin",
- "USB SCSI Adaptor",
- US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
- US_FL_SCM_MULT_TARG ),
-
-/* Iomega Clik! Drive
- * Reported by David Chatenay <dchatenay@hotmail.com>
- * The reason this is needed is not fully known.
- */
-UNUSUAL_DEV( 0x0525, 0xa140, 0x0100, 0x0100,
- "Iomega",
- "USB Clik! 40",
- US_SC_8070, US_PR_BULK, NULL,
- US_FL_FIX_INQUIRY | US_FL_START_STOP ),
-
-/* This entry is needed because the device reports Sub=ff */
-UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0422,
- "Sony",
- "DSC-S30/S70/S75/505V/F505",
- US_SC_SCSI, US_PR_CB, NULL,
- US_FL_SINGLE_LUN | US_FL_START_STOP | US_FL_MODE_XLATE ),
-
-/* Reported by wim@geeks.nl */
-UNUSUAL_DEV( 0x054c, 0x0025, 0x0100, 0x0100,
- "Sony",
- "Memorystick NW-MS7",
- US_SC_UFI, US_PR_CB, NULL,
- US_FL_SINGLE_LUN | US_FL_START_STOP ),
-
-UNUSUAL_DEV( 0x054c, 0x002d, 0x0100, 0x0100,
- "Sony",
- "Memorystick MSAC-US1",
- US_SC_UFI, US_PR_CB, NULL,
- US_FL_SINGLE_LUN | US_FL_START_STOP ),
-
-/* Submitted by Klaus Mueller <k.mueller@intershop.de> */
-UNUSUAL_DEV( 0x054c, 0x002e, 0x0106, 0x0310,
- "Sony",
- "Handycam",
- US_SC_SCSI, US_PR_CB, NULL,
- US_FL_SINGLE_LUN | US_FL_START_STOP | US_FL_MODE_XLATE),
-
-UNUSUAL_DEV( 0x054c, 0x0032, 0x0000, 0x9999,
- "Sony",
- "Memorystick MSC-U01N",
- US_SC_UFI, US_PR_CB, NULL,
- US_FL_SINGLE_LUN | US_FL_START_STOP ),
-
-/* Submitted by Nathan Babb <nathan@lexi.com> */
-UNUSUAL_DEV( 0x054c, 0x006d, 0x0000, 0x9999,
- "Sony",
- "PEG Mass Storage",
- US_SC_8070, US_PR_CBI, NULL,
- US_FL_FIX_INQUIRY ),
-
-UNUSUAL_DEV( 0x057b, 0x0000, 0x0000, 0x0299,
- "Y-E Data",
- "Flashbuster-U",
- US_SC_UFI, US_PR_CB, NULL,
- US_FL_SINGLE_LUN),
-
-UNUSUAL_DEV( 0x057b, 0x0000, 0x0300, 0x9999,
- "Y-E Data",
- "Flashbuster-U",
- US_SC_UFI, US_PR_CBI, NULL,
- US_FL_SINGLE_LUN),
-
-UNUSUAL_DEV( 0x059f, 0xa601, 0x0200, 0x0200,
- "LaCie",
- "USB Hard Disk",
- US_SC_RBC, US_PR_CB, NULL, 0 ),
-
-#ifdef CONFIG_USB_STORAGE_ISD200
-UNUSUAL_DEV( 0x05ab, 0x0031, 0x0100, 0x0110,
- "In-System",
- "USB/IDE Bridge (ATA/ATAPI)",
- US_SC_ISD200, US_PR_BULK, isd200_Initialization,
- 0 ),
-
-UNUSUAL_DEV( 0x05ab, 0x0301, 0x0100, 0x0110,
- "In-System",
- "Portable USB Harddrive V2",
- US_SC_ISD200, US_PR_BULK, isd200_Initialization,
- 0 ),
-
-UNUSUAL_DEV( 0x05ab, 0x0351, 0x0100, 0x0110,
- "In-System",
- "Portable USB Harddrive V2",
- US_SC_ISD200, US_PR_BULK, isd200_Initialization,
- 0 ),
-
-UNUSUAL_DEV( 0x05ab, 0x5701, 0x0100, 0x0110,
- "In-System",
- "USB Storage Adapter V2",
- US_SC_ISD200, US_PR_BULK, isd200_Initialization,
- 0 ),
-
-UNUSUAL_DEV( 0x054c, 0x002b, 0x0100, 0x0110,
- "Sony",
- "Portable USB Harddrive V2",
- US_SC_ISD200, US_PR_BULK, isd200_Initialization,
- 0 ),
-#endif
-
-#ifdef CONFIG_USB_STORAGE_JUMPSHOT
-UNUSUAL_DEV( 0x05dc, 0x0001, 0x0000, 0x0001,
- "Lexar",
- "Jumpshot USB CF Reader",
- US_SC_SCSI, US_PR_JUMPSHOT, NULL,
- US_FL_MODE_XLATE | US_FL_START_STOP ),
-#endif
-
-UNUSUAL_DEV( 0x0644, 0x0000, 0x0100, 0x0100,
- "TEAC",
- "Floppy Drive",
- US_SC_UFI, US_PR_CB, NULL, 0 ),
-
-#ifdef CONFIG_USB_STORAGE_SDDR09
-UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x0100,
- "Olympus",
- "Camedia MAUSB-2",
- US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
- US_FL_SINGLE_LUN | US_FL_START_STOP ),
-#endif
-
-/* Submitted by f.brugmans@hccnet.nl
- * Needed for START_STOP flag */
-UNUSUAL_DEV( 0x0686, 0x4007, 0x0001, 0x0001,
- "Minolta",
- "Dimage S304",
- US_SC_SCSI, US_PR_BULK, NULL,
- US_FL_START_STOP ),
-
-UNUSUAL_DEV( 0x0693, 0x0002, 0x0100, 0x0100,
- "Hagiwara",
- "FlashGate SmartMedia",
- US_SC_SCSI, US_PR_BULK, NULL, 0 ),
-
-UNUSUAL_DEV( 0x0693, 0x0005, 0x0100, 0x0100,
- "Hagiwara",
- "Flashgate",
- US_SC_SCSI, US_PR_BULK, NULL, 0 ),
-
-UNUSUAL_DEV( 0x0781, 0x0001, 0x0200, 0x0200,
- "Sandisk",
- "ImageMate SDDR-05a",
- US_SC_SCSI, US_PR_CB, NULL,
- US_FL_SINGLE_LUN | US_FL_START_STOP),
-
-UNUSUAL_DEV( 0x0781, 0x0002, 0x0009, 0x0009,
- "Sandisk",
- "ImageMate SDDR-31",
- US_SC_SCSI, US_PR_BULK, NULL,
- US_FL_IGNORE_SER),
-
-UNUSUAL_DEV( 0x0781, 0x0100, 0x0100, 0x0100,
- "Sandisk",
- "ImageMate SDDR-12",
- US_SC_SCSI, US_PR_CB, NULL,
- US_FL_SINGLE_LUN ),
-
-#ifdef CONFIG_USB_STORAGE_SDDR09
-UNUSUAL_DEV( 0x0781, 0x0200, 0x0000, 0x9999,
- "Sandisk",
- "ImageMate SDDR-09",
- US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
- US_FL_SINGLE_LUN | US_FL_START_STOP ),
-#endif
-
-#ifdef CONFIG_USB_STORAGE_FREECOM
-UNUSUAL_DEV( 0x07ab, 0xfc01, 0x0000, 0x9999,
- "Freecom",
- "USB-IDE",
- US_SC_QIC, US_PR_FREECOM, freecom_init, 0),
-#endif
-
-UNUSUAL_DEV( 0x07af, 0x0004, 0x0100, 0x0133,
- "Microtech",
- "USB-SCSI-DB25",
- US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
- US_FL_SCM_MULT_TARG ),
-
-UNUSUAL_DEV( 0x07af, 0x0005, 0x0100, 0x0100,
- "Microtech",
- "USB-SCSI-HD50",
- US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
- US_FL_SCM_MULT_TARG ),
-
-#ifdef CONFIG_USB_STORAGE_DPCM
-UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100,
- "Microtech",
- "CameraMate (DPCM_USB)",
- US_SC_SCSI, US_PR_DPCM_USB, NULL,
- US_FL_START_STOP ),
-#endif
-
-#ifdef CONFIG_USB_STORAGE_DATAFAB
-UNUSUAL_DEV( 0x07c4, 0xa000, 0x0000, 0x0015,
- "Datafab",
- "MDCFE-B USB CF Reader",
- US_SC_SCSI, US_PR_DATAFAB, NULL,
- US_FL_MODE_XLATE | US_FL_START_STOP ),
-
- /*
- * The following Datafab-based devices may or may not work
- * using the current driver...the 0xffff is arbitrary since I
- * don't know what device versions exist for these guys.
- *
- * The 0xa003 and 0xa004 devices in particular I'm curious about.
- * I'm told they exist but so far nobody has come forward to say that
- * they work with this driver. Given the success we've had getting
- * other Datafab-based cards operational with this driver, I've decided
- * to leave these two devices in the list.
- */
-UNUSUAL_DEV( 0x07c4, 0xa001, 0x0000, 0xffff,
- "SIIG/Datafab",
- "SIIG/Datafab Memory Stick+CF Reader/Writer",
- US_SC_SCSI, US_PR_DATAFAB, NULL,
- US_FL_MODE_XLATE | US_FL_START_STOP ),
-
-UNUSUAL_DEV( 0x07c4, 0xa003, 0x0000, 0xffff,
- "Datafab/Unknown",
- "Datafab-based Reader",
- US_SC_SCSI, US_PR_DATAFAB, NULL,
- US_FL_MODE_XLATE | US_FL_START_STOP ),
-
-UNUSUAL_DEV( 0x07c4, 0xa004, 0x0000, 0xffff,
- "Datafab/Unknown",
- "Datafab-based Reader",
- US_SC_SCSI, US_PR_DATAFAB, NULL,
- US_FL_MODE_XLATE | US_FL_START_STOP ),
-
-UNUSUAL_DEV( 0x07c4, 0xa005, 0x0000, 0xffff,
- "PNY/Datafab",
- "PNY/Datafab CF+SM Reader",
- US_SC_SCSI, US_PR_DATAFAB, NULL,
- US_FL_MODE_XLATE | US_FL_START_STOP ),
-
-UNUSUAL_DEV( 0x07c4, 0xa006, 0x0000, 0xffff,
- "Simple Tech/Datafab",
- "Simple Tech/Datafab CF+SM Reader",
- US_SC_SCSI, US_PR_DATAFAB, NULL,
- US_FL_MODE_XLATE | US_FL_START_STOP ),
-
-/* Submitted by Olaf Hering <olh@suse.de> */
-UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff,
- "Datafab Systems, Inc.",
- "USB to CF + SM Combo (LC1)",
- US_SC_SCSI, US_PR_DATAFAB, NULL,
- US_FL_MODE_XLATE | US_FL_START_STOP ),
-#endif
-
-/* Casio QV 2x00/3x00/4000/8000 digital still cameras are not conformant
- * to the USB storage specification in two ways:
- * - They tell us they are using transport protocol CBI. In reality they
- * are using transport protocol CB.
- * - They don't like the INQUIRY command. So we must handle this command
- * of the SCSI layer ourselves.
- */
-UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9009,
- "Casio",
- "QV DigitalCamera",
- US_SC_8070, US_PR_CB, NULL,
- US_FL_FIX_INQUIRY ),
-
-UNUSUAL_DEV( 0x097a, 0x0001, 0x0000, 0x0001,
- "Minds@Work",
- "Digital Wallet",
- US_SC_SCSI, US_PR_CB, NULL,
- US_FL_MODE_XLATE ),
-
-#ifdef CONFIG_USB_STORAGE_ISD200
-UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110,
- "ATI",
- "USB Cable 205",
- US_SC_ISD200, US_PR_BULK, isd200_Initialization,
- 0 ),
-#endif
-
-/* Submitted by Brian Hall <brihall@bigfoot.com>
- * Needed for START_STOP flag */
-UNUSUAL_DEV( 0x0c76, 0x0003, 0x0100, 0x0100,
- "JMTek",
- "USBDrive",
- US_SC_SCSI, US_PR_BULK, NULL,
- US_FL_START_STOP ),
-
-/* Reported by Dan Pilone <pilone@slac.com>
- * The device needs the flags only.
- */
-UNUSUAL_DEV( 0x1065, 0x2136, 0x0000, 0x9999,
- "CCYU TECHNOLOGY",
- "EasyDisk Portable Device",
- US_SC_SCSI, US_PR_BULK, NULL,
- US_FL_MODE_XLATE | US_FL_START_STOP),
diff --git a/drivers/usb/class/storage/usb.c b/drivers/usb/class/storage/usb.c
deleted file mode 100644
index 277a322bc869..000000000000
--- a/drivers/usb/class/storage/usb.c
+++ /dev/null
@@ -1,1149 +0,0 @@
-/* Driver for USB Mass Storage compliant devices
- *
- * $Id: usb.c,v 1.70 2002/01/06 07:14:12 mdharm Exp $
- *
- * Current development and maintenance by:
- * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
- *
- * Developed with the assistance of:
- * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
- *
- * Initial work by:
- * (c) 1999 Michael Gee (michael@linuxspecific.com)
- *
- * usb_device_id support by Adam J. Richter (adam@yggdrasil.com):
- * (c) 2000 Yggdrasil Computing, Inc.
- *
- * This driver is based on the 'USB Mass Storage Class' document. This
- * describes in detail the protocol used to communicate with such
- * devices. Clearly, the designers had SCSI and ATAPI commands in
- * mind when they created this document. The commands are all very
- * similar to commands in the SCSI-II and ATAPI specifications.
- *
- * It is important to note that in a number of cases this class
- * exhibits class-specific exemptions from the USB specification.
- * Notably the usage of NAK, STALL and ACK differs from the norm, in
- * that they are used to communicate wait, failed and OK on commands.
- *
- * Also, for certain devices, the interrupt endpoint is used to convey
- * status of a command.
- *
- * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more
- * information about this driver.
- *
- * 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, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/config.h>
-#include "usb.h"
-#include "scsiglue.h"
-#include "transport.h"
-#include "protocol.h"
-#include "debug.h"
-#include "initializers.h"
-
-#ifdef CONFIG_USB_STORAGE_HP8200e
-#include "shuttle_usbat.h"
-#endif
-#ifdef CONFIG_USB_STORAGE_SDDR09
-#include "sddr09.h"
-#endif
-#ifdef CONFIG_USB_STORAGE_DPCM
-#include "dpcm.h"
-#endif
-#ifdef CONFIG_USB_STORAGE_FREECOM
-#include "freecom.h"
-#endif
-#ifdef CONFIG_USB_STORAGE_ISD200
-#include "isd200.h"
-#endif
-#ifdef CONFIG_USB_STORAGE_DATAFAB
-#include "datafab.h"
-#endif
-#ifdef CONFIG_USB_STORAGE_JUMPSHOT
-#include "jumpshot.h"
-#endif
-
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-
-/* Some informational data */
-MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>");
-MODULE_DESCRIPTION("USB Mass Storage driver for Linux");
-MODULE_LICENSE("GPL");
-
-/*
- * Per device data
- */
-
-static int my_host_number;
-
-/*
- * kernel thread actions
- */
-
-#define US_ACT_COMMAND 1
-#define US_ACT_DEVICE_RESET 2
-#define US_ACT_BUS_RESET 3
-#define US_ACT_HOST_RESET 4
-#define US_ACT_EXIT 5
-
-/* The list of structures and the protective lock for them */
-struct us_data *us_list;
-struct semaphore us_list_semaphore;
-
-static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
- const struct usb_device_id *id);
-
-static void storage_disconnect(struct usb_device *dev, void *ptr);
-
-/* The entries in this table, except for final ones here
- * (USB_MASS_STORAGE_CLASS and the empty entry), correspond,
- * line for line with the entries of us_unsuaul_dev_list[].
- * For now, we duplicate idVendor and idProduct in us_unsual_dev_list,
- * just to avoid alignment bugs.
- */
-
-#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
- vendorName, productName,useProtocol, useTransport, \
- initFunction, flags) \
-{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax) }
-
-static struct usb_device_id storage_usb_ids [] = {
-
-# include "unusual_devs.h"
-#undef UNUSUAL_DEV
- /* Control/Bulk transport for all SubClass values */
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_CB) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_CB) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_CB) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_CB) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_CB) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_CB) },
-
- /* Control/Bulk/Interrupt transport for all SubClass values */
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_CBI) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_CBI) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_CBI) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_CBI) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_CBI) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_CBI) },
-
- /* Bulk-only transport for all SubClass values */
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_BULK) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_BULK) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_BULK) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_BULK) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_BULK) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) },
-
- /* Terminating entry */
- { }
-};
-
-MODULE_DEVICE_TABLE (usb, storage_usb_ids);
-
-/* This is the list of devices we recognize, along with their flag data */
-
-/* The vendor name should be kept at eight characters or less, and
- * the product name should be kept at 16 characters or less. If a device
- * has the US_FL_FIX_INQUIRY flag, then the vendor and product names
- * normally generated by a device thorugh the INQUIRY response will be
- * taken from this list, and this is the reason for the above size
- * restriction. However, if the flag is not present, then you
- * are free to use as many characters as you like.
- */
-
-#undef UNUSUAL_DEV
-#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
- vendor_name, product_name, use_protocol, use_transport, \
- init_function, Flags) \
-{ \
- vendorName: vendor_name, \
- productName: product_name, \
- useProtocol: use_protocol, \
- useTransport: use_transport, \
- initFunction : init_function, \
- flags: Flags, \
-}
-
-static struct us_unusual_dev us_unusual_dev_list[] = {
-# include "unusual_devs.h"
-# undef UNUSUAL_DEV
- /* Control/Bulk transport for all SubClass values */
- { useProtocol: US_SC_RBC,
- useTransport: US_PR_CB},
- { useProtocol: US_SC_8020,
- useTransport: US_PR_CB},
- { useProtocol: US_SC_QIC,
- useTransport: US_PR_CB},
- { useProtocol: US_SC_UFI,
- useTransport: US_PR_CB},
- { useProtocol: US_SC_8070,
- useTransport: US_PR_CB},
- { useProtocol: US_SC_SCSI,
- useTransport: US_PR_CB},
-
- /* Control/Bulk/Interrupt transport for all SubClass values */
- { useProtocol: US_SC_RBC,
- useTransport: US_PR_CBI},
- { useProtocol: US_SC_8020,
- useTransport: US_PR_CBI},
- { useProtocol: US_SC_QIC,
- useTransport: US_PR_CBI},
- { useProtocol: US_SC_UFI,
- useTransport: US_PR_CBI},
- { useProtocol: US_SC_8070,
- useTransport: US_PR_CBI},
- { useProtocol: US_SC_SCSI,
- useTransport: US_PR_CBI},
-
- /* Bulk-only transport for all SubClass values */
- { useProtocol: US_SC_RBC,
- useTransport: US_PR_BULK},
- { useProtocol: US_SC_8020,
- useTransport: US_PR_BULK},
- { useProtocol: US_SC_QIC,
- useTransport: US_PR_BULK},
- { useProtocol: US_SC_UFI,
- useTransport: US_PR_BULK},
- { useProtocol: US_SC_8070,
- useTransport: US_PR_BULK},
- { useProtocol: US_SC_SCSI,
- useTransport: US_PR_BULK},
-
- /* Terminating entry */
- { 0 }
-};
-
-struct usb_driver usb_storage_driver = {
- name: "usb-storage",
- probe: storage_probe,
- disconnect: storage_disconnect,
- id_table: storage_usb_ids,
-};
-
-/*
- * fill_inquiry_response takes an unsigned char array (which must
- * be at least 36 characters) and populates the vendor name,
- * product name, and revision fields. Then the array is copied
- * into the SCSI command's response buffer (oddly enough
- * called request_buffer). data_len contains the length of the
- * data array, which again must be at least 36.
- */
-
-void fill_inquiry_response(struct us_data *us, unsigned char *data,
- unsigned int data_len) {
-
- int i;
- struct scatterlist *sg;
- int len =
- us->srb->request_bufflen > data_len ? data_len :
- us->srb->request_bufflen;
- int transferred;
- int amt;
-
- if (data_len<36) // You lose.
- return;
-
- if(data[0]&0x20) { /* USB device currently not connected. Return
- peripheral qualifier 001b ("...however, the
- physical device is not currently connected
- to this logical unit") and leave vendor and
- product identification empty. ("If the target
- does store some of the INQUIRY data on the
- device, it may return zeros or ASCII spaces
- (20h) in those fields until the data is
- available from the device."). */
- memset(data+8,0,28);
- } else {
- memcpy(data+8, us->unusual_dev->vendorName,
- strlen(us->unusual_dev->vendorName) > 8 ? 8 :
- strlen(us->unusual_dev->vendorName));
- memcpy(data+16, us->unusual_dev->productName,
- strlen(us->unusual_dev->productName) > 16 ? 16 :
- strlen(us->unusual_dev->productName));
- data[32] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice>>12) & 0x0F);
- data[33] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice>>8) & 0x0F);
- data[34] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice>>4) & 0x0F);
- data[35] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice) & 0x0F);
- }
-
- if (us->srb->use_sg) {
- sg = (struct scatterlist *)us->srb->request_buffer;
- for (i=0; i<us->srb->use_sg; i++)
- memset(page_address(sg[i].page) + sg[i].offset, 0, sg[i].length);
- for (i=0, transferred=0;
- i<us->srb->use_sg && transferred < len;
- i++) {
- amt = sg[i].length > len-transferred ?
- len-transferred : sg[i].length;
- memcpy(page_address(sg[i].page) + sg[i].offset, data+transferred, amt);
- transferred -= amt;
- }
- } else {
- memset(us->srb->request_buffer, 0, us->srb->request_bufflen);
- memcpy(us->srb->request_buffer, data, len);
- }
-}
-
-static int usb_stor_control_thread(void * __us)
-{
- struct us_data *us = (struct us_data *)__us;
- int action;
-
- lock_kernel();
-
- /*
- * This thread doesn't need any user-level access,
- * so get rid of all our resources..
- */
- daemonize();
-
- /* avoid getting signals */
- spin_lock_irq(&current->sigmask_lock);
- flush_signals(current);
- sigfillset(&current->blocked);
- recalc_sigpending();
- spin_unlock_irq(&current->sigmask_lock);
-
- /* set our name for identification purposes */
- sprintf(current->comm, "usb-storage-%d", us->host_number);
-
- unlock_kernel();
-
- /* set up for wakeups by new commands */
- init_MUTEX_LOCKED(&us->sema);
-
- /* signal that we've started the thread */
- complete(&(us->notify));
- set_current_state(TASK_INTERRUPTIBLE);
-
- for(;;) {
- US_DEBUGP("*** thread sleeping.\n");
- if(down_interruptible(&us->sema))
- break;
-
- US_DEBUGP("*** thread awakened.\n");
-
- /* lock access to the queue element */
- down(&(us->queue_exclusion));
-
- /* take the command off the queue */
- action = us->action;
- us->action = 0;
- us->srb = us->queue_srb;
-
- /* release the queue lock as fast as possible */
- up(&(us->queue_exclusion));
-
- switch (action) {
- case US_ACT_COMMAND:
- /* reject the command if the direction indicator
- * is UNKNOWN
- */
- if (us->srb->sc_data_direction == SCSI_DATA_UNKNOWN) {
- US_DEBUGP("UNKNOWN data direction\n");
- us->srb->result = DID_ERROR << 16;
- set_current_state(TASK_INTERRUPTIBLE);
- us->srb->scsi_done(us->srb);
- us->srb = NULL;
- break;
- }
-
- /* reject if target != 0 or if LUN is higher than
- * the maximum known LUN
- */
- if (us->srb->target &&
- !(us->flags & US_FL_SCM_MULT_TARG)) {
- US_DEBUGP("Bad target number (%d/%d)\n",
- us->srb->target, us->srb->lun);
- us->srb->result = DID_BAD_TARGET << 16;
-
- set_current_state(TASK_INTERRUPTIBLE);
- us->srb->scsi_done(us->srb);
- us->srb = NULL;
- break;
- }
-
- if (us->srb->lun > us->max_lun) {
- US_DEBUGP("Bad LUN (%d/%d)\n",
- us->srb->target, us->srb->lun);
- us->srb->result = DID_BAD_TARGET << 16;
-
- set_current_state(TASK_INTERRUPTIBLE);
- us->srb->scsi_done(us->srb);
- us->srb = NULL;
- break;
- }
-
- /* handle those devices which can't do a START_STOP */
- if ((us->srb->cmnd[0] == START_STOP) &&
- (us->flags & US_FL_START_STOP)) {
- US_DEBUGP("Skipping START_STOP command\n");
- us->srb->result = GOOD << 1;
-
- set_current_state(TASK_INTERRUPTIBLE);
- us->srb->scsi_done(us->srb);
- us->srb = NULL;
- break;
- }
-
- /* lock the device pointers */
- down(&(us->dev_semaphore));
-
- /* our device has gone - pretend not ready */
- if (!us->pusb_dev) {
- US_DEBUGP("Request is for removed device\n");
- /* For REQUEST_SENSE, it's the data. But
- * for anything else, it should look like
- * we auto-sensed for it.
- */
- if (us->srb->cmnd[0] == REQUEST_SENSE) {
- memcpy(us->srb->request_buffer,
- usb_stor_sense_notready,
- sizeof(usb_stor_sense_notready));
- us->srb->result = GOOD << 1;
- } else if(us->srb->cmnd[0] == INQUIRY) {
- unsigned char data_ptr[36] = {
- 0x20, 0x80, 0x02, 0x02,
- 0x1F, 0x00, 0x00, 0x00};
- US_DEBUGP("Faking INQUIRY command for disconnected device\n");
- fill_inquiry_response(us, data_ptr, 36);
- us->srb->result = GOOD << 1;
- } else {
- memcpy(us->srb->sense_buffer,
- usb_stor_sense_notready,
- sizeof(usb_stor_sense_notready));
- us->srb->result = CHECK_CONDITION << 1;
- }
- } else { /* !us->pusb_dev */
-
- /* Handle those devices which need us to fake
- * their inquiry data */
- if ((us->srb->cmnd[0] == INQUIRY) &&
- (us->flags & US_FL_FIX_INQUIRY)) {
- unsigned char data_ptr[36] = {
- 0x00, 0x80, 0x02, 0x02,
- 0x1F, 0x00, 0x00, 0x00};
-
- US_DEBUGP("Faking INQUIRY command\n");
- fill_inquiry_response(us, data_ptr, 36);
- us->srb->result = GOOD << 1;
- } else {
- /* we've got a command, let's do it! */
- US_DEBUG(usb_stor_show_command(us->srb));
- us->proto_handler(us->srb, us);
- }
- }
-
- /* unlock the device pointers */
- up(&(us->dev_semaphore));
-
- /* indicate that the command is done */
- if (us->srb->result != DID_ABORT << 16) {
- US_DEBUGP("scsi cmd done, result=0x%x\n",
- us->srb->result);
- set_current_state(TASK_INTERRUPTIBLE);
- us->srb->scsi_done(us->srb);
- } else {
- US_DEBUGP("scsi command aborted\n");
- set_current_state(TASK_INTERRUPTIBLE);
- complete(&(us->notify));
- }
- us->srb = NULL;
- break;
-
- case US_ACT_DEVICE_RESET:
- break;
-
- case US_ACT_BUS_RESET:
- break;
-
- case US_ACT_HOST_RESET:
- break;
-
- } /* end switch on action */
-
- /* exit if we get a signal to exit */
- if (action == US_ACT_EXIT) {
- US_DEBUGP("-- US_ACT_EXIT command received\n");
- break;
- }
- } /* for (;;) */
-
- /* clean up after ourselves */
- set_current_state(TASK_INTERRUPTIBLE);
-
- /* notify the exit routine that we're actually exiting now */
- complete(&(us->notify));
-
- return 0;
-}
-
-/* Set up the IRQ pipe and handler
- * Note that this function assumes that all the data in the us_data
- * strucuture is current. This includes the ep_int field, which gives us
- * the endpoint for the interrupt.
- * Returns non-zero on failure, zero on success
- */
-static int usb_stor_allocate_irq(struct us_data *ss)
-{
- unsigned int pipe;
- int maxp;
- int result;
-
- US_DEBUGP("Allocating IRQ for CBI transport\n");
-
- /* lock access to the data structure */
- down(&(ss->irq_urb_sem));
-
- /* allocate the URB */
- ss->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!ss->irq_urb) {
- up(&(ss->irq_urb_sem));
- US_DEBUGP("couldn't allocate interrupt URB");
- return 1;
- }
-
- /* calculate the pipe and max packet size */
- pipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int->bEndpointAddress &
- USB_ENDPOINT_NUMBER_MASK);
- maxp = usb_maxpacket(ss->pusb_dev, pipe, usb_pipeout(pipe));
- if (maxp > sizeof(ss->irqbuf))
- maxp = sizeof(ss->irqbuf);
-
- /* fill in the URB with our data */
- FILL_INT_URB(ss->irq_urb, ss->pusb_dev, pipe, ss->irqbuf, maxp,
- usb_stor_CBI_irq, ss, ss->ep_int->bInterval);
-
- /* submit the URB for processing */
- result = usb_submit_urb(ss->irq_urb, GFP_KERNEL);
- US_DEBUGP("usb_submit_urb() returns %d\n", result);
- if (result) {
- usb_free_urb(ss->irq_urb);
- up(&(ss->irq_urb_sem));
- return 2;
- }
-
- /* unlock the data structure and return success */
- up(&(ss->irq_urb_sem));
- return 0;
-}
-
-/* Probe to see if a new device is actually a SCSI device */
-static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
- const struct usb_device_id *id)
-{
- int i;
- const int id_index = id - storage_usb_ids;
- char mf[USB_STOR_STRING_LEN]; /* manufacturer */
- char prod[USB_STOR_STRING_LEN]; /* product */
- char serial[USB_STOR_STRING_LEN]; /* serial number */
- GUID(guid); /* Global Unique Identifier */
- unsigned int flags;
- struct us_unusual_dev *unusual_dev;
- struct us_data *ss = NULL;
-#ifdef CONFIG_USB_STORAGE_SDDR09
- int result;
-#endif
-
- /* these are temporary copies -- we test on these, then put them
- * in the us-data structure
- */
- struct usb_endpoint_descriptor *ep_in = NULL;
- struct usb_endpoint_descriptor *ep_out = NULL;
- struct usb_endpoint_descriptor *ep_int = NULL;
- u8 subclass = 0;
- u8 protocol = 0;
-
- /* the altsettting on the interface we're probing that matched our
- * usb_match_id table
- */
- struct usb_interface *intf = dev->actconfig->interface;
- struct usb_interface_descriptor *altsetting =
- intf[ifnum].altsetting + intf[ifnum].act_altsetting;
- US_DEBUGP("act_altsettting is %d\n", intf[ifnum].act_altsetting);
-
- /* clear the temporary strings */
- memset(mf, 0, sizeof(mf));
- memset(prod, 0, sizeof(prod));
- memset(serial, 0, sizeof(serial));
-
- /*
- * Can we support this device, either because we know about it
- * from our unusual device list, or because it advertises that it's
- * compliant to the specification?
- *
- * id_index is calculated in the declaration to be the index number
- * of the match from the usb_device_id table, so we can find the
- * corresponding entry in the private table.
- */
- US_DEBUGP("id_index calculated to be: %d\n", id_index);
- US_DEBUGP("Array length appears to be: %d\n", sizeof(us_unusual_dev_list) / sizeof(us_unusual_dev_list[0]));
- if (id_index <
- sizeof(us_unusual_dev_list) / sizeof(us_unusual_dev_list[0])) {
- unusual_dev = &us_unusual_dev_list[id_index];
- if (unusual_dev->vendorName)
- US_DEBUGP("Vendor: %s\n", unusual_dev->vendorName);
- if (unusual_dev->productName)
- US_DEBUGP("Product: %s\n", unusual_dev->productName);
- } else
- /* no, we can't support it */
- return NULL;
-
- /* At this point, we know we've got a live one */
- US_DEBUGP("USB Mass Storage device detected\n");
-
- /* Determine subclass and protocol, or copy from the interface */
- subclass = unusual_dev->useProtocol;
- protocol = unusual_dev->useTransport;
- flags = unusual_dev->flags;
-
- /*
- * Find the endpoints we need
- * We are expecting a minimum of 2 endpoints - in and out (bulk).
- * An optional interrupt is OK (necessary for CBI protocol).
- * We will ignore any others.
- */
- for (i = 0; i < altsetting->bNumEndpoints; i++) {
- /* is it an BULK endpoint? */
- if ((altsetting->endpoint[i].bmAttributes &
- USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
- /* BULK in or out? */
- if (altsetting->endpoint[i].bEndpointAddress &
- USB_DIR_IN)
- ep_in = &altsetting->endpoint[i];
- else
- ep_out = &altsetting->endpoint[i];
- }
-
- /* is it an interrupt endpoint? */
- if ((altsetting->endpoint[i].bmAttributes &
- USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
- ep_int = &altsetting->endpoint[i];
- }
- }
- US_DEBUGP("Endpoints: In: 0x%p Out: 0x%p Int: 0x%p (Period %d)\n",
- ep_in, ep_out, ep_int, ep_int ? ep_int->bInterval : 0);
-
-#ifdef CONFIG_USB_STORAGE_SDDR09
- if (protocol == US_PR_EUSB_SDDR09 || protocol == US_PR_DPCM_USB) {
- /* set the configuration -- STALL is an acceptable response here */
- result = usb_set_configuration(dev, 1);
-
- US_DEBUGP("Result from usb_set_configuration is %d\n", result);
- if (result == -EPIPE) {
- US_DEBUGP("-- clearing stall on control interface\n");
- usb_clear_halt(dev, usb_sndctrlpipe(dev, 0));
- } else if (result != 0) {
- /* it's not a stall, but another error -- time to bail */
- US_DEBUGP("-- Unknown error. Rejecting device\n");
- return NULL;
- }
- }
-#endif
-
- /* Do some basic sanity checks, and bail if we find a problem */
- if (!ep_in || !ep_out || (protocol == US_PR_CBI && !ep_int)) {
- US_DEBUGP("Endpoint sanity check failed! Rejecting dev.\n");
- return NULL;
- }
-
- /* At this point, we're committed to using the device */
- usb_inc_dev_use(dev);
-
- /* clear the GUID and fetch the strings */
- GUID_CLEAR(guid);
- if (dev->descriptor.iManufacturer)
- usb_string(dev, dev->descriptor.iManufacturer,
- mf, sizeof(mf));
- if (dev->descriptor.iProduct)
- usb_string(dev, dev->descriptor.iProduct,
- prod, sizeof(prod));
- if (dev->descriptor.iSerialNumber && !(flags & US_FL_IGNORE_SER))
- usb_string(dev, dev->descriptor.iSerialNumber,
- serial, sizeof(serial));
-
- /* Create a GUID for this device */
- if (dev->descriptor.iSerialNumber && serial[0]) {
- /* If we have a serial number, and it's a non-NULL string */
- make_guid(guid, dev->descriptor.idVendor,
- dev->descriptor.idProduct, serial);
- } else {
- /* We don't have a serial number, so we use 0 */
- make_guid(guid, dev->descriptor.idVendor,
- dev->descriptor.idProduct, "0");
- }
-
- /*
- * Now check if we have seen this GUID before
- * We're looking for a device with a matching GUID that isn't
- * already on the system
- */
- ss = us_list;
- while ((ss != NULL) &&
- ((ss->pusb_dev) || !GUID_EQUAL(guid, ss->guid)))
- ss = ss->next;
-
- if (ss != NULL) {
- /* Existing device -- re-connect */
- US_DEBUGP("Found existing GUID " GUID_FORMAT "\n",
- GUID_ARGS(guid));
-
- /* lock the device pointers */
- down(&(ss->dev_semaphore));
-
- /* establish the connection to the new device upon reconnect */
- ss->ifnum = ifnum;
- ss->pusb_dev = dev;
-
- /* copy over the endpoint data */
- if (ep_in)
- ss->ep_in = ep_in->bEndpointAddress &
- USB_ENDPOINT_NUMBER_MASK;
- if (ep_out)
- ss->ep_out = ep_out->bEndpointAddress &
- USB_ENDPOINT_NUMBER_MASK;
- ss->ep_int = ep_int;
-
- /* allocate an IRQ callback if one is needed */
- if ((ss->protocol == US_PR_CBI) && usb_stor_allocate_irq(ss)) {
- usb_dec_dev_use(dev);
- return NULL;
- }
-
- /* allocate the URB we're going to use */
- ss->current_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!ss->current_urb) {
- usb_dec_dev_use(dev);
- return NULL;
- }
-
- /* Re-Initialize the device if it needs it */
- if (unusual_dev && unusual_dev->initFunction)
- (unusual_dev->initFunction)(ss);
-
- /* unlock the device pointers */
- up(&(ss->dev_semaphore));
-
- } else {
- /* New device -- allocate memory and initialize */
- US_DEBUGP("New GUID " GUID_FORMAT "\n", GUID_ARGS(guid));
-
- if ((ss = (struct us_data *)kmalloc(sizeof(struct us_data),
- GFP_KERNEL)) == NULL) {
- printk(KERN_WARNING USB_STORAGE "Out of memory\n");
- usb_dec_dev_use(dev);
- return NULL;
- }
- memset(ss, 0, sizeof(struct us_data));
-
- /* allocate the URB we're going to use */
- ss->current_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!ss->current_urb) {
- kfree(ss);
- usb_dec_dev_use(dev);
- return NULL;
- }
-
- /* Initialize the mutexes only when the struct is new */
- init_completion(&(ss->notify));
- init_MUTEX_LOCKED(&(ss->ip_waitq));
- init_MUTEX(&(ss->queue_exclusion));
- init_MUTEX(&(ss->irq_urb_sem));
- init_MUTEX(&(ss->current_urb_sem));
- init_MUTEX(&(ss->dev_semaphore));
-
- /* copy over the subclass and protocol data */
- ss->subclass = subclass;
- ss->protocol = protocol;
- ss->flags = flags;
- ss->unusual_dev = unusual_dev;
-
- /* copy over the endpoint data */
- if (ep_in)
- ss->ep_in = ep_in->bEndpointAddress &
- USB_ENDPOINT_NUMBER_MASK;
- if (ep_out)
- ss->ep_out = ep_out->bEndpointAddress &
- USB_ENDPOINT_NUMBER_MASK;
- ss->ep_int = ep_int;
-
- /* establish the connection to the new device */
- ss->ifnum = ifnum;
- ss->pusb_dev = dev;
-
- /* copy over the identifiying strings */
- strncpy(ss->vendor, mf, USB_STOR_STRING_LEN);
- strncpy(ss->product, prod, USB_STOR_STRING_LEN);
- strncpy(ss->serial, serial, USB_STOR_STRING_LEN);
- if (strlen(ss->vendor) == 0) {
- if (unusual_dev->vendorName)
- strncpy(ss->vendor, unusual_dev->vendorName,
- USB_STOR_STRING_LEN);
- else
- strncpy(ss->vendor, "Unknown",
- USB_STOR_STRING_LEN);
- }
- if (strlen(ss->product) == 0) {
- if (unusual_dev->productName)
- strncpy(ss->product, unusual_dev->productName,
- USB_STOR_STRING_LEN);
- else
- strncpy(ss->product, "Unknown",
- USB_STOR_STRING_LEN);
- }
- if (strlen(ss->serial) == 0)
- strncpy(ss->serial, "None", USB_STOR_STRING_LEN);
-
- /* copy the GUID we created before */
- memcpy(ss->guid, guid, sizeof(guid));
-
- /*
- * Set the handler pointers based on the protocol
- * Again, this data is persistant across reattachments
- */
- switch (ss->protocol) {
- case US_PR_CB:
- ss->transport_name = "Control/Bulk";
- ss->transport = usb_stor_CB_transport;
- ss->transport_reset = usb_stor_CB_reset;
- ss->max_lun = 7;
- break;
-
- case US_PR_CBI:
- ss->transport_name = "Control/Bulk/Interrupt";
- ss->transport = usb_stor_CBI_transport;
- ss->transport_reset = usb_stor_CB_reset;
- ss->max_lun = 7;
- break;
-
- case US_PR_BULK:
- ss->transport_name = "Bulk";
- ss->transport = usb_stor_Bulk_transport;
- ss->transport_reset = usb_stor_Bulk_reset;
- ss->max_lun = usb_stor_Bulk_max_lun(ss);
- break;
-
-#ifdef CONFIG_USB_STORAGE_HP8200e
- case US_PR_SCM_ATAPI:
- ss->transport_name = "SCM/ATAPI";
- ss->transport = hp8200e_transport;
- ss->transport_reset = usb_stor_CB_reset;
- ss->max_lun = 1;
- break;
-#endif
-
-#ifdef CONFIG_USB_STORAGE_SDDR09
- case US_PR_EUSB_SDDR09:
- ss->transport_name = "EUSB/SDDR09";
- ss->transport = sddr09_transport;
- ss->transport_reset = usb_stor_CB_reset;
- ss->max_lun = 0;
- break;
-#endif
-
-#ifdef CONFIG_USB_STORAGE_DPCM
- case US_PR_DPCM_USB:
- ss->transport_name = "Control/Bulk-EUSB/SDDR09";
- ss->transport = dpcm_transport;
- ss->transport_reset = usb_stor_CB_reset;
- ss->max_lun = 1;
- break;
-#endif
-
-#ifdef CONFIG_USB_STORAGE_FREECOM
- case US_PR_FREECOM:
- ss->transport_name = "Freecom";
- ss->transport = freecom_transport;
- ss->transport_reset = usb_stor_freecom_reset;
- ss->max_lun = 0;
- break;
-#endif
-
-#ifdef CONFIG_USB_STORAGE_DATAFAB
- case US_PR_DATAFAB:
- ss->transport_name = "Datafab Bulk-Only";
- ss->transport = datafab_transport;
- ss->transport_reset = usb_stor_Bulk_reset;
- ss->max_lun = 1;
- break;
-#endif
-
-#ifdef CONFIG_USB_STORAGE_JUMPSHOT
- case US_PR_JUMPSHOT:
- ss->transport_name = "Lexar Jumpshot Control/Bulk";
- ss->transport = jumpshot_transport;
- ss->transport_reset = usb_stor_Bulk_reset;
- ss->max_lun = 1;
- break;
-#endif
-
- default:
- ss->transport_name = "Unknown";
- kfree(ss->current_urb);
- kfree(ss);
- usb_dec_dev_use(dev);
- return NULL;
- break;
- }
- US_DEBUGP("Transport: %s\n", ss->transport_name);
-
- /* fix for single-lun devices */
- if (ss->flags & US_FL_SINGLE_LUN)
- ss->max_lun = 0;
-
- switch (ss->subclass) {
- case US_SC_RBC:
- ss->protocol_name = "Reduced Block Commands (RBC)";
- ss->proto_handler = usb_stor_transparent_scsi_command;
- break;
-
- case US_SC_8020:
- ss->protocol_name = "8020i";
- ss->proto_handler = usb_stor_ATAPI_command;
- ss->max_lun = 0;
- break;
-
- case US_SC_QIC:
- ss->protocol_name = "QIC-157";
- ss->proto_handler = usb_stor_qic157_command;
- ss->max_lun = 0;
- break;
-
- case US_SC_8070:
- ss->protocol_name = "8070i";
- ss->proto_handler = usb_stor_ATAPI_command;
- ss->max_lun = 0;
- break;
-
- case US_SC_SCSI:
- ss->protocol_name = "Transparent SCSI";
- ss->proto_handler = usb_stor_transparent_scsi_command;
- break;
-
- case US_SC_UFI:
- ss->protocol_name = "Uniform Floppy Interface (UFI)";
- ss->proto_handler = usb_stor_ufi_command;
- break;
-
-#ifdef CONFIG_USB_STORAGE_ISD200
- case US_SC_ISD200:
- ss->protocol_name = "ISD200 ATA/ATAPI";
- ss->proto_handler = isd200_ata_command;
- break;
-#endif
-
- default:
- ss->protocol_name = "Unknown";
- kfree(ss->current_urb);
- kfree(ss);
- return NULL;
- break;
- }
- US_DEBUGP("Protocol: %s\n", ss->protocol_name);
-
- /* allocate an IRQ callback if one is needed */
- if ((ss->protocol == US_PR_CBI) && usb_stor_allocate_irq(ss)) {
- usb_dec_dev_use(dev);
- return NULL;
- }
-
- /*
- * Since this is a new device, we need to generate a scsi
- * host definition, and register with the higher SCSI layers
- */
-
- /* Initialize the host template based on the default one */
- memcpy(&(ss->htmplt), &usb_stor_host_template,
- sizeof(usb_stor_host_template));
-
- /* Grab the next host number */
- ss->host_number = my_host_number++;
-
- /* We abuse this pointer so we can pass the ss pointer to
- * the host controller thread in us_detect. But how else are
- * we to do it?
- */
- (struct us_data *)ss->htmplt.proc_dir = ss;
-
- /* Just before we start our control thread, initialize
- * the device if it needs initialization */
- if (unusual_dev && unusual_dev->initFunction)
- unusual_dev->initFunction(ss);
-
- /* start up our control thread */
- ss->pid = kernel_thread(usb_stor_control_thread, ss,
- CLONE_VM);
- if (ss->pid < 0) {
- printk(KERN_WARNING USB_STORAGE
- "Unable to start control thread\n");
- kfree(ss->current_urb);
- kfree(ss);
- usb_dec_dev_use(dev);
- return NULL;
- }
-
- /* wait for the thread to start */
- wait_for_completion(&(ss->notify));
-
- /* now register - our detect function will be called */
- ss->htmplt.module = THIS_MODULE;
- scsi_register_host(&ss->htmplt);
-
- /* lock access to the data structures */
- down(&us_list_semaphore);
-
- /* put us in the list */
- ss->next = us_list;
- us_list = ss;
-
- /* release the data structure lock */
- up(&us_list_semaphore);
- }
-
- printk(KERN_DEBUG
- "WARNING: USB Mass Storage data integrity not assured\n");
- printk(KERN_DEBUG
- "USB Mass Storage device found at %d\n", dev->devnum);
-
- /* return a pointer for the disconnect function */
- return ss;
-}
-
-/* Handle a disconnect event from the USB core */
-static void storage_disconnect(struct usb_device *dev, void *ptr)
-{
- struct us_data *ss = ptr;
- int result;
-
- US_DEBUGP("storage_disconnect() called\n");
-
- /* this is the odd case -- we disconnected but weren't using it */
- if (!ss) {
- US_DEBUGP("-- device was not in use\n");
- return;
- }
-
- /* lock access to the device data structure */
- down(&(ss->dev_semaphore));
-
- /* release the IRQ, if we have one */
- down(&(ss->irq_urb_sem));
- if (ss->irq_urb) {
- US_DEBUGP("-- releasing irq URB\n");
- result = usb_unlink_urb(ss->irq_urb);
- US_DEBUGP("-- usb_unlink_urb() returned %d\n", result);
- usb_free_urb(ss->irq_urb);
- ss->irq_urb = NULL;
- }
- up(&(ss->irq_urb_sem));
-
- /* free up the main URB for this device */
- US_DEBUGP("-- releasing main URB\n");
- result = usb_unlink_urb(ss->current_urb);
- US_DEBUGP("-- usb_unlink_urb() returned %d\n", result);
- usb_free_urb(ss->current_urb);
- ss->current_urb = NULL;
-
- /* mark the device as gone */
- usb_dec_dev_use(ss->pusb_dev);
- ss->pusb_dev = NULL;
-
- /* unlock access to the device data structure */
- up(&(ss->dev_semaphore));
-}
-
-/***********************************************************************
- * Initialization and registration
- ***********************************************************************/
-
-int __init usb_stor_init(void)
-{
- printk(KERN_INFO "Initializing USB Mass Storage driver...\n");
-
- /* initialize internal global data elements */
- us_list = NULL;
- init_MUTEX(&us_list_semaphore);
- my_host_number = 0;
-
- /* register the driver, return -1 if error */
- if (usb_register(&usb_storage_driver) < 0)
- return -1;
-
- /* we're all set */
- printk(KERN_INFO "USB Mass Storage support registered.\n");
- return 0;
-}
-
-void __exit usb_stor_exit(void)
-{
- struct us_data *next;
-
- US_DEBUGP("usb_stor_exit() called\n");
-
- /* Deregister the driver
- * This eliminates races with probes and disconnects
- */
- US_DEBUGP("-- calling usb_deregister()\n");
- usb_deregister(&usb_storage_driver) ;
-
- /* While there are still virtual hosts, unregister them
- * Note that it's important to do this completely before removing
- * the structures because of possible races with the /proc
- * interface
- */
- for (next = us_list; next; next = next->next) {
- US_DEBUGP("-- calling scsi_unregister_host()\n");
- scsi_unregister_host(&next->htmplt);
- }
-
- /* While there are still structures, free them. Note that we are
- * now race-free, since these structures can no longer be accessed
- * from either the SCSI command layer or the /proc interface
- */
- while (us_list) {
- /* keep track of where the next one is */
- next = us_list->next;
-
- /* If there's extra data in the us_data structure then
- * free that first */
- if (us_list->extra) {
- /* call the destructor routine, if it exists */
- if (us_list->extra_destructor) {
- US_DEBUGP("-- calling extra_destructor()\n");
- us_list->extra_destructor(us_list->extra);
- }
-
- /* destroy the extra data */
- US_DEBUGP("-- freeing the data structure\n");
- kfree(us_list->extra);
- }
-
- /* free the structure itself */
- kfree (us_list);
-
- /* advance the list pointer */
- us_list = next;
- }
-}
-
-module_init(usb_stor_init);
-module_exit(usb_stor_exit);
diff --git a/drivers/usb/class/storage/usb.h b/drivers/usb/class/storage/usb.h
deleted file mode 100644
index 5fd910ec70a7..000000000000
--- a/drivers/usb/class/storage/usb.h
+++ /dev/null
@@ -1,191 +0,0 @@
-/* Driver for USB Mass Storage compliant devices
- * Main Header File
- *
- * $Id: usb.h,v 1.18 2001/07/30 00:27:59 mdharm Exp $
- *
- * Current development and maintenance by:
- * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
- *
- * Initial work by:
- * (c) 1999 Michael Gee (michael@linuxspecific.com)
- *
- * This driver is based on the 'USB Mass Storage Class' document. This
- * describes in detail the protocol used to communicate with such
- * devices. Clearly, the designers had SCSI and ATAPI commands in
- * mind when they created this document. The commands are all very
- * similar to commands in the SCSI-II and ATAPI specifications.
- *
- * It is important to note that in a number of cases this class
- * exhibits class-specific exemptions from the USB specification.
- * Notably the usage of NAK, STALL and ACK differs from the norm, in
- * that they are used to communicate wait, failed and OK on commands.
- *
- * Also, for certain devices, the interrupt endpoint is used to convey
- * status of a command.
- *
- * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more
- * information about this driver.
- *
- * 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, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _USB_H_
-#define _USB_H_
-
-#include <linux/usb.h>
-#include <linux/blk.h>
-#include <linux/smp_lock.h>
-#include <linux/completion.h>
-#include "scsi.h"
-#include "hosts.h"
-
-/*
- * GUID definitions
- */
-
-#define GUID(x) __u32 x[3]
-#define GUID_EQUAL(x, y) (x[0] == y[0] && x[1] == y[1] && x[2] == y[2])
-#define GUID_CLEAR(x) x[0] = x[1] = x[2] = 0;
-#define GUID_NONE(x) (!x[0] && !x[1] && !x[2])
-#define GUID_FORMAT "%08x%08x%08x"
-#define GUID_ARGS(x) x[0], x[1], x[2]
-
-static inline void make_guid( __u32 *pg, __u16 vendor, __u16 product, char *serial)
-{
- pg[0] = (vendor << 16) | product;
- pg[1] = pg[2] = 0;
- while (*serial) {
- pg[1] <<= 4;
- pg[1] |= pg[2] >> 28;
- pg[2] <<= 4;
- if (*serial >= 'a')
- *serial -= 'a' - 'A';
- pg[2] |= (*serial <= '9' && *serial >= '0') ? *serial - '0'
- : *serial - 'A' + 10;
- serial++;
- }
-}
-
-struct us_data;
-
-/*
- * Unusual device list definitions
- */
-
-struct us_unusual_dev {
- const char* vendorName;
- const char* productName;
- __u8 useProtocol;
- __u8 useTransport;
- int (*initFunction)(struct us_data *);
- unsigned int flags;
-};
-
-/* Flag definitions */
-#define US_FL_SINGLE_LUN 0x00000001 /* allow access to only LUN 0 */
-#define US_FL_MODE_XLATE 0x00000002 /* translate _6 to _10 commands for
- Win/MacOS compatibility */
-#define US_FL_START_STOP 0x00000004 /* ignore START_STOP commands */
-#define US_FL_IGNORE_SER 0x00000010 /* Ignore the serial number given */
-#define US_FL_SCM_MULT_TARG 0x00000020 /* supports multiple targets */
-#define US_FL_FIX_INQUIRY 0x00000040 /* INQUIRY response needs fixing */
-
-#define USB_STOR_STRING_LEN 32
-
-typedef int (*trans_cmnd)(Scsi_Cmnd*, struct us_data*);
-typedef int (*trans_reset)(struct us_data*);
-typedef void (*proto_cmnd)(Scsi_Cmnd*, struct us_data*);
-typedef void (*extra_data_destructor)(void *); /* extra data destructor */
-
-/* we allocate one of these for every device that we remember */
-struct us_data {
- struct us_data *next; /* next device */
-
- /* the device we're working with */
- struct semaphore dev_semaphore; /* protect pusb_dev */
- struct usb_device *pusb_dev; /* this usb_device */
-
- unsigned int flags; /* from filter initially */
-
- /* information about the device -- always good */
- char vendor[USB_STOR_STRING_LEN];
- char product[USB_STOR_STRING_LEN];
- char serial[USB_STOR_STRING_LEN];
- char *transport_name;
- char *protocol_name;
- u8 subclass;
- u8 protocol;
- u8 max_lun;
-
- /* information about the device -- only good if device is attached */
- u8 ifnum; /* interface number */
- u8 ep_in; /* bulk in endpoint */
- u8 ep_out; /* bulk out endpoint */
- struct usb_endpoint_descriptor *ep_int; /* interrupt endpoint */
-
- /* function pointers for this device */
- trans_cmnd transport; /* transport function */
- trans_reset transport_reset; /* transport device reset */
- proto_cmnd proto_handler; /* protocol handler */
-
- /* SCSI interfaces */
- GUID(guid); /* unique dev id */
- struct Scsi_Host *host; /* our dummy host data */
- Scsi_Host_Template htmplt; /* own host template */
- int host_number; /* to find us */
- int host_no; /* allocated by scsi */
- Scsi_Cmnd *srb; /* current srb */
-
- /* thread information */
- Scsi_Cmnd *queue_srb; /* the single queue slot */
- int action; /* what to do */
- int pid; /* control thread */
-
- /* interrupt info for CBI devices -- only good if attached */
- struct semaphore ip_waitq; /* for CBI interrupts */
- atomic_t ip_wanted[1]; /* is an IRQ expected? */
-
- /* interrupt communications data */
- struct semaphore irq_urb_sem; /* to protect irq_urb */
- struct urb *irq_urb; /* for USB int requests */
- unsigned char irqbuf[2]; /* buffer for USB IRQ */
- unsigned char irqdata[2]; /* data from USB IRQ */
-
- /* control and bulk communications data */
- struct semaphore current_urb_sem; /* to protect irq_urb */
- struct urb *current_urb; /* non-int USB requests */
-
- /* the semaphore for sleeping the control thread */
- struct semaphore sema; /* to sleep thread on */
-
- /* mutual exclusion structures */
- struct completion notify; /* thread begin/end */
- struct semaphore queue_exclusion; /* to protect data structs */
- struct us_unusual_dev *unusual_dev; /* If unusual device */
- void *extra; /* Any extra data */
- extra_data_destructor extra_destructor;/* extra data destructor */
-};
-
-/* The list of structures and the protective lock for them */
-extern struct us_data *us_list;
-extern struct semaphore us_list_semaphore;
-
-/* The structure which defines our driver */
-extern struct usb_driver usb_storage_driver;
-
-/* Function to fill an inquiry response. See usb.c for details */
-extern void fill_inquiry_response(struct us_data *us,
- unsigned char *data, unsigned int data_len);
-#endif
diff --git a/drivers/usb/class/usbkbd.c b/drivers/usb/class/usbkbd.c
deleted file mode 100644
index 31edd4e7b52b..000000000000
--- a/drivers/usb/class/usbkbd.c
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * $Id: usbkbd.c,v 1.27 2001/12/27 10:37:41 vojtech Exp $
- *
- * Copyright (c) 1999-2001 Vojtech Pavlik
- *
- * USB HIDBP Keyboard support
- */
-
-/*
- * 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
- *
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/input.h>
-#include <linux/init.h>
-#include <linux/usb.h>
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION ""
-#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
-#define DRIVER_DESC "USB HID Boot Protocol keyboard driver"
-#define DRIVER_LICENSE "GPL"
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE(DRIVER_LICENSE);
-
-static unsigned char usb_kbd_keycode[256] = {
- 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
- 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3,
- 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26,
- 27, 43, 84, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
- 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
- 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
- 72, 73, 82, 83, 86,127,116,117, 85, 89, 90, 91, 92, 93, 94, 95,
- 120,121,122,123,134,138,130,132,128,129,131,137,133,135,136,113,
- 115,114, 0, 0, 0,124, 0,181,182,183,184,185,186,187,188,189,
- 190,191,192,193,194,195,196,197,198, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
- 150,158,159,128,136,177,178,176,142,152,173,140
-};
-
-struct usb_kbd {
- struct input_dev dev;
- struct usb_device *usbdev;
- unsigned char new[8];
- unsigned char old[8];
- struct urb *irq, *led;
- struct usb_ctrlrequest cr;
- unsigned char leds, newleds;
- char name[128];
- char phys[64];
- int open;
-};
-
-static void usb_kbd_irq(struct urb *urb)
-{
- struct usb_kbd *kbd = urb->context;
- int i;
-
- if (urb->status) return;
-
- for (i = 0; i < 8; i++)
- input_report_key(&kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1);
-
- for (i = 2; i < 8; i++) {
-
- if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == kbd->new + 8) {
- if (usb_kbd_keycode[kbd->old[i]])
- input_report_key(&kbd->dev, usb_kbd_keycode[kbd->old[i]], 0);
- else
- info("Unknown key (scancode %#x) released.", kbd->old[i]);
- }
-
- if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) {
- if (usb_kbd_keycode[kbd->new[i]])
- input_report_key(&kbd->dev, usb_kbd_keycode[kbd->new[i]], 1);
- else
- info("Unknown key (scancode %#x) pressed.", kbd->new[i]);
- }
- }
-
- memcpy(kbd->old, kbd->new, 8);
-}
-
-int usb_kbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
-{
- struct usb_kbd *kbd = dev->private;
-
- if (type != EV_LED) return -1;
-
-
- kbd->newleds = (!!test_bit(LED_KANA, dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) |
- (!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL, dev->led) << 1) |
- (!!test_bit(LED_NUML, dev->led));
-
- if (kbd->led->status == -EINPROGRESS)
- return 0;
-
- if (kbd->leds == kbd->newleds)
- return 0;
-
- kbd->leds = kbd->newleds;
- kbd->led->dev = kbd->usbdev;
- if (usb_submit_urb(kbd->led, GFP_ATOMIC))
- err("usb_submit_urb(leds) failed");
-
- return 0;
-}
-
-static void usb_kbd_led(struct urb *urb)
-{
- struct usb_kbd *kbd = urb->context;
-
- if (urb->status)
- warn("led urb status %d received", urb->status);
-
- if (kbd->leds == kbd->newleds)
- return;
-
- kbd->leds = kbd->newleds;
- kbd->led->dev = kbd->usbdev;
- if (usb_submit_urb(kbd->led, GFP_ATOMIC))
- err("usb_submit_urb(leds) failed");
-}
-
-static int usb_kbd_open(struct input_dev *dev)
-{
- struct usb_kbd *kbd = dev->private;
-
- if (kbd->open++)
- return 0;
-
- kbd->irq->dev = kbd->usbdev;
- if (usb_submit_urb(kbd->irq, GFP_KERNEL))
- return -EIO;
-
- return 0;
-}
-
-static void usb_kbd_close(struct input_dev *dev)
-{
- struct usb_kbd *kbd = dev->private;
-
- if (!--kbd->open)
- usb_unlink_urb(kbd->irq);
-}
-
-static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum,
- const struct usb_device_id *id)
-{
- struct usb_interface *iface;
- struct usb_interface_descriptor *interface;
- struct usb_endpoint_descriptor *endpoint;
- struct usb_kbd *kbd;
- int i, pipe, maxp;
- char path[64];
- char *buf;
-
- iface = &dev->actconfig->interface[ifnum];
- interface = &iface->altsetting[iface->act_altsetting];
-
- if (interface->bNumEndpoints != 1) return NULL;
-
- endpoint = interface->endpoint + 0;
- if (!(endpoint->bEndpointAddress & 0x80)) return NULL;
- if ((endpoint->bmAttributes & 3) != 3) return NULL;
-
- pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
- maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
-
- if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL;
- memset(kbd, 0, sizeof(struct usb_kbd));
-
- kbd->irq = usb_alloc_urb(0, GFP_KERNEL);
- if (!kbd->irq) {
- kfree(kbd);
- return NULL;
- }
- kbd->led = usb_alloc_urb(0, GFP_KERNEL);
- if (!kbd->led) {
- usb_free_urb(kbd->irq);
- kfree(kbd);
- return NULL;
- }
-
- kbd->usbdev = dev;
-
- kbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
- kbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL) | BIT(LED_COMPOSE) | BIT(LED_KANA);
-
- for (i = 0; i < 255; i++)
- set_bit(usb_kbd_keycode[i], kbd->dev.keybit);
- clear_bit(0, kbd->dev.keybit);
-
- kbd->dev.private = kbd;
- kbd->dev.event = usb_kbd_event;
- kbd->dev.open = usb_kbd_open;
- kbd->dev.close = usb_kbd_close;
-
- FILL_INT_URB(kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
- usb_kbd_irq, kbd, endpoint->bInterval);
-
- kbd->cr.bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
- kbd->cr.bRequest = 0x09;
- kbd->cr.wValue = 0x200;
- kbd->cr.wIndex = interface->bInterfaceNumber;
- kbd->cr.wLength = 1;
-
- usb_make_path(dev, path, 64);
- sprintf(kbd->phys, "%s/input0", path);
-
- kbd->dev.name = kbd->name;
- kbd->dev.phys = kbd->phys;
- kbd->dev.idbus = BUS_USB;
- kbd->dev.idvendor = dev->descriptor.idVendor;
- kbd->dev.idproduct = dev->descriptor.idProduct;
- kbd->dev.idversion = dev->descriptor.bcdDevice;
-
- if (!(buf = kmalloc(63, GFP_KERNEL))) {
- kfree(kbd);
- return NULL;
- }
-
- if (dev->descriptor.iManufacturer &&
- usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0)
- strcat(kbd->name, buf);
- if (dev->descriptor.iProduct &&
- usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0)
- sprintf(kbd->name, "%s %s", kbd->name, buf);
-
- if (!strlen(kbd->name))
- sprintf(kbd->name, "USB HIDBP Keyboard %04x:%04x",
- kbd->dev.idvendor, kbd->dev.idproduct);
-
- kfree(buf);
-
- FILL_CONTROL_URB(kbd->led, dev, usb_sndctrlpipe(dev, 0),
- (void*) &kbd->cr, &kbd->leds, 1, usb_kbd_led, kbd);
-
- input_register_device(&kbd->dev);
-
- printk(KERN_INFO "input: %s on %s\n", kbd->name, path);
-
- return kbd;
-}
-
-static void usb_kbd_disconnect(struct usb_device *dev, void *ptr)
-{
- struct usb_kbd *kbd = ptr;
- usb_unlink_urb(kbd->irq);
- input_unregister_device(&kbd->dev);
- usb_free_urb(kbd->irq);
- usb_free_urb(kbd->led);
- kfree(kbd);
-}
-
-static struct usb_device_id usb_kbd_id_table [] = {
- { USB_INTERFACE_INFO(3, 1, 1) },
- { } /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
-
-static struct usb_driver usb_kbd_driver = {
- name: "keyboard",
- probe: usb_kbd_probe,
- disconnect: usb_kbd_disconnect,
- id_table: usb_kbd_id_table,
-};
-
-static int __init usb_kbd_init(void)
-{
- usb_register(&usb_kbd_driver);
- info(DRIVER_VERSION ":" DRIVER_DESC);
- return 0;
-}
-
-static void __exit usb_kbd_exit(void)
-{
- usb_deregister(&usb_kbd_driver);
-}
-
-module_init(usb_kbd_init);
-module_exit(usb_kbd_exit);
diff --git a/drivers/usb/class/usbmouse.c b/drivers/usb/class/usbmouse.c
deleted file mode 100644
index 22673b42d60a..000000000000
--- a/drivers/usb/class/usbmouse.c
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * $Id: usbmouse.c,v 1.15 2001/12/27 10:37:41 vojtech Exp $
- *
- * Copyright (c) 1999-2001 Vojtech Pavlik
- *
- * USB HIDBP Mouse support
- */
-
-/*
- * 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
- *
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/input.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/usb.h>
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.6"
-#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
-#define DRIVER_DESC "USB HID Boot Protocol mouse driver"
-#define DRIVER_LICENSE "GPL"
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE(DRIVER_LICENSE);
-
-struct usb_mouse {
- signed char data[8];
- char name[128];
- char phys[64];
- struct usb_device *usbdev;
- struct input_dev dev;
- struct urb *irq;
- int open;
-};
-
-static void usb_mouse_irq(struct urb *urb)
-{
- struct usb_mouse *mouse = urb->context;
- signed char *data = mouse->data;
- struct input_dev *dev = &mouse->dev;
-
- if (urb->status) return;
-
- input_report_key(dev, BTN_LEFT, data[0] & 0x01);
- input_report_key(dev, BTN_RIGHT, data[0] & 0x02);
- input_report_key(dev, BTN_MIDDLE, data[0] & 0x04);
- input_report_key(dev, BTN_SIDE, data[0] & 0x08);
- input_report_key(dev, BTN_EXTRA, data[0] & 0x10);
-
- input_report_rel(dev, REL_X, data[1]);
- input_report_rel(dev, REL_Y, data[2]);
- input_report_rel(dev, REL_WHEEL, data[3]);
-}
-
-static int usb_mouse_open(struct input_dev *dev)
-{
- struct usb_mouse *mouse = dev->private;
-
- if (mouse->open++)
- return 0;
-
- mouse->irq->dev = mouse->usbdev;
- if (usb_submit_urb(mouse->irq, GFP_KERNEL))
- return -EIO;
-
- return 0;
-}
-
-static void usb_mouse_close(struct input_dev *dev)
-{
- struct usb_mouse *mouse = dev->private;
-
- if (!--mouse->open)
- usb_unlink_urb(mouse->irq);
-}
-
-static void *usb_mouse_probe(struct usb_device *dev, unsigned int ifnum,
- const struct usb_device_id *id)
-{
- struct usb_interface *iface;
- struct usb_interface_descriptor *interface;
- struct usb_endpoint_descriptor *endpoint;
- struct usb_mouse *mouse;
- int pipe, maxp;
- char path[64];
- char *buf;
-
- iface = &dev->actconfig->interface[ifnum];
- interface = &iface->altsetting[iface->act_altsetting];
-
- if (interface->bNumEndpoints != 1) return NULL;
-
- endpoint = interface->endpoint + 0;
- if (!(endpoint->bEndpointAddress & 0x80)) return NULL;
- if ((endpoint->bmAttributes & 3) != 3) return NULL;
-
- pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
- maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
-
- if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL))) return NULL;
- memset(mouse, 0, sizeof(struct usb_mouse));
-
- mouse->irq = usb_alloc_urb(0, GFP_KERNEL);
- if (!mouse->irq) {
- kfree(mouse);
- return NULL;
- }
-
- mouse->usbdev = dev;
-
- mouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- mouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
- mouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
- mouse->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA);
- mouse->dev.relbit[0] |= BIT(REL_WHEEL);
-
- mouse->dev.private = mouse;
- mouse->dev.open = usb_mouse_open;
- mouse->dev.close = usb_mouse_close;
-
- usb_make_path(dev, path, 64);
- sprintf(mouse->phys, "%s/input0", path);
-
- mouse->dev.name = mouse->name;
- mouse->dev.phys = mouse->phys;
- mouse->dev.idbus = BUS_USB;
- mouse->dev.idvendor = dev->descriptor.idVendor;
- mouse->dev.idproduct = dev->descriptor.idProduct;
- mouse->dev.idversion = dev->descriptor.bcdDevice;
-
- if (!(buf = kmalloc(63, GFP_KERNEL))) {
- kfree(mouse);
- return NULL;
- }
-
- if (dev->descriptor.iManufacturer &&
- usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0)
- strcat(mouse->name, buf);
- if (dev->descriptor.iProduct &&
- usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0)
- sprintf(mouse->name, "%s %s", mouse->name, buf);
-
- if (!strlen(mouse->name))
- sprintf(mouse->name, "USB HIDBP Mouse %04x:%04x",
- mouse->dev.idvendor, mouse->dev.idproduct);
-
- kfree(buf);
-
- FILL_INT_URB(mouse->irq, dev, pipe, mouse->data, maxp > 8 ? 8 : maxp,
- usb_mouse_irq, mouse, endpoint->bInterval);
-
- input_register_device(&mouse->dev);
-
- printk(KERN_INFO "input: %s on %s\n", mouse->name, path);
-
- return mouse;
-}
-
-static void usb_mouse_disconnect(struct usb_device *dev, void *ptr)
-{
- struct usb_mouse *mouse = ptr;
- usb_unlink_urb(mouse->irq);
- input_unregister_device(&mouse->dev);
- usb_free_urb(mouse->irq);
- kfree(mouse);
-}
-
-static struct usb_device_id usb_mouse_id_table [] = {
- { USB_INTERFACE_INFO(3, 1, 2) },
- { } /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, usb_mouse_id_table);
-
-static struct usb_driver usb_mouse_driver = {
- name: "usb_mouse",
- probe: usb_mouse_probe,
- disconnect: usb_mouse_disconnect,
- id_table: usb_mouse_id_table,
-};
-
-static int __init usb_mouse_init(void)
-{
- usb_register(&usb_mouse_driver);
- info(DRIVER_VERSION ":" DRIVER_DESC);
- return 0;
-}
-
-static void __exit usb_mouse_exit(void)
-{
- usb_deregister(&usb_mouse_driver);
-}
-
-module_init(usb_mouse_init);
-module_exit(usb_mouse_exit);