summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/char/nvram.c10
-rw-r--r--drivers/char/pc_keyb.c16
-rw-r--r--drivers/char/stallion.c (renamed from drivers/media/video/stallion.c)0
-rw-r--r--drivers/scsi/esp.c9
-rw-r--r--drivers/scsi/qlogicpti.c1
-rw-r--r--drivers/sound/sound_core.c6
-rw-r--r--drivers/usb/Makefile2
-rw-r--r--drivers/usb/storage/Makefile81
-rw-r--r--drivers/usb/storage/debug.c4
-rw-r--r--drivers/usb/storage/debug.h4
-rw-r--r--drivers/usb/storage/dpcm.c5
-rw-r--r--drivers/usb/storage/dpcm.h4
-rw-r--r--drivers/usb/storage/freecom.c375
-rw-r--r--drivers/usb/storage/freecom.h35
-rw-r--r--drivers/usb/storage/protocol.c4
-rw-r--r--drivers/usb/storage/protocol.h4
-rw-r--r--drivers/usb/storage/scsiglue.c4
-rw-r--r--drivers/usb/storage/scsiglue.h4
-rw-r--r--drivers/usb/storage/sddr09.c176
-rw-r--r--drivers/usb/storage/sddr09.h16
-rw-r--r--drivers/usb/storage/shuttle_usbat.c10
-rw-r--r--drivers/usb/storage/shuttle_usbat.h5
-rw-r--r--drivers/usb/storage/transport.c86
-rw-r--r--drivers/usb/storage/transport.h10
-rw-r--r--drivers/usb/storage/usb.c173
-rw-r--r--drivers/usb/storage/usb.h4
26 files changed, 813 insertions, 235 deletions
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index 6fa72fc8e..a8c29311f 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -246,7 +246,8 @@ static ssize_t nvram_read(struct file * file,
spin_unlock_irq (&rtc_lock);
- copy_to_user_ret (buf, contents, tmp - contents, -EFAULT);
+ if (copy_to_user (buf, contents, tmp - contents))
+ return -EFAULT;
*ppos = i;
@@ -264,10 +265,9 @@ static ssize_t nvram_write(struct file * file,
unsigned i = *ppos;
char * tmp;
- /* could comebody please help me indent this better? */
- copy_from_user_ret (contents, buf, (NVRAM_BYTES - i) < count ?
- (NVRAM_BYTES - i) : count,
- -EFAULT);
+ if (copy_from_user (contents, buf, (NVRAM_BYTES - i) < count ?
+ (NVRAM_BYTES - i) : count))
+ return -EFAULT;
spin_lock_irq (&rtc_lock);
diff --git a/drivers/char/pc_keyb.c b/drivers/char/pc_keyb.c
index 34e13c97f..d9276b753 100644
--- a/drivers/char/pc_keyb.c
+++ b/drivers/char/pc_keyb.c
@@ -62,6 +62,7 @@ static void kbd_write_command_w(int data);
static void kbd_write_output_w(int data);
#ifdef CONFIG_PSMOUSE
static void aux_write_ack(int val);
+static void __aux_write_ack(int val);
#endif
spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
@@ -404,7 +405,7 @@ static inline void handle_mouse_event(unsigned char scancode)
}
else if(scancode == AUX_RECONNECT){
queue->head = queue->tail = 0; /* Flush input queue */
- aux_write_ack(AUX_ENABLE_DEV); /* ping the mouse :) */
+ __aux_write_ack(AUX_ENABLE_DEV); /* ping the mouse :) */
return;
}
@@ -822,11 +823,8 @@ static void aux_write_dev(int val)
/*
* Send a byte to the mouse & handle returned ack
*/
-static void aux_write_ack(int val)
+static void __aux_write_ack(int val)
{
- unsigned long flags;
-
- spin_lock_irqsave(&kbd_controller_lock, flags);
kb_wait();
kbd_write_command(KBD_CCMD_WRITE_MOUSE);
kb_wait();
@@ -834,6 +832,14 @@ static void aux_write_ack(int val)
/* we expect an ACK in response. */
mouse_reply_expected++;
kb_wait();
+}
+
+static void aux_write_ack(int val)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&kbd_controller_lock, flags);
+ __aux_write_ack(val);
spin_unlock_irqrestore(&kbd_controller_lock, flags);
}
diff --git a/drivers/media/video/stallion.c b/drivers/char/stallion.c
index a0faeada4..a0faeada4 100644
--- a/drivers/media/video/stallion.c
+++ b/drivers/char/stallion.c
diff --git a/drivers/scsi/esp.c b/drivers/scsi/esp.c
index 1dcc8acb8..6339d1e90 100644
--- a/drivers/scsi/esp.c
+++ b/drivers/scsi/esp.c
@@ -1,4 +1,4 @@
-/* $Id: esp.c,v 1.94 2000/03/30 02:09:10 davem Exp $
+/* $Id: esp.c,v 1.95 2000/08/23 22:32:37 davem Exp $
* esp.c: EnhancedScsiProcessor Sun SCSI driver code.
*
* Copyright (C) 1995, 1998 David S. Miller (davem@caip.rutgers.edu)
@@ -32,13 +32,16 @@
#include <asm/sbus.h>
#include <asm/dma.h>
#include <asm/system.h>
-#include <asm/machines.h>
#include <asm/ptrace.h>
#include <asm/pgtable.h>
#include <asm/oplib.h>
#include <asm/io.h>
#include <asm/irq.h>
+
+#ifndef __sparc_v9__
+#include <asm/machines.h>
#include <asm/idprom.h>
+#endif
#include <linux/module.h>
@@ -1634,6 +1637,7 @@ do_sync_known:
*/
int cdrom_hwbug_wkaround = 0;
+#ifndef __sparc_v9__
/* Never allow disconnects or synchronous transfers on
* SparcStation1 and SparcStation1+. Allowing those
* to be enabled seems to lockup the machine completely.
@@ -1654,6 +1658,7 @@ do_sync_known:
esp->snip = 0;
goto do_sync_known;
}
+#endif /* !(__sparc_v9__) */
/* We've talked to this guy before,
* but never negotiated. Let's try,
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c
index d61c832c5..b510231be 100644
--- a/drivers/scsi/qlogicpti.c
+++ b/drivers/scsi/qlogicpti.c
@@ -32,7 +32,6 @@
#include <asm/sbus.h>
#include <asm/dma.h>
#include <asm/system.h>
-#include <asm/machines.h>
#include <asm/ptrace.h>
#include <asm/pgtable.h>
#include <asm/oplib.h>
diff --git a/drivers/sound/sound_core.c b/drivers/sound/sound_core.c
index aa2890f05..8a85d4c42 100644
--- a/drivers/sound/sound_core.c
+++ b/drivers/sound/sound_core.c
@@ -456,7 +456,11 @@ static int soundcore_open(struct inode *, struct file *);
static struct file_operations soundcore_fops=
{
- owner: THIS_MODULE,
+/* owner: THIS_MODULE, * this is a bug: if we have an owner, the kernel
+ generates a MOD_INC_USE_COUNT - thus
+ the module cannot be unloaded since the device
+ is never released here ! - solution: owner
+ has to be NULL. Patch by Peter Wahl <Peter.Wahl@epost.de> */
open: soundcore_open,
};
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 7112ae635..d011f206b 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -79,7 +79,7 @@ endif
ifeq ($(CONFIG_USB_STORAGE),y)
SUB_DIRS += storage
- obj-y += storage/usb-storage.o
+ obj-y += storage/storage.o
else
ifeq ($(CONFIG_USB_STORAGE),m)
MOD_IN_SUB_DIRS += storage
diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
index e7761863e..e09a8cac1 100644
--- a/drivers/usb/storage/Makefile
+++ b/drivers/usb/storage/Makefile
@@ -1,47 +1,44 @@
#
# Makefile for the USB Mass Storage device drivers.
#
+# 15 Aug 2000, Christoph Hellwig <hch@caldera.de>
+# 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-objs := scsiglue.o protocol.o transport.o usb.o \
+ $(usb-storage-obj-y)
+
+# Extract lists of the multi-part drivers.
+# The 'int-*' lists are the intermediate files used to build the multi's.
+multi-y := $(filter $(list-multi), $(obj-y))
+multi-m := $(filter $(list-multi), $(obj-m))
+int-y := $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs)))
+int-m := $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs)))
+
+# Take multi-part drivers out of obj-y and put components in.
+obj-y := $(filter-out $(list-multi), $(obj-y)) $(int-y)
+
+# Translate to Rules.make lists.
+O_OBJS := $(obj-y)
+M_OBJS := $(obj-m)
+MI_OBJS := $(int-m)
-O_TARGET := usb-storage.o
-M_OBJS := usb-storage.o
-O_OBJS := scsiglue.o protocol.o transport.o usb.o
-MOD_LIST_NAME := USB_STORAGE_MODULES
-
-CFLAGS_scsiglue.o:= -I../../scsi/
-CFLAGS_protocol.o:= -I../../scsi/
-CFLAGS_transport.o:= -I../../scsi/
-CFLAGS_debug.o:= -I../../scsi/
-CFLAGS_usb.o:= -I../../scsi/
-CFLAGS_shuttle_usbat.o:= -I../../scsi/
-CFLAGS_sddr09.o:= -I../../scsi/
-CFLAGS_dpcm.o:= -I../../scsi/
-
-ifeq ($(CONFIG_USB_STORAGE_DEBUG),y)
- O_OBJS += debug.o
-endif
-
-ifeq ($(CONFIG_USB_STORAGE_HP8200e),y)
- O_OBJS += shuttle_usbat.o
-endif
-
-ifeq ($(CONFIG_USB_STORAGE_SDDR09),y)
- O_OBJS += sddr09.o
-endif
-
-ifeq ($(CONFIG_USB_STORAGE_FREECOM),y)
- O_OBJS += freecom.o
-endif
-
-ifeq ($(CONFIG_USB_STORAGE_SHUTTLE_SMARTMEDIA),y)
- O_OBJS += shuttle_sm.o
-endif
-
-ifeq ($(CONFIG_USB_STORAGE_SHUTTLE_COMPACTFLASH),y)
- O_OBJS += shuttle_cf.o
-endif
-
-ifeq ($(CONFIG_USB_STORAGE_DPCM),y)
- O_OBJS += dpcm.o
-endif
-
include $(TOPDIR)/Rules.make
+
+usb-storage.o: $(usb-storage-objs)
+ $(LD) -r -o $@ $(usb-storage-objs)
diff --git a/drivers/usb/storage/debug.c b/drivers/usb/storage/debug.c
index 2a5127bb6..9f4693b95 100644
--- a/drivers/usb/storage/debug.c
+++ b/drivers/usb/storage/debug.c
@@ -1,9 +1,9 @@
/* Driver for USB Mass Storage compliant devices
* Debugging Functions Source Code File
*
- * $Id: debug.c,v 1.2 2000/07/19 17:21:39 groovyjava Exp $
+ * $Id: debug.c,v 1.3 2000/08/25 00:13:51 mdharm Exp $
*
- * Current development and maintainance by:
+ * Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
* Initial work by:
diff --git a/drivers/usb/storage/debug.h b/drivers/usb/storage/debug.h
index 04a08be2e..f03c53351 100644
--- a/drivers/usb/storage/debug.h
+++ b/drivers/usb/storage/debug.h
@@ -1,9 +1,9 @@
/* Driver for USB Mass Storage compliant devices
* Debugging Functions Header File
*
- * $Id: debug.h,v 1.3 2000/07/19 19:34:48 groovyjava Exp $
+ * $Id: debug.h,v 1.4 2000/08/25 00:13:51 mdharm Exp $
*
- * Current development and maintainance by:
+ * Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
* Initial work by:
diff --git a/drivers/usb/storage/dpcm.c b/drivers/usb/storage/dpcm.c
index 8b7195bfc..33cb674e2 100644
--- a/drivers/usb/storage/dpcm.c
+++ b/drivers/usb/storage/dpcm.c
@@ -1,12 +1,12 @@
/* Driver for Microtech DPCM-USB CompactFlash/SmartMedia reader
*
- * $Id: dpcm.c,v 1.1 2000/08/08 01:26:12 webbb Exp $
+ * $Id: dpcm.c,v 1.3 2000/08/25 00:13:51 mdharm Exp $
*
* DPCM driver v0.1:
*
* First release
*
- * Current development and maintainance by:
+ * Current development and maintenance by:
* (c) 2000 Brian Webb (webbb@earthlink.net)
*
* This device contains both a CompactFlash card reader, which
@@ -37,7 +37,6 @@
#include "dpcm.h"
#include "sddr09.h"
-
/*
* Transport for the Microtech DPCM-USB
*
diff --git a/drivers/usb/storage/dpcm.h b/drivers/usb/storage/dpcm.h
index d6e5f86ad..e6e5637d6 100644
--- a/drivers/usb/storage/dpcm.h
+++ b/drivers/usb/storage/dpcm.h
@@ -1,12 +1,12 @@
/* Driver for Microtech DPCM-USB CompactFlash/SmartMedia reader
*
- * $Id: dpcm.h,v 1.1 2000/08/08 01:26:12 webbb Exp $
+ * $Id: dpcm.h,v 1.2 2000/08/25 00:13:51 mdharm Exp $
*
* DPCM driver v0.1:
*
* First release
*
- * Current development and maintainance by:
+ * Current development and maintenance by:
* (c) 2000 Brian Webb (webbb@earthlink.net)
*
* See dpcm.c for more explanation
diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
new file mode 100644
index 000000000..6b0914cf6
--- /dev/null
+++ b/drivers/usb/storage/freecom.c
@@ -0,0 +1,375 @@
+/* Driver for Freecom USB/IDE adaptor
+ *
+ * $Id: freecom.c,v 1.7 2000/08/25 00:13:51 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"
+
+static void pdump (void *, int);
+
+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];
+};
+
+struct freecom_status {
+ __u8 Status;
+ __u8 Reason;
+ __u16 Count;
+ __u8 Pad[60];
+};
+
+/* These are the packet types. The low bit indicates that this command
+ * should wait for an interrupt. */
+#define FCM_PACKET_ATAPI 0x21
+
+/* Receive data from the IDE interface. The ATAPI packet has already
+ * waited, so the data should be immediately available. */
+#define FCM_PACKET_INPUT 0x90
+
+/* All packets (except for status) are 64 bytes long. */
+#define FCM_PACKET_LENGTH 64
+
+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;
+ int offset;
+ __u8 *buffer = extra->buffer;
+
+ 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));
+
+ printk (KERN_DEBUG "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("us_transfer_partial(): transfer aborted\n");
+ return US_BULK_TRANSFER_ABORTED;
+ }
+
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+ printk (KERN_DEBUG "Done issuing read request: %d %d\n",
+ result, partial);
+
+ /* Now transfer all of our blocks. */
+ if (srb->use_sg) {
+ US_DEBUGP ("Need to implement scatter-gather\n");
+ return USB_STOR_TRANSPORT_ERROR;
+ } else {
+ offset = 0;
+
+ while (offset < count) {
+ printk (KERN_DEBUG "Start of read\n");
+ /* Use the given buffer directly, but only if there
+ * is space for an entire packet. */
+
+ if (offset + 64 <= srb->request_bufflen) {
+ result = usb_stor_bulk_msg (
+ us, srb->request_buffer+offset,
+ ipipe, 64, &partial);
+ printk (KERN_DEBUG "Read111 = %d, %d\n",
+ result, partial);
+ pdump (srb->request_buffer+offset,
+ partial);
+ } else {
+ result = usb_stor_bulk_msg (
+ us, buffer,
+ ipipe, 64, &partial);
+ printk (KERN_DEBUG "Read112 = %d, %d\n",
+ result, partial);
+ memcpy (srb->request_buffer+offset,
+ buffer,
+ srb->request_bufflen - offset);
+ pdump (srb->request_buffer+offset,
+ srb->request_bufflen - offset);
+ }
+
+ if (result != 0) {
+ US_DEBUGP ("Freecom readblock r=%d, p=%d\n",
+ result, partial);
+
+ /* -ENOENT -- we canceled this transfer */
+ if (result == -ENOENT) {
+ US_DEBUGP("us_transfer_partial(): transfer aborted\n");
+ return US_BULK_TRANSFER_ABORTED;
+ }
+
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+ offset += 64;
+ }
+ }
+
+ printk (KERN_DEBUG "freecom_readdata 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;
+
+ /* 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) {
+ printk (KERN_WARNING USB_STORAGE "Out of memory\n");
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+ }
+
+ extra = (freecom_udata_t) us->extra;
+
+ fcb = (struct freecom_cb_wrap *) extra->buffer;
+ fst = (struct freecom_status *) extra->buffer;
+
+ printk (KERN_DEBUG "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);
+
+#if 0
+ /* Yuck, let's see if this helps us. Artificially increase the
+ * length on this. */
+ if (srb->cmnd[0] == 0x03 && srb->cmnd[4] == 0x12)
+ srb->cmnd[4] = 0x0E;
+#endif
+
+ /* The ATAPI Command always goes out first. */
+ fcb->Type = FCM_PACKET_ATAPI;
+ fcb->Timeout = 0;
+ memcpy (fcb->Atapi, srb->cmnd, 12);
+ memset (fcb->Filler, 0, sizeof (fcb->Filler));
+
+ 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("us_transfer_partial(): 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);
+ printk (KERN_DEBUG "foo Status result %d %d\n", result, partial);
+ /* -ENOENT -- we canceled this transfer */
+ if (result == -ENOENT) {
+ US_DEBUGP("us_transfer_partial(): transfer aborted\n");
+ return US_BULK_TRANSFER_ABORTED;
+ }
+
+ pdump ((void *) fst, partial);
+ if (partial != 4 || result != 0) {
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+ if ((fst->Reason & 1) != 0) {
+ printk (KERN_DEBUG "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. */
+ printk (KERN_DEBUG "Device indicates that it has %d bytes available\n",
+ le16_to_cpu (fst->Count));
+
+ /* Find the length we desire to read. It is the lesser of the SCSI
+ * layer's requested length, and the length the device claims to
+ * have available. */
+ length = us_transfer_length (srb);
+ printk (KERN_DEBUG "SCSI requested %d\n", length);
+ if (length > le16_to_cpu (fst->Count))
+ length = le16_to_cpu (fst->Count);
+
+ /* 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:
+ result = freecom_readdata (srb, us, ipipe, opipe, length);
+ if (result != USB_STOR_TRANSPORT_GOOD)
+ return result;
+ 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;
+ }
+
+#if 0
+ /* After the transfer, we can read our status register. */
+ printk (KERN_DEBUG "Going to read status register\n");
+ result = usb_stor_bulk_msg (us, &fst, ipipe,
+ FCM_PACKET_LENGTH, &partial);
+ printk (KERN_DEBUG "Result from read %d %d\n", result, partial);
+ if (result != 0) {
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+ if ((fst.Reason & 1) != 0) {
+ return USB_STOR_TRANSPORT_FAILED;
+ }
+#endif
+
+ return USB_STOR_TRANSPORT_GOOD;
+
+ printk (KERN_DEBUG "Freecom: transfer_length = %d\n",
+ us_transfer_length (srb));
+
+ printk (KERN_DEBUG "Freecom: direction = %d\n",
+ srb->sc_data_direction);
+
+ return USB_STOR_TRANSPORT_ERROR;
+}
+
+int usb_stor_freecom_reset(struct us_data *us)
+{
+ printk (KERN_DEBUG "freecom reset called\n");
+
+ /* We don't really have this feature. */
+ return USB_STOR_TRANSPORT_ERROR;
+}
+
+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;
+ printk (KERN_DEBUG "%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;
+ printk (KERN_DEBUG "%s\n", line);
+ offset = 0;
+}
+
diff --git a/drivers/usb/storage/freecom.h b/drivers/usb/storage/freecom.h
new file mode 100644
index 000000000..98ac919fa
--- /dev/null
+++ b/drivers/usb/storage/freecom.h
@@ -0,0 +1,35 @@
+/* Driver for Freecom USB/IDE adaptor
+ *
+ * $Id: freecom.h,v 1.3 2000/08/25 00:13:51 mdharm 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);
+
+#endif
diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
index aee6b420e..2aa83ea6d 100644
--- a/drivers/usb/storage/protocol.c
+++ b/drivers/usb/storage/protocol.c
@@ -1,8 +1,8 @@
/* Driver for USB Mass Storage compliant devices
*
- * $Id: protocol.c,v 1.4 2000/08/01 22:01:19 mdharm Exp $
+ * $Id: protocol.c,v 1.5 2000/08/25 00:13:51 mdharm Exp $
*
- * Current development and maintainance by:
+ * Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
* Developed with the assistance of:
diff --git a/drivers/usb/storage/protocol.h b/drivers/usb/storage/protocol.h
index 239d37983..a9306e6c9 100644
--- a/drivers/usb/storage/protocol.h
+++ b/drivers/usb/storage/protocol.h
@@ -1,9 +1,9 @@
/* Driver for USB Mass Storage compliant devices
* Protocol Functions Header File
*
- * $Id: protocol.h,v 1.2 2000/08/01 22:01:19 mdharm Exp $
+ * $Id: protocol.h,v 1.3 2000/08/25 00:13:51 mdharm Exp $
*
- * Current development and maintainance by:
+ * 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
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index c823aaed1..9d4f983fc 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -1,9 +1,9 @@
/* Driver for USB Mass Storage compliant devices
* SCSI layer glue code
*
- * $Id: scsiglue.c,v 1.8 2000/08/11 23:15:05 mdharm Exp $
+ * $Id: scsiglue.c,v 1.9 2000/08/25 00:13:51 mdharm Exp $
*
- * Current development and maintainance by:
+ * Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
* Developed with the assistance of:
diff --git a/drivers/usb/storage/scsiglue.h b/drivers/usb/storage/scsiglue.h
index f81787678..13b9f3bec 100644
--- a/drivers/usb/storage/scsiglue.h
+++ b/drivers/usb/storage/scsiglue.h
@@ -1,9 +1,9 @@
/* Driver for USB Mass Storage compliant devices
* SCSI Connecting Glue Header File
*
- * $Id: scsiglue.h,v 1.3 2000/07/25 23:04:47 mdharm Exp $
+ * $Id: scsiglue.h,v 1.4 2000/08/25 00:13:51 mdharm Exp $
*
- * Current development and maintainance by:
+ * 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
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
index 6bf9f1477..5641a751a 100644
--- a/drivers/usb/storage/sddr09.c
+++ b/drivers/usb/storage/sddr09.c
@@ -1,10 +1,12 @@
/* Driver for SanDisk SDDR-09 SmartMedia reader
*
+ * $Id: sddr09.c,v 1.10 2000/08/25 00:13:51 mdharm Exp $
+ *
* SDDR09 driver v0.1:
*
* First release
*
- * Current development and maintainance by:
+ * Current development and maintenance by:
* (c) 2000 Robert Baruch (autophile@dol.net)
*
* The SanDisk SDDR-09 SmartMedia reader uses the Shuttle EUSB-01 chip.
@@ -316,9 +318,9 @@ int sddr09_read_data(struct us_data *us,
// Figure out the initial LBA and page
- pba = (address/info->pagesize)>>4;
+ pba = address >> (info->pageshift + info->blockshift);
lba = info->pba_to_lba[pba];
- page = (address/info->pagesize)&0x0F;
+ 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.
@@ -329,15 +331,16 @@ int sddr09_read_data(struct us_data *us,
// Read as many sectors as possible in this block
- pages = 0x10-page;
+ pages = info->blocksize - page;
if (pages > sectors)
pages = sectors;
- US_DEBUGP("Read %01X pages, from PBA %04X"
- " (LBA %04X) page %01X\n",
+ US_DEBUGP("Read %02X pages, from PBA %04X"
+ " (LBA %04X) page %02X\n",
pages, pba, lba, page);
- address = ((pba<<4)+page)*info->pagesize;
+ address = ( (pba << info->blockshift) + page ) <<
+ info->pageshift;
// Unlike in the documentation, the address is in
// words of 2 bytes.
@@ -370,7 +373,7 @@ int sddr09_read_data(struct us_data *us,
result = sddr09_bulk_transport(us,
SCSI_DATA_READ, ptr,
- pages*info->pagesize, 0);
+ pages<<info->pageshift, 0);
if (result != USB_STOR_TRANSPORT_GOOD) {
if (use_sg)
@@ -381,7 +384,7 @@ int sddr09_read_data(struct us_data *us,
page = 0;
lba++;
sectors -= pages;
- ptr += pages*info->pagesize;
+ ptr += (pages << info->pageshift);
}
if (use_sg) {
@@ -435,7 +438,7 @@ int sddr09_read_control(struct us_data *us,
result = sddr09_bulk_transport(us,
SCSI_DATA_READ, content,
- blocks*0x40, use_sg);
+ blocks<<6, use_sg); // 0x40 bytes per block
US_DEBUGP("Result for bulk read in read_control %d\n",
result);
@@ -525,7 +528,7 @@ int sddr09_reset(struct us_data *us) {
}
unsigned long sddr09_get_capacity(struct us_data *us,
- unsigned int *pagesize) {
+ unsigned int *pagesize, unsigned int *blocksize) {
unsigned char manufacturerID;
unsigned char deviceID;
@@ -547,6 +550,7 @@ unsigned long sddr09_get_capacity(struct us_data *us,
US_DEBUGP("Manuf ID = %02X\n", manufacturerID);
*pagesize = 512;
+ *blocksize = 16;
switch (deviceID) {
@@ -556,8 +560,8 @@ unsigned long sddr09_get_capacity(struct us_data *us,
*pagesize = 256;
return 0x00100000;
- case 0x5d: // 2MB
- case 0xea:
+ case 0xea: // 2MB
+ case 0x5d: // 5d is a ROM card with pagesize 512.
case 0x64:
if (deviceID!=0x5D)
*pagesize = 256;
@@ -574,9 +578,11 @@ unsigned long sddr09_get_capacity(struct us_data *us,
return 0x00800000;
case 0x73: // 16MB
+ *blocksize = 32;
return 0x01000000;
case 0x75: // 32MB
+ *blocksize = 32;
return 0x02000000;
default: // unknown
@@ -587,7 +593,7 @@ unsigned long sddr09_get_capacity(struct us_data *us,
int sddr09_read_map(struct us_data *us) {
- unsigned char *control;
+ struct scatterlist *sg;
struct sddr09_card_info *info = (struct sddr09_card_info *)(us->extra);
int numblocks;
int i;
@@ -599,25 +605,60 @@ int sddr09_read_map(struct us_data *us) {
1, 0, 0, 1, 0, 1, 1, 0
};
int result;
+ int alloc_len;
+ int alloc_blocks;
if (!info->capacity)
return -1;
- /* read 64 (2^6) bytes for every block (8192 (2^13) bytes)
- of capacity:
- 64*(capacity/8192) = capacity*(2^6)*(2^-13) =
- capacity*2^(6-13) = capacity*(2^-7)
- */
-
- control = kmalloc(info->capacity>>7, GFP_KERNEL);
+ // 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_KERNEL);
+ if (sg == NULL)
+ return 0;
+ for (i=0; i<alloc_blocks; i++) {
+ if (i<alloc_blocks-1) {
+ sg[i].address = kmalloc( (1<<17), GFP_KERNEL );
+ sg[i].length = (1<<17);
+ } else {
+ sg[i].address = kmalloc(alloc_len, GFP_KERNEL);
+ sg[i].length = alloc_len;
+ }
+ alloc_len -= sg[i].length;
+ }
+ for (i=0; i<alloc_blocks; i++)
+ if (sg[i].address == NULL) {
+ for (i=0; i<alloc_blocks; i++)
+ if (sg[i].address != NULL)
+ kfree(sg[i].address);
+ kfree(sg);
+ return 0;
+ }
- numblocks = info->capacity>>13;
+ numblocks = info->capacity >> (info->blockshift + info->pageshift);
if ( (result = sddr09_read_control(us, 0, numblocks,
- control, 0)) !=
+ (unsigned char *)sg, alloc_blocks)) !=
USB_STOR_TRANSPORT_GOOD) {
- kfree(control);
+ for (i=0; i<alloc_blocks; i++)
+ kfree(sg[i].address);
+ kfree(sg);
return -1;
}
@@ -629,11 +670,28 @@ int sddr09_read_map(struct us_data *us) {
kfree(info->pba_to_lba);
info->lba_to_pba = kmalloc(numblocks*sizeof(int), GFP_KERNEL);
info->pba_to_lba = kmalloc(numblocks*sizeof(int), GFP_KERNEL);
+
+ 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(sg[i].address);
+ 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 = control+64*i;
+ ptr = sg[i>>11].address+(i<<6);
if (ptr[0]!=0xFF || ptr[1]!=0xFF || ptr[2]!=0xFF ||
ptr[3]!=0xFF || ptr[4]!=0xFF || ptr[5]!=0xFF)
continue;
@@ -655,20 +713,30 @@ int sddr09_read_map(struct us_data *us) {
lba = (lba&0x07FF)>>1;
+ /* Every 1024 physical blocks, the LBA numbers
+ * go back to zero, but are within a higher
+ * block of LBA's. In other words, in blocks
+ * 1024-2047 you will find LBA 0-1023 which are
+ * really LBA 1024-2047.
+ */
+
+ lba += (i&~0x3FF);
+
if (lba>=numblocks) {
US_DEBUGP("Bad LBA %04X for block %04X\n", lba, i);
continue;
}
- if (i<0x10)
- US_DEBUGP("LBA %04X <-> PBA %04X\n",
- lba, i);
+ if (lba<0x10)
+ US_DEBUGP("LBA %04X <-> PBA %04X\n", lba, i);
info->pba_to_lba[i] = lba;
info->lba_to_pba[lba] = i;
}
- kfree(control);
+ for (i=0; i<alloc_blocks; i++)
+ kfree(sg[i].address);
+ kfree(sg);
return 0;
}
@@ -687,6 +755,9 @@ static int init_sddr09(struct us_data *us) {
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;
@@ -741,11 +812,7 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us)
int i;
char string[64];
unsigned char inquiry_response[36] = {
- 0x00, 0x80, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x00,
- 'S', 'a', 'n', 'D', 'i', 's', 'k', ' ',
- 'I', 'm', 'a', 'g', 'e', 'M', 'a', 't',
- 'e', ' ', 'S', 'D', 'D', 'R', '0', '9',
- ' ', ' ', ' ', ' '
+ 0x00, 0x80, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x00
};
unsigned char mode_page_01[12] = {
0x01, 0x0a, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
@@ -758,17 +825,11 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us)
unsigned short pages;
struct sddr09_card_info *info = (struct sddr09_card_info *)(us->extra);
-/*
- if (us->flags & US_FL_NEED_INIT) {
- US_DEBUGP("SDDR-09: initializing\n");
- init_sddr09(us);
- us->flags &= ~US_FL_NEED_INIT;
- }
-*/
-
if (!us->extra) {
us->extra = kmalloc(
sizeof(struct sddr09_card_info), GFP_KERNEL);
+ if (!us->extra)
+ return USB_STOR_TRANSPORT_ERROR;
memset(us->extra, 0, sizeof(struct sddr09_card_info));
us->extra_destructor = sddr09_card_info_destructor;
}
@@ -779,14 +840,29 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us)
respond to INQUIRY commands */
if (srb->cmnd[0] == INQUIRY) {
- memcpy(ptr, inquiry_response, 36);
+ 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);
+ 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
@@ -836,12 +912,14 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us)
// convert page to block and page-within-block
- lba = page>>4;
- page = page&0x0F;
+ lba = page >> info->blockshift;
+ page = page & info->blockmask;
// locate physical block corresponding to logical block
- if (lba>=(info->capacity>>13)) {
+ if (lba >=
+ (info->capacity >>
+ (info->pageshift + info->blockshift) ) ) {
// FIXME: sense buffer?
@@ -866,8 +944,8 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us)
pba, lba, page, pages);
return sddr09_read_data(us,
- ((pba<<4)+page)*info->pagesize, pages,
- ptr, srb->use_sg);
+ ( (pba << info->blockshift) + page) << info->pageshift,
+ pages, ptr, srb->use_sg);
}
// Pass TEST_UNIT_READY and REQUEST_SENSE through
diff --git a/drivers/usb/storage/sddr09.h b/drivers/usb/storage/sddr09.h
index ecd9b7611..ac984469f 100644
--- a/drivers/usb/storage/sddr09.h
+++ b/drivers/usb/storage/sddr09.h
@@ -1,7 +1,9 @@
/* Driver for SanDisk SDDR-09 SmartMedia reader
* Header File
*
- * Current development and maintainance by:
+ * $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
@@ -29,10 +31,14 @@
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 *lba_to_pba; /* logical to physical map */
- int *pba_to_lba; /* physical to logical map */
+ 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/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
index 492bc7259..6a96ad0a7 100644
--- a/drivers/usb/storage/shuttle_usbat.c
+++ b/drivers/usb/storage/shuttle_usbat.c
@@ -1,6 +1,6 @@
/* Driver for SCM Microsystems USB-ATAPI cable
*
- * $Id: shuttle_usbat.c,v 1.2 2000/08/03 00:03:39 groovyjava Exp $
+ * $Id: shuttle_usbat.c,v 1.4 2000/08/25 00:13:51 mdharm Exp $
*
* SCM driver v0.2:
*
@@ -14,7 +14,7 @@
*
* First release - hp8200e.
*
- * Current development and maintainance by:
+ * Current development and maintenance by:
* (c) 2000 Robert Baruch (autophile@dol.net)
*
* Many originally ATAPI devices were slightly modified to meet the USB
@@ -734,7 +734,7 @@ static int hp_8200e_select_and_test_registers(struct us_data *us) {
return result;
}
-static int init_8200e(struct us_data *us) {
+int init_8200e(struct us_data *us) {
int result;
unsigned char status;
@@ -895,11 +895,11 @@ int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us)
"XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* C0-DF */
"XDXXXXXXXXXXXXXX" "XXW00HXXXXXXXXXX"; /* E0-FF */
- if (us->flags & US_FL_NEED_INIT) {
+/* if (us->flags & US_FL_NEED_INIT) {
US_DEBUGP("8200e: initializing\n");
init_8200e(us);
us->flags &= ~US_FL_NEED_INIT;
- }
+ } */
len = srb->request_bufflen;
diff --git a/drivers/usb/storage/shuttle_usbat.h b/drivers/usb/storage/shuttle_usbat.h
index ff5c07541..4bd2673c6 100644
--- a/drivers/usb/storage/shuttle_usbat.h
+++ b/drivers/usb/storage/shuttle_usbat.h
@@ -1,9 +1,9 @@
/* Driver for SCM Microsystems USB-ATAPI cable
* Header File
*
- * $Id: shuttle_usbat.h,v 1.2 2000/08/03 00:03:39 groovyjava Exp $
+ * $Id: shuttle_usbat.h,v 1.4 2000/08/25 00:13:51 mdharm Exp $
*
- * Current development and maintainance by:
+ * Current development and maintenance by:
* (c) 2000 Robert Baruch (autophile@dol.net)
*
* See scm.c for more explanation
@@ -74,5 +74,6 @@ extern int usbat_write_user_io(struct us_data *us,
/* 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/storage/transport.c b/drivers/usb/storage/transport.c
index dd3c489f1..cad9253b3 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -1,8 +1,8 @@
/* Driver for USB Mass Storage compliant devices
*
- * $Id: transport.c,v 1.12 2000/08/08 15:22:38 gowdy Exp $
+ * $Id: transport.c,v 1.18 2000/08/25 00:13:51 mdharm Exp $
*
- * Current development and maintainance by:
+ * Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
* Developed with the assistance of:
@@ -59,43 +59,7 @@
/* Calculate the length of the data transfer (not the command) for any
* given SCSI command
*/
-static unsigned int us_transfer_length(Scsi_Cmnd *srb, struct us_data *us)
-{
- int i;
- unsigned int total = 0;
- struct scatterlist *sg;
-
- /* support those devices which need the length calculated
- * differently
- */
- if (srb->cmnd[0] == INQUIRY) {
- srb->cmnd[4] = 36;
- }
-
- if ((srb->cmnd[0] == INQUIRY) || (srb->cmnd[0] == MODE_SENSE))
- return srb->cmnd[4];
-
- if (srb->cmnd[0] == TEST_UNIT_READY)
- return 0;
-
- /* Are we going to scatter gather? */
- if (srb->use_sg) {
- /* Add up the sizes of all the scatter-gather segments */
- sg = (struct scatterlist *) srb->request_buffer;
- for (i = 0; i < srb->use_sg; i++)
- total += sg[i].length;
-
- return total;
- }
- else
- /* Just return the length of the buffer */
- return srb->request_bufflen;
-}
-
-/* Calculate the length of the data transfer (not the command) for any
- * given SCSI command
- */
-static unsigned int us_transfer_length_new(Scsi_Cmnd *srb, struct us_data *us)
+static unsigned int us_transfer_length(Scsi_Cmnd *srb)
{
int i;
int doDefault = 0;
@@ -245,10 +209,6 @@ static unsigned int us_transfer_length_new(Scsi_Cmnd *srb, struct us_data *us)
WRITE_SAME 41
*/
- /* Not sure this is right as an INQUIRY can contain nonstandard info */
- if (srb->cmnd[0] == INQUIRY)
- srb->cmnd[4] = 36;
-
if (srb->sc_data_direction == SCSI_DATA_WRITE) {
doDefault = 1;
}
@@ -611,6 +571,16 @@ static void us_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 = us_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) {
@@ -620,8 +590,19 @@ static void us_transfer(Scsi_Cmnd *srb, struct us_data* us)
*/
sg = (struct scatterlist *) srb->request_buffer;
for (i = 0; i < srb->use_sg; i++) {
- result = us_transfer_partial(us, sg[i].address,
- sg[i].length);
+
+ /* transfer the lesser of the next buffer or the
+ * remaining data */
+ if (transfer_amount - total_transferred >=
+ sg[i].length) {
+ result = us_transfer_partial(us, sg[i].address,
+ sg[i].length);
+ total_transferred += sg[i].length;
+ } else
+ result = us_transfer_partial(us, sg[i].address,
+ transfer_amount - total_transferred);
+
+ /* if we get an error, end the loop here */
if (result)
break;
}
@@ -629,7 +610,7 @@ static void us_transfer(Scsi_Cmnd *srb, struct us_data* us)
else
/* no scatter-gather, just make the request */
result = us_transfer_partial(us, srb->request_buffer,
- srb->request_bufflen);
+ transfer_amount);
/* return the result in the data structure itself */
srb->result = result;
@@ -874,7 +855,7 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
/* DATA STAGE */
/* transfer the data payload for this command, if one exists*/
- if (us_transfer_length(srb, us)) {
+ if (us_transfer_length(srb)) {
us_transfer(srb, us);
US_DEBUGP("CBI data stage result is 0x%x\n", srb->result);
@@ -975,7 +956,7 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
/* DATA STAGE */
/* transfer the data payload for this command, if one exists*/
- if (us_transfer_length(srb, us)) {
+ if (us_transfer_length(srb)) {
us_transfer(srb, us);
US_DEBUGP("CB data stage result is 0x%x\n", srb->result);
@@ -1039,10 +1020,12 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
/* set up the command wrapper */
bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN);
- bcb.DataTransferLength = cpu_to_le32(us_transfer_length(srb, us));
+ bcb.DataTransferLength = cpu_to_le32(us_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 */
@@ -1053,8 +1036,9 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
memcpy(bcb.CDB, srb->cmnd, bcb.Length);
/* send it to out endpoint */
- US_DEBUGP("Bulk command S 0x%x T 0x%x LUN %d L %d F %d CL %d\n",
- le32_to_cpu(bcb.Signature), bcb.Tag, bcb.Lun,
+ 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);
diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
index 4615569f3..3f300053d 100644
--- a/drivers/usb/storage/transport.h
+++ b/drivers/usb/storage/transport.h
@@ -1,9 +1,9 @@
/* Driver for USB Mass Storage compliant devices
* Transport Functions Header File
*
- * $Id: transport.h,v 1.8 2000/08/08 01:23:55 webbb Exp $
+ * $Id: transport.h,v 1.11 2000/08/25 00:13:51 mdharm Exp $
*
- * Current development and maintainance by:
+ * 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
@@ -41,8 +41,8 @@
#ifndef _TRANSPORT_H_
#define _TRANSPORT_H_
-#include <linux/config.h>
#include <linux/blk.h>
+#include <linux/config.h>
#include "usb.h"
#include "scsi.h"
@@ -60,6 +60,10 @@
#endif
#define US_PR_DPCM_USB 0xf0 /* Combination CB/SDDR09 */
+#ifdef CONFIG_USB_STORAGE_FREECOM
+#define US_PR_FREECOM 0xf1 /* Freecom */
+#endif
+
/*
* Bulk only data structures
*/
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 50ebddd6f..07f0598e5 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -1,8 +1,8 @@
/* Driver for USB Mass Storage compliant devices
*
- * $Id: usb.c,v 1.23 2000/08/08 20:46:45 mdharm Exp $
+ * $Id: usb.c,v 1.33 2000/08/25 00:13:51 mdharm Exp $
*
- * Current development and maintainance by:
+ * Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
* Developed with the assistance of:
@@ -43,7 +43,6 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/config.h>
#include "usb.h"
#include "scsiglue.h"
#include "transport.h"
@@ -58,12 +57,16 @@
#ifdef CONFIG_USB_STORAGE_DPCM
#include "dpcm.h"
#endif
+#ifdef CONFIG_USB_STORAGE_FREECOM
+#include "freecom.h"
+#endif
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/malloc.h>
+#include <linux/config.h>
/* Some informational data */
MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>");
@@ -213,8 +216,20 @@ static int usb_stor_control_thread(void * __us)
/* reject if target != 0 or if LUN is higher than
* the maximum known LUN
*/
- if (us->srb->target || (us->srb->lun > us->max_lun)) {
- US_DEBUGP("Bad device number (%d/%d)\n",
+ 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;
@@ -314,6 +329,19 @@ static int usb_stor_control_thread(void * __us)
* are free to use as many characters as you like.
*/
+int euscsi_init(struct us_data *us)
+{
+ unsigned char bar = 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, &bar, 0x1, 5*HZ);
+ US_DEBUGP("-- result is %d\n", result);
+ US_DEBUGP("-- bar afterwards is %d\n", bar);
+}
+
static struct us_unusual_dev us_unusual_dev_list[] = {
{ 0x03f0, 0x0107, 0x0200, 0x0200,
@@ -339,15 +367,61 @@ static struct us_unusual_dev us_unusual_dev_list[] = {
{ 0x04e6, 0x0002, 0x0100, 0x0100,
"Shuttle",
"eUSCSI Bridge",
- US_SC_SCSI, US_PR_BULK, NULL,
- 0 },
+ US_SC_SCSI, US_PR_BULK, euscsi_init,
+ US_FL_SCM_MULT_TARG },
+
+#ifdef CONFIG_USB_STORAGE_SDDR09
+ { 0x04e6, 0x0003, 0x0000, 0x9999,
+ "Sandisk",
+ "ImageMate SDDR09",
+ US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
+ US_FL_SINGLE_LUN | US_FL_START_STOP },
+#endif
+
+#ifdef CONFIG_USB_STORAGE_DPCM
+ { 0x0436, 0x0005, 0x0100, 0x0100,
+ "Microtech",
+ "CameraMate (DPCM_USB)",
+ US_SC_SCSI, US_PR_DPCM_USB, NULL,
+ US_FL_START_STOP },
+#endif
- { 0x04e6, 0x0006, 0x0100, 0x0100,
+ { 0x04e6, 0x0006, 0x0100, 0x0200,
"Shuttle",
"eUSB MMC Adapter",
US_SC_SCSI, US_PR_CB, NULL,
US_FL_SINGLE_LUN},
+ { 0x04e6, 0x0009, 0x0200, 0x0200,
+ "Shuttle",
+ "ATA/ATAPI Bridge",
+ US_SC_8020, US_PR_CB, NULL,
+ US_FL_SINGLE_LUN},
+
+ { 0x04e6, 0x000A, 0x0200, 0x0200,
+ "Shuttle",
+ "Compact Flash Reader",
+ US_SC_8020, US_PR_CB, NULL,
+ US_FL_SINGLE_LUN},
+
+ { 0x04e6, 0x000B, 0x0100, 0x0100,
+ "Shuttle",
+ "eUSCSI Bridge",
+ US_SC_SCSI, US_PR_BULK, euscsi_init,
+ US_FL_SCM_MULT_TARG },
+
+ { 0x04e6, 0x000C, 0x0100, 0x0100,
+ "Shuttle",
+ "eUSCSI Bridge",
+ US_SC_SCSI, US_PR_BULK, euscsi_init,
+ US_FL_SCM_MULT_TARG },
+
+ { 0x04e6, 0x0101, 0x0200, 0x0200,
+ "Shuttle",
+ "CD-RW Device",
+ US_SC_8020, US_PR_CB, NULL,
+ US_FL_SINGLE_LUN},
+
{ 0x054c, 0x0010, 0x0210, 0x0210,
"Sony",
"DSC-S30/S70",
@@ -372,6 +446,24 @@ static struct us_unusual_dev us_unusual_dev_list[] = {
US_SC_UFI, US_PR_CBI, NULL,
US_FL_SINGLE_LUN},
+ { 0x059f, 0xa601, 0x0200, 0x0200,
+ "LaCie",
+ "USB Hard Disk",
+ US_SC_RBC, US_PR_CB, NULL,
+ 0 },
+
+ { 0x05ab, 0x0031, 0x0100, 0x0100,
+ "In-System",
+ "USB/IDE Bridge",
+ US_SC_8070, US_PR_BULK, NULL,
+ 0 },
+
+ { 0x0693, 0x0005, 0x0100, 0x0100,
+ "Hagiwara",
+ "Flashgate",
+ US_SC_SCSI, US_PR_BULK, NULL,
+ 0 },
+
{ 0x0693, 0x0002, 0x0100, 0x0100,
"Hagiwara",
"FlashGate SmartMedia",
@@ -401,14 +493,21 @@ static struct us_unusual_dev us_unusual_dev_list[] = {
{ 0x07af, 0x0004, 0x0100, 0x0100,
"Microtech",
"USB-SCSI-DB25",
- US_SC_SCSI, US_PR_BULK, NULL,
- 0 },
+ US_SC_SCSI, US_PR_BULK, euscsi_init,
+ US_FL_SCM_MULT_TARG },
+
+#ifdef CONFIG_USB_STORAGE_FREECOM
+ { 0x07ab, 0xfc01, 0x0921, 0x0921,
+ "Freecom",
+ "USB-IDE",
+ US_SC_8070, US_PR_FREECOM, NULL, US_FL_SINGLE_LUN },
+#endif
- { 0x059f, 0xa601, 0x0200, 0x0200,
- "LaCie",
- "USB Hard Disk",
- US_SC_RBC, US_PR_CB, NULL,
- 0 },
+ { 0x07af, 0x0005, 0x0100, 0x0100,
+ "Microtech",
+ "USB-SCSI-HD50",
+ US_SC_SCSI, US_PR_BULK, euscsi_init,
+ US_FL_SCM_MULT_TARG },
#ifdef CONFIG_USB_STORAGE_DPCM
{ 0x07af, 0x0006, 0x0100, 0x0100,
@@ -417,25 +516,6 @@ static struct us_unusual_dev us_unusual_dev_list[] = {
US_SC_SCSI, US_PR_DPCM_USB, NULL,
US_FL_START_STOP },
#endif
-
- { 0x07af, 0x0005, 0x0100, 0x0100,
- "Microtech",
- "USB-SCSI-HD50",
- US_SC_SCSI, US_PR_BULK, NULL,
- 0 },
-
- { 0x05ab, 0x0031, 0x0100, 0x0100,
- "In-System",
- "USB/IDE Bridge",
- US_SC_8070, US_PR_BULK, NULL,
- 0 },
-
- { 0x0693, 0x0005, 0x0100, 0x0100,
- "Hagiwara",
- "Flashgate",
- US_SC_SCSI, US_PR_BULK, NULL,
- 0 },
-
{ 0 }
};
@@ -615,15 +695,10 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum)
/* set the interface -- STALL is an acceptable response here */
#ifdef CONFIG_USB_STORAGE_SDDR09
- if (protocol != US_PR_EUSB_SDDR09)
- result = usb_set_interface(dev,
- altsetting->bInterfaceNumber, 0);
- else
+ if (protocol == US_PR_EUSB_SDDR09)
result = usb_set_configuration(dev, 1);
-#else
- result = usb_set_interface(dev, altsetting->bInterfaceNumber, 0);
-#endif
- US_DEBUGP("Result from usb_set_interface is %d\n", result);
+
+ 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));
@@ -632,6 +707,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum)
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)) {
@@ -702,7 +778,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum)
/* Re-Initialize the device if it needs it */
if (unusual_dev && unusual_dev->initFunction)
- (*unusual_dev->initFunction)(ss);
+ (unusual_dev->initFunction)(ss);
} else {
/* New device -- allocate memory and initialize */
@@ -828,6 +904,15 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum)
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
default:
ss->transport_name = "Unknown";
@@ -909,7 +994,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum)
/* Just before we start our control thread, initialize
* the device if it needs initialization */
if (unusual_dev && unusual_dev->initFunction)
- (*unusual_dev->initFunction)(ss);
+ (unusual_dev->initFunction)(ss);
/* start up our control thread */
ss->pid = kernel_thread(usb_stor_control_thread, ss,
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index 435ad9777..38b0d420a 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -1,9 +1,9 @@
/* Driver for USB Mass Storage compliant devices
* Main Header File
*
- * $Id: usb.h,v 1.7 2000/08/15 00:06:38 mdharm Exp $
+ * $Id: usb.h,v 1.8 2000/08/25 00:13:51 mdharm Exp $
*
- * Current development and maintainance by:
+ * Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
* Initial work by: