diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/usb/storage/sddr55.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/usb/storage/sddr55.c')
-rw-r--r-- | drivers/usb/storage/sddr55.c | 938 |
1 files changed, 938 insertions, 0 deletions
diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c new file mode 100644 index 000000000000..229ca181716b --- /dev/null +++ b/drivers/usb/storage/sddr55.c | |||
@@ -0,0 +1,938 @@ | |||
1 | /* Driver for SanDisk SDDR-55 SmartMedia reader | ||
2 | * | ||
3 | * $Id:$ | ||
4 | * | ||
5 | * SDDR55 driver v0.1: | ||
6 | * | ||
7 | * First release | ||
8 | * | ||
9 | * Current development and maintenance by: | ||
10 | * (c) 2002 Simon Munton | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2, or (at your option) any | ||
15 | * later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, but | ||
18 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
20 | * General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License along | ||
23 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
24 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #include <linux/jiffies.h> | ||
28 | #include <linux/errno.h> | ||
29 | #include <linux/slab.h> | ||
30 | |||
31 | #include <scsi/scsi.h> | ||
32 | #include <scsi/scsi_cmnd.h> | ||
33 | |||
34 | #include "usb.h" | ||
35 | #include "transport.h" | ||
36 | #include "protocol.h" | ||
37 | #include "debug.h" | ||
38 | #include "sddr55.h" | ||
39 | |||
40 | |||
41 | #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) ) | ||
42 | #define LSB_of(s) ((s)&0xFF) | ||
43 | #define MSB_of(s) ((s)>>8) | ||
44 | #define PAGESIZE 512 | ||
45 | |||
46 | #define set_sense_info(sk, asc, ascq) \ | ||
47 | do { \ | ||
48 | info->sense_data[2] = sk; \ | ||
49 | info->sense_data[12] = asc; \ | ||
50 | info->sense_data[13] = ascq; \ | ||
51 | } while (0) | ||
52 | |||
53 | |||
54 | struct sddr55_card_info { | ||
55 | unsigned long capacity; /* Size of card in bytes */ | ||
56 | int max_log_blks; /* maximum number of logical blocks */ | ||
57 | int pageshift; /* log2 of pagesize */ | ||
58 | int smallpageshift; /* 1 if pagesize == 256 */ | ||
59 | int blocksize; /* Size of block in pages */ | ||
60 | int blockshift; /* log2 of blocksize */ | ||
61 | int blockmask; /* 2^blockshift - 1 */ | ||
62 | int read_only; /* non zero if card is write protected */ | ||
63 | int force_read_only; /* non zero if we find a map error*/ | ||
64 | int *lba_to_pba; /* logical to physical map */ | ||
65 | int *pba_to_lba; /* physical to logical map */ | ||
66 | int fatal_error; /* set if we detect something nasty */ | ||
67 | unsigned long last_access; /* number of jiffies since we last talked to device */ | ||
68 | unsigned char sense_data[18]; | ||
69 | }; | ||
70 | |||
71 | |||
72 | #define NOT_ALLOCATED 0xffffffff | ||
73 | #define BAD_BLOCK 0xffff | ||
74 | #define CIS_BLOCK 0x400 | ||
75 | #define UNUSED_BLOCK 0x3ff | ||
76 | |||
77 | static int | ||
78 | sddr55_bulk_transport(struct us_data *us, int direction, | ||
79 | unsigned char *data, unsigned int len) { | ||
80 | struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; | ||
81 | unsigned int pipe = (direction == DMA_FROM_DEVICE) ? | ||
82 | us->recv_bulk_pipe : us->send_bulk_pipe; | ||
83 | |||
84 | if (!len) | ||
85 | return USB_STOR_XFER_GOOD; | ||
86 | info->last_access = jiffies; | ||
87 | return usb_stor_bulk_transfer_buf(us, pipe, data, len, NULL); | ||
88 | } | ||
89 | |||
90 | /* check if card inserted, if there is, update read_only status | ||
91 | * return non zero if no card | ||
92 | */ | ||
93 | |||
94 | static int sddr55_status(struct us_data *us) | ||
95 | { | ||
96 | int result; | ||
97 | unsigned char *command = us->iobuf; | ||
98 | unsigned char *status = us->iobuf; | ||
99 | struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; | ||
100 | |||
101 | /* send command */ | ||
102 | memset(command, 0, 8); | ||
103 | command[5] = 0xB0; | ||
104 | command[7] = 0x80; | ||
105 | result = sddr55_bulk_transport(us, | ||
106 | DMA_TO_DEVICE, command, 8); | ||
107 | |||
108 | US_DEBUGP("Result for send_command in status %d\n", | ||
109 | result); | ||
110 | |||
111 | if (result != USB_STOR_XFER_GOOD) { | ||
112 | set_sense_info (4, 0, 0); /* hardware error */ | ||
113 | return USB_STOR_TRANSPORT_ERROR; | ||
114 | } | ||
115 | |||
116 | result = sddr55_bulk_transport(us, | ||
117 | DMA_FROM_DEVICE, status, 4); | ||
118 | |||
119 | /* expect to get short transfer if no card fitted */ | ||
120 | if (result == USB_STOR_XFER_SHORT || result == USB_STOR_XFER_STALLED) { | ||
121 | /* had a short transfer, no card inserted, free map memory */ | ||
122 | if (info->lba_to_pba) | ||
123 | kfree(info->lba_to_pba); | ||
124 | if (info->pba_to_lba) | ||
125 | kfree(info->pba_to_lba); | ||
126 | info->lba_to_pba = NULL; | ||
127 | info->pba_to_lba = NULL; | ||
128 | |||
129 | info->fatal_error = 0; | ||
130 | info->force_read_only = 0; | ||
131 | |||
132 | set_sense_info (2, 0x3a, 0); /* not ready, medium not present */ | ||
133 | return USB_STOR_TRANSPORT_FAILED; | ||
134 | } | ||
135 | |||
136 | if (result != USB_STOR_XFER_GOOD) { | ||
137 | set_sense_info (4, 0, 0); /* hardware error */ | ||
138 | return USB_STOR_TRANSPORT_FAILED; | ||
139 | } | ||
140 | |||
141 | /* check write protect status */ | ||
142 | info->read_only = (status[0] & 0x20); | ||
143 | |||
144 | /* now read status */ | ||
145 | result = sddr55_bulk_transport(us, | ||
146 | DMA_FROM_DEVICE, status, 2); | ||
147 | |||
148 | if (result != USB_STOR_XFER_GOOD) { | ||
149 | set_sense_info (4, 0, 0); /* hardware error */ | ||
150 | } | ||
151 | |||
152 | return (result == USB_STOR_XFER_GOOD ? | ||
153 | USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_FAILED); | ||
154 | } | ||
155 | |||
156 | |||
157 | static int sddr55_read_data(struct us_data *us, | ||
158 | unsigned int lba, | ||
159 | unsigned int page, | ||
160 | unsigned short sectors) { | ||
161 | |||
162 | int result = USB_STOR_TRANSPORT_GOOD; | ||
163 | unsigned char *command = us->iobuf; | ||
164 | unsigned char *status = us->iobuf; | ||
165 | struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; | ||
166 | unsigned char *buffer; | ||
167 | |||
168 | unsigned int pba; | ||
169 | unsigned long address; | ||
170 | |||
171 | unsigned short pages; | ||
172 | unsigned int len, index, offset; | ||
173 | |||
174 | // Since we only read in one block at a time, we have to create | ||
175 | // a bounce buffer and move the data a piece at a time between the | ||
176 | // bounce buffer and the actual transfer buffer. | ||
177 | |||
178 | len = min((unsigned int) sectors, (unsigned int) info->blocksize >> | ||
179 | info->smallpageshift) * PAGESIZE; | ||
180 | buffer = kmalloc(len, GFP_NOIO); | ||
181 | if (buffer == NULL) | ||
182 | return USB_STOR_TRANSPORT_ERROR; /* out of memory */ | ||
183 | index = offset = 0; | ||
184 | |||
185 | while (sectors>0) { | ||
186 | |||
187 | /* have we got to end? */ | ||
188 | if (lba >= info->max_log_blks) | ||
189 | break; | ||
190 | |||
191 | pba = info->lba_to_pba[lba]; | ||
192 | |||
193 | // Read as many sectors as possible in this block | ||
194 | |||
195 | pages = min((unsigned int) sectors << info->smallpageshift, | ||
196 | info->blocksize - page); | ||
197 | len = pages << info->pageshift; | ||
198 | |||
199 | US_DEBUGP("Read %02X pages, from PBA %04X" | ||
200 | " (LBA %04X) page %02X\n", | ||
201 | pages, pba, lba, page); | ||
202 | |||
203 | if (pba == NOT_ALLOCATED) { | ||
204 | /* no pba for this lba, fill with zeroes */ | ||
205 | memset (buffer, 0, len); | ||
206 | } else { | ||
207 | |||
208 | address = (pba << info->blockshift) + page; | ||
209 | |||
210 | command[0] = 0; | ||
211 | command[1] = LSB_of(address>>16); | ||
212 | command[2] = LSB_of(address>>8); | ||
213 | command[3] = LSB_of(address); | ||
214 | |||
215 | command[4] = 0; | ||
216 | command[5] = 0xB0; | ||
217 | command[6] = LSB_of(pages << (1 - info->smallpageshift)); | ||
218 | command[7] = 0x85; | ||
219 | |||
220 | /* send command */ | ||
221 | result = sddr55_bulk_transport(us, | ||
222 | DMA_TO_DEVICE, command, 8); | ||
223 | |||
224 | US_DEBUGP("Result for send_command in read_data %d\n", | ||
225 | result); | ||
226 | |||
227 | if (result != USB_STOR_XFER_GOOD) { | ||
228 | result = USB_STOR_TRANSPORT_ERROR; | ||
229 | goto leave; | ||
230 | } | ||
231 | |||
232 | /* read data */ | ||
233 | result = sddr55_bulk_transport(us, | ||
234 | DMA_FROM_DEVICE, buffer, len); | ||
235 | |||
236 | if (result != USB_STOR_XFER_GOOD) { | ||
237 | result = USB_STOR_TRANSPORT_ERROR; | ||
238 | goto leave; | ||
239 | } | ||
240 | |||
241 | /* now read status */ | ||
242 | result = sddr55_bulk_transport(us, | ||
243 | DMA_FROM_DEVICE, status, 2); | ||
244 | |||
245 | if (result != USB_STOR_XFER_GOOD) { | ||
246 | result = USB_STOR_TRANSPORT_ERROR; | ||
247 | goto leave; | ||
248 | } | ||
249 | |||
250 | /* check status for error */ | ||
251 | if (status[0] == 0xff && status[1] == 0x4) { | ||
252 | set_sense_info (3, 0x11, 0); | ||
253 | result = USB_STOR_TRANSPORT_FAILED; | ||
254 | goto leave; | ||
255 | } | ||
256 | } | ||
257 | |||
258 | // Store the data in the transfer buffer | ||
259 | usb_stor_access_xfer_buf(buffer, len, us->srb, | ||
260 | &index, &offset, TO_XFER_BUF); | ||
261 | |||
262 | page = 0; | ||
263 | lba++; | ||
264 | sectors -= pages >> info->smallpageshift; | ||
265 | } | ||
266 | |||
267 | result = USB_STOR_TRANSPORT_GOOD; | ||
268 | |||
269 | leave: | ||
270 | kfree(buffer); | ||
271 | |||
272 | return result; | ||
273 | } | ||
274 | |||
275 | static int sddr55_write_data(struct us_data *us, | ||
276 | unsigned int lba, | ||
277 | unsigned int page, | ||
278 | unsigned short sectors) { | ||
279 | |||
280 | int result = USB_STOR_TRANSPORT_GOOD; | ||
281 | unsigned char *command = us->iobuf; | ||
282 | unsigned char *status = us->iobuf; | ||
283 | struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; | ||
284 | unsigned char *buffer; | ||
285 | |||
286 | unsigned int pba; | ||
287 | unsigned int new_pba; | ||
288 | unsigned long address; | ||
289 | |||
290 | unsigned short pages; | ||
291 | int i; | ||
292 | unsigned int len, index, offset; | ||
293 | |||
294 | /* check if we are allowed to write */ | ||
295 | if (info->read_only || info->force_read_only) { | ||
296 | set_sense_info (7, 0x27, 0); /* read only */ | ||
297 | return USB_STOR_TRANSPORT_FAILED; | ||
298 | } | ||
299 | |||
300 | // Since we only write one block at a time, we have to create | ||
301 | // a bounce buffer and move the data a piece at a time between the | ||
302 | // bounce buffer and the actual transfer buffer. | ||
303 | |||
304 | len = min((unsigned int) sectors, (unsigned int) info->blocksize >> | ||
305 | info->smallpageshift) * PAGESIZE; | ||
306 | buffer = kmalloc(len, GFP_NOIO); | ||
307 | if (buffer == NULL) | ||
308 | return USB_STOR_TRANSPORT_ERROR; | ||
309 | index = offset = 0; | ||
310 | |||
311 | while (sectors > 0) { | ||
312 | |||
313 | /* have we got to end? */ | ||
314 | if (lba >= info->max_log_blks) | ||
315 | break; | ||
316 | |||
317 | pba = info->lba_to_pba[lba]; | ||
318 | |||
319 | // Write as many sectors as possible in this block | ||
320 | |||
321 | pages = min((unsigned int) sectors << info->smallpageshift, | ||
322 | info->blocksize - page); | ||
323 | len = pages << info->pageshift; | ||
324 | |||
325 | // Get the data from the transfer buffer | ||
326 | usb_stor_access_xfer_buf(buffer, len, us->srb, | ||
327 | &index, &offset, FROM_XFER_BUF); | ||
328 | |||
329 | US_DEBUGP("Write %02X pages, to PBA %04X" | ||
330 | " (LBA %04X) page %02X\n", | ||
331 | pages, pba, lba, page); | ||
332 | |||
333 | command[4] = 0; | ||
334 | |||
335 | if (pba == NOT_ALLOCATED) { | ||
336 | /* no pba allocated for this lba, find a free pba to use */ | ||
337 | |||
338 | int max_pba = (info->max_log_blks / 250 ) * 256; | ||
339 | int found_count = 0; | ||
340 | int found_pba = -1; | ||
341 | |||
342 | /* set pba to first block in zone lba is in */ | ||
343 | pba = (lba / 1000) * 1024; | ||
344 | |||
345 | US_DEBUGP("No PBA for LBA %04X\n",lba); | ||
346 | |||
347 | if (max_pba > 1024) | ||
348 | max_pba = 1024; | ||
349 | |||
350 | /* | ||
351 | * Scan through the map looking for an unused block | ||
352 | * leave 16 unused blocks at start (or as many as | ||
353 | * possible) since the sddr55 seems to reuse a used | ||
354 | * block when it shouldn't if we don't leave space. | ||
355 | */ | ||
356 | for (i = 0; i < max_pba; i++, pba++) { | ||
357 | if (info->pba_to_lba[pba] == UNUSED_BLOCK) { | ||
358 | found_pba = pba; | ||
359 | if (found_count++ > 16) | ||
360 | break; | ||
361 | } | ||
362 | } | ||
363 | |||
364 | pba = found_pba; | ||
365 | |||
366 | if (pba == -1) { | ||
367 | /* oh dear */ | ||
368 | US_DEBUGP("Couldn't find unallocated block\n"); | ||
369 | |||
370 | set_sense_info (3, 0x31, 0); /* medium error */ | ||
371 | result = USB_STOR_TRANSPORT_FAILED; | ||
372 | goto leave; | ||
373 | } | ||
374 | |||
375 | US_DEBUGP("Allocating PBA %04X for LBA %04X\n", pba, lba); | ||
376 | |||
377 | /* set writing to unallocated block flag */ | ||
378 | command[4] = 0x40; | ||
379 | } | ||
380 | |||
381 | address = (pba << info->blockshift) + page; | ||
382 | |||
383 | command[1] = LSB_of(address>>16); | ||
384 | command[2] = LSB_of(address>>8); | ||
385 | command[3] = LSB_of(address); | ||
386 | |||
387 | /* set the lba into the command, modulo 1000 */ | ||
388 | command[0] = LSB_of(lba % 1000); | ||
389 | command[6] = MSB_of(lba % 1000); | ||
390 | |||
391 | command[4] |= LSB_of(pages >> info->smallpageshift); | ||
392 | command[5] = 0xB0; | ||
393 | command[7] = 0x86; | ||
394 | |||
395 | /* send command */ | ||
396 | result = sddr55_bulk_transport(us, | ||
397 | DMA_TO_DEVICE, command, 8); | ||
398 | |||
399 | if (result != USB_STOR_XFER_GOOD) { | ||
400 | US_DEBUGP("Result for send_command in write_data %d\n", | ||
401 | result); | ||
402 | |||
403 | /* set_sense_info is superfluous here? */ | ||
404 | set_sense_info (3, 0x3, 0);/* peripheral write error */ | ||
405 | result = USB_STOR_TRANSPORT_FAILED; | ||
406 | goto leave; | ||
407 | } | ||
408 | |||
409 | /* send the data */ | ||
410 | result = sddr55_bulk_transport(us, | ||
411 | DMA_TO_DEVICE, buffer, len); | ||
412 | |||
413 | if (result != USB_STOR_XFER_GOOD) { | ||
414 | US_DEBUGP("Result for send_data in write_data %d\n", | ||
415 | result); | ||
416 | |||
417 | /* set_sense_info is superfluous here? */ | ||
418 | set_sense_info (3, 0x3, 0);/* peripheral write error */ | ||
419 | result = USB_STOR_TRANSPORT_FAILED; | ||
420 | goto leave; | ||
421 | } | ||
422 | |||
423 | /* now read status */ | ||
424 | result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, status, 6); | ||
425 | |||
426 | if (result != USB_STOR_XFER_GOOD) { | ||
427 | US_DEBUGP("Result for get_status in write_data %d\n", | ||
428 | result); | ||
429 | |||
430 | /* set_sense_info is superfluous here? */ | ||
431 | set_sense_info (3, 0x3, 0);/* peripheral write error */ | ||
432 | result = USB_STOR_TRANSPORT_FAILED; | ||
433 | goto leave; | ||
434 | } | ||
435 | |||
436 | new_pba = (status[3] + (status[4] << 8) + (status[5] << 16)) | ||
437 | >> info->blockshift; | ||
438 | |||
439 | /* check status for error */ | ||
440 | if (status[0] == 0xff && status[1] == 0x4) { | ||
441 | info->pba_to_lba[new_pba] = BAD_BLOCK; | ||
442 | |||
443 | set_sense_info (3, 0x0c, 0); | ||
444 | result = USB_STOR_TRANSPORT_FAILED; | ||
445 | goto leave; | ||
446 | } | ||
447 | |||
448 | US_DEBUGP("Updating maps for LBA %04X: old PBA %04X, new PBA %04X\n", | ||
449 | lba, pba, new_pba); | ||
450 | |||
451 | /* update the lba<->pba maps, note new_pba might be the same as pba */ | ||
452 | info->lba_to_pba[lba] = new_pba; | ||
453 | info->pba_to_lba[pba] = UNUSED_BLOCK; | ||
454 | |||
455 | /* check that new_pba wasn't already being used */ | ||
456 | if (info->pba_to_lba[new_pba] != UNUSED_BLOCK) { | ||
457 | printk(KERN_ERR "sddr55 error: new PBA %04X already in use for LBA %04X\n", | ||
458 | new_pba, info->pba_to_lba[new_pba]); | ||
459 | info->fatal_error = 1; | ||
460 | set_sense_info (3, 0x31, 0); | ||
461 | result = USB_STOR_TRANSPORT_FAILED; | ||
462 | goto leave; | ||
463 | } | ||
464 | |||
465 | /* update the pba<->lba maps for new_pba */ | ||
466 | info->pba_to_lba[new_pba] = lba % 1000; | ||
467 | |||
468 | page = 0; | ||
469 | lba++; | ||
470 | sectors -= pages >> info->smallpageshift; | ||
471 | } | ||
472 | result = USB_STOR_TRANSPORT_GOOD; | ||
473 | |||
474 | leave: | ||
475 | kfree(buffer); | ||
476 | return result; | ||
477 | } | ||
478 | |||
479 | static int sddr55_read_deviceID(struct us_data *us, | ||
480 | unsigned char *manufacturerID, | ||
481 | unsigned char *deviceID) { | ||
482 | |||
483 | int result; | ||
484 | unsigned char *command = us->iobuf; | ||
485 | unsigned char *content = us->iobuf; | ||
486 | |||
487 | memset(command, 0, 8); | ||
488 | command[5] = 0xB0; | ||
489 | command[7] = 0x84; | ||
490 | result = sddr55_bulk_transport(us, DMA_TO_DEVICE, command, 8); | ||
491 | |||
492 | US_DEBUGP("Result of send_control for device ID is %d\n", | ||
493 | result); | ||
494 | |||
495 | if (result != USB_STOR_XFER_GOOD) | ||
496 | return USB_STOR_TRANSPORT_ERROR; | ||
497 | |||
498 | result = sddr55_bulk_transport(us, | ||
499 | DMA_FROM_DEVICE, content, 4); | ||
500 | |||
501 | if (result != USB_STOR_XFER_GOOD) | ||
502 | return USB_STOR_TRANSPORT_ERROR; | ||
503 | |||
504 | *manufacturerID = content[0]; | ||
505 | *deviceID = content[1]; | ||
506 | |||
507 | if (content[0] != 0xff) { | ||
508 | result = sddr55_bulk_transport(us, | ||
509 | DMA_FROM_DEVICE, content, 2); | ||
510 | } | ||
511 | |||
512 | return USB_STOR_TRANSPORT_GOOD; | ||
513 | } | ||
514 | |||
515 | |||
516 | int sddr55_reset(struct us_data *us) { | ||
517 | return 0; | ||
518 | } | ||
519 | |||
520 | |||
521 | static unsigned long sddr55_get_capacity(struct us_data *us) { | ||
522 | |||
523 | unsigned char manufacturerID; | ||
524 | unsigned char deviceID; | ||
525 | int result; | ||
526 | struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; | ||
527 | |||
528 | US_DEBUGP("Reading capacity...\n"); | ||
529 | |||
530 | result = sddr55_read_deviceID(us, | ||
531 | &manufacturerID, | ||
532 | &deviceID); | ||
533 | |||
534 | US_DEBUGP("Result of read_deviceID is %d\n", | ||
535 | result); | ||
536 | |||
537 | if (result != USB_STOR_XFER_GOOD) | ||
538 | return 0; | ||
539 | |||
540 | US_DEBUGP("Device ID = %02X\n", deviceID); | ||
541 | US_DEBUGP("Manuf ID = %02X\n", manufacturerID); | ||
542 | |||
543 | info->pageshift = 9; | ||
544 | info->smallpageshift = 0; | ||
545 | info->blocksize = 16; | ||
546 | info->blockshift = 4; | ||
547 | info->blockmask = 15; | ||
548 | |||
549 | switch (deviceID) { | ||
550 | |||
551 | case 0x6e: // 1MB | ||
552 | case 0xe8: | ||
553 | case 0xec: | ||
554 | info->pageshift = 8; | ||
555 | info->smallpageshift = 1; | ||
556 | return 0x00100000; | ||
557 | |||
558 | case 0xea: // 2MB | ||
559 | case 0x64: | ||
560 | info->pageshift = 8; | ||
561 | info->smallpageshift = 1; | ||
562 | case 0x5d: // 5d is a ROM card with pagesize 512. | ||
563 | return 0x00200000; | ||
564 | |||
565 | case 0xe3: // 4MB | ||
566 | case 0xe5: | ||
567 | case 0x6b: | ||
568 | case 0xd5: | ||
569 | return 0x00400000; | ||
570 | |||
571 | case 0xe6: // 8MB | ||
572 | case 0xd6: | ||
573 | return 0x00800000; | ||
574 | |||
575 | case 0x73: // 16MB | ||
576 | info->blocksize = 32; | ||
577 | info->blockshift = 5; | ||
578 | info->blockmask = 31; | ||
579 | return 0x01000000; | ||
580 | |||
581 | case 0x75: // 32MB | ||
582 | info->blocksize = 32; | ||
583 | info->blockshift = 5; | ||
584 | info->blockmask = 31; | ||
585 | return 0x02000000; | ||
586 | |||
587 | case 0x76: // 64MB | ||
588 | info->blocksize = 32; | ||
589 | info->blockshift = 5; | ||
590 | info->blockmask = 31; | ||
591 | return 0x04000000; | ||
592 | |||
593 | case 0x79: // 128MB | ||
594 | info->blocksize = 32; | ||
595 | info->blockshift = 5; | ||
596 | info->blockmask = 31; | ||
597 | return 0x08000000; | ||
598 | |||
599 | default: // unknown | ||
600 | return 0; | ||
601 | |||
602 | } | ||
603 | } | ||
604 | |||
605 | static int sddr55_read_map(struct us_data *us) { | ||
606 | |||
607 | struct sddr55_card_info *info = (struct sddr55_card_info *)(us->extra); | ||
608 | int numblocks; | ||
609 | unsigned char *buffer; | ||
610 | unsigned char *command = us->iobuf; | ||
611 | int i; | ||
612 | unsigned short lba; | ||
613 | unsigned short max_lba; | ||
614 | int result; | ||
615 | |||
616 | if (!info->capacity) | ||
617 | return -1; | ||
618 | |||
619 | numblocks = info->capacity >> (info->blockshift + info->pageshift); | ||
620 | |||
621 | buffer = kmalloc( numblocks * 2, GFP_NOIO ); | ||
622 | |||
623 | if (!buffer) | ||
624 | return -1; | ||
625 | |||
626 | memset(command, 0, 8); | ||
627 | command[5] = 0xB0; | ||
628 | command[6] = numblocks * 2 / 256; | ||
629 | command[7] = 0x8A; | ||
630 | |||
631 | result = sddr55_bulk_transport(us, DMA_TO_DEVICE, command, 8); | ||
632 | |||
633 | if ( result != USB_STOR_XFER_GOOD) { | ||
634 | kfree (buffer); | ||
635 | return -1; | ||
636 | } | ||
637 | |||
638 | result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, buffer, numblocks * 2); | ||
639 | |||
640 | if ( result != USB_STOR_XFER_GOOD) { | ||
641 | kfree (buffer); | ||
642 | return -1; | ||
643 | } | ||
644 | |||
645 | result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, command, 2); | ||
646 | |||
647 | if ( result != USB_STOR_XFER_GOOD) { | ||
648 | kfree (buffer); | ||
649 | return -1; | ||
650 | } | ||
651 | |||
652 | if (info->lba_to_pba) | ||
653 | kfree(info->lba_to_pba); | ||
654 | if (info->pba_to_lba) | ||
655 | kfree(info->pba_to_lba); | ||
656 | info->lba_to_pba = kmalloc(numblocks*sizeof(int), GFP_NOIO); | ||
657 | info->pba_to_lba = kmalloc(numblocks*sizeof(int), GFP_NOIO); | ||
658 | |||
659 | if (info->lba_to_pba == NULL || info->pba_to_lba == NULL) { | ||
660 | if (info->lba_to_pba != NULL) | ||
661 | kfree(info->lba_to_pba); | ||
662 | if (info->pba_to_lba != NULL) | ||
663 | kfree(info->pba_to_lba); | ||
664 | info->lba_to_pba = NULL; | ||
665 | info->pba_to_lba = NULL; | ||
666 | kfree(buffer); | ||
667 | return -1; | ||
668 | } | ||
669 | |||
670 | memset(info->lba_to_pba, 0xff, numblocks*sizeof(int)); | ||
671 | memset(info->pba_to_lba, 0xff, numblocks*sizeof(int)); | ||
672 | |||
673 | /* set maximum lba */ | ||
674 | max_lba = info->max_log_blks; | ||
675 | if (max_lba > 1000) | ||
676 | max_lba = 1000; | ||
677 | |||
678 | // Each block is 64 bytes of control data, so block i is located in | ||
679 | // scatterlist block i*64/128k = i*(2^6)*(2^-17) = i*(2^-11) | ||
680 | |||
681 | for (i=0; i<numblocks; i++) { | ||
682 | int zone = i / 1024; | ||
683 | |||
684 | lba = short_pack(buffer[i * 2], buffer[i * 2 + 1]); | ||
685 | |||
686 | /* Every 1024 physical blocks ("zone"), the LBA numbers | ||
687 | * go back to zero, but are within a higher | ||
688 | * block of LBA's. Also, there is a maximum of | ||
689 | * 1000 LBA's per zone. In other words, in PBA | ||
690 | * 1024-2047 you will find LBA 0-999 which are | ||
691 | * really LBA 1000-1999. Yes, this wastes 24 | ||
692 | * physical blocks per zone. Go figure. | ||
693 | * These devices can have blocks go bad, so there | ||
694 | * are 24 spare blocks to use when blocks do go bad. | ||
695 | */ | ||
696 | |||
697 | /* SDDR55 returns 0xffff for a bad block, and 0x400 for the | ||
698 | * CIS block. (Is this true for cards 8MB or less??) | ||
699 | * Record these in the physical to logical map | ||
700 | */ | ||
701 | |||
702 | info->pba_to_lba[i] = lba; | ||
703 | |||
704 | if (lba >= max_lba) { | ||
705 | continue; | ||
706 | } | ||
707 | |||
708 | if (info->lba_to_pba[lba + zone * 1000] != NOT_ALLOCATED && | ||
709 | !info->force_read_only) { | ||
710 | printk("sddr55: map inconsistency at LBA %04X\n", lba + zone * 1000); | ||
711 | info->force_read_only = 1; | ||
712 | } | ||
713 | |||
714 | if (lba<0x10 || (lba>=0x3E0 && lba<0x3EF)) | ||
715 | US_DEBUGP("LBA %04X <-> PBA %04X\n", lba, i); | ||
716 | |||
717 | info->lba_to_pba[lba + zone * 1000] = i; | ||
718 | } | ||
719 | |||
720 | kfree(buffer); | ||
721 | return 0; | ||
722 | } | ||
723 | |||
724 | |||
725 | static void sddr55_card_info_destructor(void *extra) { | ||
726 | struct sddr55_card_info *info = (struct sddr55_card_info *)extra; | ||
727 | |||
728 | if (!extra) | ||
729 | return; | ||
730 | |||
731 | if (info->lba_to_pba) | ||
732 | kfree(info->lba_to_pba); | ||
733 | if (info->pba_to_lba) | ||
734 | kfree(info->pba_to_lba); | ||
735 | } | ||
736 | |||
737 | |||
738 | /* | ||
739 | * Transport for the Sandisk SDDR-55 | ||
740 | */ | ||
741 | int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us) | ||
742 | { | ||
743 | int result; | ||
744 | static unsigned char inquiry_response[8] = { | ||
745 | 0x00, 0x80, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x00 | ||
746 | }; | ||
747 | // write-protected for now, no block descriptor support | ||
748 | static unsigned char mode_page_01[20] = { | ||
749 | 0x0, 0x12, 0x00, 0x80, 0x0, 0x0, 0x0, 0x0, | ||
750 | 0x01, 0x0A, | ||
751 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
752 | }; | ||
753 | unsigned char *ptr = us->iobuf; | ||
754 | unsigned long capacity; | ||
755 | unsigned int lba; | ||
756 | unsigned int pba; | ||
757 | unsigned int page; | ||
758 | unsigned short pages; | ||
759 | struct sddr55_card_info *info; | ||
760 | |||
761 | if (!us->extra) { | ||
762 | us->extra = kmalloc( | ||
763 | sizeof(struct sddr55_card_info), GFP_NOIO); | ||
764 | if (!us->extra) | ||
765 | return USB_STOR_TRANSPORT_ERROR; | ||
766 | memset(us->extra, 0, sizeof(struct sddr55_card_info)); | ||
767 | us->extra_destructor = sddr55_card_info_destructor; | ||
768 | } | ||
769 | |||
770 | info = (struct sddr55_card_info *)(us->extra); | ||
771 | |||
772 | if (srb->cmnd[0] == REQUEST_SENSE) { | ||
773 | US_DEBUGP("SDDR55: request sense %02x/%02x/%02x\n", info->sense_data[2], info->sense_data[12], info->sense_data[13]); | ||
774 | |||
775 | memcpy (ptr, info->sense_data, sizeof info->sense_data); | ||
776 | ptr[0] = 0x70; | ||
777 | ptr[7] = 11; | ||
778 | usb_stor_set_xfer_buf (ptr, sizeof info->sense_data, srb); | ||
779 | memset (info->sense_data, 0, sizeof info->sense_data); | ||
780 | |||
781 | return USB_STOR_TRANSPORT_GOOD; | ||
782 | } | ||
783 | |||
784 | memset (info->sense_data, 0, sizeof info->sense_data); | ||
785 | |||
786 | /* Dummy up a response for INQUIRY since SDDR55 doesn't | ||
787 | respond to INQUIRY commands */ | ||
788 | |||
789 | if (srb->cmnd[0] == INQUIRY) { | ||
790 | memcpy(ptr, inquiry_response, 8); | ||
791 | fill_inquiry_response(us, ptr, 36); | ||
792 | return USB_STOR_TRANSPORT_GOOD; | ||
793 | } | ||
794 | |||
795 | /* only check card status if the map isn't allocated, ie no card seen yet | ||
796 | * or if it's been over half a second since we last accessed it | ||
797 | */ | ||
798 | if (info->lba_to_pba == NULL || time_after(jiffies, info->last_access + HZ/2)) { | ||
799 | |||
800 | /* check to see if a card is fitted */ | ||
801 | result = sddr55_status (us); | ||
802 | if (result) { | ||
803 | result = sddr55_status (us); | ||
804 | if (!result) { | ||
805 | set_sense_info (6, 0x28, 0); /* new media, set unit attention, not ready to ready */ | ||
806 | } | ||
807 | return USB_STOR_TRANSPORT_FAILED; | ||
808 | } | ||
809 | } | ||
810 | |||
811 | /* if we detected a problem with the map when writing, | ||
812 | don't allow any more access */ | ||
813 | if (info->fatal_error) { | ||
814 | |||
815 | set_sense_info (3, 0x31, 0); | ||
816 | return USB_STOR_TRANSPORT_FAILED; | ||
817 | } | ||
818 | |||
819 | if (srb->cmnd[0] == READ_CAPACITY) { | ||
820 | |||
821 | capacity = sddr55_get_capacity(us); | ||
822 | |||
823 | if (!capacity) { | ||
824 | set_sense_info (3, 0x30, 0); /* incompatible medium */ | ||
825 | return USB_STOR_TRANSPORT_FAILED; | ||
826 | } | ||
827 | |||
828 | info->capacity = capacity; | ||
829 | |||
830 | /* figure out the maximum logical block number, allowing for | ||
831 | * the fact that only 250 out of every 256 are used */ | ||
832 | info->max_log_blks = ((info->capacity >> (info->pageshift + info->blockshift)) / 256) * 250; | ||
833 | |||
834 | /* Last page in the card, adjust as we only use 250 out of | ||
835 | * every 256 pages */ | ||
836 | capacity = (capacity / 256) * 250; | ||
837 | |||
838 | capacity /= PAGESIZE; | ||
839 | capacity--; | ||
840 | |||
841 | ((__be32 *) ptr)[0] = cpu_to_be32(capacity); | ||
842 | ((__be32 *) ptr)[1] = cpu_to_be32(PAGESIZE); | ||
843 | usb_stor_set_xfer_buf(ptr, 8, srb); | ||
844 | |||
845 | sddr55_read_map(us); | ||
846 | |||
847 | return USB_STOR_TRANSPORT_GOOD; | ||
848 | } | ||
849 | |||
850 | if (srb->cmnd[0] == MODE_SENSE_10) { | ||
851 | |||
852 | memcpy(ptr, mode_page_01, sizeof mode_page_01); | ||
853 | ptr[3] = (info->read_only || info->force_read_only) ? 0x80 : 0; | ||
854 | usb_stor_set_xfer_buf(ptr, sizeof(mode_page_01), srb); | ||
855 | |||
856 | if ( (srb->cmnd[2] & 0x3F) == 0x01 ) { | ||
857 | US_DEBUGP( | ||
858 | "SDDR55: Dummy up request for mode page 1\n"); | ||
859 | return USB_STOR_TRANSPORT_GOOD; | ||
860 | |||
861 | } else if ( (srb->cmnd[2] & 0x3F) == 0x3F ) { | ||
862 | US_DEBUGP( | ||
863 | "SDDR55: Dummy up request for all mode pages\n"); | ||
864 | return USB_STOR_TRANSPORT_GOOD; | ||
865 | } | ||
866 | |||
867 | set_sense_info (5, 0x24, 0); /* invalid field in command */ | ||
868 | return USB_STOR_TRANSPORT_FAILED; | ||
869 | } | ||
870 | |||
871 | if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) { | ||
872 | |||
873 | US_DEBUGP( | ||
874 | "SDDR55: %s medium removal. Not that I can do" | ||
875 | " anything about it...\n", | ||
876 | (srb->cmnd[4]&0x03) ? "Prevent" : "Allow"); | ||
877 | |||
878 | return USB_STOR_TRANSPORT_GOOD; | ||
879 | |||
880 | } | ||
881 | |||
882 | if (srb->cmnd[0] == READ_10 || srb->cmnd[0] == WRITE_10) { | ||
883 | |||
884 | page = short_pack(srb->cmnd[3], srb->cmnd[2]); | ||
885 | page <<= 16; | ||
886 | page |= short_pack(srb->cmnd[5], srb->cmnd[4]); | ||
887 | pages = short_pack(srb->cmnd[8], srb->cmnd[7]); | ||
888 | |||
889 | page <<= info->smallpageshift; | ||
890 | |||
891 | // convert page to block and page-within-block | ||
892 | |||
893 | lba = page >> info->blockshift; | ||
894 | page = page & info->blockmask; | ||
895 | |||
896 | // locate physical block corresponding to logical block | ||
897 | |||
898 | if (lba >= info->max_log_blks) { | ||
899 | |||
900 | US_DEBUGP("Error: Requested LBA %04X exceeds maximum " | ||
901 | "block %04X\n", lba, info->max_log_blks-1); | ||
902 | |||
903 | set_sense_info (5, 0x24, 0); /* invalid field in command */ | ||
904 | |||
905 | return USB_STOR_TRANSPORT_FAILED; | ||
906 | } | ||
907 | |||
908 | pba = info->lba_to_pba[lba]; | ||
909 | |||
910 | if (srb->cmnd[0] == WRITE_10) { | ||
911 | US_DEBUGP("WRITE_10: write block %04X (LBA %04X) page %01X" | ||
912 | " pages %d\n", | ||
913 | pba, lba, page, pages); | ||
914 | |||
915 | return sddr55_write_data(us, lba, page, pages); | ||
916 | } else { | ||
917 | US_DEBUGP("READ_10: read block %04X (LBA %04X) page %01X" | ||
918 | " pages %d\n", | ||
919 | pba, lba, page, pages); | ||
920 | |||
921 | return sddr55_read_data(us, lba, page, pages); | ||
922 | } | ||
923 | } | ||
924 | |||
925 | |||
926 | if (srb->cmnd[0] == TEST_UNIT_READY) { | ||
927 | return USB_STOR_TRANSPORT_GOOD; | ||
928 | } | ||
929 | |||
930 | if (srb->cmnd[0] == START_STOP) { | ||
931 | return USB_STOR_TRANSPORT_GOOD; | ||
932 | } | ||
933 | |||
934 | set_sense_info (5, 0x20, 0); /* illegal command */ | ||
935 | |||
936 | return USB_STOR_TRANSPORT_FAILED; // FIXME: sense buffer? | ||
937 | } | ||
938 | |||