15fd54aceSGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0+ 2f0183a33SFelipe Balbi /* 3f0183a33SFelipe Balbi * Driver for SanDisk SDDR-55 SmartMedia reader 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * SDDR55 driver v0.1: 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds * First release 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds * Current development and maintenance by: 101da177e4SLinus Torvalds * (c) 2002 Simon Munton 111da177e4SLinus Torvalds */ 121da177e4SLinus Torvalds 131da177e4SLinus Torvalds #include <linux/jiffies.h> 141da177e4SLinus Torvalds #include <linux/errno.h> 1570fcc005SAlan Stern #include <linux/module.h> 161da177e4SLinus Torvalds #include <linux/slab.h> 171da177e4SLinus Torvalds 181da177e4SLinus Torvalds #include <scsi/scsi.h> 191da177e4SLinus Torvalds #include <scsi/scsi_cmnd.h> 201da177e4SLinus Torvalds 211da177e4SLinus Torvalds #include "usb.h" 221da177e4SLinus Torvalds #include "transport.h" 231da177e4SLinus Torvalds #include "protocol.h" 241da177e4SLinus Torvalds #include "debug.h" 25aa519be3SAkinobu Mita #include "scsiglue.h" 26aa519be3SAkinobu Mita 27aa519be3SAkinobu Mita #define DRV_NAME "ums-sddr55" 2870fcc005SAlan Stern 294246b06aSMaciej Grela MODULE_DESCRIPTION("Driver for SanDisk SDDR-55 SmartMedia reader"); 304246b06aSMaciej Grela MODULE_AUTHOR("Simon Munton"); 314246b06aSMaciej Grela MODULE_LICENSE("GPL"); 3270fcc005SAlan Stern 3370fcc005SAlan Stern /* 3470fcc005SAlan Stern * The table of devices 3570fcc005SAlan Stern */ 3670fcc005SAlan Stern #define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ 3770fcc005SAlan Stern vendorName, productName, useProtocol, useTransport, \ 3870fcc005SAlan Stern initFunction, flags) \ 3970fcc005SAlan Stern { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ 40f61870eeSSebastian Andrzej Siewior .driver_info = (flags) } 4170fcc005SAlan Stern 42566b8bbfSFelipe Balbi static struct usb_device_id sddr55_usb_ids[] = { 4370fcc005SAlan Stern # include "unusual_sddr55.h" 4470fcc005SAlan Stern { } /* Terminating entry */ 4570fcc005SAlan Stern }; 4670fcc005SAlan Stern MODULE_DEVICE_TABLE(usb, sddr55_usb_ids); 4770fcc005SAlan Stern 4870fcc005SAlan Stern #undef UNUSUAL_DEV 4970fcc005SAlan Stern 5070fcc005SAlan Stern /* 5170fcc005SAlan Stern * The flags table 5270fcc005SAlan Stern */ 5370fcc005SAlan Stern #define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ 5470fcc005SAlan Stern vendor_name, product_name, use_protocol, use_transport, \ 5570fcc005SAlan Stern init_function, Flags) \ 5670fcc005SAlan Stern { \ 5770fcc005SAlan Stern .vendorName = vendor_name, \ 5870fcc005SAlan Stern .productName = product_name, \ 5970fcc005SAlan Stern .useProtocol = use_protocol, \ 6070fcc005SAlan Stern .useTransport = use_transport, \ 6170fcc005SAlan Stern .initFunction = init_function, \ 6270fcc005SAlan Stern } 6370fcc005SAlan Stern 6470fcc005SAlan Stern static struct us_unusual_dev sddr55_unusual_dev_list[] = { 6570fcc005SAlan Stern # include "unusual_sddr55.h" 6670fcc005SAlan Stern { } /* Terminating entry */ 6770fcc005SAlan Stern }; 6870fcc005SAlan Stern 6970fcc005SAlan Stern #undef UNUSUAL_DEV 701da177e4SLinus Torvalds 711da177e4SLinus Torvalds 721da177e4SLinus Torvalds #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) ) 731da177e4SLinus Torvalds #define LSB_of(s) ((s)&0xFF) 741da177e4SLinus Torvalds #define MSB_of(s) ((s)>>8) 751da177e4SLinus Torvalds #define PAGESIZE 512 761da177e4SLinus Torvalds 771da177e4SLinus Torvalds #define set_sense_info(sk, asc, ascq) \ 781da177e4SLinus Torvalds do { \ 791da177e4SLinus Torvalds info->sense_data[2] = sk; \ 801da177e4SLinus Torvalds info->sense_data[12] = asc; \ 811da177e4SLinus Torvalds info->sense_data[13] = ascq; \ 821da177e4SLinus Torvalds } while (0) 831da177e4SLinus Torvalds 841da177e4SLinus Torvalds 851da177e4SLinus Torvalds struct sddr55_card_info { 861da177e4SLinus Torvalds unsigned long capacity; /* Size of card in bytes */ 871da177e4SLinus Torvalds int max_log_blks; /* maximum number of logical blocks */ 881da177e4SLinus Torvalds int pageshift; /* log2 of pagesize */ 891da177e4SLinus Torvalds int smallpageshift; /* 1 if pagesize == 256 */ 901da177e4SLinus Torvalds int blocksize; /* Size of block in pages */ 911da177e4SLinus Torvalds int blockshift; /* log2 of blocksize */ 921da177e4SLinus Torvalds int blockmask; /* 2^blockshift - 1 */ 931da177e4SLinus Torvalds int read_only; /* non zero if card is write protected */ 941da177e4SLinus Torvalds int force_read_only; /* non zero if we find a map error*/ 951da177e4SLinus Torvalds int *lba_to_pba; /* logical to physical map */ 961da177e4SLinus Torvalds int *pba_to_lba; /* physical to logical map */ 971da177e4SLinus Torvalds int fatal_error; /* set if we detect something nasty */ 981da177e4SLinus Torvalds unsigned long last_access; /* number of jiffies since we last talked to device */ 991da177e4SLinus Torvalds unsigned char sense_data[18]; 1001da177e4SLinus Torvalds }; 1011da177e4SLinus Torvalds 1021da177e4SLinus Torvalds 1031da177e4SLinus Torvalds #define NOT_ALLOCATED 0xffffffff 1041da177e4SLinus Torvalds #define BAD_BLOCK 0xffff 1051da177e4SLinus Torvalds #define CIS_BLOCK 0x400 1061da177e4SLinus Torvalds #define UNUSED_BLOCK 0x3ff 1071da177e4SLinus Torvalds 1081da177e4SLinus Torvalds static int 1091da177e4SLinus Torvalds sddr55_bulk_transport(struct us_data *us, int direction, 1101da177e4SLinus Torvalds unsigned char *data, unsigned int len) { 1111da177e4SLinus Torvalds struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; 1121da177e4SLinus Torvalds unsigned int pipe = (direction == DMA_FROM_DEVICE) ? 1131da177e4SLinus Torvalds us->recv_bulk_pipe : us->send_bulk_pipe; 1141da177e4SLinus Torvalds 1151da177e4SLinus Torvalds if (!len) 1161da177e4SLinus Torvalds return USB_STOR_XFER_GOOD; 1171da177e4SLinus Torvalds info->last_access = jiffies; 1181da177e4SLinus Torvalds return usb_stor_bulk_transfer_buf(us, pipe, data, len, NULL); 1191da177e4SLinus Torvalds } 1201da177e4SLinus Torvalds 121f0183a33SFelipe Balbi /* 122f0183a33SFelipe Balbi * check if card inserted, if there is, update read_only status 1231da177e4SLinus Torvalds * return non zero if no card 1241da177e4SLinus Torvalds */ 1251da177e4SLinus Torvalds 1261da177e4SLinus Torvalds static int sddr55_status(struct us_data *us) 1271da177e4SLinus Torvalds { 1281da177e4SLinus Torvalds int result; 1291da177e4SLinus Torvalds unsigned char *command = us->iobuf; 1301da177e4SLinus Torvalds unsigned char *status = us->iobuf; 1311da177e4SLinus Torvalds struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; 1321da177e4SLinus Torvalds 1331da177e4SLinus Torvalds /* send command */ 1341da177e4SLinus Torvalds memset(command, 0, 8); 1351da177e4SLinus Torvalds command[5] = 0xB0; 1361da177e4SLinus Torvalds command[7] = 0x80; 1371da177e4SLinus Torvalds result = sddr55_bulk_transport(us, 1381da177e4SLinus Torvalds DMA_TO_DEVICE, command, 8); 1391da177e4SLinus Torvalds 140191648d0SJoe Perches usb_stor_dbg(us, "Result for send_command in status %d\n", result); 1411da177e4SLinus Torvalds 1421da177e4SLinus Torvalds if (result != USB_STOR_XFER_GOOD) { 1431da177e4SLinus Torvalds set_sense_info (4, 0, 0); /* hardware error */ 1441da177e4SLinus Torvalds return USB_STOR_TRANSPORT_ERROR; 1451da177e4SLinus Torvalds } 1461da177e4SLinus Torvalds 1471da177e4SLinus Torvalds result = sddr55_bulk_transport(us, 1481da177e4SLinus Torvalds DMA_FROM_DEVICE, status, 4); 1491da177e4SLinus Torvalds 1501da177e4SLinus Torvalds /* expect to get short transfer if no card fitted */ 1511da177e4SLinus Torvalds if (result == USB_STOR_XFER_SHORT || result == USB_STOR_XFER_STALLED) { 1521da177e4SLinus Torvalds /* had a short transfer, no card inserted, free map memory */ 1531da177e4SLinus Torvalds kfree(info->lba_to_pba); 1541da177e4SLinus Torvalds kfree(info->pba_to_lba); 1551da177e4SLinus Torvalds info->lba_to_pba = NULL; 1561da177e4SLinus Torvalds info->pba_to_lba = NULL; 1571da177e4SLinus Torvalds 1581da177e4SLinus Torvalds info->fatal_error = 0; 1591da177e4SLinus Torvalds info->force_read_only = 0; 1601da177e4SLinus Torvalds 1611da177e4SLinus Torvalds set_sense_info (2, 0x3a, 0); /* not ready, medium not present */ 1621da177e4SLinus Torvalds return USB_STOR_TRANSPORT_FAILED; 1631da177e4SLinus Torvalds } 1641da177e4SLinus Torvalds 1651da177e4SLinus Torvalds if (result != USB_STOR_XFER_GOOD) { 1661da177e4SLinus Torvalds set_sense_info (4, 0, 0); /* hardware error */ 1671da177e4SLinus Torvalds return USB_STOR_TRANSPORT_FAILED; 1681da177e4SLinus Torvalds } 1691da177e4SLinus Torvalds 1701da177e4SLinus Torvalds /* check write protect status */ 1711da177e4SLinus Torvalds info->read_only = (status[0] & 0x20); 1721da177e4SLinus Torvalds 1731da177e4SLinus Torvalds /* now read status */ 1741da177e4SLinus Torvalds result = sddr55_bulk_transport(us, 1751da177e4SLinus Torvalds DMA_FROM_DEVICE, status, 2); 1761da177e4SLinus Torvalds 1771da177e4SLinus Torvalds if (result != USB_STOR_XFER_GOOD) { 1781da177e4SLinus Torvalds set_sense_info (4, 0, 0); /* hardware error */ 1791da177e4SLinus Torvalds } 1801da177e4SLinus Torvalds 1811da177e4SLinus Torvalds return (result == USB_STOR_XFER_GOOD ? 1821da177e4SLinus Torvalds USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_FAILED); 1831da177e4SLinus Torvalds } 1841da177e4SLinus Torvalds 1851da177e4SLinus Torvalds 1861da177e4SLinus Torvalds static int sddr55_read_data(struct us_data *us, 1871da177e4SLinus Torvalds unsigned int lba, 1881da177e4SLinus Torvalds unsigned int page, 1891da177e4SLinus Torvalds unsigned short sectors) { 1901da177e4SLinus Torvalds 1911da177e4SLinus Torvalds int result = USB_STOR_TRANSPORT_GOOD; 1921da177e4SLinus Torvalds unsigned char *command = us->iobuf; 1931da177e4SLinus Torvalds unsigned char *status = us->iobuf; 1941da177e4SLinus Torvalds struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; 1951da177e4SLinus Torvalds unsigned char *buffer; 1961da177e4SLinus Torvalds 1971da177e4SLinus Torvalds unsigned int pba; 1981da177e4SLinus Torvalds unsigned long address; 1991da177e4SLinus Torvalds 2001da177e4SLinus Torvalds unsigned short pages; 2011f6f31a0SJens Axboe unsigned int len, offset; 2021f6f31a0SJens Axboe struct scatterlist *sg; 2031da177e4SLinus Torvalds 2041da177e4SLinus Torvalds // Since we only read in one block at a time, we have to create 2051da177e4SLinus Torvalds // a bounce buffer and move the data a piece at a time between the 2061da177e4SLinus Torvalds // bounce buffer and the actual transfer buffer. 2071da177e4SLinus Torvalds 2081da177e4SLinus Torvalds len = min((unsigned int) sectors, (unsigned int) info->blocksize >> 2091da177e4SLinus Torvalds info->smallpageshift) * PAGESIZE; 2101da177e4SLinus Torvalds buffer = kmalloc(len, GFP_NOIO); 2111da177e4SLinus Torvalds if (buffer == NULL) 2121da177e4SLinus Torvalds return USB_STOR_TRANSPORT_ERROR; /* out of memory */ 2131f6f31a0SJens Axboe offset = 0; 2141f6f31a0SJens Axboe sg = NULL; 2151da177e4SLinus Torvalds 2161da177e4SLinus Torvalds while (sectors>0) { 2171da177e4SLinus Torvalds 2181da177e4SLinus Torvalds /* have we got to end? */ 2191da177e4SLinus Torvalds if (lba >= info->max_log_blks) 2201da177e4SLinus Torvalds break; 2211da177e4SLinus Torvalds 2221da177e4SLinus Torvalds pba = info->lba_to_pba[lba]; 2231da177e4SLinus Torvalds 2241da177e4SLinus Torvalds // Read as many sectors as possible in this block 2251da177e4SLinus Torvalds 2261da177e4SLinus Torvalds pages = min((unsigned int) sectors << info->smallpageshift, 2271da177e4SLinus Torvalds info->blocksize - page); 2281da177e4SLinus Torvalds len = pages << info->pageshift; 2291da177e4SLinus Torvalds 230191648d0SJoe Perches usb_stor_dbg(us, "Read %02X pages, from PBA %04X (LBA %04X) page %02X\n", 2311da177e4SLinus Torvalds pages, pba, lba, page); 2321da177e4SLinus Torvalds 2331da177e4SLinus Torvalds if (pba == NOT_ALLOCATED) { 2341da177e4SLinus Torvalds /* no pba for this lba, fill with zeroes */ 2351da177e4SLinus Torvalds memset (buffer, 0, len); 2361da177e4SLinus Torvalds } else { 2371da177e4SLinus Torvalds 2381da177e4SLinus Torvalds address = (pba << info->blockshift) + page; 2391da177e4SLinus Torvalds 2401da177e4SLinus Torvalds command[0] = 0; 2411da177e4SLinus Torvalds command[1] = LSB_of(address>>16); 2421da177e4SLinus Torvalds command[2] = LSB_of(address>>8); 2431da177e4SLinus Torvalds command[3] = LSB_of(address); 2441da177e4SLinus Torvalds 2451da177e4SLinus Torvalds command[4] = 0; 2461da177e4SLinus Torvalds command[5] = 0xB0; 2471da177e4SLinus Torvalds command[6] = LSB_of(pages << (1 - info->smallpageshift)); 2481da177e4SLinus Torvalds command[7] = 0x85; 2491da177e4SLinus Torvalds 2501da177e4SLinus Torvalds /* send command */ 2511da177e4SLinus Torvalds result = sddr55_bulk_transport(us, 2521da177e4SLinus Torvalds DMA_TO_DEVICE, command, 8); 2531da177e4SLinus Torvalds 254191648d0SJoe Perches usb_stor_dbg(us, "Result for send_command in read_data %d\n", 2551da177e4SLinus Torvalds result); 2561da177e4SLinus Torvalds 2571da177e4SLinus Torvalds if (result != USB_STOR_XFER_GOOD) { 2581da177e4SLinus Torvalds result = USB_STOR_TRANSPORT_ERROR; 2591da177e4SLinus Torvalds goto leave; 2601da177e4SLinus Torvalds } 2611da177e4SLinus Torvalds 2621da177e4SLinus Torvalds /* read data */ 2631da177e4SLinus Torvalds result = sddr55_bulk_transport(us, 2641da177e4SLinus Torvalds DMA_FROM_DEVICE, buffer, len); 2651da177e4SLinus Torvalds 2661da177e4SLinus Torvalds if (result != USB_STOR_XFER_GOOD) { 2671da177e4SLinus Torvalds result = USB_STOR_TRANSPORT_ERROR; 2681da177e4SLinus Torvalds goto leave; 2691da177e4SLinus Torvalds } 2701da177e4SLinus Torvalds 2711da177e4SLinus Torvalds /* now read status */ 2721da177e4SLinus Torvalds result = sddr55_bulk_transport(us, 2731da177e4SLinus Torvalds DMA_FROM_DEVICE, status, 2); 2741da177e4SLinus Torvalds 2751da177e4SLinus Torvalds if (result != USB_STOR_XFER_GOOD) { 2761da177e4SLinus Torvalds result = USB_STOR_TRANSPORT_ERROR; 2771da177e4SLinus Torvalds goto leave; 2781da177e4SLinus Torvalds } 2791da177e4SLinus Torvalds 2801da177e4SLinus Torvalds /* check status for error */ 2811da177e4SLinus Torvalds if (status[0] == 0xff && status[1] == 0x4) { 2821da177e4SLinus Torvalds set_sense_info (3, 0x11, 0); 2831da177e4SLinus Torvalds result = USB_STOR_TRANSPORT_FAILED; 2841da177e4SLinus Torvalds goto leave; 2851da177e4SLinus Torvalds } 2861da177e4SLinus Torvalds } 2871da177e4SLinus Torvalds 2881da177e4SLinus Torvalds // Store the data in the transfer buffer 2891da177e4SLinus Torvalds usb_stor_access_xfer_buf(buffer, len, us->srb, 2901f6f31a0SJens Axboe &sg, &offset, TO_XFER_BUF); 2911da177e4SLinus Torvalds 2921da177e4SLinus Torvalds page = 0; 2931da177e4SLinus Torvalds lba++; 2941da177e4SLinus Torvalds sectors -= pages >> info->smallpageshift; 2951da177e4SLinus Torvalds } 2961da177e4SLinus Torvalds 2971da177e4SLinus Torvalds result = USB_STOR_TRANSPORT_GOOD; 2981da177e4SLinus Torvalds 2991da177e4SLinus Torvalds leave: 3001da177e4SLinus Torvalds kfree(buffer); 3011da177e4SLinus Torvalds 3021da177e4SLinus Torvalds return result; 3031da177e4SLinus Torvalds } 3041da177e4SLinus Torvalds 3051da177e4SLinus Torvalds static int sddr55_write_data(struct us_data *us, 3061da177e4SLinus Torvalds unsigned int lba, 3071da177e4SLinus Torvalds unsigned int page, 3081da177e4SLinus Torvalds unsigned short sectors) { 3091da177e4SLinus Torvalds 3101da177e4SLinus Torvalds int result = USB_STOR_TRANSPORT_GOOD; 3111da177e4SLinus Torvalds unsigned char *command = us->iobuf; 3121da177e4SLinus Torvalds unsigned char *status = us->iobuf; 3131da177e4SLinus Torvalds struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; 3141da177e4SLinus Torvalds unsigned char *buffer; 3151da177e4SLinus Torvalds 3161da177e4SLinus Torvalds unsigned int pba; 3171da177e4SLinus Torvalds unsigned int new_pba; 3181da177e4SLinus Torvalds unsigned long address; 3191da177e4SLinus Torvalds 3201da177e4SLinus Torvalds unsigned short pages; 3211da177e4SLinus Torvalds int i; 3221f6f31a0SJens Axboe unsigned int len, offset; 3231f6f31a0SJens Axboe struct scatterlist *sg; 3241da177e4SLinus Torvalds 3251da177e4SLinus Torvalds /* check if we are allowed to write */ 3261da177e4SLinus Torvalds if (info->read_only || info->force_read_only) { 3271da177e4SLinus Torvalds set_sense_info (7, 0x27, 0); /* read only */ 3281da177e4SLinus Torvalds return USB_STOR_TRANSPORT_FAILED; 3291da177e4SLinus Torvalds } 3301da177e4SLinus Torvalds 3311da177e4SLinus Torvalds // Since we only write one block at a time, we have to create 3321da177e4SLinus Torvalds // a bounce buffer and move the data a piece at a time between the 3331da177e4SLinus Torvalds // bounce buffer and the actual transfer buffer. 3341da177e4SLinus Torvalds 3351da177e4SLinus Torvalds len = min((unsigned int) sectors, (unsigned int) info->blocksize >> 3361da177e4SLinus Torvalds info->smallpageshift) * PAGESIZE; 3371da177e4SLinus Torvalds buffer = kmalloc(len, GFP_NOIO); 3381da177e4SLinus Torvalds if (buffer == NULL) 3391da177e4SLinus Torvalds return USB_STOR_TRANSPORT_ERROR; 3401f6f31a0SJens Axboe offset = 0; 3411f6f31a0SJens Axboe sg = NULL; 3421da177e4SLinus Torvalds 3431da177e4SLinus Torvalds while (sectors > 0) { 3441da177e4SLinus Torvalds 3451da177e4SLinus Torvalds /* have we got to end? */ 3461da177e4SLinus Torvalds if (lba >= info->max_log_blks) 3471da177e4SLinus Torvalds break; 3481da177e4SLinus Torvalds 3491da177e4SLinus Torvalds pba = info->lba_to_pba[lba]; 3501da177e4SLinus Torvalds 3511da177e4SLinus Torvalds // Write as many sectors as possible in this block 3521da177e4SLinus Torvalds 3531da177e4SLinus Torvalds pages = min((unsigned int) sectors << info->smallpageshift, 3541da177e4SLinus Torvalds info->blocksize - page); 3551da177e4SLinus Torvalds len = pages << info->pageshift; 3561da177e4SLinus Torvalds 3571da177e4SLinus Torvalds // Get the data from the transfer buffer 3581da177e4SLinus Torvalds usb_stor_access_xfer_buf(buffer, len, us->srb, 3591f6f31a0SJens Axboe &sg, &offset, FROM_XFER_BUF); 3601da177e4SLinus Torvalds 361191648d0SJoe Perches usb_stor_dbg(us, "Write %02X pages, to PBA %04X (LBA %04X) page %02X\n", 3621da177e4SLinus Torvalds pages, pba, lba, page); 3631da177e4SLinus Torvalds 3641da177e4SLinus Torvalds command[4] = 0; 3651da177e4SLinus Torvalds 3661da177e4SLinus Torvalds if (pba == NOT_ALLOCATED) { 3671da177e4SLinus Torvalds /* no pba allocated for this lba, find a free pba to use */ 3681da177e4SLinus Torvalds 3691da177e4SLinus Torvalds int max_pba = (info->max_log_blks / 250 ) * 256; 3701da177e4SLinus Torvalds int found_count = 0; 3711da177e4SLinus Torvalds int found_pba = -1; 3721da177e4SLinus Torvalds 3731da177e4SLinus Torvalds /* set pba to first block in zone lba is in */ 3741da177e4SLinus Torvalds pba = (lba / 1000) * 1024; 3751da177e4SLinus Torvalds 376191648d0SJoe Perches usb_stor_dbg(us, "No PBA for LBA %04X\n", lba); 3771da177e4SLinus Torvalds 3781da177e4SLinus Torvalds if (max_pba > 1024) 3791da177e4SLinus Torvalds max_pba = 1024; 3801da177e4SLinus Torvalds 3811da177e4SLinus Torvalds /* 3821da177e4SLinus Torvalds * Scan through the map looking for an unused block 3831da177e4SLinus Torvalds * leave 16 unused blocks at start (or as many as 3841da177e4SLinus Torvalds * possible) since the sddr55 seems to reuse a used 3851da177e4SLinus Torvalds * block when it shouldn't if we don't leave space. 3861da177e4SLinus Torvalds */ 3871da177e4SLinus Torvalds for (i = 0; i < max_pba; i++, pba++) { 3881da177e4SLinus Torvalds if (info->pba_to_lba[pba] == UNUSED_BLOCK) { 3891da177e4SLinus Torvalds found_pba = pba; 3901da177e4SLinus Torvalds if (found_count++ > 16) 3911da177e4SLinus Torvalds break; 3921da177e4SLinus Torvalds } 3931da177e4SLinus Torvalds } 3941da177e4SLinus Torvalds 3951da177e4SLinus Torvalds pba = found_pba; 3961da177e4SLinus Torvalds 3971da177e4SLinus Torvalds if (pba == -1) { 3981da177e4SLinus Torvalds /* oh dear */ 399191648d0SJoe Perches usb_stor_dbg(us, "Couldn't find unallocated block\n"); 4001da177e4SLinus Torvalds 4011da177e4SLinus Torvalds set_sense_info (3, 0x31, 0); /* medium error */ 4021da177e4SLinus Torvalds result = USB_STOR_TRANSPORT_FAILED; 4031da177e4SLinus Torvalds goto leave; 4041da177e4SLinus Torvalds } 4051da177e4SLinus Torvalds 406191648d0SJoe Perches usb_stor_dbg(us, "Allocating PBA %04X for LBA %04X\n", 407191648d0SJoe Perches pba, lba); 4081da177e4SLinus Torvalds 4091da177e4SLinus Torvalds /* set writing to unallocated block flag */ 4101da177e4SLinus Torvalds command[4] = 0x40; 4111da177e4SLinus Torvalds } 4121da177e4SLinus Torvalds 4131da177e4SLinus Torvalds address = (pba << info->blockshift) + page; 4141da177e4SLinus Torvalds 4151da177e4SLinus Torvalds command[1] = LSB_of(address>>16); 4161da177e4SLinus Torvalds command[2] = LSB_of(address>>8); 4171da177e4SLinus Torvalds command[3] = LSB_of(address); 4181da177e4SLinus Torvalds 4191da177e4SLinus Torvalds /* set the lba into the command, modulo 1000 */ 4201da177e4SLinus Torvalds command[0] = LSB_of(lba % 1000); 4211da177e4SLinus Torvalds command[6] = MSB_of(lba % 1000); 4221da177e4SLinus Torvalds 4231da177e4SLinus Torvalds command[4] |= LSB_of(pages >> info->smallpageshift); 4241da177e4SLinus Torvalds command[5] = 0xB0; 4251da177e4SLinus Torvalds command[7] = 0x86; 4261da177e4SLinus Torvalds 4271da177e4SLinus Torvalds /* send command */ 4281da177e4SLinus Torvalds result = sddr55_bulk_transport(us, 4291da177e4SLinus Torvalds DMA_TO_DEVICE, command, 8); 4301da177e4SLinus Torvalds 4311da177e4SLinus Torvalds if (result != USB_STOR_XFER_GOOD) { 432191648d0SJoe Perches usb_stor_dbg(us, "Result for send_command in write_data %d\n", 4331da177e4SLinus Torvalds result); 4341da177e4SLinus Torvalds 4351da177e4SLinus Torvalds /* set_sense_info is superfluous here? */ 4361da177e4SLinus Torvalds set_sense_info (3, 0x3, 0);/* peripheral write error */ 4371da177e4SLinus Torvalds result = USB_STOR_TRANSPORT_FAILED; 4381da177e4SLinus Torvalds goto leave; 4391da177e4SLinus Torvalds } 4401da177e4SLinus Torvalds 4411da177e4SLinus Torvalds /* send the data */ 4421da177e4SLinus Torvalds result = sddr55_bulk_transport(us, 4431da177e4SLinus Torvalds DMA_TO_DEVICE, buffer, len); 4441da177e4SLinus Torvalds 4451da177e4SLinus Torvalds if (result != USB_STOR_XFER_GOOD) { 446191648d0SJoe Perches usb_stor_dbg(us, "Result for send_data in write_data %d\n", 4471da177e4SLinus Torvalds result); 4481da177e4SLinus Torvalds 4491da177e4SLinus Torvalds /* set_sense_info is superfluous here? */ 4501da177e4SLinus Torvalds set_sense_info (3, 0x3, 0);/* peripheral write error */ 4511da177e4SLinus Torvalds result = USB_STOR_TRANSPORT_FAILED; 4521da177e4SLinus Torvalds goto leave; 4531da177e4SLinus Torvalds } 4541da177e4SLinus Torvalds 4551da177e4SLinus Torvalds /* now read status */ 4561da177e4SLinus Torvalds result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, status, 6); 4571da177e4SLinus Torvalds 4581da177e4SLinus Torvalds if (result != USB_STOR_XFER_GOOD) { 459191648d0SJoe Perches usb_stor_dbg(us, "Result for get_status in write_data %d\n", 4601da177e4SLinus Torvalds result); 4611da177e4SLinus Torvalds 4621da177e4SLinus Torvalds /* set_sense_info is superfluous here? */ 4631da177e4SLinus Torvalds set_sense_info (3, 0x3, 0);/* peripheral write error */ 4641da177e4SLinus Torvalds result = USB_STOR_TRANSPORT_FAILED; 4651da177e4SLinus Torvalds goto leave; 4661da177e4SLinus Torvalds } 4671da177e4SLinus Torvalds 4681da177e4SLinus Torvalds new_pba = (status[3] + (status[4] << 8) + (status[5] << 16)) 4691da177e4SLinus Torvalds >> info->blockshift; 4701da177e4SLinus Torvalds 4711da177e4SLinus Torvalds /* check status for error */ 4721da177e4SLinus Torvalds if (status[0] == 0xff && status[1] == 0x4) { 4731da177e4SLinus Torvalds info->pba_to_lba[new_pba] = BAD_BLOCK; 4741da177e4SLinus Torvalds 4751da177e4SLinus Torvalds set_sense_info (3, 0x0c, 0); 4761da177e4SLinus Torvalds result = USB_STOR_TRANSPORT_FAILED; 4771da177e4SLinus Torvalds goto leave; 4781da177e4SLinus Torvalds } 4791da177e4SLinus Torvalds 480191648d0SJoe Perches usb_stor_dbg(us, "Updating maps for LBA %04X: old PBA %04X, new PBA %04X\n", 4811da177e4SLinus Torvalds lba, pba, new_pba); 4821da177e4SLinus Torvalds 4831da177e4SLinus Torvalds /* update the lba<->pba maps, note new_pba might be the same as pba */ 4841da177e4SLinus Torvalds info->lba_to_pba[lba] = new_pba; 4851da177e4SLinus Torvalds info->pba_to_lba[pba] = UNUSED_BLOCK; 4861da177e4SLinus Torvalds 4871da177e4SLinus Torvalds /* check that new_pba wasn't already being used */ 4881da177e4SLinus Torvalds if (info->pba_to_lba[new_pba] != UNUSED_BLOCK) { 4891da177e4SLinus Torvalds printk(KERN_ERR "sddr55 error: new PBA %04X already in use for LBA %04X\n", 4901da177e4SLinus Torvalds new_pba, info->pba_to_lba[new_pba]); 4911da177e4SLinus Torvalds info->fatal_error = 1; 4921da177e4SLinus Torvalds set_sense_info (3, 0x31, 0); 4931da177e4SLinus Torvalds result = USB_STOR_TRANSPORT_FAILED; 4941da177e4SLinus Torvalds goto leave; 4951da177e4SLinus Torvalds } 4961da177e4SLinus Torvalds 4971da177e4SLinus Torvalds /* update the pba<->lba maps for new_pba */ 4981da177e4SLinus Torvalds info->pba_to_lba[new_pba] = lba % 1000; 4991da177e4SLinus Torvalds 5001da177e4SLinus Torvalds page = 0; 5011da177e4SLinus Torvalds lba++; 5021da177e4SLinus Torvalds sectors -= pages >> info->smallpageshift; 5031da177e4SLinus Torvalds } 5041da177e4SLinus Torvalds result = USB_STOR_TRANSPORT_GOOD; 5051da177e4SLinus Torvalds 5061da177e4SLinus Torvalds leave: 5071da177e4SLinus Torvalds kfree(buffer); 5081da177e4SLinus Torvalds return result; 5091da177e4SLinus Torvalds } 5101da177e4SLinus Torvalds 5111da177e4SLinus Torvalds static int sddr55_read_deviceID(struct us_data *us, 5121da177e4SLinus Torvalds unsigned char *manufacturerID, 5131da177e4SLinus Torvalds unsigned char *deviceID) { 5141da177e4SLinus Torvalds 5151da177e4SLinus Torvalds int result; 5161da177e4SLinus Torvalds unsigned char *command = us->iobuf; 5171da177e4SLinus Torvalds unsigned char *content = us->iobuf; 5181da177e4SLinus Torvalds 5191da177e4SLinus Torvalds memset(command, 0, 8); 5201da177e4SLinus Torvalds command[5] = 0xB0; 5211da177e4SLinus Torvalds command[7] = 0x84; 5221da177e4SLinus Torvalds result = sddr55_bulk_transport(us, DMA_TO_DEVICE, command, 8); 5231da177e4SLinus Torvalds 524191648d0SJoe Perches usb_stor_dbg(us, "Result of send_control for device ID is %d\n", 5251da177e4SLinus Torvalds result); 5261da177e4SLinus Torvalds 5271da177e4SLinus Torvalds if (result != USB_STOR_XFER_GOOD) 5281da177e4SLinus Torvalds return USB_STOR_TRANSPORT_ERROR; 5291da177e4SLinus Torvalds 5301da177e4SLinus Torvalds result = sddr55_bulk_transport(us, 5311da177e4SLinus Torvalds DMA_FROM_DEVICE, content, 4); 5321da177e4SLinus Torvalds 5331da177e4SLinus Torvalds if (result != USB_STOR_XFER_GOOD) 5341da177e4SLinus Torvalds return USB_STOR_TRANSPORT_ERROR; 5351da177e4SLinus Torvalds 5361da177e4SLinus Torvalds *manufacturerID = content[0]; 5371da177e4SLinus Torvalds *deviceID = content[1]; 5381da177e4SLinus Torvalds 5391da177e4SLinus Torvalds if (content[0] != 0xff) { 5401da177e4SLinus Torvalds result = sddr55_bulk_transport(us, 5411da177e4SLinus Torvalds DMA_FROM_DEVICE, content, 2); 5421da177e4SLinus Torvalds } 5431da177e4SLinus Torvalds 5441da177e4SLinus Torvalds return USB_STOR_TRANSPORT_GOOD; 5451da177e4SLinus Torvalds } 5461da177e4SLinus Torvalds 5471da177e4SLinus Torvalds 54870fcc005SAlan Stern static int sddr55_reset(struct us_data *us) 54970fcc005SAlan Stern { 5501da177e4SLinus Torvalds return 0; 5511da177e4SLinus Torvalds } 5521da177e4SLinus Torvalds 5531da177e4SLinus Torvalds 5541da177e4SLinus Torvalds static unsigned long sddr55_get_capacity(struct us_data *us) { 5551da177e4SLinus Torvalds 5568a20acc5SAndrew Morton unsigned char uninitialized_var(manufacturerID); 5578a20acc5SAndrew Morton unsigned char uninitialized_var(deviceID); 5581da177e4SLinus Torvalds int result; 5591da177e4SLinus Torvalds struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; 5601da177e4SLinus Torvalds 561191648d0SJoe Perches usb_stor_dbg(us, "Reading capacity...\n"); 5621da177e4SLinus Torvalds 5631da177e4SLinus Torvalds result = sddr55_read_deviceID(us, 5641da177e4SLinus Torvalds &manufacturerID, 5651da177e4SLinus Torvalds &deviceID); 5661da177e4SLinus Torvalds 567191648d0SJoe Perches usb_stor_dbg(us, "Result of read_deviceID is %d\n", result); 5681da177e4SLinus Torvalds 5691da177e4SLinus Torvalds if (result != USB_STOR_XFER_GOOD) 5701da177e4SLinus Torvalds return 0; 5711da177e4SLinus Torvalds 572191648d0SJoe Perches usb_stor_dbg(us, "Device ID = %02X\n", deviceID); 573191648d0SJoe Perches usb_stor_dbg(us, "Manuf ID = %02X\n", manufacturerID); 5741da177e4SLinus Torvalds 5751da177e4SLinus Torvalds info->pageshift = 9; 5761da177e4SLinus Torvalds info->smallpageshift = 0; 5771da177e4SLinus Torvalds info->blocksize = 16; 5781da177e4SLinus Torvalds info->blockshift = 4; 5791da177e4SLinus Torvalds info->blockmask = 15; 5801da177e4SLinus Torvalds 5811da177e4SLinus Torvalds switch (deviceID) { 5821da177e4SLinus Torvalds 5831da177e4SLinus Torvalds case 0x6e: // 1MB 5841da177e4SLinus Torvalds case 0xe8: 5851da177e4SLinus Torvalds case 0xec: 5861da177e4SLinus Torvalds info->pageshift = 8; 5871da177e4SLinus Torvalds info->smallpageshift = 1; 5881da177e4SLinus Torvalds return 0x00100000; 5891da177e4SLinus Torvalds 5901da177e4SLinus Torvalds case 0xea: // 2MB 5911da177e4SLinus Torvalds case 0x64: 5921da177e4SLinus Torvalds info->pageshift = 8; 5931da177e4SLinus Torvalds info->smallpageshift = 1; 594c2300cd6SGustavo A. R. Silva /* fall through */ 5951da177e4SLinus Torvalds case 0x5d: // 5d is a ROM card with pagesize 512. 5961da177e4SLinus Torvalds return 0x00200000; 5971da177e4SLinus Torvalds 5981da177e4SLinus Torvalds case 0xe3: // 4MB 5991da177e4SLinus Torvalds case 0xe5: 6001da177e4SLinus Torvalds case 0x6b: 6011da177e4SLinus Torvalds case 0xd5: 6021da177e4SLinus Torvalds return 0x00400000; 6031da177e4SLinus Torvalds 6041da177e4SLinus Torvalds case 0xe6: // 8MB 6051da177e4SLinus Torvalds case 0xd6: 6061da177e4SLinus Torvalds return 0x00800000; 6071da177e4SLinus Torvalds 6081da177e4SLinus Torvalds case 0x73: // 16MB 6091da177e4SLinus Torvalds info->blocksize = 32; 6101da177e4SLinus Torvalds info->blockshift = 5; 6111da177e4SLinus Torvalds info->blockmask = 31; 6121da177e4SLinus Torvalds return 0x01000000; 6131da177e4SLinus Torvalds 6141da177e4SLinus Torvalds case 0x75: // 32MB 6151da177e4SLinus Torvalds info->blocksize = 32; 6161da177e4SLinus Torvalds info->blockshift = 5; 6171da177e4SLinus Torvalds info->blockmask = 31; 6181da177e4SLinus Torvalds return 0x02000000; 6191da177e4SLinus Torvalds 6201da177e4SLinus Torvalds case 0x76: // 64MB 6211da177e4SLinus Torvalds info->blocksize = 32; 6221da177e4SLinus Torvalds info->blockshift = 5; 6231da177e4SLinus Torvalds info->blockmask = 31; 6241da177e4SLinus Torvalds return 0x04000000; 6251da177e4SLinus Torvalds 6261da177e4SLinus Torvalds case 0x79: // 128MB 6271da177e4SLinus Torvalds info->blocksize = 32; 6281da177e4SLinus Torvalds info->blockshift = 5; 6291da177e4SLinus Torvalds info->blockmask = 31; 6301da177e4SLinus Torvalds return 0x08000000; 6311da177e4SLinus Torvalds 6321da177e4SLinus Torvalds default: // unknown 6331da177e4SLinus Torvalds return 0; 6341da177e4SLinus Torvalds 6351da177e4SLinus Torvalds } 6361da177e4SLinus Torvalds } 6371da177e4SLinus Torvalds 6381da177e4SLinus Torvalds static int sddr55_read_map(struct us_data *us) { 6391da177e4SLinus Torvalds 6401da177e4SLinus Torvalds struct sddr55_card_info *info = (struct sddr55_card_info *)(us->extra); 6411da177e4SLinus Torvalds int numblocks; 6421da177e4SLinus Torvalds unsigned char *buffer; 6431da177e4SLinus Torvalds unsigned char *command = us->iobuf; 6441da177e4SLinus Torvalds int i; 6451da177e4SLinus Torvalds unsigned short lba; 6461da177e4SLinus Torvalds unsigned short max_lba; 6471da177e4SLinus Torvalds int result; 6481da177e4SLinus Torvalds 6491da177e4SLinus Torvalds if (!info->capacity) 6501da177e4SLinus Torvalds return -1; 6511da177e4SLinus Torvalds 6521da177e4SLinus Torvalds numblocks = info->capacity >> (info->blockshift + info->pageshift); 6531da177e4SLinus Torvalds 6546da2ec56SKees Cook buffer = kmalloc_array(numblocks, 2, GFP_NOIO ); 6551da177e4SLinus Torvalds 6561da177e4SLinus Torvalds if (!buffer) 6571da177e4SLinus Torvalds return -1; 6581da177e4SLinus Torvalds 6591da177e4SLinus Torvalds memset(command, 0, 8); 6601da177e4SLinus Torvalds command[5] = 0xB0; 6611da177e4SLinus Torvalds command[6] = numblocks * 2 / 256; 6621da177e4SLinus Torvalds command[7] = 0x8A; 6631da177e4SLinus Torvalds 6641da177e4SLinus Torvalds result = sddr55_bulk_transport(us, DMA_TO_DEVICE, command, 8); 6651da177e4SLinus Torvalds 6661da177e4SLinus Torvalds if ( result != USB_STOR_XFER_GOOD) { 6671da177e4SLinus Torvalds kfree (buffer); 6681da177e4SLinus Torvalds return -1; 6691da177e4SLinus Torvalds } 6701da177e4SLinus Torvalds 6711da177e4SLinus Torvalds result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, buffer, numblocks * 2); 6721da177e4SLinus Torvalds 6731da177e4SLinus Torvalds if ( result != USB_STOR_XFER_GOOD) { 6741da177e4SLinus Torvalds kfree (buffer); 6751da177e4SLinus Torvalds return -1; 6761da177e4SLinus Torvalds } 6771da177e4SLinus Torvalds 6781da177e4SLinus Torvalds result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, command, 2); 6791da177e4SLinus Torvalds 6801da177e4SLinus Torvalds if ( result != USB_STOR_XFER_GOOD) { 6811da177e4SLinus Torvalds kfree (buffer); 6821da177e4SLinus Torvalds return -1; 6831da177e4SLinus Torvalds } 6841da177e4SLinus Torvalds 6851da177e4SLinus Torvalds kfree(info->lba_to_pba); 6861da177e4SLinus Torvalds kfree(info->pba_to_lba); 6876da2ec56SKees Cook info->lba_to_pba = kmalloc_array(numblocks, sizeof(int), GFP_NOIO); 6886da2ec56SKees Cook info->pba_to_lba = kmalloc_array(numblocks, sizeof(int), GFP_NOIO); 6891da177e4SLinus Torvalds 6901da177e4SLinus Torvalds if (info->lba_to_pba == NULL || info->pba_to_lba == NULL) { 6911da177e4SLinus Torvalds kfree(info->lba_to_pba); 6921da177e4SLinus Torvalds kfree(info->pba_to_lba); 6931da177e4SLinus Torvalds info->lba_to_pba = NULL; 6941da177e4SLinus Torvalds info->pba_to_lba = NULL; 6951da177e4SLinus Torvalds kfree(buffer); 6961da177e4SLinus Torvalds return -1; 6971da177e4SLinus Torvalds } 6981da177e4SLinus Torvalds 6991da177e4SLinus Torvalds memset(info->lba_to_pba, 0xff, numblocks*sizeof(int)); 7001da177e4SLinus Torvalds memset(info->pba_to_lba, 0xff, numblocks*sizeof(int)); 7011da177e4SLinus Torvalds 7021da177e4SLinus Torvalds /* set maximum lba */ 7031da177e4SLinus Torvalds max_lba = info->max_log_blks; 7041da177e4SLinus Torvalds if (max_lba > 1000) 7051da177e4SLinus Torvalds max_lba = 1000; 7061da177e4SLinus Torvalds 707f0183a33SFelipe Balbi /* 708f0183a33SFelipe Balbi * Each block is 64 bytes of control data, so block i is located in 709f0183a33SFelipe Balbi * scatterlist block i*64/128k = i*(2^6)*(2^-17) = i*(2^-11) 710f0183a33SFelipe Balbi */ 7111da177e4SLinus Torvalds 7121da177e4SLinus Torvalds for (i=0; i<numblocks; i++) { 7131da177e4SLinus Torvalds int zone = i / 1024; 7141da177e4SLinus Torvalds 7151da177e4SLinus Torvalds lba = short_pack(buffer[i * 2], buffer[i * 2 + 1]); 7161da177e4SLinus Torvalds 717f0183a33SFelipe Balbi /* 718f0183a33SFelipe Balbi * Every 1024 physical blocks ("zone"), the LBA numbers 7191da177e4SLinus Torvalds * go back to zero, but are within a higher 7201da177e4SLinus Torvalds * block of LBA's. Also, there is a maximum of 7211da177e4SLinus Torvalds * 1000 LBA's per zone. In other words, in PBA 7221da177e4SLinus Torvalds * 1024-2047 you will find LBA 0-999 which are 7231da177e4SLinus Torvalds * really LBA 1000-1999. Yes, this wastes 24 7241da177e4SLinus Torvalds * physical blocks per zone. Go figure. 7251da177e4SLinus Torvalds * These devices can have blocks go bad, so there 7261da177e4SLinus Torvalds * are 24 spare blocks to use when blocks do go bad. 7271da177e4SLinus Torvalds */ 7281da177e4SLinus Torvalds 729f0183a33SFelipe Balbi /* 730f0183a33SFelipe Balbi * SDDR55 returns 0xffff for a bad block, and 0x400 for the 7311da177e4SLinus Torvalds * CIS block. (Is this true for cards 8MB or less??) 7321da177e4SLinus Torvalds * Record these in the physical to logical map 7331da177e4SLinus Torvalds */ 7341da177e4SLinus Torvalds 7351da177e4SLinus Torvalds info->pba_to_lba[i] = lba; 7361da177e4SLinus Torvalds 7371da177e4SLinus Torvalds if (lba >= max_lba) { 7381da177e4SLinus Torvalds continue; 7391da177e4SLinus Torvalds } 7401da177e4SLinus Torvalds 7411da177e4SLinus Torvalds if (info->lba_to_pba[lba + zone * 1000] != NOT_ALLOCATED && 7421da177e4SLinus Torvalds !info->force_read_only) { 7436f8aa65bSFrank Seidel printk(KERN_WARNING 7446f8aa65bSFrank Seidel "sddr55: map inconsistency at LBA %04X\n", 7456f8aa65bSFrank Seidel lba + zone * 1000); 7461da177e4SLinus Torvalds info->force_read_only = 1; 7471da177e4SLinus Torvalds } 7481da177e4SLinus Torvalds 7491da177e4SLinus Torvalds if (lba<0x10 || (lba>=0x3E0 && lba<0x3EF)) 750191648d0SJoe Perches usb_stor_dbg(us, "LBA %04X <-> PBA %04X\n", lba, i); 7511da177e4SLinus Torvalds 7521da177e4SLinus Torvalds info->lba_to_pba[lba + zone * 1000] = i; 7531da177e4SLinus Torvalds } 7541da177e4SLinus Torvalds 7551da177e4SLinus Torvalds kfree(buffer); 7561da177e4SLinus Torvalds return 0; 7571da177e4SLinus Torvalds } 7581da177e4SLinus Torvalds 7591da177e4SLinus Torvalds 7601da177e4SLinus Torvalds static void sddr55_card_info_destructor(void *extra) { 7611da177e4SLinus Torvalds struct sddr55_card_info *info = (struct sddr55_card_info *)extra; 7621da177e4SLinus Torvalds 7631da177e4SLinus Torvalds if (!extra) 7641da177e4SLinus Torvalds return; 7651da177e4SLinus Torvalds 7661da177e4SLinus Torvalds kfree(info->lba_to_pba); 7671da177e4SLinus Torvalds kfree(info->pba_to_lba); 7681da177e4SLinus Torvalds } 7691da177e4SLinus Torvalds 7701da177e4SLinus Torvalds 7711da177e4SLinus Torvalds /* 7721da177e4SLinus Torvalds * Transport for the Sandisk SDDR-55 7731da177e4SLinus Torvalds */ 77470fcc005SAlan Stern static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us) 7751da177e4SLinus Torvalds { 7761da177e4SLinus Torvalds int result; 7771da177e4SLinus Torvalds static unsigned char inquiry_response[8] = { 7781da177e4SLinus Torvalds 0x00, 0x80, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x00 7791da177e4SLinus Torvalds }; 7801da177e4SLinus Torvalds // write-protected for now, no block descriptor support 7811da177e4SLinus Torvalds static unsigned char mode_page_01[20] = { 7821da177e4SLinus Torvalds 0x0, 0x12, 0x00, 0x80, 0x0, 0x0, 0x0, 0x0, 7831da177e4SLinus Torvalds 0x01, 0x0A, 7841da177e4SLinus Torvalds 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 7851da177e4SLinus Torvalds }; 7861da177e4SLinus Torvalds unsigned char *ptr = us->iobuf; 7871da177e4SLinus Torvalds unsigned long capacity; 7881da177e4SLinus Torvalds unsigned int lba; 7891da177e4SLinus Torvalds unsigned int pba; 7901da177e4SLinus Torvalds unsigned int page; 7911da177e4SLinus Torvalds unsigned short pages; 7921da177e4SLinus Torvalds struct sddr55_card_info *info; 7931da177e4SLinus Torvalds 7941da177e4SLinus Torvalds if (!us->extra) { 795887c2560SOliver Neukum us->extra = kzalloc( 7961da177e4SLinus Torvalds sizeof(struct sddr55_card_info), GFP_NOIO); 7971da177e4SLinus Torvalds if (!us->extra) 7981da177e4SLinus Torvalds return USB_STOR_TRANSPORT_ERROR; 7991da177e4SLinus Torvalds us->extra_destructor = sddr55_card_info_destructor; 8001da177e4SLinus Torvalds } 8011da177e4SLinus Torvalds 8021da177e4SLinus Torvalds info = (struct sddr55_card_info *)(us->extra); 8031da177e4SLinus Torvalds 8041da177e4SLinus Torvalds if (srb->cmnd[0] == REQUEST_SENSE) { 805191648d0SJoe Perches usb_stor_dbg(us, "request sense %02x/%02x/%02x\n", 806191648d0SJoe Perches info->sense_data[2], 807191648d0SJoe Perches info->sense_data[12], 808191648d0SJoe Perches info->sense_data[13]); 8091da177e4SLinus Torvalds 8101da177e4SLinus Torvalds memcpy (ptr, info->sense_data, sizeof info->sense_data); 8111da177e4SLinus Torvalds ptr[0] = 0x70; 8121da177e4SLinus Torvalds ptr[7] = 11; 8131da177e4SLinus Torvalds usb_stor_set_xfer_buf (ptr, sizeof info->sense_data, srb); 8141da177e4SLinus Torvalds memset (info->sense_data, 0, sizeof info->sense_data); 8151da177e4SLinus Torvalds 8161da177e4SLinus Torvalds return USB_STOR_TRANSPORT_GOOD; 8171da177e4SLinus Torvalds } 8181da177e4SLinus Torvalds 8191da177e4SLinus Torvalds memset (info->sense_data, 0, sizeof info->sense_data); 8201da177e4SLinus Torvalds 821f0183a33SFelipe Balbi /* 822f0183a33SFelipe Balbi * Dummy up a response for INQUIRY since SDDR55 doesn't 823f0183a33SFelipe Balbi * respond to INQUIRY commands 824f0183a33SFelipe Balbi */ 8251da177e4SLinus Torvalds 8261da177e4SLinus Torvalds if (srb->cmnd[0] == INQUIRY) { 8271da177e4SLinus Torvalds memcpy(ptr, inquiry_response, 8); 8281da177e4SLinus Torvalds fill_inquiry_response(us, ptr, 36); 8291da177e4SLinus Torvalds return USB_STOR_TRANSPORT_GOOD; 8301da177e4SLinus Torvalds } 8311da177e4SLinus Torvalds 832f0183a33SFelipe Balbi /* 833f0183a33SFelipe Balbi * only check card status if the map isn't allocated, ie no card seen yet 8341da177e4SLinus Torvalds * or if it's been over half a second since we last accessed it 8351da177e4SLinus Torvalds */ 8361da177e4SLinus Torvalds if (info->lba_to_pba == NULL || time_after(jiffies, info->last_access + HZ/2)) { 8371da177e4SLinus Torvalds 8381da177e4SLinus Torvalds /* check to see if a card is fitted */ 8391da177e4SLinus Torvalds result = sddr55_status (us); 8401da177e4SLinus Torvalds if (result) { 8411da177e4SLinus Torvalds result = sddr55_status (us); 8421da177e4SLinus Torvalds if (!result) { 8431da177e4SLinus Torvalds set_sense_info (6, 0x28, 0); /* new media, set unit attention, not ready to ready */ 8441da177e4SLinus Torvalds } 8451da177e4SLinus Torvalds return USB_STOR_TRANSPORT_FAILED; 8461da177e4SLinus Torvalds } 8471da177e4SLinus Torvalds } 8481da177e4SLinus Torvalds 849f0183a33SFelipe Balbi /* 850f0183a33SFelipe Balbi * if we detected a problem with the map when writing, 851f0183a33SFelipe Balbi * don't allow any more access 852f0183a33SFelipe Balbi */ 8531da177e4SLinus Torvalds if (info->fatal_error) { 8541da177e4SLinus Torvalds 8551da177e4SLinus Torvalds set_sense_info (3, 0x31, 0); 8561da177e4SLinus Torvalds return USB_STOR_TRANSPORT_FAILED; 8571da177e4SLinus Torvalds } 8581da177e4SLinus Torvalds 8591da177e4SLinus Torvalds if (srb->cmnd[0] == READ_CAPACITY) { 8601da177e4SLinus Torvalds 8611da177e4SLinus Torvalds capacity = sddr55_get_capacity(us); 8621da177e4SLinus Torvalds 8631da177e4SLinus Torvalds if (!capacity) { 8641da177e4SLinus Torvalds set_sense_info (3, 0x30, 0); /* incompatible medium */ 8651da177e4SLinus Torvalds return USB_STOR_TRANSPORT_FAILED; 8661da177e4SLinus Torvalds } 8671da177e4SLinus Torvalds 8681da177e4SLinus Torvalds info->capacity = capacity; 8691da177e4SLinus Torvalds 870f0183a33SFelipe Balbi /* 871f0183a33SFelipe Balbi * figure out the maximum logical block number, allowing for 872f0183a33SFelipe Balbi * the fact that only 250 out of every 256 are used 873f0183a33SFelipe Balbi */ 8741da177e4SLinus Torvalds info->max_log_blks = ((info->capacity >> (info->pageshift + info->blockshift)) / 256) * 250; 8751da177e4SLinus Torvalds 876f0183a33SFelipe Balbi /* 877f0183a33SFelipe Balbi * Last page in the card, adjust as we only use 250 out of 878f0183a33SFelipe Balbi * every 256 pages 879f0183a33SFelipe Balbi */ 8801da177e4SLinus Torvalds capacity = (capacity / 256) * 250; 8811da177e4SLinus Torvalds 8821da177e4SLinus Torvalds capacity /= PAGESIZE; 8831da177e4SLinus Torvalds capacity--; 8841da177e4SLinus Torvalds 8851da177e4SLinus Torvalds ((__be32 *) ptr)[0] = cpu_to_be32(capacity); 8861da177e4SLinus Torvalds ((__be32 *) ptr)[1] = cpu_to_be32(PAGESIZE); 8871da177e4SLinus Torvalds usb_stor_set_xfer_buf(ptr, 8, srb); 8881da177e4SLinus Torvalds 8891da177e4SLinus Torvalds sddr55_read_map(us); 8901da177e4SLinus Torvalds 8911da177e4SLinus Torvalds return USB_STOR_TRANSPORT_GOOD; 8921da177e4SLinus Torvalds } 8931da177e4SLinus Torvalds 8941da177e4SLinus Torvalds if (srb->cmnd[0] == MODE_SENSE_10) { 8951da177e4SLinus Torvalds 8961da177e4SLinus Torvalds memcpy(ptr, mode_page_01, sizeof mode_page_01); 8971da177e4SLinus Torvalds ptr[3] = (info->read_only || info->force_read_only) ? 0x80 : 0; 8981da177e4SLinus Torvalds usb_stor_set_xfer_buf(ptr, sizeof(mode_page_01), srb); 8991da177e4SLinus Torvalds 9001da177e4SLinus Torvalds if ( (srb->cmnd[2] & 0x3F) == 0x01 ) { 901191648d0SJoe Perches usb_stor_dbg(us, "Dummy up request for mode page 1\n"); 9021da177e4SLinus Torvalds return USB_STOR_TRANSPORT_GOOD; 9031da177e4SLinus Torvalds 9041da177e4SLinus Torvalds } else if ( (srb->cmnd[2] & 0x3F) == 0x3F ) { 905191648d0SJoe Perches usb_stor_dbg(us, "Dummy up request for all mode pages\n"); 9061da177e4SLinus Torvalds return USB_STOR_TRANSPORT_GOOD; 9071da177e4SLinus Torvalds } 9081da177e4SLinus Torvalds 9091da177e4SLinus Torvalds set_sense_info (5, 0x24, 0); /* invalid field in command */ 9101da177e4SLinus Torvalds return USB_STOR_TRANSPORT_FAILED; 9111da177e4SLinus Torvalds } 9121da177e4SLinus Torvalds 9131da177e4SLinus Torvalds if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) { 9141da177e4SLinus Torvalds 915191648d0SJoe Perches usb_stor_dbg(us, "%s medium removal. Not that I can do anything about it...\n", 9161da177e4SLinus Torvalds (srb->cmnd[4]&0x03) ? "Prevent" : "Allow"); 9171da177e4SLinus Torvalds 9181da177e4SLinus Torvalds return USB_STOR_TRANSPORT_GOOD; 9191da177e4SLinus Torvalds 9201da177e4SLinus Torvalds } 9211da177e4SLinus Torvalds 9221da177e4SLinus Torvalds if (srb->cmnd[0] == READ_10 || srb->cmnd[0] == WRITE_10) { 9231da177e4SLinus Torvalds 9241da177e4SLinus Torvalds page = short_pack(srb->cmnd[3], srb->cmnd[2]); 9251da177e4SLinus Torvalds page <<= 16; 9261da177e4SLinus Torvalds page |= short_pack(srb->cmnd[5], srb->cmnd[4]); 9271da177e4SLinus Torvalds pages = short_pack(srb->cmnd[8], srb->cmnd[7]); 9281da177e4SLinus Torvalds 9291da177e4SLinus Torvalds page <<= info->smallpageshift; 9301da177e4SLinus Torvalds 9311da177e4SLinus Torvalds // convert page to block and page-within-block 9321da177e4SLinus Torvalds 9331da177e4SLinus Torvalds lba = page >> info->blockshift; 9341da177e4SLinus Torvalds page = page & info->blockmask; 9351da177e4SLinus Torvalds 9361da177e4SLinus Torvalds // locate physical block corresponding to logical block 9371da177e4SLinus Torvalds 9381da177e4SLinus Torvalds if (lba >= info->max_log_blks) { 9391da177e4SLinus Torvalds 940191648d0SJoe Perches usb_stor_dbg(us, "Error: Requested LBA %04X exceeds maximum block %04X\n", 941191648d0SJoe Perches lba, info->max_log_blks - 1); 9421da177e4SLinus Torvalds 9431da177e4SLinus Torvalds set_sense_info (5, 0x24, 0); /* invalid field in command */ 9441da177e4SLinus Torvalds 9451da177e4SLinus Torvalds return USB_STOR_TRANSPORT_FAILED; 9461da177e4SLinus Torvalds } 9471da177e4SLinus Torvalds 9481da177e4SLinus Torvalds pba = info->lba_to_pba[lba]; 9491da177e4SLinus Torvalds 9501da177e4SLinus Torvalds if (srb->cmnd[0] == WRITE_10) { 951191648d0SJoe Perches usb_stor_dbg(us, "WRITE_10: write block %04X (LBA %04X) page %01X pages %d\n", 9521da177e4SLinus Torvalds pba, lba, page, pages); 9531da177e4SLinus Torvalds 9541da177e4SLinus Torvalds return sddr55_write_data(us, lba, page, pages); 9551da177e4SLinus Torvalds } else { 956191648d0SJoe Perches usb_stor_dbg(us, "READ_10: read block %04X (LBA %04X) page %01X pages %d\n", 9571da177e4SLinus Torvalds pba, lba, page, pages); 9581da177e4SLinus Torvalds 9591da177e4SLinus Torvalds return sddr55_read_data(us, lba, page, pages); 9601da177e4SLinus Torvalds } 9611da177e4SLinus Torvalds } 9621da177e4SLinus Torvalds 9631da177e4SLinus Torvalds 9641da177e4SLinus Torvalds if (srb->cmnd[0] == TEST_UNIT_READY) { 9651da177e4SLinus Torvalds return USB_STOR_TRANSPORT_GOOD; 9661da177e4SLinus Torvalds } 9671da177e4SLinus Torvalds 9681da177e4SLinus Torvalds if (srb->cmnd[0] == START_STOP) { 9691da177e4SLinus Torvalds return USB_STOR_TRANSPORT_GOOD; 9701da177e4SLinus Torvalds } 9711da177e4SLinus Torvalds 9721da177e4SLinus Torvalds set_sense_info (5, 0x20, 0); /* illegal command */ 9731da177e4SLinus Torvalds 9741da177e4SLinus Torvalds return USB_STOR_TRANSPORT_FAILED; // FIXME: sense buffer? 9751da177e4SLinus Torvalds } 9761da177e4SLinus Torvalds 977aa519be3SAkinobu Mita static struct scsi_host_template sddr55_host_template; 97870fcc005SAlan Stern 97970fcc005SAlan Stern static int sddr55_probe(struct usb_interface *intf, 98070fcc005SAlan Stern const struct usb_device_id *id) 98170fcc005SAlan Stern { 98270fcc005SAlan Stern struct us_data *us; 98370fcc005SAlan Stern int result; 98470fcc005SAlan Stern 98570fcc005SAlan Stern result = usb_stor_probe1(&us, intf, id, 986aa519be3SAkinobu Mita (id - sddr55_usb_ids) + sddr55_unusual_dev_list, 987aa519be3SAkinobu Mita &sddr55_host_template); 98870fcc005SAlan Stern if (result) 98970fcc005SAlan Stern return result; 99070fcc005SAlan Stern 99170fcc005SAlan Stern us->transport_name = "SDDR55"; 99270fcc005SAlan Stern us->transport = sddr55_transport; 99370fcc005SAlan Stern us->transport_reset = sddr55_reset; 99470fcc005SAlan Stern us->max_lun = 0; 99570fcc005SAlan Stern 99670fcc005SAlan Stern result = usb_stor_probe2(us); 99770fcc005SAlan Stern return result; 99870fcc005SAlan Stern } 99970fcc005SAlan Stern 100070fcc005SAlan Stern static struct usb_driver sddr55_driver = { 1001aa519be3SAkinobu Mita .name = DRV_NAME, 100270fcc005SAlan Stern .probe = sddr55_probe, 100370fcc005SAlan Stern .disconnect = usb_stor_disconnect, 100470fcc005SAlan Stern .suspend = usb_stor_suspend, 100570fcc005SAlan Stern .resume = usb_stor_resume, 100670fcc005SAlan Stern .reset_resume = usb_stor_reset_resume, 100770fcc005SAlan Stern .pre_reset = usb_stor_pre_reset, 100870fcc005SAlan Stern .post_reset = usb_stor_post_reset, 100970fcc005SAlan Stern .id_table = sddr55_usb_ids, 101070fcc005SAlan Stern .soft_unbind = 1, 1011e73b2db6SHuajun Li .no_dynamic_id = 1, 101270fcc005SAlan Stern }; 101370fcc005SAlan Stern 1014aa519be3SAkinobu Mita module_usb_stor_driver(sddr55_driver, sddr55_host_template, DRV_NAME); 1015