|
|
|
|
# --- T2-COPYRIGHT-NOTE-BEGIN ---
|
|
|
|
|
# This copyright note is auto-generated by ./scripts/Create-CopyPatch.
|
|
|
|
|
#
|
|
|
|
|
# T2 SDE: package/.../linux26/adaptec-usbxchange.patch
|
|
|
|
|
# Copyright (C) 2006 The T2 SDE Project
|
|
|
|
|
#
|
|
|
|
|
# More information can be found in the files COPYING and README.
|
|
|
|
|
#
|
|
|
|
|
# This patch file is dual-licensed. It is available under the license the
|
|
|
|
|
# patched project is licensed under, as long as it is an OpenSource license
|
|
|
|
|
# as defined at http://www.opensource.org/ (e.g. BSD, X11) or 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.
|
|
|
|
|
# --- T2-COPYRIGHT-NOTE-END ---
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Support for the Adaptec USB*Xchange family of USB<->SCSI cables.
|
|
|
|
|
|
|
|
|
|
- Rene Rebe <rene@exactcode.de>
|
|
|
|
|
|
|
|
|
|
--- linux-2.6.15-mm4/drivers/usb/storage/Kconfig 2006-01-30 12:16:10.838447250 +0100
|
|
|
|
|
+++ linux-2.6.15-usb2x/drivers/usb/storage/Kconfig 2006-01-30 12:09:28.857325000 +0100
|
|
|
|
|
@@ -134,6 +134,13 @@
|
|
|
|
|
this input in any keybinding software. (e.g. gnome's keyboard short-
|
|
|
|
|
cuts)
|
|
|
|
|
|
|
|
|
|
+config USB_USBXCHANGE
|
|
|
|
|
+ tristate "Adaptec USBXchange and USB2Xchange firmware loader"
|
|
|
|
|
+ depends on USB_STORAGE
|
|
|
|
|
+ help
|
|
|
|
|
+ Say Y here to include additional code to load the firmware into the
|
|
|
|
|
+ Adaptec USBXchange and USB2Xchange USB --> SCSI converter dongle.
|
|
|
|
|
+
|
|
|
|
|
config USB_LIBUSUAL
|
|
|
|
|
bool "The shared table of common (or usual) storage devices"
|
|
|
|
|
depends on USB
|
|
|
|
|
--- linux-2.6.15-mm4/drivers/usb/storage/Makefile 2006-01-30 12:16:10.838447250 +0100
|
|
|
|
|
+++ linux-2.6.15-usb2x/drivers/usb/storage/Makefile 2006-01-30 12:08:29.781633000 +0100
|
|
|
|
|
@@ -24,6 +24,8 @@
|
|
|
|
|
usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \
|
|
|
|
|
initializers.o $(usb-storage-obj-y)
|
|
|
|
|
|
|
|
|
|
+obj-$(CONFIG_USB_USBXCHANGE) += usbxchange_fw.o
|
|
|
|
|
+
|
|
|
|
|
ifneq ($(CONFIG_USB_LIBUSUAL),)
|
|
|
|
|
obj-$(CONFIG_USB) += libusual.o
|
|
|
|
|
endif
|
|
|
|
|
--- linux-2.6.15-mm4/drivers/usb/storage/initializers.c 2006-01-30 12:16:10.826446500 +0100
|
|
|
|
|
+++ linux-2.6.15-usb2x/drivers/usb/storage/initializers.c 2006-01-30 12:08:09.340355500 +0100
|
|
|
|
|
@@ -164,3 +164,27 @@
|
|
|
|
|
return USB_STOR_TRANSPORT_FAILED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+/* Firmware Initialisation for the Adaptec USB2Xchange, needed for
|
|
|
|
|
+ * to recognize devices properly. Ren<EFBFBD> Rebe <rene@exactcode.de> */
|
|
|
|
|
+int usb2xchange_init(struct us_data *us)
|
|
|
|
|
+{
|
|
|
|
|
+ int result;
|
|
|
|
|
+
|
|
|
|
|
+ US_DEBUGP ("usb2xchange_init: initialising after reenumeration.\n");
|
|
|
|
|
+
|
|
|
|
|
+ result = usb_control_msg(us->pusb_dev, us->send_ctrl_pipe,
|
|
|
|
|
+ 0x5a, 0x40, 0x01,
|
|
|
|
|
+ 0, 0, // buffer,
|
|
|
|
|
+ 0, // length,
|
|
|
|
|
+ 300);
|
|
|
|
|
+ US_DEBUGP ("usb2xchange_init: reset #1 (%d)\n", result);
|
|
|
|
|
+
|
|
|
|
|
+ result = usb_control_msg(us->pusb_dev, us->send_ctrl_pipe,
|
|
|
|
|
+ 0x5a, 0x40, 0x02,
|
|
|
|
|
+ 0, 0, // buffer,
|
|
|
|
|
+ 0, // length,
|
|
|
|
|
+ 300);
|
|
|
|
|
+ US_DEBUGP ("usb2xchange_init: reset #2 (%d)\n", result);
|
|
|
|
|
+
|
|
|
|
|
+ return result;
|
|
|
|
|
+}
|
|
|
|
|
--- linux-2.6.15-mm4/drivers/usb/storage/initializers.h 2006-01-30 12:16:10.826446500 +0100
|
|
|
|
|
+++ linux-2.6.15-usb2x/drivers/usb/storage/initializers.h 2006-01-30 12:04:35.110967000 +0100
|
|
|
|
|
@@ -49,3 +49,6 @@
|
|
|
|
|
* flash reader */
|
|
|
|
|
int usb_stor_ucr61s2b_init(struct us_data *us);
|
|
|
|
|
int rio_karma_init(struct us_data *us);
|
|
|
|
|
+
|
|
|
|
|
+/* Firmware Initialization for the Adaptec USB2Xchange */
|
|
|
|
|
+int usb2xchange_init(struct us_data *us);
|
|
|
|
|
--- linux-2.6.15-mm4/drivers/usb/storage/unusual_devs.h 2006-01-30 12:16:10.870449250 +0100
|
|
|
|
|
+++ linux-2.6.15-usb2x/drivers/usb/storage/unusual_devs.h 2006-01-27 21:49:46.570867000 +0100
|
|
|
|
|
@@ -1180,6 +1180,21 @@
|
|
|
|
|
US_FL_SINGLE_LUN),
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
+/* Adaptec USBXchange and USB2Xchange, after firmware download.
|
|
|
|
|
+ * Requires Ez-USB Style firmware loader. Ren<EFBFBD> Rebe <rene@exactcode.de> */
|
|
|
|
|
+
|
|
|
|
|
+UNUSUAL_DEV( 0x03f3, 0x2001, 0x0000, 0xffff,
|
|
|
|
|
+ "Adaptec",
|
|
|
|
|
+ "USBXchange",
|
|
|
|
|
+ US_SC_SCSI, US_PR_BULK, NULL,
|
|
|
|
|
+ 0 ),
|
|
|
|
|
+
|
|
|
|
|
+UNUSUAL_DEV( 0x03f3, 0x2003, 0x0000, 0xffff,
|
|
|
|
|
+ "Adaptec",
|
|
|
|
|
+ "USB2Xchange",
|
|
|
|
|
+ US_SC_SCSI, US_PR_BULK, usb2xchange_init,
|
|
|
|
|
+ US_FL_SCM_MULT_TARG ),
|
|
|
|
|
+
|
|
|
|
|
/* Control/Bulk transport for all SubClass values */
|
|
|
|
|
USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR),
|
|
|
|
|
USUAL_DEV(US_SC_8020, US_PR_CB, USB_US_TYPE_STOR),
|
|
|
|
|
--- linux-2.6.15-mm4/drivers/usb/storage/usbxchange_fw.c 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
+++ linux-2.6.15-usb2x/drivers/usb/storage/usbxchange_fw.c 2006-01-28 09:45:14.308438000 +0100
|
|
|
|
|
@@ -0,0 +1,215 @@
|
|
|
|
|
+/*
|
|
|
|
|
+ * Firmware loader for Adaptec USBXchange / USB2Xchange.
|
|
|
|
|
+ *
|
|
|
|
|
+ * Uploads device firmware into the Adaptec USBXchange and USB2Xchange
|
|
|
|
|
+ * USB --> SCSI dongle.
|
|
|
|
|
+ *
|
|
|
|
|
+ * Current development and maintenance by:
|
|
|
|
|
+ * (c) 2005 Ren<EFBFBD> Rebe <rene@exactcode.de>
|
|
|
|
|
+ *
|
|
|
|
|
+ * Initial work by:
|
|
|
|
|
+ * (c) 2004 Beier & Dauskardt IT <sda@bdit.de>
|
|
|
|
|
+ *
|
|
|
|
|
+ * Based on emi26.c:
|
|
|
|
|
+ * (c) 2002 Tapio Laxstr<EFBFBD>m <tapio.laxstrom@iptime.fi>
|
|
|
|
|
+ *
|
|
|
|
|
+ * To use this driver, you need to get the devices firmware from some
|
|
|
|
|
+ * windows driver:
|
|
|
|
|
+ * usbxchg_win_v120.exe - for USBXchange
|
|
|
|
|
+ * usb2xchg_win_drv_v200.exe - for USB2Xchange
|
|
|
|
|
+ *
|
|
|
|
|
+ * Hotplug firmware loader compatible files can be found at:
|
|
|
|
|
+ * http://dl.exactcode.de/adaptec-usbxchange/
|
|
|
|
|
+ *
|
|
|
|
|
+ * Note:
|
|
|
|
|
+ * The USB2Xchange seems to have some internal buffer < 64K.
|
|
|
|
|
+ * Sending 64K requests crashes the device. Possibly it needs a
|
|
|
|
|
+ * "max_sectors: 8" setting.
|
|
|
|
|
+ *
|
|
|
|
|
+ * 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.
|
|
|
|
|
+ *
|
|
|
|
|
+ * 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, version 2.
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+#include <linux/kernel.h>
|
|
|
|
|
+#include <linux/errno.h>
|
|
|
|
|
+#include <linux/slab.h>
|
|
|
|
|
+#include <linux/module.h>
|
|
|
|
|
+#include <linux/init.h>
|
|
|
|
|
+#include <linux/usb.h>
|
|
|
|
|
+#include <linux/firmware.h>
|
|
|
|
|
+
|
|
|
|
|
+#include "usbxchange_fw.h"
|
|
|
|
|
+
|
|
|
|
|
+static int usbxchange_writememory(struct usb_device *dev, int address,
|
|
|
|
|
+ unsigned char *data, int length,
|
|
|
|
|
+ __u8 bRequest);
|
|
|
|
|
+static int usbxchange_set_reset(struct usb_device *dev, int cpureg,
|
|
|
|
|
+ unsigned char reset_bit);
|
|
|
|
|
+static int usbxchange_load_firmware(struct usb_device *dev);
|
|
|
|
|
+
|
|
|
|
|
+static int usbxchange_probe(struct usb_interface *iface,
|
|
|
|
|
+ const struct usb_device_id *id);
|
|
|
|
|
+static void usbxchange_disconnect(struct usb_interface *iface);
|
|
|
|
|
+static int __init usbxchange_init(void);
|
|
|
|
|
+static void __exit usbxchange_exit(void);
|
|
|
|
|
+
|
|
|
|
|
+#define usbxchange_VENDOR_ID 0x03f3
|
|
|
|
|
+#define usbxchange_PRODUCT_ID 0x2000
|
|
|
|
|
+#define usb2xchange_PRODUCT_ID 0x2002
|
|
|
|
|
+
|
|
|
|
|
+static struct usb_device_id usbxchange_usb_ids[] = {
|
|
|
|
|
+ {USB_DEVICE(usbxchange_VENDOR_ID, usbxchange_PRODUCT_ID)},
|
|
|
|
|
+ {USB_DEVICE(usbxchange_VENDOR_ID, usb2xchange_PRODUCT_ID)},
|
|
|
|
|
+ {} /* terminating entry */
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+MODULE_DEVICE_TABLE(usb, usbxchange_usb_ids);
|
|
|
|
|
+
|
|
|
|
|
+/* thanks to drivers/usb/serial/keyspan_pda.c code */
|
|
|
|
|
+static int usbxchange_writememory(struct usb_device *dev, int address,
|
|
|
|
|
+ unsigned char *data, int length, __u8 request)
|
|
|
|
|
+{
|
|
|
|
|
+ int result;
|
|
|
|
|
+ unsigned char *buffer = kmalloc(length, GFP_KERNEL);
|
|
|
|
|
+
|
|
|
|
|
+ if (!buffer) {
|
|
|
|
|
+ printk(KERN_ERR "usbxchange: kmalloc(%d) failed.\n", length);
|
|
|
|
|
+ return -ENOMEM;
|
|
|
|
|
+ }
|
|
|
|
|
+ memcpy(buffer, data, length);
|
|
|
|
|
+ result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request, 0x40,
|
|
|
|
|
+ address, 0, buffer, length, 300);
|
|
|
|
|
+ kfree(buffer);
|
|
|
|
|
+ return result;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* thanks to drivers/usb/serial/keyspan_pda.c code */
|
|
|
|
|
+static int usbxchange_set_reset(struct usb_device *dev, int cpureg,
|
|
|
|
|
+ unsigned char reset_bit)
|
|
|
|
|
+{
|
|
|
|
|
+ int response;
|
|
|
|
|
+ printk(KERN_INFO "%s - %d\n", __FUNCTION__, reset_bit);
|
|
|
|
|
+ response =
|
|
|
|
|
+ usbxchange_writememory(dev, cpureg, &reset_bit, 1,
|
|
|
|
|
+ ANCHOR_LOAD_INTERNAL);
|
|
|
|
|
+ if (response < 0) {
|
|
|
|
|
+ printk(KERN_ERR "usbxchange: set_reset (%d) failed\n",
|
|
|
|
|
+ reset_bit);
|
|
|
|
|
+ }
|
|
|
|
|
+ return response;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int usbxchange_load_firmware(struct usb_device *dev)
|
|
|
|
|
+{
|
|
|
|
|
+ INTEL_HEX_RECORD *record;
|
|
|
|
|
+ int err, cpureg;
|
|
|
|
|
+
|
|
|
|
|
+ const struct firmware *firmware;
|
|
|
|
|
+
|
|
|
|
|
+ switch (le16_to_cpu(dev->descriptor.idProduct)) {
|
|
|
|
|
+ case usbxchange_PRODUCT_ID:
|
|
|
|
|
+ err = request_firmware(&firmware, "usbxchange.fw", &dev->dev);
|
|
|
|
|
+ cpureg = CPUCS_REG;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case usb2xchange_PRODUCT_ID:
|
|
|
|
|
+ err = request_firmware(&firmware, "usb2xchange.fw", &dev->dev);
|
|
|
|
|
+ cpureg = CPUCS_REG_FX2;
|
|
|
|
|
+ break;
|
|
|
|
|
+ default:
|
|
|
|
|
+ printk(KERN_ERR "%s - device not recognized %x\n", __FUNCTION__,
|
|
|
|
|
+ le16_to_cpu(dev->descriptor.idProduct));
|
|
|
|
|
+ return 1;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (err != 0) {
|
|
|
|
|
+ printk(KERN_ERR "Hotplug firmware request failed.\n");
|
|
|
|
|
+ return err;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* Stop CPU */
|
|
|
|
|
+ err = usbxchange_set_reset(dev, cpureg, 1);
|
|
|
|
|
+ err = usbxchange_set_reset(dev, cpureg, 1);
|
|
|
|
|
+ if (err < 0) {
|
|
|
|
|
+ printk(KERN_ERR "%s - error stopping dongle CPU: error = %d\n",
|
|
|
|
|
+ __FUNCTION__, err);
|
|
|
|
|
+ return err;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* Upload firmware */
|
|
|
|
|
+ for (record = (INTEL_HEX_RECORD *)firmware->data;
|
|
|
|
|
+ record->type == 0; record++) {
|
|
|
|
|
+
|
|
|
|
|
+ err = usbxchange_writememory(dev, le32_to_cpu(record->address),
|
|
|
|
|
+ record->data,
|
|
|
|
|
+ le32_to_cpu(record->length),
|
|
|
|
|
+ ANCHOR_LOAD_INTERNAL);
|
|
|
|
|
+ if (err < 0) {
|
|
|
|
|
+ printk(KERN_ERR
|
|
|
|
|
+ "%s - error loading firmware: error = %d\n",
|
|
|
|
|
+ __FUNCTION__, err);
|
|
|
|
|
+ return err;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* De-assert reset (let the CPU run) */
|
|
|
|
|
+ err = usbxchange_set_reset(dev, cpureg, 1);
|
|
|
|
|
+ err = usbxchange_set_reset(dev, cpureg, 0);
|
|
|
|
|
+ if (err < 0) {
|
|
|
|
|
+ printk(KERN_ERR "%s - error resetting dongle CPU: error = %d\n",
|
|
|
|
|
+ __FUNCTION__, err);
|
|
|
|
|
+ return err;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int usbxchange_probe(struct usb_interface *iface,
|
|
|
|
|
+ const struct usb_device_id *id)
|
|
|
|
|
+{
|
|
|
|
|
+ struct usb_device *dev = interface_to_usbdev(iface);
|
|
|
|
|
+
|
|
|
|
|
+ printk(KERN_INFO "%s start\n", __FUNCTION__);
|
|
|
|
|
+
|
|
|
|
|
+ usbxchange_load_firmware(dev);
|
|
|
|
|
+
|
|
|
|
|
+ /* forcing an unload would save some kB of kernel memory ... */
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void usbxchange_disconnect(struct usb_interface *iface)
|
|
|
|
|
+{
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static struct usb_driver usbxchange_driver = {
|
|
|
|
|
+ .name = "usbxchange_fw",
|
|
|
|
|
+ .probe = usbxchange_probe,
|
|
|
|
|
+ .disconnect = usbxchange_disconnect,
|
|
|
|
|
+ .id_table = usbxchange_usb_ids,
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+static int __init usbxchange_init(void)
|
|
|
|
|
+{
|
|
|
|
|
+ usb_register(&usbxchange_driver);
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void __exit usbxchange_exit(void)
|
|
|
|
|
+{
|
|
|
|
|
+ usb_deregister(&usbxchange_driver);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+module_init(usbxchange_init);
|
|
|
|
|
+module_exit(usbxchange_exit);
|
|
|
|
|
+
|
|
|
|
|
+MODULE_AUTHOR("Ren<EFBFBD> Rebe <rene@exactcode.de>, Sancho Dauskardt <sda@bdit.de>");
|
|
|
|
|
+MODULE_DESCRIPTION("Adaptec USBXchange firmware loader.");
|
|
|
|
|
+MODULE_LICENSE("GPL");
|
|
|
|
|
+
|
|
|
|
|
+/* vi:ai:syntax=c:sw=8:ts=8:tw=80
|
|
|
|
|
+ */
|
|
|
|
|
--- linux-2.6.15-mm4/drivers/usb/storage/usbxchange_fw.h 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
+++ linux-2.6.15-usb2x/drivers/usb/storage/usbxchange_fw.h 2006-01-27 17:18:18.246377000 +0100
|
|
|
|
|
@@ -0,0 +1,45 @@
|
|
|
|
|
+/*
|
|
|
|
|
+ * Firmware loader for Adaptec USBXchange / USB2Xchange.
|
|
|
|
|
+ *
|
|
|
|
|
+ * Uploads device firmware into the Adaptec USBXchange and USB2Xchange
|
|
|
|
|
+ * USB --> SCSI dongle.
|
|
|
|
|
+ *
|
|
|
|
|
+ * Current development and maintenance by:
|
|
|
|
|
+ * (c) 2005 Ren<EFBFBD> Rebe <rene@exactcode.de>
|
|
|
|
|
+ *
|
|
|
|
|
+ * Initial work by:
|
|
|
|
|
+ * (c) 2004 Beier & Dauskardt IT <sda@bdit.de>
|
|
|
|
|
+ *
|
|
|
|
|
+ * Based on emi26.c:
|
|
|
|
|
+ * (c) 2002 Tapio Laxstr<EFBFBD>m <tapio.laxstrom@iptime.fi>
|
|
|
|
|
+ *
|
|
|
|
|
+ * 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.
|
|
|
|
|
+ *
|
|
|
|
|
+ * 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, version 2.
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+#ifndef _USB_USBXCHANGE_FW_H_INCLUDED
|
|
|
|
|
+#define _USB_USBXCHANGE_FW_H_INCLUDED
|
|
|
|
|
+
|
|
|
|
|
+#define MAX_INTEL_HEX_RECORD_LENGTH 16
|
|
|
|
|
+typedef struct _INTEL_HEX_RECORD {
|
|
|
|
|
+ __u32 length;
|
|
|
|
|
+ __u32 address;
|
|
|
|
|
+ __u32 type;
|
|
|
|
|
+ __u8 data[MAX_INTEL_HEX_RECORD_LENGTH];
|
|
|
|
|
+} INTEL_HEX_RECORD, *PINTEL_HEX_RECORD;
|
|
|
|
|
+
|
|
|
|
|
+/* Vendor specific request code for Anchor Upload/Download
|
|
|
|
|
+ (This one is implemented in the core). */
|
|
|
|
|
+#define ANCHOR_LOAD_INTERNAL 0xA0
|
|
|
|
|
+
|
|
|
|
|
+/* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */
|
|
|
|
|
+#define CPUCS_REG 0x7F92 /* original / FX */
|
|
|
|
|
+#define CPUCS_REG_FX2 0xE600 /* FX2 */
|
|
|
|
|
+
|
|
|
|
|
+#endif
|
|
|
|
|
--- linux-2.6.15/drivers/usb/storage/transport.c 2006-01-03 04:21:10.000000000 +0100
|
|
|
|
|
+++ ./drivers/usb/storage/transport.c 2006-01-30 19:41:26.727402000 +0100
|
|
|
|
|
@@ -984,6 +984,11 @@
|
|
|
|
|
bcb->Lun = srb->device->lun;
|
|
|
|
|
if (us->flags & US_FL_SCM_MULT_TARG)
|
|
|
|
|
bcb->Lun |= srb->device->id << 4;
|
|
|
|
|
+ /* Adaptec USB2Xchange */
|
|
|
|
|
+ if (us->pusb_dev->descriptor.idVendor == 0x03f3 &&
|
|
|
|
|
+ us->pusb_dev->descriptor.idProduct == 0x2003)
|
|
|
|
|
+ bcb->Lun = srb->device->id;
|
|
|
|
|
+
|
|
|
|
|
bcb->Length = srb->cmd_len;
|
|
|
|
|
|
|
|
|
|
/* copy the command payload */
|
|
|
|
|
@@ -1069,6 +1074,20 @@
|
|
|
|
|
US_DEBUGP("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n",
|
|
|
|
|
le32_to_cpu(bcs->Signature), bcs->Tag,
|
|
|
|
|
residue, bcs->Status);
|
|
|
|
|
+ if (bcs->Status > US_BULK_STAT_FAIL) {
|
|
|
|
|
+ /* Adaptec USB2XCHANGE ? */
|
|
|
|
|
+ if (us->pusb_dev->descriptor.idVendor == 0x03f3 &&
|
|
|
|
|
+ us->pusb_dev->descriptor.idProduct == 0x2003) {
|
|
|
|
|
+
|
|
|
|
|
+ /* This device will send
|
|
|
|
|
+ * bcs->Status == 0x8a for unused LUN's
|
|
|
|
|
+ * bcs->Status == 0x02 for SRB's that require SENSE.
|
|
|
|
|
+ */
|
|
|
|
|
+ bcs->Status = US_BULK_STAT_OK;
|
|
|
|
|
+ fake_sense = 1;
|
|
|
|
|
+ US_DEBUGP("Patched Bulk status to %d.\n", bcs->Status);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
if (bcs->Tag != us->tag || bcs->Status > US_BULK_STAT_PHASE) {
|
|
|
|
|
US_DEBUGP("Bulk logical error\n");
|
|
|
|
|
return USB_STOR_TRANSPORT_ERROR;
|