Dash:
[t2-trunk.git] / architecture / riscv / package / linux / adaptec-usbxchange.patch
blobbb38752ce6f12e260c2fe3031c075989d9dceebf
1 # --- T2-COPYRIGHT-NOTE-BEGIN ---
2 # This copyright note is auto-generated by scripts/Create-CopyPatch.
3 #
4 # T2 SDE: architecture/riscv/package/*/adaptec-usbxchange.patch
5 # Copyright (C) 2006 - 2021 The T2 SDE Project
6 #
7 # More information can be found in the files COPYING and README.
8 #
9 # This patch file is dual-licensed. It is available under the license the
10 # patched project is licensed under, as long as it is an OpenSource license
11 # as defined at http://www.opensource.org/ (e.g. BSD, X11) or under the terms
12 # of the GNU General Public License as published by the Free Software
13 # Foundation; either version 2 of the License, or (at your option) any later
14 # version.
15 # --- T2-COPYRIGHT-NOTE-END ---
17 Support for the Adaptec USB*Xchange family of USB<->SCSI cables.
19 - Rene Rebe <rene@exactcode.de>
21 --- ./drivers/usb/storage/Kconfig.orig 2015-05-21 11:36:32.350907684 +0200
22 +++ ./drivers/usb/storage/Kconfig 2015-05-21 11:42:06.774892238 +0200
23 @@ -200,6 +200,13 @@
24 To compile this driver as a module, choose M here: the
25 module will be called ums-eneub6250.
27 +config USB_USBXCHANGE
28 + tristate "Adaptec USBXchange and USB2Xchange firmware loader"
29 + depends on USB_STORAGE
30 + help
31 + Say Y here to include additional code to load the firmware into the
32 + Adaptec USBXchange and USB2Xchange USB --> SCSI converter dongle.
34 config USB_UAS
35 tristate "USB Attached SCSI"
36 depends on SCSI && USB_STORAGE
37 --- ./drivers/usb/storage/Makefile.orig 2015-05-21 11:36:32.350907684 +0200
38 +++ ./drivers/usb/storage/Makefile 2015-05-21 11:43:33.182888247 +0200
39 @@ -28,6 +28,7 @@
40 obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o
41 obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o
42 obj-$(CONFIG_USB_STORAGE_USBAT) += ums-usbat.o
43 +obj-$(CONFIG_USB_USBXCHANGE) += usbxchange_fw.o
45 ums-alauda-y := alauda.o
46 ums-cypress-y := cypress_atacb.o
47 --- ./drivers/usb/storage/initializers.c.orig 2015-04-13 00:12:50.000000000 +0200
48 +++ ./drivers/usb/storage/initializers.c 2015-05-21 12:16:15.790797598 +0200
49 @@ -103,3 +103,28 @@
50 usb_stor_dbg(us, "Huawei mode set result is %d\n", result);
51 return 0;
54 +/* Firmware Initialisation for the Adaptec USB2Xchange, needed for
55 + * to recognize devices properly. René Rebe <rene@exactcode.de> */
56 +int usb2xchange_init(struct us_data *us)
58 + int result;
60 + usb_stor_dbg(us, "usb2xchange_init: initialising after reenumeration.\n");
62 + result = usb_control_msg(us->pusb_dev, us->send_ctrl_pipe,
63 + 0x5a, 0x40, 0x01,
64 + 0, 0, // buffer,
65 + 0, // length,
66 + 300);
67 + usb_stor_dbg(us, "usb2xchange_init: reset #1 (%d)\n", result);
69 + result = usb_control_msg(us->pusb_dev, us->send_ctrl_pipe,
70 + 0x5a, 0x40, 0x02,
71 + 0, 0, // buffer,
72 + 0, // length,
73 + 300);
74 + usb_stor_dbg(us, "usb2xchange_init: reset #2 (%d)\n", result);
76 + return result;
78 --- ./drivers/usb/storage/initializers.h.orig 2015-04-13 00:12:50.000000000 +0200
79 +++ ./drivers/usb/storage/initializers.h 2015-05-21 11:36:32.350907684 +0200
80 @@ -47,4 +47,7 @@
81 int usb_stor_ucr61s2b_init(struct us_data *us);
83 /* This places the HUAWEI E220 devices in multi-port mode */
85 +/* Firmware Initialization for the Adaptec USB2Xchange */
86 +int usb2xchange_init(struct us_data *us);
87 int usb_stor_huawei_e220_init(struct us_data *us);
88 --- ./drivers/usb/storage/unusual_devs.h.orig 2015-04-13 00:12:50.000000000 +0200
89 +++ ./drivers/usb/storage/unusual_devs.h 2015-05-21 11:36:32.354907684 +0200
90 @@ -2183,6 +2183,21 @@
91 #include "unusual_uas.h"
92 #endif
94 +/* Adaptec USBXchange and USB2Xchange, after firmware download.
95 + * Requires Ez-USB Style firmware loader. René Rebe <rene@exactcode.de> */
97 +UNUSUAL_DEV( 0x03f3, 0x2001, 0x0000, 0xffff,
98 + "Adaptec",
99 + "USBXchange",
100 + USB_SC_SCSI, USB_PR_BULK, NULL,
101 + 0 ),
103 +UNUSUAL_DEV( 0x03f3, 0x2003, 0x0000, 0xffff,
104 + "Adaptec",
105 + "USB2Xchange",
106 + USB_SC_SCSI, USB_PR_BULK, usb2xchange_init,
107 + US_FL_SCM_MULT_TARG ),
109 /* Control/Bulk transport for all SubClass values */
110 USUAL_DEV(USB_SC_RBC, USB_PR_CB),
111 USUAL_DEV(USB_SC_8020, USB_PR_CB),
112 --- ./drivers/usb/storage/transport.c.orig 2015-04-13 00:12:50.000000000 +0200
113 +++ ./drivers/usb/storage/transport.c 2015-05-21 11:56:00.986853707 +0200
114 @@ -1086,6 +1086,11 @@
115 bcb->Lun = srb->device->lun;
116 if (us->fflags & US_FL_SCM_MULT_TARG)
117 bcb->Lun |= srb->device->id << 4;
118 + /* Adaptec USB2Xchange */
119 + if (us->pusb_dev->descriptor.idVendor == 0x03f3 &&
120 + us->pusb_dev->descriptor.idProduct == 0x2003)
121 + bcb->Lun = srb->device->id;
123 bcb->Length = srb->cmd_len;
125 /* copy the command payload */
126 @@ -1195,6 +1200,20 @@
127 usb_stor_dbg(us, "Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n",
128 le32_to_cpu(bcs->Signature), bcs->Tag,
129 residue, bcs->Status);
131 + if (bcs->Status > US_BULK_STAT_FAIL) {
132 + /* Adaptec USB2XCHANGE ? */
133 + if (us->pusb_dev->descriptor.idVendor == 0x03f3 &&
134 + us->pusb_dev->descriptor.idProduct == 0x2003) {
135 + /* This device will send
136 + * bcs->Status == 0x8a for unused LUN's
137 + * bcs->Status == 0x02 for SRB's that require SENSE. */
138 + bcs->Status = US_BULK_STAT_OK;
139 + fake_sense = 1;
140 + usb_stor_dbg(us, "Patched Bulk status to %d.\n", bcs->Status);
144 if (!(bcs->Tag == us->tag || (us->fflags & US_FL_BULK_IGNORE_TAG)) ||
145 bcs->Status > US_BULK_STAT_PHASE) {
146 usb_stor_dbg(us, "Bulk logical error\n");
147 --- ./drivers/usb/storage/usbxchange_fw.h.orig 2015-05-22 12:17:12.815229404 +0200
148 +++ ./drivers/usb/storage/usbxchange_fw.h 2015-05-21 11:36:32.354907684 +0200
149 @@ -0,0 +1,45 @@
150 +/*
151 + * Firmware loader for Adaptec USBXchange / USB2Xchange.
153 + * Uploads device firmware into the Adaptec USBXchange and USB2Xchange
154 + * USB --> SCSI dongle.
156 + * Current development and maintenance by:
157 + * (c) 2005 René Rebe <rene@exactcode.de>
159 + * Initial work by:
160 + * (c) 2004 Beier & Dauskardt IT <sda@bdit.de>
162 + * Based on emi26.c:
163 + * (c) 2002 Tapio Laxström <tapio.laxstrom@iptime.fi>
165 + * This program is distributed in the hope that it will be useful, but
166 + * WITHOUT ANY WARRANTY; without even the implied warranty of
167 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
168 + * General Public License for more details.
170 + * This program is free software; you can redistribute it and/or modify
171 + * it under the terms of the GNU General Public License, as published by
172 + * the Free Software Foundation, version 2.
173 + */
175 +#ifndef _USB_USBXCHANGE_FW_H_INCLUDED
176 +#define _USB_USBXCHANGE_FW_H_INCLUDED
178 +#define MAX_INTEL_HEX_RECORD_LENGTH 16
179 +typedef struct _INTEL_HEX_RECORD {
180 + __u32 length;
181 + __u32 address;
182 + __u32 type;
183 + __u8 data[MAX_INTEL_HEX_RECORD_LENGTH];
184 +} INTEL_HEX_RECORD, *PINTEL_HEX_RECORD;
186 +/* Vendor specific request code for Anchor Upload/Download
187 + (This one is implemented in the core). */
188 +#define ANCHOR_LOAD_INTERNAL 0xA0
190 +/* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */
191 +#define CPUCS_REG 0x7F92 /* original / FX */
192 +#define CPUCS_REG_FX2 0xE600 /* FX2 */
194 +#endif
195 --- ./drivers/usb/storage/usbxchange_fw.c.orig 2015-05-22 12:17:16.535229448 +0200
196 +++ ./drivers/usb/storage/usbxchange_fw.c 2015-05-21 12:14:53.390801404 +0200
197 @@ -0,0 +1,215 @@
199 + * Firmware loader for Adaptec USBXchange / USB2Xchange.
201 + * Uploads device firmware into the Adaptec USBXchange and USB2Xchange
202 + * USB --> SCSI dongle.
204 + * Current development and maintenance by:
205 + * (c) 2005 René Rebe <rene@exactcode.de>
207 + * Initial work by:
208 + * (c) 2004 Beier & Dauskardt IT <sda@bdit.de>
210 + * Based on emi26.c:
211 + * (c) 2002 Tapio Laxström <tapio.laxstrom@iptime.fi>
213 + * To use this driver, you need to get the devices firmware from some
214 + * windows driver:
215 + * usbxchg_win_v120.exe - for USBXchange
216 + * usb2xchg_win_drv_v200.exe - for USB2Xchange
218 + * Hotplug firmware loader compatible files can be found at:
219 + * http://dl.exactcode.de/adaptec-usbxchange/
221 + * Note:
222 + * The USB2Xchange seems to have some internal buffer < 64K.
223 + * Sending 64K requests crashes the device. Possibly it needs a
224 + * "max_sectors: 8" setting.
226 + * This program is distributed in the hope that it will be useful, but
227 + * WITHOUT ANY WARRANTY; without even the implied warranty of
228 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
229 + * General Public License for more details.
231 + * This program is free software; you can redistribute it and/or modify
232 + * it under the terms of the GNU General Public License, as published by
233 + * the Free Software Foundation, version 2.
234 + */
236 +#include <linux/kernel.h>
237 +#include <linux/errno.h>
238 +#include <linux/slab.h>
239 +#include <linux/module.h>
240 +#include <linux/init.h>
241 +#include <linux/usb.h>
242 +#include <linux/firmware.h>
244 +#include "usbxchange_fw.h"
246 +static int usbxchange_writememory(struct usb_device *dev, int address,
247 + unsigned char *data, int length,
248 + __u8 bRequest);
249 +static int usbxchange_set_reset(struct usb_device *dev, int cpureg,
250 + unsigned char reset_bit);
251 +static int usbxchange_load_firmware(struct usb_device *dev);
253 +static int usbxchange_probe(struct usb_interface *iface,
254 + const struct usb_device_id *id);
255 +static void usbxchange_disconnect(struct usb_interface *iface);
256 +static int __init usbxchange_init(void);
257 +static void __exit usbxchange_exit(void);
259 +#define usbxchange_VENDOR_ID 0x03f3
260 +#define usbxchange_PRODUCT_ID 0x2000
261 +#define usb2xchange_PRODUCT_ID 0x2002
263 +static struct usb_device_id usbxchange_usb_ids[] = {
264 + {USB_DEVICE(usbxchange_VENDOR_ID, usbxchange_PRODUCT_ID)},
265 + {USB_DEVICE(usbxchange_VENDOR_ID, usb2xchange_PRODUCT_ID)},
266 + {} /* terminating entry */
269 +MODULE_DEVICE_TABLE(usb, usbxchange_usb_ids);
271 +/* thanks to drivers/usb/serial/keyspan_pda.c code */
272 +static int usbxchange_writememory(struct usb_device *dev, int address,
273 + unsigned char *data, int length, __u8 request)
275 + int result;
276 + unsigned char *buffer = kmalloc(length, GFP_KERNEL);
278 + if (!buffer) {
279 + printk(KERN_ERR "usbxchange: kmalloc(%d) failed.\n", length);
280 + return -ENOMEM;
282 + memcpy(buffer, data, length);
283 + result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request, 0x40,
284 + address, 0, buffer, length, 300);
285 + kfree(buffer);
286 + return result;
289 +/* thanks to drivers/usb/serial/keyspan_pda.c code */
290 +static int usbxchange_set_reset(struct usb_device *dev, int cpureg,
291 + unsigned char reset_bit)
293 + int response;
294 + printk(KERN_INFO "%s - %d\n", __FUNCTION__, reset_bit);
295 + response =
296 + usbxchange_writememory(dev, cpureg, &reset_bit, 1,
297 + ANCHOR_LOAD_INTERNAL);
298 + if (response < 0) {
299 + printk(KERN_ERR "usbxchange: set_reset (%d) failed\n",
300 + reset_bit);
302 + return response;
305 +static int usbxchange_load_firmware(struct usb_device *dev)
307 + INTEL_HEX_RECORD *record;
308 + int err, cpureg;
310 + const struct firmware *firmware;
312 + switch (le16_to_cpu(dev->descriptor.idProduct)) {
313 + case usbxchange_PRODUCT_ID:
314 + err = request_firmware(&firmware, "usbxchange.fw", &dev->dev);
315 + cpureg = CPUCS_REG;
316 + break;
317 + case usb2xchange_PRODUCT_ID:
318 + err = request_firmware(&firmware, "usb2xchange.fw", &dev->dev);
319 + cpureg = CPUCS_REG_FX2;
320 + break;
321 + default:
322 + printk(KERN_ERR "%s - device not recognized %x\n", __FUNCTION__,
323 + le16_to_cpu(dev->descriptor.idProduct));
324 + return 1;
327 + if (err != 0) {
328 + printk(KERN_ERR "Hotplug firmware request failed.\n");
329 + return err;
332 + /* Stop CPU */
333 + err = usbxchange_set_reset(dev, cpureg, 1);
334 + err = usbxchange_set_reset(dev, cpureg, 1);
335 + if (err < 0) {
336 + printk(KERN_ERR "%s - error stopping dongle CPU: error = %d\n",
337 + __FUNCTION__, err);
338 + return err;
341 + /* Upload firmware */
342 + for (record = (INTEL_HEX_RECORD *)firmware->data;
343 + record->type == 0; record++) {
345 + err = usbxchange_writememory(dev, le32_to_cpu(record->address),
346 + record->data,
347 + le32_to_cpu(record->length),
348 + ANCHOR_LOAD_INTERNAL);
349 + if (err < 0) {
350 + printk(KERN_ERR
351 + "%s - error loading firmware: error = %d\n",
352 + __FUNCTION__, err);
353 + return err;
357 + /* De-assert reset (let the CPU run) */
358 + err = usbxchange_set_reset(dev, cpureg, 1);
359 + err = usbxchange_set_reset(dev, cpureg, 0);
360 + if (err < 0) {
361 + printk(KERN_ERR "%s - error resetting dongle CPU: error = %d\n",
362 + __FUNCTION__, err);
363 + return err;
366 + return 0;
369 +static int usbxchange_probe(struct usb_interface *iface,
370 + const struct usb_device_id *id)
372 + struct usb_device *dev = interface_to_usbdev(iface);
374 + printk(KERN_INFO "%s start\n", __FUNCTION__);
376 + usbxchange_load_firmware(dev);
378 + /* forcing an unload would save some kB of kernel memory ... */
379 + return 0;
382 +static void usbxchange_disconnect(struct usb_interface *iface)
386 +static struct usb_driver usbxchange_driver = {
387 + .name = "usbxchange_fw",
388 + .probe = usbxchange_probe,
389 + .disconnect = usbxchange_disconnect,
390 + .id_table = usbxchange_usb_ids,
393 +static int __init usbxchange_init(void)
395 + usb_register(&usbxchange_driver);
396 + return 0;
399 +static void __exit usbxchange_exit(void)
401 + usb_deregister(&usbxchange_driver);
404 +module_init(usbxchange_init);
405 +module_exit(usbxchange_exit);
407 +MODULE_AUTHOR("René Rebe <rene@exactcode.de>, Sancho Dauskardt <sda@bdit.de>");
408 +MODULE_DESCRIPTION("Adaptec USBXchange firmware loader.");
409 +MODULE_LICENSE("GPL");
411 +/* vi:ai:syntax=c:sw=8:ts=8:tw=80
412 + */