diff options
Diffstat (limited to 'drivers/usb/storage/sddr09.c')
-rw-r--r-- | drivers/usb/storage/sddr09.c | 214 |
1 files changed, 130 insertions, 84 deletions
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 | } | ||