diff options
-rw-r--r-- | drivers/usb/storage/Kconfig | 9 | ||||
-rw-r--r-- | drivers/usb/storage/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/storage/alauda.c | 1119 | ||||
-rw-r--r-- | drivers/usb/storage/alauda.h | 100 | ||||
-rw-r--r-- | drivers/usb/storage/unusual_devs.h | 14 | ||||
-rw-r--r-- | drivers/usb/storage/usb.c | 12 | ||||
-rw-r--r-- | include/linux/usb_usual.h | 3 |
7 files changed, 1258 insertions, 0 deletions
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index bdfcb95d9c12..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)" |
diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 2d416e9028bb..8cbba22508a4 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile | |||
@@ -18,6 +18,7 @@ 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 \ |
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/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index be3c06d17533..7a865dd04683 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h | |||
@@ -535,6 +535,13 @@ UNUSUAL_DEV( 0x057b, 0x0022, 0x0000, 0x9999, | |||
535 | "Silicon Media R/W", | 535 | "Silicon Media R/W", |
536 | US_SC_DEVICE, US_PR_DEVICE, NULL, 0), | 536 | US_SC_DEVICE, US_PR_DEVICE, NULL, 0), |
537 | 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 | |||
538 | /* Fabrizio Fellini <fello@libero.it> */ | 545 | /* Fabrizio Fellini <fello@libero.it> */ |
539 | UNUSUAL_DEV( 0x0595, 0x4343, 0x0000, 0x2210, | 546 | UNUSUAL_DEV( 0x0595, 0x4343, 0x0000, 0x2210, |
540 | "Fujifilm", | 547 | "Fujifilm", |
@@ -784,6 +791,13 @@ UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100, | |||
784 | US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ), | 791 | US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ), |
785 | #endif | 792 | #endif |
786 | 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 | |||
787 | #ifdef CONFIG_USB_STORAGE_DATAFAB | 801 | #ifdef CONFIG_USB_STORAGE_DATAFAB |
788 | UNUSUAL_DEV( 0x07c4, 0xa000, 0x0000, 0x0015, | 802 | UNUSUAL_DEV( 0x07c4, 0xa000, 0x0000, 0x0015, |
789 | "Datafab", | 803 | "Datafab", |
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 85c8c17b3c0c..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>"); |
@@ -644,6 +647,15 @@ static int get_protocol(struct us_data *us) | |||
644 | break; | 647 | break; |
645 | #endif | 648 | #endif |
646 | 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 | |||
647 | default: | 659 | default: |
648 | return -EIO; | 660 | return -EIO; |
649 | } | 661 | } |
diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h index f9c058f33712..b2d08984a9f7 100644 --- a/include/linux/usb_usual.h +++ b/include/linux/usb_usual.h | |||
@@ -102,6 +102,9 @@ enum { US_DO_ALL_FLAGS }; | |||
102 | #ifdef CONFIG_USB_STORAGE_JUMPSHOT | 102 | #ifdef CONFIG_USB_STORAGE_JUMPSHOT |
103 | #define US_PR_JUMPSHOT 0xf3 /* Lexar Jumpshot */ | 103 | #define US_PR_JUMPSHOT 0xf3 /* Lexar Jumpshot */ |
104 | #endif | 104 | #endif |
105 | #ifdef CONFIG_USB_STORAGE_ALAUDA | ||
106 | #define US_PR_ALAUDA 0xf4 /* Alauda chipsets */ | ||
107 | #endif | ||
105 | 108 | ||
106 | #define US_PR_DEVICE 0xff /* Use device's value */ | 109 | #define US_PR_DEVICE 0xff /* Use device's value */ |
107 | 110 | ||