You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							414 lines
						
					
					
						
							13 KiB
						
					
					
				
			
		
		
	
	
							414 lines
						
					
					
						
							13 KiB
						
					
					
				# --- SDE-COPYRIGHT-NOTE-BEGIN --- | 
						||
# This copyright note is auto-generated by ./scripts/Create-CopyPatch. | 
						||
# | 
						||
# Filename: package/.../linux26/adaptec-usbxchange.patch.disabled | 
						||
# Copyright (C) 2008 - 2010 The OpenSDE Project | 
						||
# Copyright (C) 2006 - 2008 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. | 
						||
# --- SDE-COPYRIGHT-NOTE-END --- | 
						||
 | 
						||
Support for the Adaptec USB*Xchange family of USB<->SCSI cables. | 
						||
 | 
						||
  - Rene Rebe <[email protected]> | 
						||
 | 
						||
--- 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.19/drivers/usb/storage/initializers.c.vanilla	2006-11-30 09:14:20.000000000 +0100 | 
						||
+++ linux-2.6.19/drivers/usb/storage/initializers.c	2006-11-30 09:14:55.000000000 +0100 | 
						||
@@ -91,3 +91,28 @@ | 
						||
  | 
						||
 	return (res ? -1 : 0); | 
						||
 } | 
						||
+ | 
						||
+/* Firmware Initialisation for the Adaptec USB2Xchange, needed for | 
						||
+ * to recognize devices properly. Ren<EFBFBD> Rebe <[email protected]> */ | 
						||
+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 | 
						||
@@ -48,2 +48,5 @@ | 
						||
  * flash reader */ | 
						||
 int usb_stor_ucr61s2b_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 <[email protected]> */ | 
						||
+ | 
						||
+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 <[email protected]> | 
						||
+ * | 
						||
+ * Initial work by: | 
						||
+ *   (c) 2004 Beier & Dauskardt IT <[email protected]> | 
						||
+ * | 
						||
+ * Based on emi26.c: | 
						||
+ *   (c) 2002 Tapio Laxstr<EFBFBD>m <[email protected]> | 
						||
+ * | 
						||
+ * 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 <[email protected]>, Sancho Dauskardt <[email protected]>"); | 
						||
+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 <[email protected]> | 
						||
+ * | 
						||
+ * Initial work by: | 
						||
+ *   (c) 2004 Beier & Dauskardt IT <[email protected]> | 
						||
+ * | 
						||
+ * Based on emi26.c: | 
						||
+ *   (c) 2002 Tapio Laxstr<EFBFBD>m <[email protected]> | 
						||
+ * | 
						||
+ * 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 | 
						||
--- ./drivers/usb/storage/transport.c~	2008-10-10 00:13:53.000000000 +0200 | 
						||
+++ ./drivers/usb/storage/transport.c	2008-10-17 10:14:01.000000000 +0200 | 
						||
@@ -925,6 +925,11 @@ | 
						||
 	bcb->Lun = srb->device->lun; | 
						||
 	if (us->fflags & 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 */ | 
						||
@@ -1008,6 +1013,22 @@ | 
						||
 	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 || (us->fflags & US_FL_BULK_IGNORE_TAG)) || | 
						||
 		bcs->Status > US_BULK_STAT_PHASE) { | 
						||
 		US_DEBUGP("Bulk logical error\n");
 | 
						||
 |