diff options
Diffstat (limited to 'drivers/usb/storage')
-rw-r--r-- | drivers/usb/storage/Kconfig | 23 | ||||
-rw-r--r-- | drivers/usb/storage/Makefile | 5 | ||||
-rw-r--r-- | drivers/usb/storage/alauda.c | 1119 | ||||
-rw-r--r-- | drivers/usb/storage/alauda.h | 100 | ||||
-rw-r--r-- | drivers/usb/storage/debug.c | 1 | ||||
-rw-r--r-- | drivers/usb/storage/initializers.h | 4 | ||||
-rw-r--r-- | drivers/usb/storage/libusual.c | 266 | ||||
-rw-r--r-- | drivers/usb/storage/onetouch.c | 27 | ||||
-rw-r--r-- | drivers/usb/storage/protocol.h | 14 | ||||
-rw-r--r-- | drivers/usb/storage/sddr09.c | 214 | ||||
-rw-r--r-- | drivers/usb/storage/sddr09.h | 15 | ||||
-rw-r--r-- | drivers/usb/storage/transport.h | 31 | ||||
-rw-r--r-- | drivers/usb/storage/unusual_devs.h | 74 | ||||
-rw-r--r-- | drivers/usb/storage/usb.c | 160 | ||||
-rw-r--r-- | drivers/usb/storage/usb.h | 40 |
15 files changed, 1798 insertions, 295 deletions
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index c41d64dbb0f0..92be101feba7 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig | |||
@@ -112,6 +112,15 @@ config USB_STORAGE_JUMPSHOT | |||
112 | Say Y here to include additional code to support the Lexar Jumpshot | 112 | Say Y here to include additional code to support the Lexar Jumpshot |
113 | USB CompactFlash reader. | 113 | USB CompactFlash reader. |
114 | 114 | ||
115 | config USB_STORAGE_ALAUDA | ||
116 | bool "Olympus MAUSB-10/Fuji DPC-R1 support (EXPERIMENTAL)" | ||
117 | depends on USB_STORAGE && EXPERIMENTAL | ||
118 | help | ||
119 | Say Y here to include additional code to support the Olympus MAUSB-10 | ||
120 | and Fujifilm DPC-R1 USB Card reader/writer devices. | ||
121 | |||
122 | These devices are based on the Alauda chip and support support both | ||
123 | XD and SmartMedia cards. | ||
115 | 124 | ||
116 | config USB_STORAGE_ONETOUCH | 125 | config USB_STORAGE_ONETOUCH |
117 | bool "Support OneTouch Button on Maxtor Hard Drives (EXPERIMENTAL)" | 126 | bool "Support OneTouch Button on Maxtor Hard Drives (EXPERIMENTAL)" |
@@ -124,3 +133,17 @@ config USB_STORAGE_ONETOUCH | |||
124 | hard drive's as an input device. An action can be associated with | 133 | hard drive's as an input device. An action can be associated with |
125 | this input in any keybinding software. (e.g. gnome's keyboard short- | 134 | this input in any keybinding software. (e.g. gnome's keyboard short- |
126 | cuts) | 135 | cuts) |
136 | |||
137 | config USB_LIBUSUAL | ||
138 | bool "The shared table of common (or usual) storage devices" | ||
139 | depends on USB | ||
140 | help | ||
141 | This module contains a table of common (or usual) devices | ||
142 | for usb-storage and ub drivers, and allows to switch binding | ||
143 | of these devices without rebuilding modules. | ||
144 | |||
145 | Typical syntax of /etc/modprobe.conf is: | ||
146 | |||
147 | options libusual bias="ub" | ||
148 | |||
149 | If unsure, say N. | ||
diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 44ab8f9978fe..8cbba22508a4 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile | |||
@@ -18,7 +18,12 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_DPCM) += dpcm.o | |||
18 | usb-storage-obj-$(CONFIG_USB_STORAGE_ISD200) += isd200.o | 18 | usb-storage-obj-$(CONFIG_USB_STORAGE_ISD200) += isd200.o |
19 | usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o | 19 | usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o |
20 | usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o | 20 | usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o |
21 | usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA) += alauda.o | ||
21 | usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o | 22 | usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o |
22 | 23 | ||
23 | usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \ | 24 | usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \ |
24 | initializers.o $(usb-storage-obj-y) | 25 | initializers.o $(usb-storage-obj-y) |
26 | |||
27 | ifneq ($(CONFIG_USB_LIBUSUAL),) | ||
28 | obj-$(CONFIG_USB) += libusual.o | ||
29 | endif | ||
diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c new file mode 100644 index 000000000000..4d3cbb12b713 --- /dev/null +++ b/drivers/usb/storage/alauda.c | |||
@@ -0,0 +1,1119 @@ | |||
1 | /* | ||
2 | * Driver for Alauda-based card readers | ||
3 | * | ||
4 | * Current development and maintenance by: | ||
5 | * (c) 2005 Daniel Drake <dsd@gentoo.org> | ||
6 | * | ||
7 | * The 'Alauda' is a chip manufacturered by RATOC for OEM use. | ||
8 | * | ||
9 | * Alauda implements a vendor-specific command set to access two media reader | ||
10 | * ports (XD, SmartMedia). This driver converts SCSI commands to the commands | ||
11 | * which are accepted by these devices. | ||
12 | * | ||
13 | * The driver was developed through reverse-engineering, with the help of the | ||
14 | * sddr09 driver which has many similarities, and with some help from the | ||
15 | * (very old) vendor-supplied GPL sma03 driver. | ||
16 | * | ||
17 | * For protocol info, see http://alauda.sourceforge.net | ||
18 | * | ||
19 | * This program is free software; you can redistribute it and/or modify it | ||
20 | * under the terms of the GNU General Public License as published by the | ||
21 | * Free Software Foundation; either version 2, or (at your option) any | ||
22 | * later version. | ||
23 | * | ||
24 | * This program is distributed in the hope that it will be useful, but | ||
25 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
27 | * General Public License for more details. | ||
28 | * | ||
29 | * You should have received a copy of the GNU General Public License along | ||
30 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
31 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
32 | */ | ||
33 | |||
34 | #include <scsi/scsi.h> | ||
35 | #include <scsi/scsi_cmnd.h> | ||
36 | #include <scsi/scsi_device.h> | ||
37 | |||
38 | #include "usb.h" | ||
39 | #include "transport.h" | ||
40 | #include "protocol.h" | ||
41 | #include "debug.h" | ||
42 | #include "alauda.h" | ||
43 | |||
44 | #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) ) | ||
45 | #define LSB_of(s) ((s)&0xFF) | ||
46 | #define MSB_of(s) ((s)>>8) | ||
47 | |||
48 | #define MEDIA_PORT(us) us->srb->device->lun | ||
49 | #define MEDIA_INFO(us) ((struct alauda_info *)us->extra)->port[MEDIA_PORT(us)] | ||
50 | |||
51 | #define PBA_LO(pba) ((pba & 0xF) << 5) | ||
52 | #define PBA_HI(pba) (pba >> 3) | ||
53 | #define PBA_ZONE(pba) (pba >> 11) | ||
54 | |||
55 | /* | ||
56 | * Media handling | ||
57 | */ | ||
58 | |||
59 | struct alauda_card_info { | ||
60 | unsigned char id; /* id byte */ | ||
61 | unsigned char chipshift; /* 1<<cs bytes total capacity */ | ||
62 | unsigned char pageshift; /* 1<<ps bytes in a page */ | ||
63 | unsigned char blockshift; /* 1<<bs pages per block */ | ||
64 | unsigned char zoneshift; /* 1<<zs blocks per zone */ | ||
65 | }; | ||
66 | |||
67 | static struct alauda_card_info alauda_card_ids[] = { | ||
68 | /* NAND flash */ | ||
69 | { 0x6e, 20, 8, 4, 8}, /* 1 MB */ | ||
70 | { 0xe8, 20, 8, 4, 8}, /* 1 MB */ | ||
71 | { 0xec, 20, 8, 4, 8}, /* 1 MB */ | ||
72 | { 0x64, 21, 8, 4, 9}, /* 2 MB */ | ||
73 | { 0xea, 21, 8, 4, 9}, /* 2 MB */ | ||
74 | { 0x6b, 22, 9, 4, 9}, /* 4 MB */ | ||
75 | { 0xe3, 22, 9, 4, 9}, /* 4 MB */ | ||
76 | { 0xe5, 22, 9, 4, 9}, /* 4 MB */ | ||
77 | { 0xe6, 23, 9, 4, 10}, /* 8 MB */ | ||
78 | { 0x73, 24, 9, 5, 10}, /* 16 MB */ | ||
79 | { 0x75, 25, 9, 5, 10}, /* 32 MB */ | ||
80 | { 0x76, 26, 9, 5, 10}, /* 64 MB */ | ||
81 | { 0x79, 27, 9, 5, 10}, /* 128 MB */ | ||
82 | { 0x71, 28, 9, 5, 10}, /* 256 MB */ | ||
83 | |||
84 | /* MASK ROM */ | ||
85 | { 0x5d, 21, 9, 4, 8}, /* 2 MB */ | ||
86 | { 0xd5, 22, 9, 4, 9}, /* 4 MB */ | ||
87 | { 0xd6, 23, 9, 4, 10}, /* 8 MB */ | ||
88 | { 0x57, 24, 9, 4, 11}, /* 16 MB */ | ||
89 | { 0x58, 25, 9, 4, 12}, /* 32 MB */ | ||
90 | { 0,} | ||
91 | }; | ||
92 | |||
93 | static struct alauda_card_info *alauda_card_find_id(unsigned char id) { | ||
94 | int i; | ||
95 | |||
96 | for (i = 0; alauda_card_ids[i].id != 0; i++) | ||
97 | if (alauda_card_ids[i].id == id) | ||
98 | return &(alauda_card_ids[i]); | ||
99 | return NULL; | ||
100 | } | ||
101 | |||
102 | /* | ||
103 | * ECC computation. | ||
104 | */ | ||
105 | |||
106 | static unsigned char parity[256]; | ||
107 | static unsigned char ecc2[256]; | ||
108 | |||
109 | static void nand_init_ecc(void) { | ||
110 | int i, j, a; | ||
111 | |||
112 | parity[0] = 0; | ||
113 | for (i = 1; i < 256; i++) | ||
114 | parity[i] = (parity[i&(i-1)] ^ 1); | ||
115 | |||
116 | for (i = 0; i < 256; i++) { | ||
117 | a = 0; | ||
118 | for (j = 0; j < 8; j++) { | ||
119 | if (i & (1<<j)) { | ||
120 | if ((j & 1) == 0) | ||
121 | a ^= 0x04; | ||
122 | if ((j & 2) == 0) | ||
123 | a ^= 0x10; | ||
124 | if ((j & 4) == 0) | ||
125 | a ^= 0x40; | ||
126 | } | ||
127 | } | ||
128 | ecc2[i] = ~(a ^ (a<<1) ^ (parity[i] ? 0xa8 : 0)); | ||
129 | } | ||
130 | } | ||
131 | |||
132 | /* compute 3-byte ecc on 256 bytes */ | ||
133 | static void nand_compute_ecc(unsigned char *data, unsigned char *ecc) { | ||
134 | int i, j, a; | ||
135 | unsigned char par, bit, bits[8]; | ||
136 | |||
137 | par = 0; | ||
138 | for (j = 0; j < 8; j++) | ||
139 | bits[j] = 0; | ||
140 | |||
141 | /* collect 16 checksum bits */ | ||
142 | for (i = 0; i < 256; i++) { | ||
143 | par ^= data[i]; | ||
144 | bit = parity[data[i]]; | ||
145 | for (j = 0; j < 8; j++) | ||
146 | if ((i & (1<<j)) == 0) | ||
147 | bits[j] ^= bit; | ||
148 | } | ||
149 | |||
150 | /* put 4+4+4 = 12 bits in the ecc */ | ||
151 | a = (bits[3] << 6) + (bits[2] << 4) + (bits[1] << 2) + bits[0]; | ||
152 | ecc[0] = ~(a ^ (a<<1) ^ (parity[par] ? 0xaa : 0)); | ||
153 | |||
154 | a = (bits[7] << 6) + (bits[6] << 4) + (bits[5] << 2) + bits[4]; | ||
155 | ecc[1] = ~(a ^ (a<<1) ^ (parity[par] ? 0xaa : 0)); | ||
156 | |||
157 | ecc[2] = ecc2[par]; | ||
158 | } | ||
159 | |||
160 | static int nand_compare_ecc(unsigned char *data, unsigned char *ecc) { | ||
161 | return (data[0] == ecc[0] && data[1] == ecc[1] && data[2] == ecc[2]); | ||
162 | } | ||
163 | |||
164 | static void nand_store_ecc(unsigned char *data, unsigned char *ecc) { | ||
165 | memcpy(data, ecc, 3); | ||
166 | } | ||
167 | |||
168 | /* | ||
169 | * Alauda driver | ||
170 | */ | ||
171 | |||
172 | /* | ||
173 | * Forget our PBA <---> LBA mappings for a particular port | ||
174 | */ | ||
175 | static void alauda_free_maps (struct alauda_media_info *media_info) | ||
176 | { | ||
177 | unsigned int shift = media_info->zoneshift | ||
178 | + media_info->blockshift + media_info->pageshift; | ||
179 | unsigned int num_zones = media_info->capacity >> shift; | ||
180 | unsigned int i; | ||
181 | |||
182 | if (media_info->lba_to_pba != NULL) | ||
183 | for (i = 0; i < num_zones; i++) { | ||
184 | kfree(media_info->lba_to_pba[i]); | ||
185 | media_info->lba_to_pba[i] = NULL; | ||
186 | } | ||
187 | |||
188 | if (media_info->pba_to_lba != NULL) | ||
189 | for (i = 0; i < num_zones; i++) { | ||
190 | kfree(media_info->pba_to_lba[i]); | ||
191 | media_info->pba_to_lba[i] = NULL; | ||
192 | } | ||
193 | } | ||
194 | |||
195 | /* | ||
196 | * Returns 2 bytes of status data | ||
197 | * The first byte describes media status, and second byte describes door status | ||
198 | */ | ||
199 | static int alauda_get_media_status(struct us_data *us, unsigned char *data) | ||
200 | { | ||
201 | int rc; | ||
202 | unsigned char command; | ||
203 | |||
204 | if (MEDIA_PORT(us) == ALAUDA_PORT_XD) | ||
205 | command = ALAUDA_GET_XD_MEDIA_STATUS; | ||
206 | else | ||
207 | command = ALAUDA_GET_SM_MEDIA_STATUS; | ||
208 | |||
209 | rc = usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe, | ||
210 | command, 0xc0, 0, 1, data, 2); | ||
211 | |||
212 | US_DEBUGP("alauda_get_media_status: Media status %02X %02X\n", | ||
213 | data[0], data[1]); | ||
214 | |||
215 | return rc; | ||
216 | } | ||
217 | |||
218 | /* | ||
219 | * Clears the "media was changed" bit so that we know when it changes again | ||
220 | * in the future. | ||
221 | */ | ||
222 | static int alauda_ack_media(struct us_data *us) | ||
223 | { | ||
224 | unsigned char command; | ||
225 | |||
226 | if (MEDIA_PORT(us) == ALAUDA_PORT_XD) | ||
227 | command = ALAUDA_ACK_XD_MEDIA_CHANGE; | ||
228 | else | ||
229 | command = ALAUDA_ACK_SM_MEDIA_CHANGE; | ||
230 | |||
231 | return usb_stor_ctrl_transfer(us, us->send_ctrl_pipe, | ||
232 | command, 0x40, 0, 1, NULL, 0); | ||
233 | } | ||
234 | |||
235 | /* | ||
236 | * Retrieves a 4-byte media signature, which indicates manufacturer, capacity, | ||
237 | * and some other details. | ||
238 | */ | ||
239 | static int alauda_get_media_signature(struct us_data *us, unsigned char *data) | ||
240 | { | ||
241 | unsigned char command; | ||
242 | |||
243 | if (MEDIA_PORT(us) == ALAUDA_PORT_XD) | ||
244 | command = ALAUDA_GET_XD_MEDIA_SIG; | ||
245 | else | ||
246 | command = ALAUDA_GET_SM_MEDIA_SIG; | ||
247 | |||
248 | return usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe, | ||
249 | command, 0xc0, 0, 0, data, 4); | ||
250 | } | ||
251 | |||
252 | /* | ||
253 | * Resets the media status (but not the whole device?) | ||
254 | */ | ||
255 | static int alauda_reset_media(struct us_data *us) | ||
256 | { | ||
257 | unsigned char *command = us->iobuf; | ||
258 | |||
259 | memset(command, 0, 9); | ||
260 | command[0] = ALAUDA_BULK_CMD; | ||
261 | command[1] = ALAUDA_BULK_RESET_MEDIA; | ||
262 | command[8] = MEDIA_PORT(us); | ||
263 | |||
264 | return usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, | ||
265 | command, 9, NULL); | ||
266 | } | ||
267 | |||
268 | /* | ||
269 | * Examines the media and deduces capacity, etc. | ||
270 | */ | ||
271 | static int alauda_init_media(struct us_data *us) | ||
272 | { | ||
273 | unsigned char *data = us->iobuf; | ||
274 | int ready = 0; | ||
275 | struct alauda_card_info *media_info; | ||
276 | unsigned int num_zones; | ||
277 | |||
278 | while (ready == 0) { | ||
279 | msleep(20); | ||
280 | |||
281 | if (alauda_get_media_status(us, data) != USB_STOR_XFER_GOOD) | ||
282 | return USB_STOR_TRANSPORT_ERROR; | ||
283 | |||
284 | if (data[0] & 0x10) | ||
285 | ready = 1; | ||
286 | } | ||
287 | |||
288 | US_DEBUGP("alauda_init_media: We are ready for action!\n"); | ||
289 | |||
290 | if (alauda_ack_media(us) != USB_STOR_XFER_GOOD) | ||
291 | return USB_STOR_TRANSPORT_ERROR; | ||
292 | |||
293 | msleep(10); | ||
294 | |||
295 | if (alauda_get_media_status(us, data) != USB_STOR_XFER_GOOD) | ||
296 | return USB_STOR_TRANSPORT_ERROR; | ||
297 | |||
298 | if (data[0] != 0x14) { | ||
299 | US_DEBUGP("alauda_init_media: Media not ready after ack\n"); | ||
300 | return USB_STOR_TRANSPORT_ERROR; | ||
301 | } | ||
302 | |||
303 | if (alauda_get_media_signature(us, data) != USB_STOR_XFER_GOOD) | ||
304 | return USB_STOR_TRANSPORT_ERROR; | ||
305 | |||
306 | US_DEBUGP("alauda_init_media: Media signature: %02X %02X %02X %02X\n", | ||
307 | data[0], data[1], data[2], data[3]); | ||
308 | media_info = alauda_card_find_id(data[1]); | ||
309 | if (media_info == NULL) { | ||
310 | printk("alauda_init_media: Unrecognised media signature: " | ||
311 | "%02X %02X %02X %02X\n", | ||
312 | data[0], data[1], data[2], data[3]); | ||
313 | return USB_STOR_TRANSPORT_ERROR; | ||
314 | } | ||
315 | |||
316 | MEDIA_INFO(us).capacity = 1 << media_info->chipshift; | ||
317 | US_DEBUGP("Found media with capacity: %ldMB\n", | ||
318 | MEDIA_INFO(us).capacity >> 20); | ||
319 | |||
320 | MEDIA_INFO(us).pageshift = media_info->pageshift; | ||
321 | MEDIA_INFO(us).blockshift = media_info->blockshift; | ||
322 | MEDIA_INFO(us).zoneshift = media_info->zoneshift; | ||
323 | |||
324 | MEDIA_INFO(us).pagesize = 1 << media_info->pageshift; | ||
325 | MEDIA_INFO(us).blocksize = 1 << media_info->blockshift; | ||
326 | MEDIA_INFO(us).zonesize = 1 << media_info->zoneshift; | ||
327 | |||
328 | MEDIA_INFO(us).uzonesize = ((1 << media_info->zoneshift) / 128) * 125; | ||
329 | MEDIA_INFO(us).blockmask = MEDIA_INFO(us).blocksize - 1; | ||
330 | |||
331 | num_zones = MEDIA_INFO(us).capacity >> (MEDIA_INFO(us).zoneshift | ||
332 | + MEDIA_INFO(us).blockshift + MEDIA_INFO(us).pageshift); | ||
333 | MEDIA_INFO(us).pba_to_lba = kcalloc(num_zones, sizeof(u16*), GFP_NOIO); | ||
334 | MEDIA_INFO(us).lba_to_pba = kcalloc(num_zones, sizeof(u16*), GFP_NOIO); | ||
335 | |||
336 | if (alauda_reset_media(us) != USB_STOR_XFER_GOOD) | ||
337 | return USB_STOR_TRANSPORT_ERROR; | ||
338 | |||
339 | return USB_STOR_TRANSPORT_GOOD; | ||
340 | } | ||
341 | |||
342 | /* | ||
343 | * Examines the media status and does the right thing when the media has gone, | ||
344 | * appeared, or changed. | ||
345 | */ | ||
346 | static int alauda_check_media(struct us_data *us) | ||
347 | { | ||
348 | struct alauda_info *info = (struct alauda_info *) us->extra; | ||
349 | unsigned char status[2]; | ||
350 | int rc; | ||
351 | |||
352 | rc = alauda_get_media_status(us, status); | ||
353 | |||
354 | /* Check for no media or door open */ | ||
355 | if ((status[0] & 0x80) || ((status[0] & 0x1F) == 0x10) | ||
356 | || ((status[1] & 0x01) == 0)) { | ||
357 | US_DEBUGP("alauda_check_media: No media, or door open\n"); | ||
358 | alauda_free_maps(&MEDIA_INFO(us)); | ||
359 | info->sense_key = 0x02; | ||
360 | info->sense_asc = 0x3A; | ||
361 | info->sense_ascq = 0x00; | ||
362 | return USB_STOR_TRANSPORT_FAILED; | ||
363 | } | ||
364 | |||
365 | /* Check for media change */ | ||
366 | if (status[0] & 0x08) { | ||
367 | US_DEBUGP("alauda_check_media: Media change detected\n"); | ||
368 | alauda_free_maps(&MEDIA_INFO(us)); | ||
369 | alauda_init_media(us); | ||
370 | |||
371 | info->sense_key = UNIT_ATTENTION; | ||
372 | info->sense_asc = 0x28; | ||
373 | info->sense_ascq = 0x00; | ||
374 | return USB_STOR_TRANSPORT_FAILED; | ||
375 | } | ||
376 | |||
377 | return USB_STOR_TRANSPORT_GOOD; | ||
378 | } | ||
379 | |||
380 | /* | ||
381 | * Checks the status from the 2nd status register | ||
382 | * Returns 3 bytes of status data, only the first is known | ||
383 | */ | ||
384 | static int alauda_check_status2(struct us_data *us) | ||
385 | { | ||
386 | int rc; | ||
387 | unsigned char command[] = { | ||
388 | ALAUDA_BULK_CMD, ALAUDA_BULK_GET_STATUS2, | ||
389 | 0, 0, 0, 0, 3, 0, MEDIA_PORT(us) | ||
390 | }; | ||
391 | unsigned char data[3]; | ||
392 | |||
393 | rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, | ||
394 | command, 9, NULL); | ||
395 | if (rc != USB_STOR_XFER_GOOD) | ||
396 | return rc; | ||
397 | |||
398 | rc = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, | ||
399 | data, 3, NULL); | ||
400 | if (rc != USB_STOR_XFER_GOOD) | ||
401 | return rc; | ||
402 | |||
403 | US_DEBUGP("alauda_check_status2: %02X %02X %02X\n", data[0], data[1], data[2]); | ||
404 | if (data[0] & ALAUDA_STATUS_ERROR) | ||
405 | return USB_STOR_XFER_ERROR; | ||
406 | |||
407 | return USB_STOR_XFER_GOOD; | ||
408 | } | ||
409 | |||
410 | /* | ||
411 | * Gets the redundancy data for the first page of a PBA | ||
412 | * Returns 16 bytes. | ||
413 | */ | ||
414 | static int alauda_get_redu_data(struct us_data *us, u16 pba, unsigned char *data) | ||
415 | { | ||
416 | int rc; | ||
417 | unsigned char command[] = { | ||
418 | ALAUDA_BULK_CMD, ALAUDA_BULK_GET_REDU_DATA, | ||
419 | PBA_HI(pba), PBA_ZONE(pba), 0, PBA_LO(pba), 0, 0, MEDIA_PORT(us) | ||
420 | }; | ||
421 | |||
422 | rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, | ||
423 | command, 9, NULL); | ||
424 | if (rc != USB_STOR_XFER_GOOD) | ||
425 | return rc; | ||
426 | |||
427 | return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, | ||
428 | data, 16, NULL); | ||
429 | } | ||
430 | |||
431 | /* | ||
432 | * Finds the first unused PBA in a zone | ||
433 | * Returns the absolute PBA of an unused PBA, or 0 if none found. | ||
434 | */ | ||
435 | static u16 alauda_find_unused_pba(struct alauda_media_info *info, | ||
436 | unsigned int zone) | ||
437 | { | ||
438 | u16 *pba_to_lba = info->pba_to_lba[zone]; | ||
439 | unsigned int i; | ||
440 | |||
441 | for (i = 0; i < info->zonesize; i++) | ||
442 | if (pba_to_lba[i] == UNDEF) | ||
443 | return (zone << info->zoneshift) + i; | ||
444 | |||
445 | return 0; | ||
446 | } | ||
447 | |||
448 | /* | ||
449 | * Reads the redundancy data for all PBA's in a zone | ||
450 | * Produces lba <--> pba mappings | ||
451 | */ | ||
452 | static int alauda_read_map(struct us_data *us, unsigned int zone) | ||
453 | { | ||
454 | unsigned char *data = us->iobuf; | ||
455 | int result; | ||
456 | int i, j; | ||
457 | unsigned int zonesize = MEDIA_INFO(us).zonesize; | ||
458 | unsigned int uzonesize = MEDIA_INFO(us).uzonesize; | ||
459 | unsigned int lba_offset, lba_real, blocknum; | ||
460 | unsigned int zone_base_lba = zone * uzonesize; | ||
461 | unsigned int zone_base_pba = zone * zonesize; | ||
462 | u16 *lba_to_pba = kcalloc(zonesize, sizeof(u16), GFP_NOIO); | ||
463 | u16 *pba_to_lba = kcalloc(zonesize, sizeof(u16), GFP_NOIO); | ||
464 | if (lba_to_pba == NULL || pba_to_lba == NULL) { | ||
465 | result = USB_STOR_TRANSPORT_ERROR; | ||
466 | goto error; | ||
467 | } | ||
468 | |||
469 | US_DEBUGP("alauda_read_map: Mapping blocks for zone %d\n", zone); | ||
470 | |||
471 | /* 1024 PBA's per zone */ | ||
472 | for (i = 0; i < zonesize; i++) | ||
473 | lba_to_pba[i] = pba_to_lba[i] = UNDEF; | ||
474 | |||
475 | for (i = 0; i < zonesize; i++) { | ||
476 | blocknum = zone_base_pba + i; | ||
477 | |||
478 | result = alauda_get_redu_data(us, blocknum, data); | ||
479 | if (result != USB_STOR_XFER_GOOD) { | ||
480 | result = USB_STOR_TRANSPORT_ERROR; | ||
481 | goto error; | ||
482 | } | ||
483 | |||
484 | /* special PBAs have control field 0^16 */ | ||
485 | for (j = 0; j < 16; j++) | ||
486 | if (data[j] != 0) | ||
487 | goto nonz; | ||
488 | pba_to_lba[i] = UNUSABLE; | ||
489 | US_DEBUGP("alauda_read_map: PBA %d has no logical mapping\n", blocknum); | ||
490 | continue; | ||
491 | |||
492 | nonz: | ||
493 | /* unwritten PBAs have control field FF^16 */ | ||
494 | for (j = 0; j < 16; j++) | ||
495 | if (data[j] != 0xff) | ||
496 | goto nonff; | ||
497 | continue; | ||
498 | |||
499 | nonff: | ||
500 | /* normal PBAs start with six FFs */ | ||
501 | if (j < 6) { | ||
502 | US_DEBUGP("alauda_read_map: PBA %d has no logical mapping: " | ||
503 | "reserved area = %02X%02X%02X%02X " | ||
504 | "data status %02X block status %02X\n", | ||
505 | blocknum, data[0], data[1], data[2], data[3], | ||
506 | data[4], data[5]); | ||
507 | pba_to_lba[i] = UNUSABLE; | ||
508 | continue; | ||
509 | } | ||
510 | |||
511 | if ((data[6] >> 4) != 0x01) { | ||
512 | US_DEBUGP("alauda_read_map: PBA %d has invalid address " | ||
513 | "field %02X%02X/%02X%02X\n", | ||
514 | blocknum, data[6], data[7], data[11], data[12]); | ||
515 | pba_to_lba[i] = UNUSABLE; | ||
516 | continue; | ||
517 | } | ||
518 | |||
519 | /* check even parity */ | ||
520 | if (parity[data[6] ^ data[7]]) { | ||
521 | printk("alauda_read_map: Bad parity in LBA for block %d" | ||
522 | " (%02X %02X)\n", i, data[6], data[7]); | ||
523 | pba_to_lba[i] = UNUSABLE; | ||
524 | continue; | ||
525 | } | ||
526 | |||
527 | lba_offset = short_pack(data[7], data[6]); | ||
528 | lba_offset = (lba_offset & 0x07FF) >> 1; | ||
529 | lba_real = lba_offset + zone_base_lba; | ||
530 | |||
531 | /* | ||
532 | * Every 1024 physical blocks ("zone"), the LBA numbers | ||
533 | * go back to zero, but are within a higher block of LBA's. | ||
534 | * Also, there is a maximum of 1000 LBA's per zone. | ||
535 | * In other words, in PBA 1024-2047 you will find LBA 0-999 | ||
536 | * which are really LBA 1000-1999. This allows for 24 bad | ||
537 | * or special physical blocks per zone. | ||
538 | */ | ||
539 | |||
540 | if (lba_offset >= uzonesize) { | ||
541 | printk("alauda_read_map: Bad low LBA %d for block %d\n", | ||
542 | lba_real, blocknum); | ||
543 | continue; | ||
544 | } | ||
545 | |||
546 | if (lba_to_pba[lba_offset] != UNDEF) { | ||
547 | printk("alauda_read_map: LBA %d seen for PBA %d and %d\n", | ||
548 | lba_real, lba_to_pba[lba_offset], blocknum); | ||
549 | continue; | ||
550 | } | ||
551 | |||
552 | pba_to_lba[i] = lba_real; | ||
553 | lba_to_pba[lba_offset] = blocknum; | ||
554 | continue; | ||
555 | } | ||
556 | |||
557 | MEDIA_INFO(us).lba_to_pba[zone] = lba_to_pba; | ||
558 | MEDIA_INFO(us).pba_to_lba[zone] = pba_to_lba; | ||
559 | result = 0; | ||
560 | goto out; | ||
561 | |||
562 | error: | ||
563 | kfree(lba_to_pba); | ||
564 | kfree(pba_to_lba); | ||
565 | out: | ||
566 | return result; | ||
567 | } | ||
568 | |||
569 | /* | ||
570 | * Checks to see whether we have already mapped a certain zone | ||
571 | * If we haven't, the map is generated | ||
572 | */ | ||
573 | static void alauda_ensure_map_for_zone(struct us_data *us, unsigned int zone) | ||
574 | { | ||
575 | if (MEDIA_INFO(us).lba_to_pba[zone] == NULL | ||
576 | || MEDIA_INFO(us).pba_to_lba[zone] == NULL) | ||
577 | alauda_read_map(us, zone); | ||
578 | } | ||
579 | |||
580 | /* | ||
581 | * Erases an entire block | ||
582 | */ | ||
583 | static int alauda_erase_block(struct us_data *us, u16 pba) | ||
584 | { | ||
585 | int rc; | ||
586 | unsigned char command[] = { | ||
587 | ALAUDA_BULK_CMD, ALAUDA_BULK_ERASE_BLOCK, PBA_HI(pba), | ||
588 | PBA_ZONE(pba), 0, PBA_LO(pba), 0x02, 0, MEDIA_PORT(us) | ||
589 | }; | ||
590 | unsigned char buf[2]; | ||
591 | |||
592 | US_DEBUGP("alauda_erase_block: Erasing PBA %d\n", pba); | ||
593 | |||
594 | rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, | ||
595 | command, 9, NULL); | ||
596 | if (rc != USB_STOR_XFER_GOOD) | ||
597 | return rc; | ||
598 | |||
599 | rc = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, | ||
600 | buf, 2, NULL); | ||
601 | if (rc != USB_STOR_XFER_GOOD) | ||
602 | return rc; | ||
603 | |||
604 | US_DEBUGP("alauda_erase_block: Erase result: %02X %02X\n", | ||
605 | buf[0], buf[1]); | ||
606 | return rc; | ||
607 | } | ||
608 | |||
609 | /* | ||
610 | * Reads data from a certain offset page inside a PBA, including interleaved | ||
611 | * redundancy data. Returns (pagesize+64)*pages bytes in data. | ||
612 | */ | ||
613 | static int alauda_read_block_raw(struct us_data *us, u16 pba, | ||
614 | unsigned int page, unsigned int pages, unsigned char *data) | ||
615 | { | ||
616 | int rc; | ||
617 | unsigned char command[] = { | ||
618 | ALAUDA_BULK_CMD, ALAUDA_BULK_READ_BLOCK, PBA_HI(pba), | ||
619 | PBA_ZONE(pba), 0, PBA_LO(pba) + page, pages, 0, MEDIA_PORT(us) | ||
620 | }; | ||
621 | |||
622 | US_DEBUGP("alauda_read_block: pba %d page %d count %d\n", | ||
623 | pba, page, pages); | ||
624 | |||
625 | rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, | ||
626 | command, 9, NULL); | ||
627 | if (rc != USB_STOR_XFER_GOOD) | ||
628 | return rc; | ||
629 | |||
630 | return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, | ||
631 | data, (MEDIA_INFO(us).pagesize + 64) * pages, NULL); | ||
632 | } | ||
633 | |||
634 | /* | ||
635 | * Reads data from a certain offset page inside a PBA, excluding redundancy | ||
636 | * data. Returns pagesize*pages bytes in data. Note that data must be big enough | ||
637 | * to hold (pagesize+64)*pages bytes of data, but you can ignore those 'extra' | ||
638 | * trailing bytes outside this function. | ||
639 | */ | ||
640 | static int alauda_read_block(struct us_data *us, u16 pba, | ||
641 | unsigned int page, unsigned int pages, unsigned char *data) | ||
642 | { | ||
643 | int i, rc; | ||
644 | unsigned int pagesize = MEDIA_INFO(us).pagesize; | ||
645 | |||
646 | rc = alauda_read_block_raw(us, pba, page, pages, data); | ||
647 | if (rc != USB_STOR_XFER_GOOD) | ||
648 | return rc; | ||
649 | |||
650 | /* Cut out the redundancy data */ | ||
651 | for (i = 0; i < pages; i++) { | ||
652 | int dest_offset = i * pagesize; | ||
653 | int src_offset = i * (pagesize + 64); | ||
654 | memmove(data + dest_offset, data + src_offset, pagesize); | ||
655 | } | ||
656 | |||
657 | return rc; | ||
658 | } | ||
659 | |||
660 | /* | ||
661 | * Writes an entire block of data and checks status after write. | ||
662 | * Redundancy data must be already included in data. Data should be | ||
663 | * (pagesize+64)*blocksize bytes in length. | ||
664 | */ | ||
665 | static int alauda_write_block(struct us_data *us, u16 pba, unsigned char *data) | ||
666 | { | ||
667 | int rc; | ||
668 | struct alauda_info *info = (struct alauda_info *) us->extra; | ||
669 | unsigned char command[] = { | ||
670 | ALAUDA_BULK_CMD, ALAUDA_BULK_WRITE_BLOCK, PBA_HI(pba), | ||
671 | PBA_ZONE(pba), 0, PBA_LO(pba), 32, 0, MEDIA_PORT(us) | ||
672 | }; | ||
673 | |||
674 | US_DEBUGP("alauda_write_block: pba %d\n", pba); | ||
675 | |||
676 | rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, | ||
677 | command, 9, NULL); | ||
678 | if (rc != USB_STOR_XFER_GOOD) | ||
679 | return rc; | ||
680 | |||
681 | rc = usb_stor_bulk_transfer_buf(us, info->wr_ep, data, | ||
682 | (MEDIA_INFO(us).pagesize + 64) * MEDIA_INFO(us).blocksize, | ||
683 | NULL); | ||
684 | if (rc != USB_STOR_XFER_GOOD) | ||
685 | return rc; | ||
686 | |||
687 | return alauda_check_status2(us); | ||
688 | } | ||
689 | |||
690 | /* | ||
691 | * Write some data to a specific LBA. | ||
692 | */ | ||
693 | static int alauda_write_lba(struct us_data *us, u16 lba, | ||
694 | unsigned int page, unsigned int pages, | ||
695 | unsigned char *ptr, unsigned char *blockbuffer) | ||
696 | { | ||
697 | u16 pba, lbap, new_pba; | ||
698 | unsigned char *bptr, *cptr, *xptr; | ||
699 | unsigned char ecc[3]; | ||
700 | int i, result; | ||
701 | unsigned int uzonesize = MEDIA_INFO(us).uzonesize; | ||
702 | unsigned int zonesize = MEDIA_INFO(us).zonesize; | ||
703 | unsigned int pagesize = MEDIA_INFO(us).pagesize; | ||
704 | unsigned int blocksize = MEDIA_INFO(us).blocksize; | ||
705 | unsigned int lba_offset = lba % uzonesize; | ||
706 | unsigned int new_pba_offset; | ||
707 | unsigned int zone = lba / uzonesize; | ||
708 | |||
709 | alauda_ensure_map_for_zone(us, zone); | ||
710 | |||
711 | pba = MEDIA_INFO(us).lba_to_pba[zone][lba_offset]; | ||
712 | if (pba == 1) { | ||
713 | /* Maybe it is impossible to write to PBA 1. | ||
714 | Fake success, but don't do anything. */ | ||
715 | printk("alauda_write_lba: avoid writing to pba 1\n"); | ||
716 | return USB_STOR_TRANSPORT_GOOD; | ||
717 | } | ||
718 | |||
719 | new_pba = alauda_find_unused_pba(&MEDIA_INFO(us), zone); | ||
720 | if (!new_pba) { | ||
721 | printk("alauda_write_lba: Out of unused blocks\n"); | ||
722 | return USB_STOR_TRANSPORT_ERROR; | ||
723 | } | ||
724 | |||
725 | /* read old contents */ | ||
726 | if (pba != UNDEF) { | ||
727 | result = alauda_read_block_raw(us, pba, 0, | ||
728 | blocksize, blockbuffer); | ||
729 | if (result != USB_STOR_XFER_GOOD) | ||
730 | return result; | ||
731 | } else { | ||
732 | memset(blockbuffer, 0, blocksize * (pagesize + 64)); | ||
733 | } | ||
734 | |||
735 | lbap = (lba_offset << 1) | 0x1000; | ||
736 | if (parity[MSB_of(lbap) ^ LSB_of(lbap)]) | ||
737 | lbap ^= 1; | ||
738 | |||
739 | /* check old contents and fill lba */ | ||
740 | for (i = 0; i < blocksize; i++) { | ||
741 | bptr = blockbuffer + (i * (pagesize + 64)); | ||
742 | cptr = bptr + pagesize; | ||
743 | nand_compute_ecc(bptr, ecc); | ||
744 | if (!nand_compare_ecc(cptr+13, ecc)) { | ||
745 | US_DEBUGP("Warning: bad ecc in page %d- of pba %d\n", | ||
746 | i, pba); | ||
747 | nand_store_ecc(cptr+13, ecc); | ||
748 | } | ||
749 | nand_compute_ecc(bptr + (pagesize / 2), ecc); | ||
750 | if (!nand_compare_ecc(cptr+8, ecc)) { | ||
751 | US_DEBUGP("Warning: bad ecc in page %d+ of pba %d\n", | ||
752 | i, pba); | ||
753 | nand_store_ecc(cptr+8, ecc); | ||
754 | } | ||
755 | cptr[6] = cptr[11] = MSB_of(lbap); | ||
756 | cptr[7] = cptr[12] = LSB_of(lbap); | ||
757 | } | ||
758 | |||
759 | /* copy in new stuff and compute ECC */ | ||
760 | xptr = ptr; | ||
761 | for (i = page; i < page+pages; i++) { | ||
762 | bptr = blockbuffer + (i * (pagesize + 64)); | ||
763 | cptr = bptr + pagesize; | ||
764 | memcpy(bptr, xptr, pagesize); | ||
765 | xptr += pagesize; | ||
766 | nand_compute_ecc(bptr, ecc); | ||
767 | nand_store_ecc(cptr+13, ecc); | ||
768 | nand_compute_ecc(bptr + (pagesize / 2), ecc); | ||
769 | nand_store_ecc(cptr+8, ecc); | ||
770 | } | ||
771 | |||
772 | result = alauda_write_block(us, new_pba, blockbuffer); | ||
773 | if (result != USB_STOR_XFER_GOOD) | ||
774 | return result; | ||
775 | |||
776 | new_pba_offset = new_pba - (zone * zonesize); | ||
777 | MEDIA_INFO(us).pba_to_lba[zone][new_pba_offset] = lba; | ||
778 | MEDIA_INFO(us).lba_to_pba[zone][lba_offset] = new_pba; | ||
779 | US_DEBUGP("alauda_write_lba: Remapped LBA %d to PBA %d\n", | ||
780 | lba, new_pba); | ||
781 | |||
782 | if (pba != UNDEF) { | ||
783 | unsigned int pba_offset = pba - (zone * zonesize); | ||
784 | result = alauda_erase_block(us, pba); | ||
785 | if (result != USB_STOR_XFER_GOOD) | ||
786 | return result; | ||
787 | MEDIA_INFO(us).pba_to_lba[zone][pba_offset] = UNDEF; | ||
788 | } | ||
789 | |||
790 | return USB_STOR_TRANSPORT_GOOD; | ||
791 | } | ||
792 | |||
793 | /* | ||
794 | * Read data from a specific sector address | ||
795 | */ | ||
796 | static int alauda_read_data(struct us_data *us, unsigned long address, | ||
797 | unsigned int sectors) | ||
798 | { | ||
799 | unsigned char *buffer; | ||
800 | u16 lba, max_lba; | ||
801 | unsigned int page, len, index, offset; | ||
802 | unsigned int blockshift = MEDIA_INFO(us).blockshift; | ||
803 | unsigned int pageshift = MEDIA_INFO(us).pageshift; | ||
804 | unsigned int blocksize = MEDIA_INFO(us).blocksize; | ||
805 | unsigned int pagesize = MEDIA_INFO(us).pagesize; | ||
806 | unsigned int uzonesize = MEDIA_INFO(us).uzonesize; | ||
807 | int result; | ||
808 | |||
809 | /* | ||
810 | * Since we only read in one block at a time, we have to create | ||
811 | * a bounce buffer and move the data a piece at a time between the | ||
812 | * bounce buffer and the actual transfer buffer. | ||
813 | * We make this buffer big enough to hold temporary redundancy data, | ||
814 | * which we use when reading the data blocks. | ||
815 | */ | ||
816 | |||
817 | len = min(sectors, blocksize) * (pagesize + 64); | ||
818 | buffer = kmalloc(len, GFP_NOIO); | ||
819 | if (buffer == NULL) { | ||
820 | printk("alauda_read_data: Out of memory\n"); | ||
821 | return USB_STOR_TRANSPORT_ERROR; | ||
822 | } | ||
823 | |||
824 | /* Figure out the initial LBA and page */ | ||
825 | lba = address >> blockshift; | ||
826 | page = (address & MEDIA_INFO(us).blockmask); | ||
827 | max_lba = MEDIA_INFO(us).capacity >> (blockshift + pageshift); | ||
828 | |||
829 | result = USB_STOR_TRANSPORT_GOOD; | ||
830 | index = offset = 0; | ||
831 | |||
832 | while (sectors > 0) { | ||
833 | unsigned int zone = lba / uzonesize; /* integer division */ | ||
834 | unsigned int lba_offset = lba - (zone * uzonesize); | ||
835 | unsigned int pages; | ||
836 | u16 pba; | ||
837 | alauda_ensure_map_for_zone(us, zone); | ||
838 | |||
839 | /* Not overflowing capacity? */ | ||
840 | if (lba >= max_lba) { | ||
841 | US_DEBUGP("Error: Requested lba %u exceeds " | ||
842 | "maximum %u\n", lba, max_lba); | ||
843 | result = USB_STOR_TRANSPORT_ERROR; | ||
844 | break; | ||
845 | } | ||
846 | |||
847 | /* Find number of pages we can read in this block */ | ||
848 | pages = min(sectors, blocksize - page); | ||
849 | len = pages << pageshift; | ||
850 | |||
851 | /* Find where this lba lives on disk */ | ||
852 | pba = MEDIA_INFO(us).lba_to_pba[zone][lba_offset]; | ||
853 | |||
854 | if (pba == UNDEF) { /* this lba was never written */ | ||
855 | US_DEBUGP("Read %d zero pages (LBA %d) page %d\n", | ||
856 | pages, lba, page); | ||
857 | |||
858 | /* This is not really an error. It just means | ||
859 | that the block has never been written. | ||
860 | Instead of returning USB_STOR_TRANSPORT_ERROR | ||
861 | it is better to return all zero data. */ | ||
862 | |||
863 | memset(buffer, 0, len); | ||
864 | } else { | ||
865 | US_DEBUGP("Read %d pages, from PBA %d" | ||
866 | " (LBA %d) page %d\n", | ||
867 | pages, pba, lba, page); | ||
868 | |||
869 | result = alauda_read_block(us, pba, page, pages, buffer); | ||
870 | if (result != USB_STOR_TRANSPORT_GOOD) | ||
871 | break; | ||
872 | } | ||
873 | |||
874 | /* Store the data in the transfer buffer */ | ||
875 | usb_stor_access_xfer_buf(buffer, len, us->srb, | ||
876 | &index, &offset, TO_XFER_BUF); | ||
877 | |||
878 | page = 0; | ||
879 | lba++; | ||
880 | sectors -= pages; | ||
881 | } | ||
882 | |||
883 | kfree(buffer); | ||
884 | return result; | ||
885 | } | ||
886 | |||
887 | /* | ||
888 | * Write data to a specific sector address | ||
889 | */ | ||
890 | static int alauda_write_data(struct us_data *us, unsigned long address, | ||
891 | unsigned int sectors) | ||
892 | { | ||
893 | unsigned char *buffer, *blockbuffer; | ||
894 | unsigned int page, len, index, offset; | ||
895 | unsigned int blockshift = MEDIA_INFO(us).blockshift; | ||
896 | unsigned int pageshift = MEDIA_INFO(us).pageshift; | ||
897 | unsigned int blocksize = MEDIA_INFO(us).blocksize; | ||
898 | unsigned int pagesize = MEDIA_INFO(us).pagesize; | ||
899 | u16 lba, max_lba; | ||
900 | int result; | ||
901 | |||
902 | /* | ||
903 | * Since we don't write the user data directly to the device, | ||
904 | * we have to create a bounce buffer and move the data a piece | ||
905 | * at a time between the bounce buffer and the actual transfer buffer. | ||
906 | */ | ||
907 | |||
908 | len = min(sectors, blocksize) * pagesize; | ||
909 | buffer = kmalloc(len, GFP_NOIO); | ||
910 | if (buffer == NULL) { | ||
911 | printk("alauda_write_data: Out of memory\n"); | ||
912 | return USB_STOR_TRANSPORT_ERROR; | ||
913 | } | ||
914 | |||
915 | /* | ||
916 | * We also need a temporary block buffer, where we read in the old data, | ||
917 | * overwrite parts with the new data, and manipulate the redundancy data | ||
918 | */ | ||
919 | blockbuffer = kmalloc((pagesize + 64) * blocksize, GFP_NOIO); | ||
920 | if (blockbuffer == NULL) { | ||
921 | printk("alauda_write_data: Out of memory\n"); | ||
922 | kfree(buffer); | ||
923 | return USB_STOR_TRANSPORT_ERROR; | ||
924 | } | ||
925 | |||
926 | /* Figure out the initial LBA and page */ | ||
927 | lba = address >> blockshift; | ||
928 | page = (address & MEDIA_INFO(us).blockmask); | ||
929 | max_lba = MEDIA_INFO(us).capacity >> (pageshift + blockshift); | ||
930 | |||
931 | result = USB_STOR_TRANSPORT_GOOD; | ||
932 | index = offset = 0; | ||
933 | |||
934 | while (sectors > 0) { | ||
935 | /* Write as many sectors as possible in this block */ | ||
936 | unsigned int pages = min(sectors, blocksize - page); | ||
937 | len = pages << pageshift; | ||
938 | |||
939 | /* Not overflowing capacity? */ | ||
940 | if (lba >= max_lba) { | ||
941 | US_DEBUGP("alauda_write_data: Requested lba %u exceeds " | ||
942 | "maximum %u\n", lba, max_lba); | ||
943 | result = USB_STOR_TRANSPORT_ERROR; | ||
944 | break; | ||
945 | } | ||
946 | |||
947 | /* Get the data from the transfer buffer */ | ||
948 | usb_stor_access_xfer_buf(buffer, len, us->srb, | ||
949 | &index, &offset, FROM_XFER_BUF); | ||
950 | |||
951 | result = alauda_write_lba(us, lba, page, pages, buffer, | ||
952 | blockbuffer); | ||
953 | if (result != USB_STOR_TRANSPORT_GOOD) | ||
954 | break; | ||
955 | |||
956 | page = 0; | ||
957 | lba++; | ||
958 | sectors -= pages; | ||
959 | } | ||
960 | |||
961 | kfree(buffer); | ||
962 | kfree(blockbuffer); | ||
963 | return result; | ||
964 | } | ||
965 | |||
966 | /* | ||
967 | * Our interface with the rest of the world | ||
968 | */ | ||
969 | |||
970 | static void alauda_info_destructor(void *extra) | ||
971 | { | ||
972 | struct alauda_info *info = (struct alauda_info *) extra; | ||
973 | int port; | ||
974 | |||
975 | if (!info) | ||
976 | return; | ||
977 | |||
978 | for (port = 0; port < 2; port++) { | ||
979 | struct alauda_media_info *media_info = &info->port[port]; | ||
980 | |||
981 | alauda_free_maps(media_info); | ||
982 | kfree(media_info->lba_to_pba); | ||
983 | kfree(media_info->pba_to_lba); | ||
984 | } | ||
985 | } | ||
986 | |||
987 | /* | ||
988 | * Initialize alauda_info struct and find the data-write endpoint | ||
989 | */ | ||
990 | int init_alauda(struct us_data *us) | ||
991 | { | ||
992 | struct alauda_info *info; | ||
993 | struct usb_host_interface *altsetting = us->pusb_intf->cur_altsetting; | ||
994 | nand_init_ecc(); | ||
995 | |||
996 | us->extra = kzalloc(sizeof(struct alauda_info), GFP_NOIO); | ||
997 | if (!us->extra) { | ||
998 | US_DEBUGP("init_alauda: Gah! Can't allocate storage for" | ||
999 | "alauda info struct!\n"); | ||
1000 | return USB_STOR_TRANSPORT_ERROR; | ||
1001 | } | ||
1002 | info = (struct alauda_info *) us->extra; | ||
1003 | us->extra_destructor = alauda_info_destructor; | ||
1004 | |||
1005 | info->wr_ep = usb_sndbulkpipe(us->pusb_dev, | ||
1006 | altsetting->endpoint[0].desc.bEndpointAddress | ||
1007 | & USB_ENDPOINT_NUMBER_MASK); | ||
1008 | |||
1009 | return USB_STOR_TRANSPORT_GOOD; | ||
1010 | } | ||
1011 | |||
1012 | int alauda_transport(struct scsi_cmnd *srb, struct us_data *us) | ||
1013 | { | ||
1014 | int rc; | ||
1015 | struct alauda_info *info = (struct alauda_info *) us->extra; | ||
1016 | unsigned char *ptr = us->iobuf; | ||
1017 | static unsigned char inquiry_response[36] = { | ||
1018 | 0x00, 0x80, 0x00, 0x01, 0x1F, 0x00, 0x00, 0x00 | ||
1019 | }; | ||
1020 | |||
1021 | if (srb->cmnd[0] == INQUIRY) { | ||
1022 | US_DEBUGP("alauda_transport: INQUIRY. " | ||
1023 | "Returning bogus response.\n"); | ||
1024 | memcpy(ptr, inquiry_response, sizeof(inquiry_response)); | ||
1025 | fill_inquiry_response(us, ptr, 36); | ||
1026 | return USB_STOR_TRANSPORT_GOOD; | ||
1027 | } | ||
1028 | |||
1029 | if (srb->cmnd[0] == TEST_UNIT_READY) { | ||
1030 | US_DEBUGP("alauda_transport: TEST_UNIT_READY.\n"); | ||
1031 | return alauda_check_media(us); | ||
1032 | } | ||
1033 | |||
1034 | if (srb->cmnd[0] == READ_CAPACITY) { | ||
1035 | unsigned int num_zones; | ||
1036 | unsigned long capacity; | ||
1037 | |||
1038 | rc = alauda_check_media(us); | ||
1039 | if (rc != USB_STOR_TRANSPORT_GOOD) | ||
1040 | return rc; | ||
1041 | |||
1042 | num_zones = MEDIA_INFO(us).capacity >> (MEDIA_INFO(us).zoneshift | ||
1043 | + MEDIA_INFO(us).blockshift + MEDIA_INFO(us).pageshift); | ||
1044 | |||
1045 | capacity = num_zones * MEDIA_INFO(us).uzonesize | ||
1046 | * MEDIA_INFO(us).blocksize; | ||
1047 | |||
1048 | /* Report capacity and page size */ | ||
1049 | ((__be32 *) ptr)[0] = cpu_to_be32(capacity - 1); | ||
1050 | ((__be32 *) ptr)[1] = cpu_to_be32(512); | ||
1051 | |||
1052 | usb_stor_set_xfer_buf(ptr, 8, srb); | ||
1053 | return USB_STOR_TRANSPORT_GOOD; | ||
1054 | } | ||
1055 | |||
1056 | if (srb->cmnd[0] == READ_10) { | ||
1057 | unsigned int page, pages; | ||
1058 | |||
1059 | rc = alauda_check_media(us); | ||
1060 | if (rc != USB_STOR_TRANSPORT_GOOD) | ||
1061 | return rc; | ||
1062 | |||
1063 | page = short_pack(srb->cmnd[3], srb->cmnd[2]); | ||
1064 | page <<= 16; | ||
1065 | page |= short_pack(srb->cmnd[5], srb->cmnd[4]); | ||
1066 | pages = short_pack(srb->cmnd[8], srb->cmnd[7]); | ||
1067 | |||
1068 | US_DEBUGP("alauda_transport: READ_10: page %d pagect %d\n", | ||
1069 | page, pages); | ||
1070 | |||
1071 | return alauda_read_data(us, page, pages); | ||
1072 | } | ||
1073 | |||
1074 | if (srb->cmnd[0] == WRITE_10) { | ||
1075 | unsigned int page, pages; | ||
1076 | |||
1077 | rc = alauda_check_media(us); | ||
1078 | if (rc != USB_STOR_TRANSPORT_GOOD) | ||
1079 | return rc; | ||
1080 | |||
1081 | page = short_pack(srb->cmnd[3], srb->cmnd[2]); | ||
1082 | page <<= 16; | ||
1083 | page |= short_pack(srb->cmnd[5], srb->cmnd[4]); | ||
1084 | pages = short_pack(srb->cmnd[8], srb->cmnd[7]); | ||
1085 | |||
1086 | US_DEBUGP("alauda_transport: WRITE_10: page %d pagect %d\n", | ||
1087 | page, pages); | ||
1088 | |||
1089 | return alauda_write_data(us, page, pages); | ||
1090 | } | ||
1091 | |||
1092 | if (srb->cmnd[0] == REQUEST_SENSE) { | ||
1093 | US_DEBUGP("alauda_transport: REQUEST_SENSE.\n"); | ||
1094 | |||
1095 | memset(ptr, 0, 18); | ||
1096 | ptr[0] = 0xF0; | ||
1097 | ptr[2] = info->sense_key; | ||
1098 | ptr[7] = 11; | ||
1099 | ptr[12] = info->sense_asc; | ||
1100 | ptr[13] = info->sense_ascq; | ||
1101 | usb_stor_set_xfer_buf(ptr, 18, srb); | ||
1102 | |||
1103 | return USB_STOR_TRANSPORT_GOOD; | ||
1104 | } | ||
1105 | |||
1106 | if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) { | ||
1107 | /* sure. whatever. not like we can stop the user from popping | ||
1108 | the media out of the device (no locking doors, etc) */ | ||
1109 | return USB_STOR_TRANSPORT_GOOD; | ||
1110 | } | ||
1111 | |||
1112 | US_DEBUGP("alauda_transport: Gah! Unknown command: %d (0x%x)\n", | ||
1113 | srb->cmnd[0], srb->cmnd[0]); | ||
1114 | info->sense_key = 0x05; | ||
1115 | info->sense_asc = 0x20; | ||
1116 | info->sense_ascq = 0x00; | ||
1117 | return USB_STOR_TRANSPORT_FAILED; | ||
1118 | } | ||
1119 | |||
diff --git a/drivers/usb/storage/alauda.h b/drivers/usb/storage/alauda.h new file mode 100644 index 000000000000..a700f87d0803 --- /dev/null +++ b/drivers/usb/storage/alauda.h | |||
@@ -0,0 +1,100 @@ | |||
1 | /* | ||
2 | * Driver for Alauda-based card readers | ||
3 | * | ||
4 | * Current development and maintenance by: | ||
5 | * (c) 2005 Daniel Drake <dsd@gentoo.org> | ||
6 | * | ||
7 | * See alauda.c for more explanation. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2, or (at your option) any | ||
12 | * later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License along | ||
20 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
21 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | #ifndef _USB_ALAUDA_H | ||
25 | #define _USB_ALAUDA_H | ||
26 | |||
27 | /* | ||
28 | * Status bytes | ||
29 | */ | ||
30 | #define ALAUDA_STATUS_ERROR 0x01 | ||
31 | #define ALAUDA_STATUS_READY 0x40 | ||
32 | |||
33 | /* | ||
34 | * Control opcodes (for request field) | ||
35 | */ | ||
36 | #define ALAUDA_GET_XD_MEDIA_STATUS 0x08 | ||
37 | #define ALAUDA_GET_SM_MEDIA_STATUS 0x98 | ||
38 | #define ALAUDA_ACK_XD_MEDIA_CHANGE 0x0a | ||
39 | #define ALAUDA_ACK_SM_MEDIA_CHANGE 0x9a | ||
40 | #define ALAUDA_GET_XD_MEDIA_SIG 0x86 | ||
41 | #define ALAUDA_GET_SM_MEDIA_SIG 0x96 | ||
42 | |||
43 | /* | ||
44 | * Bulk command identity (byte 0) | ||
45 | */ | ||
46 | #define ALAUDA_BULK_CMD 0x40 | ||
47 | |||
48 | /* | ||
49 | * Bulk opcodes (byte 1) | ||
50 | */ | ||
51 | #define ALAUDA_BULK_GET_REDU_DATA 0x85 | ||
52 | #define ALAUDA_BULK_READ_BLOCK 0x94 | ||
53 | #define ALAUDA_BULK_ERASE_BLOCK 0xa3 | ||
54 | #define ALAUDA_BULK_WRITE_BLOCK 0xb4 | ||
55 | #define ALAUDA_BULK_GET_STATUS2 0xb7 | ||
56 | #define ALAUDA_BULK_RESET_MEDIA 0xe0 | ||
57 | |||
58 | /* | ||
59 | * Port to operate on (byte 8) | ||
60 | */ | ||
61 | #define ALAUDA_PORT_XD 0x00 | ||
62 | #define ALAUDA_PORT_SM 0x01 | ||
63 | |||
64 | /* | ||
65 | * LBA and PBA are unsigned ints. Special values. | ||
66 | */ | ||
67 | #define UNDEF 0xffff | ||
68 | #define SPARE 0xfffe | ||
69 | #define UNUSABLE 0xfffd | ||
70 | |||
71 | int init_alauda(struct us_data *us); | ||
72 | int alauda_transport(struct scsi_cmnd *srb, struct us_data *us); | ||
73 | |||
74 | struct alauda_media_info { | ||
75 | unsigned long capacity; /* total media size in bytes */ | ||
76 | unsigned int pagesize; /* page size in bytes */ | ||
77 | unsigned int blocksize; /* number of pages per block */ | ||
78 | unsigned int uzonesize; /* number of usable blocks per zone */ | ||
79 | unsigned int zonesize; /* number of blocks per zone */ | ||
80 | unsigned int blockmask; /* mask to get page from address */ | ||
81 | |||
82 | unsigned char pageshift; | ||
83 | unsigned char blockshift; | ||
84 | unsigned char zoneshift; | ||
85 | |||
86 | u16 **lba_to_pba; /* logical to physical block map */ | ||
87 | u16 **pba_to_lba; /* physical to logical block map */ | ||
88 | }; | ||
89 | |||
90 | struct alauda_info { | ||
91 | struct alauda_media_info port[2]; | ||
92 | int wr_ep; /* endpoint to write data out of */ | ||
93 | |||
94 | unsigned char sense_key; | ||
95 | unsigned long sense_asc; /* additional sense code */ | ||
96 | unsigned long sense_ascq; /* additional sense code qualifier */ | ||
97 | }; | ||
98 | |||
99 | #endif | ||
100 | |||
diff --git a/drivers/usb/storage/debug.c b/drivers/usb/storage/debug.c index 5a9321705a74..01e430654a13 100644 --- a/drivers/usb/storage/debug.c +++ b/drivers/usb/storage/debug.c | |||
@@ -132,6 +132,7 @@ void usb_stor_show_command(struct scsi_cmnd *srb) | |||
132 | case 0x5C: what = "READ BUFFER CAPACITY"; break; | 132 | case 0x5C: what = "READ BUFFER CAPACITY"; break; |
133 | case 0x5D: what = "SEND CUE SHEET"; break; | 133 | case 0x5D: what = "SEND CUE SHEET"; break; |
134 | case GPCMD_BLANK: what = "BLANK"; break; | 134 | case GPCMD_BLANK: what = "BLANK"; break; |
135 | case REPORT_LUNS: what = "REPORT LUNS"; break; | ||
135 | case MOVE_MEDIUM: what = "MOVE_MEDIUM or PLAY AUDIO (12)"; break; | 136 | case MOVE_MEDIUM: what = "MOVE_MEDIUM or PLAY AUDIO (12)"; break; |
136 | case READ_12: what = "READ_12"; break; | 137 | case READ_12: what = "READ_12"; break; |
137 | case WRITE_12: what = "WRITE_12"; break; | 138 | case WRITE_12: what = "WRITE_12"; break; |
diff --git a/drivers/usb/storage/initializers.h b/drivers/usb/storage/initializers.h index 7372386f33d5..4c1b2bd2e2e4 100644 --- a/drivers/usb/storage/initializers.h +++ b/drivers/usb/storage/initializers.h | |||
@@ -45,10 +45,6 @@ | |||
45 | * mode */ | 45 | * mode */ |
46 | int usb_stor_euscsi_init(struct us_data *us); | 46 | int usb_stor_euscsi_init(struct us_data *us); |
47 | 47 | ||
48 | #ifdef CONFIG_USB_STORAGE_SDDR09 | ||
49 | int sddr09_init(struct us_data *us); | ||
50 | #endif | ||
51 | |||
52 | /* This function is required to activate all four slots on the UCR-61S2B | 48 | /* This function is required to activate all four slots on the UCR-61S2B |
53 | * flash reader */ | 49 | * flash reader */ |
54 | int usb_stor_ucr61s2b_init(struct us_data *us); | 50 | int usb_stor_ucr61s2b_init(struct us_data *us); |
diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c new file mode 100644 index 000000000000..b28151d1b609 --- /dev/null +++ b/drivers/usb/storage/libusual.c | |||
@@ -0,0 +1,266 @@ | |||
1 | /* | ||
2 | * libusual | ||
3 | * | ||
4 | * The libusual contains the table of devices common for ub and usb-storage. | ||
5 | */ | ||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/usb.h> | ||
9 | #include <linux/usb_usual.h> | ||
10 | #include <linux/vmalloc.h> | ||
11 | |||
12 | /* | ||
13 | */ | ||
14 | #define USU_MOD_FL_THREAD 1 /* Thread is running */ | ||
15 | #define USU_MOD_FL_PRESENT 2 /* The module is loaded */ | ||
16 | |||
17 | struct mod_status { | ||
18 | unsigned long fls; | ||
19 | }; | ||
20 | |||
21 | static struct mod_status stat[3]; | ||
22 | static DEFINE_SPINLOCK(usu_lock); | ||
23 | |||
24 | /* | ||
25 | */ | ||
26 | #define USB_US_DEFAULT_BIAS USB_US_TYPE_STOR | ||
27 | static atomic_t usu_bias = ATOMIC_INIT(USB_US_DEFAULT_BIAS); | ||
28 | |||
29 | #define BIAS_NAME_SIZE (sizeof("usb-storage")) | ||
30 | static const char *bias_names[3] = { "none", "usb-storage", "ub" }; | ||
31 | |||
32 | static DECLARE_MUTEX_LOCKED(usu_init_notify); | ||
33 | static DECLARE_COMPLETION(usu_end_notify); | ||
34 | static atomic_t total_threads = ATOMIC_INIT(0); | ||
35 | |||
36 | static int usu_probe_thread(void *arg); | ||
37 | |||
38 | /* | ||
39 | * The table. | ||
40 | */ | ||
41 | #define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ | ||
42 | vendorName, productName,useProtocol, useTransport, \ | ||
43 | initFunction, flags) \ | ||
44 | { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \ | ||
45 | .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } | ||
46 | |||
47 | #define USUAL_DEV(useProto, useTrans, useType) \ | ||
48 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \ | ||
49 | .driver_info = ((useType)<<24) } | ||
50 | |||
51 | struct usb_device_id storage_usb_ids [] = { | ||
52 | # include "unusual_devs.h" | ||
53 | { } /* Terminating entry */ | ||
54 | }; | ||
55 | |||
56 | #undef USUAL_DEV | ||
57 | #undef UNUSUAL_DEV | ||
58 | |||
59 | MODULE_DEVICE_TABLE(usb, storage_usb_ids); | ||
60 | EXPORT_SYMBOL_GPL(storage_usb_ids); | ||
61 | |||
62 | /* | ||
63 | * @type: the module type as an integer | ||
64 | */ | ||
65 | void usb_usual_set_present(int type) | ||
66 | { | ||
67 | struct mod_status *st; | ||
68 | unsigned long flags; | ||
69 | |||
70 | if (type <= 0 || type >= 3) | ||
71 | return; | ||
72 | st = &stat[type]; | ||
73 | spin_lock_irqsave(&usu_lock, flags); | ||
74 | st->fls |= USU_MOD_FL_PRESENT; | ||
75 | spin_unlock_irqrestore(&usu_lock, flags); | ||
76 | } | ||
77 | EXPORT_SYMBOL_GPL(usb_usual_set_present); | ||
78 | |||
79 | void usb_usual_clear_present(int type) | ||
80 | { | ||
81 | struct mod_status *st; | ||
82 | unsigned long flags; | ||
83 | |||
84 | if (type <= 0 || type >= 3) | ||
85 | return; | ||
86 | st = &stat[type]; | ||
87 | spin_lock_irqsave(&usu_lock, flags); | ||
88 | st->fls &= ~USU_MOD_FL_PRESENT; | ||
89 | spin_unlock_irqrestore(&usu_lock, flags); | ||
90 | } | ||
91 | EXPORT_SYMBOL_GPL(usb_usual_clear_present); | ||
92 | |||
93 | /* | ||
94 | * Match the calling driver type against the table. | ||
95 | * Returns: 0 if the device matches. | ||
96 | */ | ||
97 | int usb_usual_check_type(const struct usb_device_id *id, int caller_type) | ||
98 | { | ||
99 | int id_type = USB_US_TYPE(id->driver_info); | ||
100 | |||
101 | if (caller_type <= 0 || caller_type >= 3) | ||
102 | return -EINVAL; | ||
103 | |||
104 | /* Drivers grab fixed assignment devices */ | ||
105 | if (id_type == caller_type) | ||
106 | return 0; | ||
107 | /* Drivers grab devices biased to them */ | ||
108 | if (id_type == USB_US_TYPE_NONE && caller_type == atomic_read(&usu_bias)) | ||
109 | return 0; | ||
110 | return -ENODEV; | ||
111 | } | ||
112 | EXPORT_SYMBOL_GPL(usb_usual_check_type); | ||
113 | |||
114 | /* | ||
115 | */ | ||
116 | static int usu_probe(struct usb_interface *intf, | ||
117 | const struct usb_device_id *id) | ||
118 | { | ||
119 | int type; | ||
120 | int rc; | ||
121 | unsigned long flags; | ||
122 | |||
123 | type = USB_US_TYPE(id->driver_info); | ||
124 | if (type == 0) | ||
125 | type = atomic_read(&usu_bias); | ||
126 | |||
127 | spin_lock_irqsave(&usu_lock, flags); | ||
128 | if ((stat[type].fls & (USU_MOD_FL_THREAD|USU_MOD_FL_PRESENT)) != 0) { | ||
129 | spin_unlock_irqrestore(&usu_lock, flags); | ||
130 | return -ENXIO; | ||
131 | } | ||
132 | stat[type].fls |= USU_MOD_FL_THREAD; | ||
133 | spin_unlock_irqrestore(&usu_lock, flags); | ||
134 | |||
135 | rc = kernel_thread(usu_probe_thread, (void*)type, CLONE_VM); | ||
136 | if (rc < 0) { | ||
137 | printk(KERN_WARNING "libusual: " | ||
138 | "Unable to start the thread for %s: %d\n", | ||
139 | bias_names[type], rc); | ||
140 | spin_lock_irqsave(&usu_lock, flags); | ||
141 | stat[type].fls &= ~USU_MOD_FL_THREAD; | ||
142 | spin_unlock_irqrestore(&usu_lock, flags); | ||
143 | return rc; /* Not being -ENXIO causes a message printed */ | ||
144 | } | ||
145 | atomic_inc(&total_threads); | ||
146 | |||
147 | return -ENXIO; | ||
148 | } | ||
149 | |||
150 | static void usu_disconnect(struct usb_interface *intf) | ||
151 | { | ||
152 | ; /* We should not be here. */ | ||
153 | } | ||
154 | |||
155 | static struct usb_driver usu_driver = { | ||
156 | .name = "libusual", | ||
157 | .probe = usu_probe, | ||
158 | .disconnect = usu_disconnect, | ||
159 | .id_table = storage_usb_ids, | ||
160 | }; | ||
161 | |||
162 | /* | ||
163 | * A whole new thread for a purpose of request_module seems quite stupid. | ||
164 | * The request_module forks once inside again. However, if we attempt | ||
165 | * to load a storage module from our own modprobe thread, that module | ||
166 | * references our symbols, which cannot be resolved until our module is | ||
167 | * initialized. I wish there was a way to wait for the end of initialization. | ||
168 | * The module notifier reports MODULE_STATE_COMING only. | ||
169 | * So, we wait until module->init ends as the next best thing. | ||
170 | */ | ||
171 | static int usu_probe_thread(void *arg) | ||
172 | { | ||
173 | int type = (unsigned long) arg; | ||
174 | struct mod_status *st = &stat[type]; | ||
175 | int rc; | ||
176 | unsigned long flags; | ||
177 | |||
178 | daemonize("libusual_%d", type); /* "usb-storage" is kinda too long */ | ||
179 | |||
180 | /* A completion does not work here because it's counted. */ | ||
181 | down(&usu_init_notify); | ||
182 | up(&usu_init_notify); | ||
183 | |||
184 | rc = request_module(bias_names[type]); | ||
185 | spin_lock_irqsave(&usu_lock, flags); | ||
186 | if (rc == 0 && (st->fls & USU_MOD_FL_PRESENT) == 0) { | ||
187 | /* | ||
188 | * This should not happen, but let us keep tabs on it. | ||
189 | */ | ||
190 | printk(KERN_NOTICE "libusual: " | ||
191 | "modprobe for %s succeeded, but module is not present\n", | ||
192 | bias_names[type]); | ||
193 | } | ||
194 | st->fls &= ~USU_MOD_FL_THREAD; | ||
195 | spin_unlock_irqrestore(&usu_lock, flags); | ||
196 | |||
197 | complete_and_exit(&usu_end_notify, 0); | ||
198 | } | ||
199 | |||
200 | /* | ||
201 | */ | ||
202 | static int __init usb_usual_init(void) | ||
203 | { | ||
204 | int rc; | ||
205 | |||
206 | rc = usb_register(&usu_driver); | ||
207 | up(&usu_init_notify); | ||
208 | return rc; | ||
209 | } | ||
210 | |||
211 | static void __exit usb_usual_exit(void) | ||
212 | { | ||
213 | /* | ||
214 | * We do not check for any drivers present, because | ||
215 | * they keep us pinned with symbol references. | ||
216 | */ | ||
217 | |||
218 | usb_deregister(&usu_driver); | ||
219 | |||
220 | while (atomic_read(&total_threads) > 0) { | ||
221 | wait_for_completion(&usu_end_notify); | ||
222 | atomic_dec(&total_threads); | ||
223 | } | ||
224 | } | ||
225 | |||
226 | /* | ||
227 | * Validate and accept the bias parameter. | ||
228 | */ | ||
229 | static int usu_set_bias(const char *bias_s, struct kernel_param *kp) | ||
230 | { | ||
231 | int i; | ||
232 | int len; | ||
233 | int bias_n = 0; | ||
234 | |||
235 | len = strlen(bias_s); | ||
236 | if (len == 0) | ||
237 | return -EDOM; | ||
238 | if (bias_s[len-1] == '\n') | ||
239 | --len; | ||
240 | |||
241 | for (i = 1; i < 3; i++) { | ||
242 | if (strncmp(bias_s, bias_names[i], len) == 0) { | ||
243 | bias_n = i; | ||
244 | break; | ||
245 | } | ||
246 | } | ||
247 | if (bias_n == 0) | ||
248 | return -EINVAL; | ||
249 | |||
250 | atomic_set(&usu_bias, bias_n); | ||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | static int usu_get_bias(char *buffer, struct kernel_param *kp) | ||
255 | { | ||
256 | return strlen(strcpy(buffer, bias_names[atomic_read(&usu_bias)])); | ||
257 | } | ||
258 | |||
259 | module_init(usb_usual_init); | ||
260 | module_exit(usb_usual_exit); | ||
261 | |||
262 | module_param_call(bias, usu_set_bias, usu_get_bias, NULL, S_IRUGO|S_IWUSR); | ||
263 | __MODULE_PARM_TYPE(bias, "string"); | ||
264 | MODULE_PARM_DESC(bias, "Bias to usb-storage or ub"); | ||
265 | |||
266 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c index 89401a59f952..55ee2d36d585 100644 --- a/drivers/usb/storage/onetouch.c +++ b/drivers/usb/storage/onetouch.c | |||
@@ -52,6 +52,7 @@ struct usb_onetouch { | |||
52 | struct urb *irq; /* urb for interrupt in report */ | 52 | struct urb *irq; /* urb for interrupt in report */ |
53 | unsigned char *data; /* input data */ | 53 | unsigned char *data; /* input data */ |
54 | dma_addr_t data_dma; | 54 | dma_addr_t data_dma; |
55 | unsigned int is_open:1; | ||
55 | }; | 56 | }; |
56 | 57 | ||
57 | static void usb_onetouch_irq(struct urb *urb, struct pt_regs *regs) | 58 | static void usb_onetouch_irq(struct urb *urb, struct pt_regs *regs) |
@@ -89,6 +90,7 @@ static int usb_onetouch_open(struct input_dev *dev) | |||
89 | { | 90 | { |
90 | struct usb_onetouch *onetouch = dev->private; | 91 | struct usb_onetouch *onetouch = dev->private; |
91 | 92 | ||
93 | onetouch->is_open = 1; | ||
92 | onetouch->irq->dev = onetouch->udev; | 94 | onetouch->irq->dev = onetouch->udev; |
93 | if (usb_submit_urb(onetouch->irq, GFP_KERNEL)) { | 95 | if (usb_submit_urb(onetouch->irq, GFP_KERNEL)) { |
94 | err("usb_submit_urb failed"); | 96 | err("usb_submit_urb failed"); |
@@ -103,8 +105,30 @@ static void usb_onetouch_close(struct input_dev *dev) | |||
103 | struct usb_onetouch *onetouch = dev->private; | 105 | struct usb_onetouch *onetouch = dev->private; |
104 | 106 | ||
105 | usb_kill_urb(onetouch->irq); | 107 | usb_kill_urb(onetouch->irq); |
108 | onetouch->is_open = 0; | ||
106 | } | 109 | } |
107 | 110 | ||
111 | #ifdef CONFIG_PM | ||
112 | static void usb_onetouch_pm_hook(struct us_data *us, int action) | ||
113 | { | ||
114 | struct usb_onetouch *onetouch = (struct usb_onetouch *) us->extra; | ||
115 | |||
116 | if (onetouch->is_open) { | ||
117 | switch (action) { | ||
118 | case US_SUSPEND: | ||
119 | usb_kill_urb(onetouch->irq); | ||
120 | break; | ||
121 | case US_RESUME: | ||
122 | if (usb_submit_urb(onetouch->irq, GFP_KERNEL) != 0) | ||
123 | err("usb_submit_urb failed"); | ||
124 | break; | ||
125 | default: | ||
126 | break; | ||
127 | } | ||
128 | } | ||
129 | } | ||
130 | #endif /* CONFIG_PM */ | ||
131 | |||
108 | int onetouch_connect_input(struct us_data *ss) | 132 | int onetouch_connect_input(struct us_data *ss) |
109 | { | 133 | { |
110 | struct usb_device *udev = ss->pusb_dev; | 134 | struct usb_device *udev = ss->pusb_dev; |
@@ -185,6 +209,9 @@ int onetouch_connect_input(struct us_data *ss) | |||
185 | 209 | ||
186 | ss->extra_destructor = onetouch_release_input; | 210 | ss->extra_destructor = onetouch_release_input; |
187 | ss->extra = onetouch; | 211 | ss->extra = onetouch; |
212 | #ifdef CONFIG_PM | ||
213 | ss->suspend_resume_hook = usb_onetouch_pm_hook; | ||
214 | #endif | ||
188 | 215 | ||
189 | input_register_device(onetouch->dev); | 216 | input_register_device(onetouch->dev); |
190 | 217 | ||
diff --git a/drivers/usb/storage/protocol.h b/drivers/usb/storage/protocol.h index 02bff01ab09c..845bed4b8031 100644 --- a/drivers/usb/storage/protocol.h +++ b/drivers/usb/storage/protocol.h | |||
@@ -41,20 +41,6 @@ | |||
41 | #ifndef _PROTOCOL_H_ | 41 | #ifndef _PROTOCOL_H_ |
42 | #define _PROTOCOL_H_ | 42 | #define _PROTOCOL_H_ |
43 | 43 | ||
44 | /* Sub Classes */ | ||
45 | |||
46 | #define US_SC_RBC 0x01 /* Typically, flash devices */ | ||
47 | #define US_SC_8020 0x02 /* CD-ROM */ | ||
48 | #define US_SC_QIC 0x03 /* QIC-157 Tapes */ | ||
49 | #define US_SC_UFI 0x04 /* Floppy */ | ||
50 | #define US_SC_8070 0x05 /* Removable media */ | ||
51 | #define US_SC_SCSI 0x06 /* Transparent */ | ||
52 | #define US_SC_ISD200 0x07 /* ISD200 ATA */ | ||
53 | #define US_SC_MIN US_SC_RBC | ||
54 | #define US_SC_MAX US_SC_ISD200 | ||
55 | |||
56 | #define US_SC_DEVICE 0xff /* Use device's value */ | ||
57 | |||
58 | /* Protocol handling routines */ | 44 | /* Protocol handling routines */ |
59 | extern void usb_stor_ATAPI_command(struct scsi_cmnd*, struct us_data*); | 45 | extern void usb_stor_ATAPI_command(struct scsi_cmnd*, struct us_data*); |
60 | extern void usb_stor_qic157_command(struct scsi_cmnd*, struct us_data*); | 46 | extern void usb_stor_qic157_command(struct scsi_cmnd*, struct us_data*); |
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c index 0ea2f5ab66ba..fb8bacaae27c 100644 --- a/drivers/usb/storage/sddr09.c +++ b/drivers/usb/storage/sddr09.c | |||
@@ -133,13 +133,11 @@ static struct nand_flash_dev nand_flash_ids[] = { | |||
133 | { 0,} | 133 | { 0,} |
134 | }; | 134 | }; |
135 | 135 | ||
136 | #define SIZE(a) (sizeof(a)/sizeof((a)[0])) | ||
137 | |||
138 | static struct nand_flash_dev * | 136 | static struct nand_flash_dev * |
139 | nand_find_id(unsigned char id) { | 137 | nand_find_id(unsigned char id) { |
140 | int i; | 138 | int i; |
141 | 139 | ||
142 | for (i = 0; i < SIZE(nand_flash_ids); i++) | 140 | for (i = 0; i < ARRAY_SIZE(nand_flash_ids); i++) |
143 | if (nand_flash_ids[i].model_id == id) | 141 | if (nand_flash_ids[i].model_id == id) |
144 | return &(nand_flash_ids[i]); | 142 | return &(nand_flash_ids[i]); |
145 | return NULL; | 143 | return NULL; |
@@ -214,6 +212,20 @@ static void nand_store_ecc(unsigned char *data, unsigned char *ecc) { | |||
214 | * The actual driver starts here. | 212 | * The actual driver starts here. |
215 | */ | 213 | */ |
216 | 214 | ||
215 | struct sddr09_card_info { | ||
216 | unsigned long capacity; /* Size of card in bytes */ | ||
217 | int pagesize; /* Size of page in bytes */ | ||
218 | int pageshift; /* log2 of pagesize */ | ||
219 | int blocksize; /* Size of block in pages */ | ||
220 | int blockshift; /* log2 of blocksize */ | ||
221 | int blockmask; /* 2^blockshift - 1 */ | ||
222 | int *lba_to_pba; /* logical to physical map */ | ||
223 | int *pba_to_lba; /* physical to logical map */ | ||
224 | int lbact; /* number of available pages */ | ||
225 | int flags; | ||
226 | #define SDDR09_WP 1 /* write protected */ | ||
227 | }; | ||
228 | |||
217 | /* | 229 | /* |
218 | * On my 16MB card, control blocks have size 64 (16 real control bytes, | 230 | * On my 16MB card, control blocks have size 64 (16 real control bytes, |
219 | * and 48 junk bytes). In reality of course the card uses 16 control bytes, | 231 | * and 48 junk bytes). In reality of course the card uses 16 control bytes, |
@@ -237,7 +249,7 @@ static void nand_store_ecc(unsigned char *data, unsigned char *ecc) { | |||
237 | #define SPARE 0xfffffffe | 249 | #define SPARE 0xfffffffe |
238 | #define UNUSABLE 0xfffffffd | 250 | #define UNUSABLE 0xfffffffd |
239 | 251 | ||
240 | static int erase_bad_lba_entries = 0; | 252 | static const int erase_bad_lba_entries = 0; |
241 | 253 | ||
242 | /* send vendor interface command (0x41) */ | 254 | /* send vendor interface command (0x41) */ |
243 | /* called for requests 0, 1, 8 */ | 255 | /* called for requests 0, 1, 8 */ |
@@ -260,8 +272,11 @@ sddr09_send_command(struct us_data *us, | |||
260 | 272 | ||
261 | rc = usb_stor_ctrl_transfer(us, pipe, request, requesttype, | 273 | rc = usb_stor_ctrl_transfer(us, pipe, request, requesttype, |
262 | 0, 0, xfer_data, xfer_len); | 274 | 0, 0, xfer_data, xfer_len); |
263 | return (rc == USB_STOR_XFER_GOOD ? USB_STOR_TRANSPORT_GOOD : | 275 | switch (rc) { |
264 | USB_STOR_TRANSPORT_ERROR); | 276 | case USB_STOR_XFER_GOOD: return 0; |
277 | case USB_STOR_XFER_STALLED: return -EPIPE; | ||
278 | default: return -EIO; | ||
279 | } | ||
265 | } | 280 | } |
266 | 281 | ||
267 | static int | 282 | static int |
@@ -308,20 +323,12 @@ sddr09_request_sense(struct us_data *us, unsigned char *sensebuf, int buflen) { | |||
308 | command[4] = buflen; | 323 | command[4] = buflen; |
309 | 324 | ||
310 | result = sddr09_send_scsi_command(us, command, 12); | 325 | result = sddr09_send_scsi_command(us, command, 12); |
311 | if (result != USB_STOR_TRANSPORT_GOOD) { | 326 | if (result) |
312 | US_DEBUGP("request sense failed\n"); | ||
313 | return result; | 327 | return result; |
314 | } | ||
315 | 328 | ||
316 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, | 329 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, |
317 | sensebuf, buflen, NULL); | 330 | sensebuf, buflen, NULL); |
318 | if (result != USB_STOR_XFER_GOOD) { | 331 | return (result == USB_STOR_XFER_GOOD ? 0 : -EIO); |
319 | US_DEBUGP("request sense bulk in failed\n"); | ||
320 | return USB_STOR_TRANSPORT_ERROR; | ||
321 | } else { | ||
322 | US_DEBUGP("request sense worked\n"); | ||
323 | return USB_STOR_TRANSPORT_GOOD; | ||
324 | } | ||
325 | } | 332 | } |
326 | 333 | ||
327 | /* | 334 | /* |
@@ -369,7 +376,7 @@ sddr09_readX(struct us_data *us, int x, unsigned long fromaddress, | |||
369 | 376 | ||
370 | result = sddr09_send_scsi_command(us, command, 12); | 377 | result = sddr09_send_scsi_command(us, command, 12); |
371 | 378 | ||
372 | if (result != USB_STOR_TRANSPORT_GOOD) { | 379 | if (result) { |
373 | US_DEBUGP("Result for send_control in sddr09_read2%d %d\n", | 380 | US_DEBUGP("Result for send_control in sddr09_read2%d %d\n", |
374 | x, result); | 381 | x, result); |
375 | return result; | 382 | return result; |
@@ -381,9 +388,9 @@ sddr09_readX(struct us_data *us, int x, unsigned long fromaddress, | |||
381 | if (result != USB_STOR_XFER_GOOD) { | 388 | if (result != USB_STOR_XFER_GOOD) { |
382 | US_DEBUGP("Result for bulk_transfer in sddr09_read2%d %d\n", | 389 | US_DEBUGP("Result for bulk_transfer in sddr09_read2%d %d\n", |
383 | x, result); | 390 | x, result); |
384 | return USB_STOR_TRANSPORT_ERROR; | 391 | return -EIO; |
385 | } | 392 | } |
386 | return USB_STOR_TRANSPORT_GOOD; | 393 | return 0; |
387 | } | 394 | } |
388 | 395 | ||
389 | /* | 396 | /* |
@@ -497,7 +504,7 @@ sddr09_erase(struct us_data *us, unsigned long Eaddress) { | |||
497 | 504 | ||
498 | result = sddr09_send_scsi_command(us, command, 12); | 505 | result = sddr09_send_scsi_command(us, command, 12); |
499 | 506 | ||
500 | if (result != USB_STOR_TRANSPORT_GOOD) | 507 | if (result) |
501 | US_DEBUGP("Result for send_control in sddr09_erase %d\n", | 508 | US_DEBUGP("Result for send_control in sddr09_erase %d\n", |
502 | result); | 509 | result); |
503 | 510 | ||
@@ -555,7 +562,7 @@ sddr09_writeX(struct us_data *us, | |||
555 | 562 | ||
556 | result = sddr09_send_scsi_command(us, command, 12); | 563 | result = sddr09_send_scsi_command(us, command, 12); |
557 | 564 | ||
558 | if (result != USB_STOR_TRANSPORT_GOOD) { | 565 | if (result) { |
559 | US_DEBUGP("Result for send_control in sddr09_writeX %d\n", | 566 | US_DEBUGP("Result for send_control in sddr09_writeX %d\n", |
560 | result); | 567 | result); |
561 | return result; | 568 | return result; |
@@ -567,9 +574,9 @@ sddr09_writeX(struct us_data *us, | |||
567 | if (result != USB_STOR_XFER_GOOD) { | 574 | if (result != USB_STOR_XFER_GOOD) { |
568 | US_DEBUGP("Result for bulk_transfer in sddr09_writeX %d\n", | 575 | US_DEBUGP("Result for bulk_transfer in sddr09_writeX %d\n", |
569 | result); | 576 | result); |
570 | return USB_STOR_TRANSPORT_ERROR; | 577 | return -EIO; |
571 | } | 578 | } |
572 | return USB_STOR_TRANSPORT_GOOD; | 579 | return 0; |
573 | } | 580 | } |
574 | 581 | ||
575 | /* erase address, write same address */ | 582 | /* erase address, write same address */ |
@@ -633,7 +640,7 @@ sddr09_read_sg_test_only(struct us_data *us) { | |||
633 | 640 | ||
634 | result = sddr09_send_scsi_command(us, command, 4*nsg+3); | 641 | result = sddr09_send_scsi_command(us, command, 4*nsg+3); |
635 | 642 | ||
636 | if (result != USB_STOR_TRANSPORT_GOOD) { | 643 | if (result) { |
637 | US_DEBUGP("Result for send_control in sddr09_read_sg %d\n", | 644 | US_DEBUGP("Result for send_control in sddr09_read_sg %d\n", |
638 | result); | 645 | result); |
639 | return result; | 646 | return result; |
@@ -641,7 +648,7 @@ sddr09_read_sg_test_only(struct us_data *us) { | |||
641 | 648 | ||
642 | buf = (unsigned char *) kmalloc(bulklen, GFP_NOIO); | 649 | buf = (unsigned char *) kmalloc(bulklen, GFP_NOIO); |
643 | if (!buf) | 650 | if (!buf) |
644 | return USB_STOR_TRANSPORT_ERROR; | 651 | return -ENOMEM; |
645 | 652 | ||
646 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, | 653 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, |
647 | buf, bulklen, NULL); | 654 | buf, bulklen, NULL); |
@@ -649,10 +656,10 @@ sddr09_read_sg_test_only(struct us_data *us) { | |||
649 | if (result != USB_STOR_XFER_GOOD) { | 656 | if (result != USB_STOR_XFER_GOOD) { |
650 | US_DEBUGP("Result for bulk_transfer in sddr09_read_sg %d\n", | 657 | US_DEBUGP("Result for bulk_transfer in sddr09_read_sg %d\n", |
651 | result); | 658 | result); |
652 | return USB_STOR_TRANSPORT_ERROR; | 659 | return -EIO; |
653 | } | 660 | } |
654 | 661 | ||
655 | return USB_STOR_TRANSPORT_GOOD; | 662 | return 0; |
656 | } | 663 | } |
657 | #endif | 664 | #endif |
658 | 665 | ||
@@ -681,14 +688,13 @@ sddr09_read_status(struct us_data *us, unsigned char *status) { | |||
681 | command[1] = LUNBITS; | 688 | command[1] = LUNBITS; |
682 | 689 | ||
683 | result = sddr09_send_scsi_command(us, command, 12); | 690 | result = sddr09_send_scsi_command(us, command, 12); |
684 | if (result != USB_STOR_TRANSPORT_GOOD) | 691 | if (result) |
685 | return result; | 692 | return result; |
686 | 693 | ||
687 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, | 694 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, |
688 | data, 64, NULL); | 695 | data, 64, NULL); |
689 | *status = data[0]; | 696 | *status = data[0]; |
690 | return (result == USB_STOR_XFER_GOOD ? | 697 | return (result == USB_STOR_XFER_GOOD ? 0 : -EIO); |
691 | USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR); | ||
692 | } | 698 | } |
693 | 699 | ||
694 | static int | 700 | static int |
@@ -703,6 +709,13 @@ sddr09_read_data(struct us_data *us, | |||
703 | unsigned int len, index, offset; | 709 | unsigned int len, index, offset; |
704 | int result; | 710 | int result; |
705 | 711 | ||
712 | // Figure out the initial LBA and page | ||
713 | lba = address >> info->blockshift; | ||
714 | page = (address & info->blockmask); | ||
715 | maxlba = info->capacity >> (info->pageshift + info->blockshift); | ||
716 | if (lba >= maxlba) | ||
717 | return -EIO; | ||
718 | |||
706 | // Since we only read in one block at a time, we have to create | 719 | // Since we only read in one block at a time, we have to create |
707 | // a bounce buffer and move the data a piece at a time between the | 720 | // a bounce buffer and move the data a piece at a time between the |
708 | // bounce buffer and the actual transfer buffer. | 721 | // bounce buffer and the actual transfer buffer. |
@@ -711,18 +724,13 @@ sddr09_read_data(struct us_data *us, | |||
711 | buffer = kmalloc(len, GFP_NOIO); | 724 | buffer = kmalloc(len, GFP_NOIO); |
712 | if (buffer == NULL) { | 725 | if (buffer == NULL) { |
713 | printk("sddr09_read_data: Out of memory\n"); | 726 | printk("sddr09_read_data: Out of memory\n"); |
714 | return USB_STOR_TRANSPORT_ERROR; | 727 | return -ENOMEM; |
715 | } | 728 | } |
716 | 729 | ||
717 | // Figure out the initial LBA and page | ||
718 | lba = address >> info->blockshift; | ||
719 | page = (address & info->blockmask); | ||
720 | maxlba = info->capacity >> (info->pageshift + info->blockshift); | ||
721 | |||
722 | // This could be made much more efficient by checking for | 730 | // This could be made much more efficient by checking for |
723 | // contiguous LBA's. Another exercise left to the student. | 731 | // contiguous LBA's. Another exercise left to the student. |
724 | 732 | ||
725 | result = USB_STOR_TRANSPORT_GOOD; | 733 | result = 0; |
726 | index = offset = 0; | 734 | index = offset = 0; |
727 | 735 | ||
728 | while (sectors > 0) { | 736 | while (sectors > 0) { |
@@ -735,7 +743,7 @@ sddr09_read_data(struct us_data *us, | |||
735 | if (lba >= maxlba) { | 743 | if (lba >= maxlba) { |
736 | US_DEBUGP("Error: Requested lba %u exceeds " | 744 | US_DEBUGP("Error: Requested lba %u exceeds " |
737 | "maximum %u\n", lba, maxlba); | 745 | "maximum %u\n", lba, maxlba); |
738 | result = USB_STOR_TRANSPORT_ERROR; | 746 | result = -EIO; |
739 | break; | 747 | break; |
740 | } | 748 | } |
741 | 749 | ||
@@ -749,7 +757,7 @@ sddr09_read_data(struct us_data *us, | |||
749 | 757 | ||
750 | /* This is not really an error. It just means | 758 | /* This is not really an error. It just means |
751 | that the block has never been written. | 759 | that the block has never been written. |
752 | Instead of returning USB_STOR_TRANSPORT_ERROR | 760 | Instead of returning an error |
753 | it is better to return all zero data. */ | 761 | it is better to return all zero data. */ |
754 | 762 | ||
755 | memset(buffer, 0, len); | 763 | memset(buffer, 0, len); |
@@ -764,7 +772,7 @@ sddr09_read_data(struct us_data *us, | |||
764 | 772 | ||
765 | result = sddr09_read20(us, address>>1, | 773 | result = sddr09_read20(us, address>>1, |
766 | pages, info->pageshift, buffer, 0); | 774 | pages, info->pageshift, buffer, 0); |
767 | if (result != USB_STOR_TRANSPORT_GOOD) | 775 | if (result) |
768 | break; | 776 | break; |
769 | } | 777 | } |
770 | 778 | ||
@@ -830,7 +838,7 @@ sddr09_write_lba(struct us_data *us, unsigned int lba, | |||
830 | pba = sddr09_find_unused_pba(info, lba); | 838 | pba = sddr09_find_unused_pba(info, lba); |
831 | if (!pba) { | 839 | if (!pba) { |
832 | printk("sddr09_write_lba: Out of unused blocks\n"); | 840 | printk("sddr09_write_lba: Out of unused blocks\n"); |
833 | return USB_STOR_TRANSPORT_ERROR; | 841 | return -ENOSPC; |
834 | } | 842 | } |
835 | info->pba_to_lba[pba] = lba; | 843 | info->pba_to_lba[pba] = lba; |
836 | info->lba_to_pba[lba] = pba; | 844 | info->lba_to_pba[lba] = pba; |
@@ -841,7 +849,7 @@ sddr09_write_lba(struct us_data *us, unsigned int lba, | |||
841 | /* Maybe it is impossible to write to PBA 1. | 849 | /* Maybe it is impossible to write to PBA 1. |
842 | Fake success, but don't do anything. */ | 850 | Fake success, but don't do anything. */ |
843 | printk("sddr09: avoid writing to pba 1\n"); | 851 | printk("sddr09: avoid writing to pba 1\n"); |
844 | return USB_STOR_TRANSPORT_GOOD; | 852 | return 0; |
845 | } | 853 | } |
846 | 854 | ||
847 | pagelen = (1 << info->pageshift) + (1 << CONTROL_SHIFT); | 855 | pagelen = (1 << info->pageshift) + (1 << CONTROL_SHIFT); |
@@ -850,7 +858,7 @@ sddr09_write_lba(struct us_data *us, unsigned int lba, | |||
850 | address = (pba << (info->pageshift + info->blockshift)); | 858 | address = (pba << (info->pageshift + info->blockshift)); |
851 | result = sddr09_read22(us, address>>1, info->blocksize, | 859 | result = sddr09_read22(us, address>>1, info->blocksize, |
852 | info->pageshift, blockbuffer, 0); | 860 | info->pageshift, blockbuffer, 0); |
853 | if (result != USB_STOR_TRANSPORT_GOOD) | 861 | if (result) |
854 | return result; | 862 | return result; |
855 | 863 | ||
856 | /* check old contents and fill lba */ | 864 | /* check old contents and fill lba */ |
@@ -897,7 +905,7 @@ sddr09_write_lba(struct us_data *us, unsigned int lba, | |||
897 | { | 905 | { |
898 | unsigned char status = 0; | 906 | unsigned char status = 0; |
899 | int result2 = sddr09_read_status(us, &status); | 907 | int result2 = sddr09_read_status(us, &status); |
900 | if (result2 != USB_STOR_TRANSPORT_GOOD) | 908 | if (result2) |
901 | US_DEBUGP("sddr09_write_inplace: cannot read status\n"); | 909 | US_DEBUGP("sddr09_write_inplace: cannot read status\n"); |
902 | else if (status != 0xc0) | 910 | else if (status != 0xc0) |
903 | US_DEBUGP("sddr09_write_inplace: status after write: 0x%x\n", | 911 | US_DEBUGP("sddr09_write_inplace: status after write: 0x%x\n", |
@@ -920,13 +928,20 @@ sddr09_write_data(struct us_data *us, | |||
920 | unsigned int sectors) { | 928 | unsigned int sectors) { |
921 | 929 | ||
922 | struct sddr09_card_info *info = (struct sddr09_card_info *) us->extra; | 930 | struct sddr09_card_info *info = (struct sddr09_card_info *) us->extra; |
923 | unsigned int lba, page, pages; | 931 | unsigned int lba, maxlba, page, pages; |
924 | unsigned int pagelen, blocklen; | 932 | unsigned int pagelen, blocklen; |
925 | unsigned char *blockbuffer; | 933 | unsigned char *blockbuffer; |
926 | unsigned char *buffer; | 934 | unsigned char *buffer; |
927 | unsigned int len, index, offset; | 935 | unsigned int len, index, offset; |
928 | int result; | 936 | int result; |
929 | 937 | ||
938 | // Figure out the initial LBA and page | ||
939 | lba = address >> info->blockshift; | ||
940 | page = (address & info->blockmask); | ||
941 | maxlba = info->capacity >> (info->pageshift + info->blockshift); | ||
942 | if (lba >= maxlba) | ||
943 | return -EIO; | ||
944 | |||
930 | // blockbuffer is used for reading in the old data, overwriting | 945 | // blockbuffer is used for reading in the old data, overwriting |
931 | // with the new data, and performing ECC calculations | 946 | // with the new data, and performing ECC calculations |
932 | 947 | ||
@@ -938,7 +953,7 @@ sddr09_write_data(struct us_data *us, | |||
938 | blockbuffer = kmalloc(blocklen, GFP_NOIO); | 953 | blockbuffer = kmalloc(blocklen, GFP_NOIO); |
939 | if (!blockbuffer) { | 954 | if (!blockbuffer) { |
940 | printk("sddr09_write_data: Out of memory\n"); | 955 | printk("sddr09_write_data: Out of memory\n"); |
941 | return USB_STOR_TRANSPORT_ERROR; | 956 | return -ENOMEM; |
942 | } | 957 | } |
943 | 958 | ||
944 | // Since we don't write the user data directly to the device, | 959 | // Since we don't write the user data directly to the device, |
@@ -950,14 +965,10 @@ sddr09_write_data(struct us_data *us, | |||
950 | if (buffer == NULL) { | 965 | if (buffer == NULL) { |
951 | printk("sddr09_write_data: Out of memory\n"); | 966 | printk("sddr09_write_data: Out of memory\n"); |
952 | kfree(blockbuffer); | 967 | kfree(blockbuffer); |
953 | return USB_STOR_TRANSPORT_ERROR; | 968 | return -ENOMEM; |
954 | } | 969 | } |
955 | 970 | ||
956 | // Figure out the initial LBA and page | 971 | result = 0; |
957 | lba = address >> info->blockshift; | ||
958 | page = (address & info->blockmask); | ||
959 | |||
960 | result = USB_STOR_TRANSPORT_GOOD; | ||
961 | index = offset = 0; | 972 | index = offset = 0; |
962 | 973 | ||
963 | while (sectors > 0) { | 974 | while (sectors > 0) { |
@@ -967,13 +978,21 @@ sddr09_write_data(struct us_data *us, | |||
967 | pages = min(sectors, info->blocksize - page); | 978 | pages = min(sectors, info->blocksize - page); |
968 | len = (pages << info->pageshift); | 979 | len = (pages << info->pageshift); |
969 | 980 | ||
981 | /* Not overflowing capacity? */ | ||
982 | if (lba >= maxlba) { | ||
983 | US_DEBUGP("Error: Requested lba %u exceeds " | ||
984 | "maximum %u\n", lba, maxlba); | ||
985 | result = -EIO; | ||
986 | break; | ||
987 | } | ||
988 | |||
970 | // Get the data from the transfer buffer | 989 | // Get the data from the transfer buffer |
971 | usb_stor_access_xfer_buf(buffer, len, us->srb, | 990 | usb_stor_access_xfer_buf(buffer, len, us->srb, |
972 | &index, &offset, FROM_XFER_BUF); | 991 | &index, &offset, FROM_XFER_BUF); |
973 | 992 | ||
974 | result = sddr09_write_lba(us, lba, page, pages, | 993 | result = sddr09_write_lba(us, lba, page, pages, |
975 | buffer, blockbuffer); | 994 | buffer, blockbuffer); |
976 | if (result != USB_STOR_TRANSPORT_GOOD) | 995 | if (result) |
977 | break; | 996 | break; |
978 | 997 | ||
979 | page = 0; | 998 | page = 0; |
@@ -1022,7 +1041,7 @@ sddr09_read_deviceID(struct us_data *us, unsigned char *deviceID) { | |||
1022 | command[1] = LUNBITS; | 1041 | command[1] = LUNBITS; |
1023 | 1042 | ||
1024 | result = sddr09_send_scsi_command(us, command, 12); | 1043 | result = sddr09_send_scsi_command(us, command, 12); |
1025 | if (result != USB_STOR_TRANSPORT_GOOD) | 1044 | if (result) |
1026 | return result; | 1045 | return result; |
1027 | 1046 | ||
1028 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, | 1047 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, |
@@ -1031,8 +1050,7 @@ sddr09_read_deviceID(struct us_data *us, unsigned char *deviceID) { | |||
1031 | for (i = 0; i < 4; i++) | 1050 | for (i = 0; i < 4; i++) |
1032 | deviceID[i] = content[i]; | 1051 | deviceID[i] = content[i]; |
1033 | 1052 | ||
1034 | return (result == USB_STOR_XFER_GOOD ? | 1053 | return (result == USB_STOR_XFER_GOOD ? 0 : -EIO); |
1035 | USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR); | ||
1036 | } | 1054 | } |
1037 | 1055 | ||
1038 | static int | 1056 | static int |
@@ -1041,7 +1059,7 @@ sddr09_get_wp(struct us_data *us, struct sddr09_card_info *info) { | |||
1041 | unsigned char status; | 1059 | unsigned char status; |
1042 | 1060 | ||
1043 | result = sddr09_read_status(us, &status); | 1061 | result = sddr09_read_status(us, &status); |
1044 | if (result != USB_STOR_TRANSPORT_GOOD) { | 1062 | if (result) { |
1045 | US_DEBUGP("sddr09_get_wp: read_status fails\n"); | 1063 | US_DEBUGP("sddr09_get_wp: read_status fails\n"); |
1046 | return result; | 1064 | return result; |
1047 | } | 1065 | } |
@@ -1057,7 +1075,7 @@ sddr09_get_wp(struct us_data *us, struct sddr09_card_info *info) { | |||
1057 | if (status & 0x1) | 1075 | if (status & 0x1) |
1058 | US_DEBUGP(" Error"); | 1076 | US_DEBUGP(" Error"); |
1059 | US_DEBUGP("\n"); | 1077 | US_DEBUGP("\n"); |
1060 | return USB_STOR_TRANSPORT_GOOD; | 1078 | return 0; |
1061 | } | 1079 | } |
1062 | 1080 | ||
1063 | #if 0 | 1081 | #if 0 |
@@ -1089,7 +1107,7 @@ sddr09_get_cardinfo(struct us_data *us, unsigned char flags) { | |||
1089 | 1107 | ||
1090 | result = sddr09_read_deviceID(us, deviceID); | 1108 | result = sddr09_read_deviceID(us, deviceID); |
1091 | 1109 | ||
1092 | if (result != USB_STOR_TRANSPORT_GOOD) { | 1110 | if (result) { |
1093 | US_DEBUGP("Result of read_deviceID is %d\n", result); | 1111 | US_DEBUGP("Result of read_deviceID is %d\n", result); |
1094 | printk("sddr09: could not read card info\n"); | 1112 | printk("sddr09: could not read card info\n"); |
1095 | return NULL; | 1113 | return NULL; |
@@ -1200,7 +1218,7 @@ sddr09_read_map(struct us_data *us) { | |||
1200 | us, address>>1, | 1218 | us, address>>1, |
1201 | min(alloc_blocks, numblocks - i), | 1219 | min(alloc_blocks, numblocks - i), |
1202 | buffer, 0); | 1220 | buffer, 0); |
1203 | if (result != USB_STOR_TRANSPORT_GOOD) { | 1221 | if (result) { |
1204 | result = -1; | 1222 | result = -1; |
1205 | goto done; | 1223 | goto done; |
1206 | } | 1224 | } |
@@ -1342,29 +1360,53 @@ sddr09_card_info_destructor(void *extra) { | |||
1342 | kfree(info->pba_to_lba); | 1360 | kfree(info->pba_to_lba); |
1343 | } | 1361 | } |
1344 | 1362 | ||
1345 | static void | 1363 | static int |
1346 | sddr09_init_card_info(struct us_data *us) { | 1364 | sddr09_common_init(struct us_data *us) { |
1347 | if (!us->extra) { | 1365 | int result; |
1348 | us->extra = kmalloc(sizeof(struct sddr09_card_info), GFP_NOIO); | 1366 | |
1349 | if (us->extra) { | 1367 | /* set the configuration -- STALL is an acceptable response here */ |
1350 | memset(us->extra, 0, sizeof(struct sddr09_card_info)); | 1368 | if (us->pusb_dev->actconfig->desc.bConfigurationValue != 1) { |
1351 | us->extra_destructor = sddr09_card_info_destructor; | 1369 | US_DEBUGP("active config #%d != 1 ??\n", us->pusb_dev |
1352 | } | 1370 | ->actconfig->desc.bConfigurationValue); |
1371 | return -EINVAL; | ||
1372 | } | ||
1373 | |||
1374 | result = usb_reset_configuration(us->pusb_dev); | ||
1375 | US_DEBUGP("Result of usb_reset_configuration is %d\n", result); | ||
1376 | if (result == -EPIPE) { | ||
1377 | US_DEBUGP("-- stall on control interface\n"); | ||
1378 | } else if (result != 0) { | ||
1379 | /* it's not a stall, but another error -- time to bail */ | ||
1380 | US_DEBUGP("-- Unknown error. Rejecting device\n"); | ||
1381 | return -EINVAL; | ||
1353 | } | 1382 | } |
1383 | |||
1384 | us->extra = kzalloc(sizeof(struct sddr09_card_info), GFP_NOIO); | ||
1385 | if (!us->extra) | ||
1386 | return -ENOMEM; | ||
1387 | us->extra_destructor = sddr09_card_info_destructor; | ||
1388 | |||
1389 | nand_init_ecc(); | ||
1390 | return 0; | ||
1354 | } | 1391 | } |
1355 | 1392 | ||
1393 | |||
1356 | /* | 1394 | /* |
1357 | * This is needed at a very early stage. If this is not listed in the | 1395 | * This is needed at a very early stage. If this is not listed in the |
1358 | * unusual devices list but called from here then LUN 0 of the combo reader | 1396 | * unusual devices list but called from here then LUN 0 of the combo reader |
1359 | * is not recognized. But I do not know what precisely these calls do. | 1397 | * is not recognized. But I do not know what precisely these calls do. |
1360 | */ | 1398 | */ |
1361 | int | 1399 | int |
1362 | sddr09_init(struct us_data *us) { | 1400 | usb_stor_sddr09_dpcm_init(struct us_data *us) { |
1363 | int result; | 1401 | int result; |
1364 | unsigned char *data = us->iobuf; | 1402 | unsigned char *data = us->iobuf; |
1365 | 1403 | ||
1404 | result = sddr09_common_init(us); | ||
1405 | if (result) | ||
1406 | return result; | ||
1407 | |||
1366 | result = sddr09_send_command(us, 0x01, USB_DIR_IN, data, 2); | 1408 | result = sddr09_send_command(us, 0x01, USB_DIR_IN, data, 2); |
1367 | if (result != USB_STOR_TRANSPORT_GOOD) { | 1409 | if (result) { |
1368 | US_DEBUGP("sddr09_init: send_command fails\n"); | 1410 | US_DEBUGP("sddr09_init: send_command fails\n"); |
1369 | return result; | 1411 | return result; |
1370 | } | 1412 | } |
@@ -1373,7 +1415,7 @@ sddr09_init(struct us_data *us) { | |||
1373 | // get 07 02 | 1415 | // get 07 02 |
1374 | 1416 | ||
1375 | result = sddr09_send_command(us, 0x08, USB_DIR_IN, data, 2); | 1417 | result = sddr09_send_command(us, 0x08, USB_DIR_IN, data, 2); |
1376 | if (result != USB_STOR_TRANSPORT_GOOD) { | 1418 | if (result) { |
1377 | US_DEBUGP("sddr09_init: 2nd send_command fails\n"); | 1419 | US_DEBUGP("sddr09_init: 2nd send_command fails\n"); |
1378 | return result; | 1420 | return result; |
1379 | } | 1421 | } |
@@ -1382,7 +1424,7 @@ sddr09_init(struct us_data *us) { | |||
1382 | // get 07 00 | 1424 | // get 07 00 |
1383 | 1425 | ||
1384 | result = sddr09_request_sense(us, data, 18); | 1426 | result = sddr09_request_sense(us, data, 18); |
1385 | if (result == USB_STOR_TRANSPORT_GOOD && data[2] != 0) { | 1427 | if (result == 0 && data[2] != 0) { |
1386 | int j; | 1428 | int j; |
1387 | for (j=0; j<18; j++) | 1429 | for (j=0; j<18; j++) |
1388 | printk(" %02X", data[j]); | 1430 | printk(" %02X", data[j]); |
@@ -1398,7 +1440,7 @@ sddr09_init(struct us_data *us) { | |||
1398 | 1440 | ||
1399 | // test unit ready | 1441 | // test unit ready |
1400 | 1442 | ||
1401 | return USB_STOR_TRANSPORT_GOOD; /* not result */ | 1443 | return 0; /* not result */ |
1402 | } | 1444 | } |
1403 | 1445 | ||
1404 | /* | 1446 | /* |
@@ -1427,13 +1469,6 @@ int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
1427 | }; | 1469 | }; |
1428 | 1470 | ||
1429 | info = (struct sddr09_card_info *)us->extra; | 1471 | info = (struct sddr09_card_info *)us->extra; |
1430 | if (!info) { | ||
1431 | nand_init_ecc(); | ||
1432 | sddr09_init_card_info(us); | ||
1433 | info = (struct sddr09_card_info *)us->extra; | ||
1434 | if (!info) | ||
1435 | return USB_STOR_TRANSPORT_ERROR; | ||
1436 | } | ||
1437 | 1472 | ||
1438 | if (srb->cmnd[0] == REQUEST_SENSE && havefakesense) { | 1473 | if (srb->cmnd[0] == REQUEST_SENSE && havefakesense) { |
1439 | /* for a faked command, we have to follow with a faked sense */ | 1474 | /* for a faked command, we have to follow with a faked sense */ |
@@ -1536,7 +1571,9 @@ int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
1536 | US_DEBUGP("READ_10: read page %d pagect %d\n", | 1571 | US_DEBUGP("READ_10: read page %d pagect %d\n", |
1537 | page, pages); | 1572 | page, pages); |
1538 | 1573 | ||
1539 | return sddr09_read_data(us, page, pages); | 1574 | result = sddr09_read_data(us, page, pages); |
1575 | return (result == 0 ? USB_STOR_TRANSPORT_GOOD : | ||
1576 | USB_STOR_TRANSPORT_ERROR); | ||
1540 | } | 1577 | } |
1541 | 1578 | ||
1542 | if (srb->cmnd[0] == WRITE_10) { | 1579 | if (srb->cmnd[0] == WRITE_10) { |
@@ -1549,7 +1586,9 @@ int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
1549 | US_DEBUGP("WRITE_10: write page %d pagect %d\n", | 1586 | US_DEBUGP("WRITE_10: write page %d pagect %d\n", |
1550 | page, pages); | 1587 | page, pages); |
1551 | 1588 | ||
1552 | return sddr09_write_data(us, page, pages); | 1589 | result = sddr09_write_data(us, page, pages); |
1590 | return (result == 0 ? USB_STOR_TRANSPORT_GOOD : | ||
1591 | USB_STOR_TRANSPORT_ERROR); | ||
1553 | } | 1592 | } |
1554 | 1593 | ||
1555 | /* catch-all for all other commands, except | 1594 | /* catch-all for all other commands, except |
@@ -1575,10 +1614,10 @@ int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
1575 | US_DEBUGP("SDDR09: Send control for command %s\n", ptr); | 1614 | US_DEBUGP("SDDR09: Send control for command %s\n", ptr); |
1576 | 1615 | ||
1577 | result = sddr09_send_scsi_command(us, srb->cmnd, 12); | 1616 | result = sddr09_send_scsi_command(us, srb->cmnd, 12); |
1578 | if (result != USB_STOR_TRANSPORT_GOOD) { | 1617 | if (result) { |
1579 | US_DEBUGP("sddr09_transport: sddr09_send_scsi_command " | 1618 | US_DEBUGP("sddr09_transport: sddr09_send_scsi_command " |
1580 | "returns %d\n", result); | 1619 | "returns %d\n", result); |
1581 | return result; | 1620 | return USB_STOR_TRANSPORT_ERROR; |
1582 | } | 1621 | } |
1583 | 1622 | ||
1584 | if (srb->request_bufflen == 0) | 1623 | if (srb->request_bufflen == 0) |
@@ -1606,3 +1645,10 @@ int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
1606 | return USB_STOR_TRANSPORT_GOOD; | 1645 | return USB_STOR_TRANSPORT_GOOD; |
1607 | } | 1646 | } |
1608 | 1647 | ||
1648 | /* | ||
1649 | * Initialization routine for the sddr09 subdriver | ||
1650 | */ | ||
1651 | int | ||
1652 | usb_stor_sddr09_init(struct us_data *us) { | ||
1653 | return sddr09_common_init(us); | ||
1654 | } | ||
diff --git a/drivers/usb/storage/sddr09.h b/drivers/usb/storage/sddr09.h index c9d78d6188b1..c03089a9ec38 100644 --- a/drivers/usb/storage/sddr09.h +++ b/drivers/usb/storage/sddr09.h | |||
@@ -31,18 +31,7 @@ | |||
31 | 31 | ||
32 | extern int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us); | 32 | extern int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us); |
33 | 33 | ||
34 | struct sddr09_card_info { | 34 | extern int usb_stor_sddr09_dpcm_init(struct us_data *us); |
35 | unsigned long capacity; /* Size of card in bytes */ | 35 | extern int usb_stor_sddr09_init(struct us_data *us); |
36 | int pagesize; /* Size of page in bytes */ | ||
37 | int pageshift; /* log2 of pagesize */ | ||
38 | int blocksize; /* Size of block in pages */ | ||
39 | int blockshift; /* log2 of blocksize */ | ||
40 | int blockmask; /* 2^blockshift - 1 */ | ||
41 | int *lba_to_pba; /* logical to physical map */ | ||
42 | int *pba_to_lba; /* physical to logical map */ | ||
43 | int lbact; /* number of available pages */ | ||
44 | int flags; | ||
45 | #define SDDR09_WP 1 /* write protected */ | ||
46 | }; | ||
47 | 36 | ||
48 | #endif | 37 | #endif |
diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h index 0a362cc781ad..633a715850a4 100644 --- a/drivers/usb/storage/transport.h +++ b/drivers/usb/storage/transport.h | |||
@@ -41,39 +41,8 @@ | |||
41 | #ifndef _TRANSPORT_H_ | 41 | #ifndef _TRANSPORT_H_ |
42 | #define _TRANSPORT_H_ | 42 | #define _TRANSPORT_H_ |
43 | 43 | ||
44 | #include <linux/config.h> | ||
45 | #include <linux/blkdev.h> | 44 | #include <linux/blkdev.h> |
46 | 45 | ||
47 | /* Protocols */ | ||
48 | |||
49 | #define US_PR_CBI 0x00 /* Control/Bulk/Interrupt */ | ||
50 | #define US_PR_CB 0x01 /* Control/Bulk w/o interrupt */ | ||
51 | #define US_PR_BULK 0x50 /* bulk only */ | ||
52 | #ifdef CONFIG_USB_STORAGE_USBAT | ||
53 | #define US_PR_USBAT 0x80 /* SCM-ATAPI bridge */ | ||
54 | #endif | ||
55 | #ifdef CONFIG_USB_STORAGE_SDDR09 | ||
56 | #define US_PR_EUSB_SDDR09 0x81 /* SCM-SCSI bridge for SDDR-09 */ | ||
57 | #endif | ||
58 | #ifdef CONFIG_USB_STORAGE_SDDR55 | ||
59 | #define US_PR_SDDR55 0x82 /* SDDR-55 (made up) */ | ||
60 | #endif | ||
61 | #define US_PR_DPCM_USB 0xf0 /* Combination CB/SDDR09 */ | ||
62 | |||
63 | #ifdef CONFIG_USB_STORAGE_FREECOM | ||
64 | #define US_PR_FREECOM 0xf1 /* Freecom */ | ||
65 | #endif | ||
66 | |||
67 | #ifdef CONFIG_USB_STORAGE_DATAFAB | ||
68 | #define US_PR_DATAFAB 0xf2 /* Datafab chipsets */ | ||
69 | #endif | ||
70 | |||
71 | #ifdef CONFIG_USB_STORAGE_JUMPSHOT | ||
72 | #define US_PR_JUMPSHOT 0xf3 /* Lexar Jumpshot */ | ||
73 | #endif | ||
74 | |||
75 | #define US_PR_DEVICE 0xff /* Use device's value */ | ||
76 | |||
77 | /* | 46 | /* |
78 | * Bulk only data structures | 47 | * Bulk only data structures |
79 | */ | 48 | */ |
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index f5f47a34b168..dc301e567cfc 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h | |||
@@ -79,13 +79,6 @@ UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001, | |||
79 | US_SC_8070, US_PR_USBAT, init_usbat, 0), | 79 | US_SC_8070, US_PR_USBAT, init_usbat, 0), |
80 | #endif | 80 | #endif |
81 | 81 | ||
82 | /* Patch submitted by Mihnea-Costin Grigore <mihnea@zulu.ro> */ | ||
83 | UNUSUAL_DEV( 0x040d, 0x6205, 0x0003, 0x0003, | ||
84 | "VIA Technologies Inc.", | ||
85 | "USB 2.0 Card Reader", | ||
86 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
87 | US_FL_IGNORE_RESIDUE ), | ||
88 | |||
89 | /* Reported by Sebastian Kapfer <sebastian_kapfer@gmx.net> | 82 | /* Reported by Sebastian Kapfer <sebastian_kapfer@gmx.net> |
90 | * and Olaf Hering <olh@suse.de> (different bcd's, same vendor/product) | 83 | * and Olaf Hering <olh@suse.de> (different bcd's, same vendor/product) |
91 | * for USB floppies that need the SINGLE_LUN enforcement. | 84 | * for USB floppies that need the SINGLE_LUN enforcement. |
@@ -96,6 +89,13 @@ UNUSUAL_DEV( 0x0409, 0x0040, 0x0000, 0x9999, | |||
96 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 89 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
97 | US_FL_SINGLE_LUN ), | 90 | US_FL_SINGLE_LUN ), |
98 | 91 | ||
92 | /* Patch submitted by Mihnea-Costin Grigore <mihnea@zulu.ro> */ | ||
93 | UNUSUAL_DEV( 0x040d, 0x6205, 0x0003, 0x0003, | ||
94 | "VIA Technologies Inc.", | ||
95 | "USB 2.0 Card Reader", | ||
96 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
97 | US_FL_IGNORE_RESIDUE ), | ||
98 | |||
99 | /* Deduced by Jonathan Woithe <jwoithe@physics.adelaide.edu.au> | 99 | /* Deduced by Jonathan Woithe <jwoithe@physics.adelaide.edu.au> |
100 | * Entry needed for flags: US_FL_FIX_INQUIRY because initial inquiry message | 100 | * Entry needed for flags: US_FL_FIX_INQUIRY because initial inquiry message |
101 | * always fails and confuses drive. | 101 | * always fails and confuses drive. |
@@ -187,6 +187,14 @@ UNUSUAL_DEV( 0x04b0, 0x0405, 0x0100, 0x0100, | |||
187 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 187 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
188 | US_FL_FIX_CAPACITY), | 188 | US_FL_FIX_CAPACITY), |
189 | 189 | ||
190 | /* Patch for Nikon coolpix 2000 | ||
191 | * Submitted by Fabien Cosse <fabien.cosse@wanadoo.fr>*/ | ||
192 | UNUSUAL_DEV( 0x04b0, 0x0301, 0x0010, 0x0010, | ||
193 | "NIKON", | ||
194 | "NIKON DSC E2000", | ||
195 | US_SC_DEVICE, US_PR_DEVICE,NULL, | ||
196 | US_FL_NOT_LOCKABLE ), | ||
197 | |||
190 | /* BENQ DC5330 | 198 | /* BENQ DC5330 |
191 | * Reported by Manuel Fombuena <mfombuena@ya.com> and | 199 | * Reported by Manuel Fombuena <mfombuena@ya.com> and |
192 | * Frank Copeland <fjc@thingy.apana.org.au> */ | 200 | * Frank Copeland <fjc@thingy.apana.org.au> */ |
@@ -276,14 +284,14 @@ UNUSUAL_DEV( 0x04e6, 0x0002, 0x0100, 0x0100, | |||
276 | UNUSUAL_DEV( 0x04e6, 0x0003, 0x0000, 0x9999, | 284 | UNUSUAL_DEV( 0x04e6, 0x0003, 0x0000, 0x9999, |
277 | "Sandisk", | 285 | "Sandisk", |
278 | "ImageMate SDDR09", | 286 | "ImageMate SDDR09", |
279 | US_SC_SCSI, US_PR_EUSB_SDDR09, NULL, | 287 | US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, |
280 | US_FL_SINGLE_LUN ), | 288 | 0), |
281 | 289 | ||
282 | /* This entry is from Andries.Brouwer@cwi.nl */ | 290 | /* This entry is from Andries.Brouwer@cwi.nl */ |
283 | UNUSUAL_DEV( 0x04e6, 0x0005, 0x0100, 0x0208, | 291 | UNUSUAL_DEV( 0x04e6, 0x0005, 0x0100, 0x0208, |
284 | "SCM Microsystems", | 292 | "SCM Microsystems", |
285 | "eUSB SmartMedia / CompactFlash Adapter", | 293 | "eUSB SmartMedia / CompactFlash Adapter", |
286 | US_SC_SCSI, US_PR_DPCM_USB, sddr09_init, | 294 | US_SC_SCSI, US_PR_DPCM_USB, usb_stor_sddr09_dpcm_init, |
287 | 0), | 295 | 0), |
288 | #endif | 296 | #endif |
289 | 297 | ||
@@ -527,6 +535,13 @@ UNUSUAL_DEV( 0x057b, 0x0022, 0x0000, 0x9999, | |||
527 | "Silicon Media R/W", | 535 | "Silicon Media R/W", |
528 | US_SC_DEVICE, US_PR_DEVICE, NULL, 0), | 536 | US_SC_DEVICE, US_PR_DEVICE, NULL, 0), |
529 | 537 | ||
538 | #ifdef CONFIG_USB_STORAGE_ALAUDA | ||
539 | UNUSUAL_DEV( 0x0584, 0x0008, 0x0102, 0x0102, | ||
540 | "Fujifilm", | ||
541 | "DPC-R1 (Alauda)", | ||
542 | US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ), | ||
543 | #endif | ||
544 | |||
530 | /* Fabrizio Fellini <fello@libero.it> */ | 545 | /* Fabrizio Fellini <fello@libero.it> */ |
531 | UNUSUAL_DEV( 0x0595, 0x4343, 0x0000, 0x2210, | 546 | UNUSUAL_DEV( 0x0595, 0x4343, 0x0000, 0x2210, |
532 | "Fujifilm", | 547 | "Fujifilm", |
@@ -673,8 +688,8 @@ UNUSUAL_DEV( 0x0644, 0x0000, 0x0100, 0x0100, | |||
673 | UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x0100, | 688 | UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x0100, |
674 | "Olympus", | 689 | "Olympus", |
675 | "Camedia MAUSB-2", | 690 | "Camedia MAUSB-2", |
676 | US_SC_SCSI, US_PR_EUSB_SDDR09, NULL, | 691 | US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, |
677 | US_FL_SINGLE_LUN ), | 692 | 0), |
678 | #endif | 693 | #endif |
679 | 694 | ||
680 | /* Reported by Darsen Lu <darsen@micro.ee.nthu.edu.tw> */ | 695 | /* Reported by Darsen Lu <darsen@micro.ee.nthu.edu.tw> */ |
@@ -739,8 +754,8 @@ UNUSUAL_DEV( 0x0781, 0x0100, 0x0100, 0x0100, | |||
739 | UNUSUAL_DEV( 0x0781, 0x0200, 0x0000, 0x9999, | 754 | UNUSUAL_DEV( 0x0781, 0x0200, 0x0000, 0x9999, |
740 | "Sandisk", | 755 | "Sandisk", |
741 | "ImageMate SDDR-09", | 756 | "ImageMate SDDR-09", |
742 | US_SC_SCSI, US_PR_EUSB_SDDR09, NULL, | 757 | US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, |
743 | US_FL_SINGLE_LUN ), | 758 | 0), |
744 | #endif | 759 | #endif |
745 | 760 | ||
746 | #ifdef CONFIG_USB_STORAGE_FREECOM | 761 | #ifdef CONFIG_USB_STORAGE_FREECOM |
@@ -776,6 +791,13 @@ UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100, | |||
776 | US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ), | 791 | US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ), |
777 | #endif | 792 | #endif |
778 | 793 | ||
794 | #ifdef CONFIG_USB_STORAGE_ALAUDA | ||
795 | UNUSUAL_DEV( 0x07b4, 0x010a, 0x0102, 0x0102, | ||
796 | "Olympus", | ||
797 | "MAUSB-10 (Alauda)", | ||
798 | US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ), | ||
799 | #endif | ||
800 | |||
779 | #ifdef CONFIG_USB_STORAGE_DATAFAB | 801 | #ifdef CONFIG_USB_STORAGE_DATAFAB |
780 | UNUSUAL_DEV( 0x07c4, 0xa000, 0x0000, 0x0015, | 802 | UNUSUAL_DEV( 0x07c4, 0xa000, 0x0000, 0x0015, |
781 | "Datafab", | 803 | "Datafab", |
@@ -1134,3 +1156,27 @@ UNUSUAL_DEV( 0x55aa, 0xa103, 0x0000, 0x9999, | |||
1134 | US_SC_SCSI, US_PR_SDDR55, NULL, | 1156 | US_SC_SCSI, US_PR_SDDR55, NULL, |
1135 | US_FL_SINGLE_LUN), | 1157 | US_FL_SINGLE_LUN), |
1136 | #endif | 1158 | #endif |
1159 | |||
1160 | /* Control/Bulk transport for all SubClass values */ | ||
1161 | USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR), | ||
1162 | USUAL_DEV(US_SC_8020, US_PR_CB, USB_US_TYPE_STOR), | ||
1163 | USUAL_DEV(US_SC_QIC, US_PR_CB, USB_US_TYPE_STOR), | ||
1164 | USUAL_DEV(US_SC_UFI, US_PR_CB, USB_US_TYPE_STOR), | ||
1165 | USUAL_DEV(US_SC_8070, US_PR_CB, USB_US_TYPE_STOR), | ||
1166 | USUAL_DEV(US_SC_SCSI, US_PR_CB, USB_US_TYPE_STOR), | ||
1167 | |||
1168 | /* Control/Bulk/Interrupt transport for all SubClass values */ | ||
1169 | USUAL_DEV(US_SC_RBC, US_PR_CBI, USB_US_TYPE_STOR), | ||
1170 | USUAL_DEV(US_SC_8020, US_PR_CBI, USB_US_TYPE_STOR), | ||
1171 | USUAL_DEV(US_SC_QIC, US_PR_CBI, USB_US_TYPE_STOR), | ||
1172 | USUAL_DEV(US_SC_UFI, US_PR_CBI, USB_US_TYPE_STOR), | ||
1173 | USUAL_DEV(US_SC_8070, US_PR_CBI, USB_US_TYPE_STOR), | ||
1174 | USUAL_DEV(US_SC_SCSI, US_PR_CBI, USB_US_TYPE_STOR), | ||
1175 | |||
1176 | /* Bulk-only transport for all SubClass values */ | ||
1177 | USUAL_DEV(US_SC_RBC, US_PR_BULK, USB_US_TYPE_STOR), | ||
1178 | USUAL_DEV(US_SC_8020, US_PR_BULK, USB_US_TYPE_STOR), | ||
1179 | USUAL_DEV(US_SC_QIC, US_PR_BULK, USB_US_TYPE_STOR), | ||
1180 | USUAL_DEV(US_SC_UFI, US_PR_BULK, USB_US_TYPE_STOR), | ||
1181 | USUAL_DEV(US_SC_8070, US_PR_BULK, USB_US_TYPE_STOR), | ||
1182 | USUAL_DEV(US_SC_SCSI, US_PR_BULK, 0), | ||
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 3847ebed2aa4..dbcf23980ff1 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c | |||
@@ -94,6 +94,9 @@ | |||
94 | #ifdef CONFIG_USB_STORAGE_ONETOUCH | 94 | #ifdef CONFIG_USB_STORAGE_ONETOUCH |
95 | #include "onetouch.h" | 95 | #include "onetouch.h" |
96 | #endif | 96 | #endif |
97 | #ifdef CONFIG_USB_STORAGE_ALAUDA | ||
98 | #include "alauda.h" | ||
99 | #endif | ||
97 | 100 | ||
98 | /* Some informational data */ | 101 | /* Some informational data */ |
99 | MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>"); | 102 | MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>"); |
@@ -112,49 +115,33 @@ static atomic_t total_threads = ATOMIC_INIT(0); | |||
112 | static DECLARE_COMPLETION(threads_gone); | 115 | static DECLARE_COMPLETION(threads_gone); |
113 | 116 | ||
114 | 117 | ||
115 | /* The entries in this table, except for final ones here | 118 | /* |
116 | * (USB_MASS_STORAGE_CLASS and the empty entry), correspond, | 119 | * The entries in this table correspond, line for line, |
117 | * line for line with the entries of us_unsuaul_dev_list[]. | 120 | * with the entries of us_unusual_dev_list[]. |
118 | */ | 121 | */ |
122 | #ifndef CONFIG_USB_LIBUSUAL | ||
119 | 123 | ||
120 | #define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ | 124 | #define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ |
121 | vendorName, productName,useProtocol, useTransport, \ | 125 | vendorName, productName,useProtocol, useTransport, \ |
122 | initFunction, flags) \ | 126 | initFunction, flags) \ |
123 | { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax) } | 127 | { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \ |
128 | .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } | ||
129 | |||
130 | #define USUAL_DEV(useProto, useTrans, useType) \ | ||
131 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \ | ||
132 | .driver_info = (USB_US_TYPE_STOR<<24) } | ||
124 | 133 | ||
125 | static struct usb_device_id storage_usb_ids [] = { | 134 | static struct usb_device_id storage_usb_ids [] = { |
126 | 135 | ||
127 | # include "unusual_devs.h" | 136 | # include "unusual_devs.h" |
128 | #undef UNUSUAL_DEV | 137 | #undef UNUSUAL_DEV |
129 | /* Control/Bulk transport for all SubClass values */ | 138 | #undef USUAL_DEV |
130 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_CB) }, | ||
131 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_CB) }, | ||
132 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_CB) }, | ||
133 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_CB) }, | ||
134 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_CB) }, | ||
135 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_CB) }, | ||
136 | |||
137 | /* Control/Bulk/Interrupt transport for all SubClass values */ | ||
138 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_CBI) }, | ||
139 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_CBI) }, | ||
140 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_CBI) }, | ||
141 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_CBI) }, | ||
142 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_CBI) }, | ||
143 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_CBI) }, | ||
144 | |||
145 | /* Bulk-only transport for all SubClass values */ | ||
146 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_BULK) }, | ||
147 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_BULK) }, | ||
148 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_BULK) }, | ||
149 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_BULK) }, | ||
150 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_BULK) }, | ||
151 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) }, | ||
152 | |||
153 | /* Terminating entry */ | 139 | /* Terminating entry */ |
154 | { } | 140 | { } |
155 | }; | 141 | }; |
156 | 142 | ||
157 | MODULE_DEVICE_TABLE (usb, storage_usb_ids); | 143 | MODULE_DEVICE_TABLE (usb, storage_usb_ids); |
144 | #endif /* CONFIG_USB_LIBUSUAL */ | ||
158 | 145 | ||
159 | /* This is the list of devices we recognize, along with their flag data */ | 146 | /* This is the list of devices we recognize, along with their flag data */ |
160 | 147 | ||
@@ -167,7 +154,6 @@ MODULE_DEVICE_TABLE (usb, storage_usb_ids); | |||
167 | * are free to use as many characters as you like. | 154 | * are free to use as many characters as you like. |
168 | */ | 155 | */ |
169 | 156 | ||
170 | #undef UNUSUAL_DEV | ||
171 | #define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ | 157 | #define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ |
172 | vendor_name, product_name, use_protocol, use_transport, \ | 158 | vendor_name, product_name, use_protocol, use_transport, \ |
173 | init_function, Flags) \ | 159 | init_function, Flags) \ |
@@ -177,53 +163,18 @@ MODULE_DEVICE_TABLE (usb, storage_usb_ids); | |||
177 | .useProtocol = use_protocol, \ | 163 | .useProtocol = use_protocol, \ |
178 | .useTransport = use_transport, \ | 164 | .useTransport = use_transport, \ |
179 | .initFunction = init_function, \ | 165 | .initFunction = init_function, \ |
180 | .flags = Flags, \ | 166 | } |
167 | |||
168 | #define USUAL_DEV(use_protocol, use_transport, use_type) \ | ||
169 | { \ | ||
170 | .useProtocol = use_protocol, \ | ||
171 | .useTransport = use_transport, \ | ||
181 | } | 172 | } |
182 | 173 | ||
183 | static struct us_unusual_dev us_unusual_dev_list[] = { | 174 | static struct us_unusual_dev us_unusual_dev_list[] = { |
184 | # include "unusual_devs.h" | 175 | # include "unusual_devs.h" |
185 | # undef UNUSUAL_DEV | 176 | # undef UNUSUAL_DEV |
186 | /* Control/Bulk transport for all SubClass values */ | 177 | # undef USUAL_DEV |
187 | { .useProtocol = US_SC_RBC, | ||
188 | .useTransport = US_PR_CB}, | ||
189 | { .useProtocol = US_SC_8020, | ||
190 | .useTransport = US_PR_CB}, | ||
191 | { .useProtocol = US_SC_QIC, | ||
192 | .useTransport = US_PR_CB}, | ||
193 | { .useProtocol = US_SC_UFI, | ||
194 | .useTransport = US_PR_CB}, | ||
195 | { .useProtocol = US_SC_8070, | ||
196 | .useTransport = US_PR_CB}, | ||
197 | { .useProtocol = US_SC_SCSI, | ||
198 | .useTransport = US_PR_CB}, | ||
199 | |||
200 | /* Control/Bulk/Interrupt transport for all SubClass values */ | ||
201 | { .useProtocol = US_SC_RBC, | ||
202 | .useTransport = US_PR_CBI}, | ||
203 | { .useProtocol = US_SC_8020, | ||
204 | .useTransport = US_PR_CBI}, | ||
205 | { .useProtocol = US_SC_QIC, | ||
206 | .useTransport = US_PR_CBI}, | ||
207 | { .useProtocol = US_SC_UFI, | ||
208 | .useTransport = US_PR_CBI}, | ||
209 | { .useProtocol = US_SC_8070, | ||
210 | .useTransport = US_PR_CBI}, | ||
211 | { .useProtocol = US_SC_SCSI, | ||
212 | .useTransport = US_PR_CBI}, | ||
213 | |||
214 | /* Bulk-only transport for all SubClass values */ | ||
215 | { .useProtocol = US_SC_RBC, | ||
216 | .useTransport = US_PR_BULK}, | ||
217 | { .useProtocol = US_SC_8020, | ||
218 | .useTransport = US_PR_BULK}, | ||
219 | { .useProtocol = US_SC_QIC, | ||
220 | .useTransport = US_PR_BULK}, | ||
221 | { .useProtocol = US_SC_UFI, | ||
222 | .useTransport = US_PR_BULK}, | ||
223 | { .useProtocol = US_SC_8070, | ||
224 | .useTransport = US_PR_BULK}, | ||
225 | { .useProtocol = US_SC_SCSI, | ||
226 | .useTransport = US_PR_BULK}, | ||
227 | 178 | ||
228 | /* Terminating entry */ | 179 | /* Terminating entry */ |
229 | { NULL } | 180 | { NULL } |
@@ -240,6 +191,8 @@ static int storage_suspend(struct usb_interface *iface, pm_message_t message) | |||
240 | down(&us->dev_semaphore); | 191 | down(&us->dev_semaphore); |
241 | 192 | ||
242 | US_DEBUGP("%s\n", __FUNCTION__); | 193 | US_DEBUGP("%s\n", __FUNCTION__); |
194 | if (us->suspend_resume_hook) | ||
195 | (us->suspend_resume_hook)(us, US_SUSPEND); | ||
243 | iface->dev.power.power_state.event = message.event; | 196 | iface->dev.power.power_state.event = message.event; |
244 | 197 | ||
245 | /* When runtime PM is working, we'll set a flag to indicate | 198 | /* When runtime PM is working, we'll set a flag to indicate |
@@ -256,6 +209,8 @@ static int storage_resume(struct usb_interface *iface) | |||
256 | down(&us->dev_semaphore); | 209 | down(&us->dev_semaphore); |
257 | 210 | ||
258 | US_DEBUGP("%s\n", __FUNCTION__); | 211 | US_DEBUGP("%s\n", __FUNCTION__); |
212 | if (us->suspend_resume_hook) | ||
213 | (us->suspend_resume_hook)(us, US_RESUME); | ||
259 | iface->dev.power.power_state.event = PM_EVENT_ON; | 214 | iface->dev.power.power_state.event = PM_EVENT_ON; |
260 | 215 | ||
261 | up(&us->dev_semaphore); | 216 | up(&us->dev_semaphore); |
@@ -484,14 +439,20 @@ static int associate_dev(struct us_data *us, struct usb_interface *intf) | |||
484 | return 0; | 439 | return 0; |
485 | } | 440 | } |
486 | 441 | ||
442 | /* Find an unusual_dev descriptor (always succeeds in the current code) */ | ||
443 | static struct us_unusual_dev *find_unusual(const struct usb_device_id *id) | ||
444 | { | ||
445 | const int id_index = id - storage_usb_ids; | ||
446 | return &us_unusual_dev_list[id_index]; | ||
447 | } | ||
448 | |||
487 | /* Get the unusual_devs entries and the string descriptors */ | 449 | /* Get the unusual_devs entries and the string descriptors */ |
488 | static void get_device_info(struct us_data *us, int id_index) | 450 | static void get_device_info(struct us_data *us, const struct usb_device_id *id) |
489 | { | 451 | { |
490 | struct usb_device *dev = us->pusb_dev; | 452 | struct usb_device *dev = us->pusb_dev; |
491 | struct usb_interface_descriptor *idesc = | 453 | struct usb_interface_descriptor *idesc = |
492 | &us->pusb_intf->cur_altsetting->desc; | 454 | &us->pusb_intf->cur_altsetting->desc; |
493 | struct us_unusual_dev *unusual_dev = &us_unusual_dev_list[id_index]; | 455 | struct us_unusual_dev *unusual_dev = find_unusual(id); |
494 | struct usb_device_id *id = &storage_usb_ids[id_index]; | ||
495 | 456 | ||
496 | /* Store the entries */ | 457 | /* Store the entries */ |
497 | us->unusual_dev = unusual_dev; | 458 | us->unusual_dev = unusual_dev; |
@@ -501,7 +462,7 @@ static void get_device_info(struct us_data *us, int id_index) | |||
501 | us->protocol = (unusual_dev->useTransport == US_PR_DEVICE) ? | 462 | us->protocol = (unusual_dev->useTransport == US_PR_DEVICE) ? |
502 | idesc->bInterfaceProtocol : | 463 | idesc->bInterfaceProtocol : |
503 | unusual_dev->useTransport; | 464 | unusual_dev->useTransport; |
504 | us->flags = unusual_dev->flags; | 465 | us->flags = USB_US_ORIG_FLAGS(id->driver_info); |
505 | 466 | ||
506 | /* | 467 | /* |
507 | * This flag is only needed when we're in high-speed, so let's | 468 | * This flag is only needed when we're in high-speed, so let's |
@@ -516,7 +477,7 @@ static void get_device_info(struct us_data *us, int id_index) | |||
516 | * from the unusual_devs.h table. | 477 | * from the unusual_devs.h table. |
517 | */ | 478 | */ |
518 | if (id->idVendor || id->idProduct) { | 479 | if (id->idVendor || id->idProduct) { |
519 | static char *msgs[3] = { | 480 | static const char *msgs[3] = { |
520 | "an unneeded SubClass entry", | 481 | "an unneeded SubClass entry", |
521 | "an unneeded Protocol entry", | 482 | "an unneeded Protocol entry", |
522 | "unneeded SubClass and Protocol entries"}; | 483 | "unneeded SubClass and Protocol entries"}; |
@@ -529,7 +490,7 @@ static void get_device_info(struct us_data *us, int id_index) | |||
529 | if (unusual_dev->useTransport != US_PR_DEVICE && | 490 | if (unusual_dev->useTransport != US_PR_DEVICE && |
530 | us->protocol == idesc->bInterfaceProtocol) | 491 | us->protocol == idesc->bInterfaceProtocol) |
531 | msg += 2; | 492 | msg += 2; |
532 | if (msg >= 0 && !(unusual_dev->flags & US_FL_NEED_OVERRIDE)) | 493 | if (msg >= 0 && !(us->flags & US_FL_NEED_OVERRIDE)) |
533 | printk(KERN_NOTICE USB_STORAGE "This device " | 494 | printk(KERN_NOTICE USB_STORAGE "This device " |
534 | "(%04x,%04x,%04x S %02x P %02x)" | 495 | "(%04x,%04x,%04x S %02x P %02x)" |
535 | " has %s in unusual_devs.h\n" | 496 | " has %s in unusual_devs.h\n" |
@@ -686,6 +647,15 @@ static int get_protocol(struct us_data *us) | |||
686 | break; | 647 | break; |
687 | #endif | 648 | #endif |
688 | 649 | ||
650 | #ifdef CONFIG_USB_STORAGE_ALAUDA | ||
651 | case US_PR_ALAUDA: | ||
652 | us->transport_name = "Alauda Control/Bulk"; | ||
653 | us->transport = alauda_transport; | ||
654 | us->transport_reset = usb_stor_Bulk_reset; | ||
655 | us->max_lun = 1; | ||
656 | break; | ||
657 | #endif | ||
658 | |||
689 | default: | 659 | default: |
690 | return -EIO; | 660 | return -EIO; |
691 | } | 661 | } |
@@ -921,10 +891,12 @@ static int storage_probe(struct usb_interface *intf, | |||
921 | { | 891 | { |
922 | struct Scsi_Host *host; | 892 | struct Scsi_Host *host; |
923 | struct us_data *us; | 893 | struct us_data *us; |
924 | const int id_index = id - storage_usb_ids; | ||
925 | int result; | 894 | int result; |
926 | struct task_struct *th; | 895 | struct task_struct *th; |
927 | 896 | ||
897 | if (usb_usual_check_type(id, USB_US_TYPE_STOR)) | ||
898 | return -ENXIO; | ||
899 | |||
928 | US_DEBUGP("USB Mass Storage device detected\n"); | 900 | US_DEBUGP("USB Mass Storage device detected\n"); |
929 | 901 | ||
930 | /* | 902 | /* |
@@ -957,29 +929,7 @@ static int storage_probe(struct usb_interface *intf, | |||
957 | * of the match from the usb_device_id table, so we can find the | 929 | * of the match from the usb_device_id table, so we can find the |
958 | * corresponding entry in the private table. | 930 | * corresponding entry in the private table. |
959 | */ | 931 | */ |
960 | get_device_info(us, id_index); | 932 | get_device_info(us, id); |
961 | |||
962 | #ifdef CONFIG_USB_STORAGE_SDDR09 | ||
963 | if (us->protocol == US_PR_EUSB_SDDR09 || | ||
964 | us->protocol == US_PR_DPCM_USB) { | ||
965 | /* set the configuration -- STALL is an acceptable response here */ | ||
966 | if (us->pusb_dev->actconfig->desc.bConfigurationValue != 1) { | ||
967 | US_DEBUGP("active config #%d != 1 ??\n", us->pusb_dev | ||
968 | ->actconfig->desc.bConfigurationValue); | ||
969 | goto BadDevice; | ||
970 | } | ||
971 | result = usb_reset_configuration(us->pusb_dev); | ||
972 | |||
973 | US_DEBUGP("Result of usb_reset_configuration is %d\n", result); | ||
974 | if (result == -EPIPE) { | ||
975 | US_DEBUGP("-- stall on control interface\n"); | ||
976 | } else if (result != 0) { | ||
977 | /* it's not a stall, but another error -- time to bail */ | ||
978 | US_DEBUGP("-- Unknown error. Rejecting device\n"); | ||
979 | goto BadDevice; | ||
980 | } | ||
981 | } | ||
982 | #endif | ||
983 | 933 | ||
984 | /* Get the transport, protocol, and pipe settings */ | 934 | /* Get the transport, protocol, and pipe settings */ |
985 | result = get_transport(us); | 935 | result = get_transport(us); |
@@ -1044,7 +994,6 @@ static void storage_disconnect(struct usb_interface *intf) | |||
1044 | ***********************************************************************/ | 994 | ***********************************************************************/ |
1045 | 995 | ||
1046 | static struct usb_driver usb_storage_driver = { | 996 | static struct usb_driver usb_storage_driver = { |
1047 | .owner = THIS_MODULE, | ||
1048 | .name = "usb-storage", | 997 | .name = "usb-storage", |
1049 | .probe = storage_probe, | 998 | .probe = storage_probe, |
1050 | .disconnect = storage_disconnect, | 999 | .disconnect = storage_disconnect, |
@@ -1062,9 +1011,10 @@ static int __init usb_stor_init(void) | |||
1062 | 1011 | ||
1063 | /* register the driver, return usb_register return code if error */ | 1012 | /* register the driver, return usb_register return code if error */ |
1064 | retval = usb_register(&usb_storage_driver); | 1013 | retval = usb_register(&usb_storage_driver); |
1065 | if (retval == 0) | 1014 | if (retval == 0) { |
1066 | printk(KERN_INFO "USB Mass Storage support registered.\n"); | 1015 | printk(KERN_INFO "USB Mass Storage support registered.\n"); |
1067 | 1016 | usb_usual_set_present(USB_US_TYPE_STOR); | |
1017 | } | ||
1068 | return retval; | 1018 | return retval; |
1069 | } | 1019 | } |
1070 | 1020 | ||
@@ -1088,6 +1038,8 @@ static void __exit usb_stor_exit(void) | |||
1088 | wait_for_completion(&threads_gone); | 1038 | wait_for_completion(&threads_gone); |
1089 | atomic_dec(&total_threads); | 1039 | atomic_dec(&total_threads); |
1090 | } | 1040 | } |
1041 | |||
1042 | usb_usual_clear_present(USB_US_TYPE_STOR); | ||
1091 | } | 1043 | } |
1092 | 1044 | ||
1093 | module_init(usb_stor_init); | 1045 | module_init(usb_stor_init); |
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h index 98b09711a739..7259fd1f6b0d 100644 --- a/drivers/usb/storage/usb.h +++ b/drivers/usb/storage/usb.h | |||
@@ -45,6 +45,7 @@ | |||
45 | #define _USB_H_ | 45 | #define _USB_H_ |
46 | 46 | ||
47 | #include <linux/usb.h> | 47 | #include <linux/usb.h> |
48 | #include <linux/usb_usual.h> | ||
48 | #include <linux/blkdev.h> | 49 | #include <linux/blkdev.h> |
49 | #include <linux/smp_lock.h> | 50 | #include <linux/smp_lock.h> |
50 | #include <linux/completion.h> | 51 | #include <linux/completion.h> |
@@ -63,38 +64,8 @@ struct us_unusual_dev { | |||
63 | __u8 useProtocol; | 64 | __u8 useProtocol; |
64 | __u8 useTransport; | 65 | __u8 useTransport; |
65 | int (*initFunction)(struct us_data *); | 66 | int (*initFunction)(struct us_data *); |
66 | unsigned int flags; | ||
67 | }; | 67 | }; |
68 | 68 | ||
69 | /* | ||
70 | * Static flag definitions. We use this roundabout technique so that the | ||
71 | * proc_info() routine can automatically display a message for each flag. | ||
72 | */ | ||
73 | #define US_DO_ALL_FLAGS \ | ||
74 | US_FLAG(SINGLE_LUN, 0x00000001) \ | ||
75 | /* allow access to only LUN 0 */ \ | ||
76 | US_FLAG(NEED_OVERRIDE, 0x00000002) \ | ||
77 | /* unusual_devs entry is necessary */ \ | ||
78 | US_FLAG(SCM_MULT_TARG, 0x00000004) \ | ||
79 | /* supports multiple targets */ \ | ||
80 | US_FLAG(FIX_INQUIRY, 0x00000008) \ | ||
81 | /* INQUIRY response needs faking */ \ | ||
82 | US_FLAG(FIX_CAPACITY, 0x00000010) \ | ||
83 | /* READ CAPACITY response too big */ \ | ||
84 | US_FLAG(IGNORE_RESIDUE, 0x00000020) \ | ||
85 | /* reported residue is wrong */ \ | ||
86 | US_FLAG(BULK32, 0x00000040) \ | ||
87 | /* Uses 32-byte CBW length */ \ | ||
88 | US_FLAG(NOT_LOCKABLE, 0x00000080) \ | ||
89 | /* PREVENT/ALLOW not supported */ \ | ||
90 | US_FLAG(GO_SLOW, 0x00000100) \ | ||
91 | /* Need delay after Command phase */ \ | ||
92 | US_FLAG(NO_WP_DETECT, 0x00000200) \ | ||
93 | /* Don't check for write-protect */ \ | ||
94 | |||
95 | #define US_FLAG(name, value) US_FL_##name = value , | ||
96 | enum { US_DO_ALL_FLAGS }; | ||
97 | #undef US_FLAG | ||
98 | 69 | ||
99 | /* Dynamic flag definitions: used in set_bit() etc. */ | 70 | /* Dynamic flag definitions: used in set_bit() etc. */ |
100 | #define US_FLIDX_URB_ACTIVE 18 /* 0x00040000 current_urb is in use */ | 71 | #define US_FLIDX_URB_ACTIVE 18 /* 0x00040000 current_urb is in use */ |
@@ -122,7 +93,11 @@ enum { US_DO_ALL_FLAGS }; | |||
122 | typedef int (*trans_cmnd)(struct scsi_cmnd *, struct us_data*); | 93 | typedef int (*trans_cmnd)(struct scsi_cmnd *, struct us_data*); |
123 | typedef int (*trans_reset)(struct us_data*); | 94 | typedef int (*trans_reset)(struct us_data*); |
124 | typedef void (*proto_cmnd)(struct scsi_cmnd*, struct us_data*); | 95 | typedef void (*proto_cmnd)(struct scsi_cmnd*, struct us_data*); |
125 | typedef void (*extra_data_destructor)(void *); /* extra data destructor */ | 96 | typedef void (*extra_data_destructor)(void *); /* extra data destructor */ |
97 | typedef void (*pm_hook)(struct us_data *, int); /* power management hook */ | ||
98 | |||
99 | #define US_SUSPEND 0 | ||
100 | #define US_RESUME 1 | ||
126 | 101 | ||
127 | /* we allocate one of these for every device that we remember */ | 102 | /* we allocate one of these for every device that we remember */ |
128 | struct us_data { | 103 | struct us_data { |
@@ -178,6 +153,9 @@ struct us_data { | |||
178 | /* subdriver information */ | 153 | /* subdriver information */ |
179 | void *extra; /* Any extra data */ | 154 | void *extra; /* Any extra data */ |
180 | extra_data_destructor extra_destructor;/* extra data destructor */ | 155 | extra_data_destructor extra_destructor;/* extra data destructor */ |
156 | #ifdef CONFIG_PM | ||
157 | pm_hook suspend_resume_hook; | ||
158 | #endif | ||
181 | }; | 159 | }; |
182 | 160 | ||
183 | /* Convert between us_data and the corresponding Scsi_Host */ | 161 | /* Convert between us_data and the corresponding Scsi_Host */ |