11da177e4SLinus Torvalds /* Driver for SanDisk SDDR-55 SmartMedia reader 21da177e4SLinus Torvalds * 31da177e4SLinus Torvalds * $Id:$ 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 * This program is free software; you can redistribute it and/or modify it 131da177e4SLinus Torvalds * under the terms of the GNU General Public License as published by the 141da177e4SLinus Torvalds * Free Software Foundation; either version 2, or (at your option) any 151da177e4SLinus Torvalds * later version. 161da177e4SLinus Torvalds * 171da177e4SLinus Torvalds * This program is distributed in the hope that it will be useful, but 181da177e4SLinus Torvalds * WITHOUT ANY WARRANTY; without even the implied warranty of 191da177e4SLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 201da177e4SLinus Torvalds * General Public License for more details. 211da177e4SLinus Torvalds * 221da177e4SLinus Torvalds * You should have received a copy of the GNU General Public License along 231da177e4SLinus Torvalds * with this program; if not, write to the Free Software Foundation, Inc., 241da177e4SLinus Torvalds * 675 Mass Ave, Cambridge, MA 02139, USA. 251da177e4SLinus Torvalds */ 261da177e4SLinus Torvalds 271da177e4SLinus Torvalds #include <linux/jiffies.h> 281da177e4SLinus Torvalds #include <linux/errno.h> 291da177e4SLinus Torvalds #include <linux/slab.h> 301da177e4SLinus Torvalds 311da177e4SLinus Torvalds #include <scsi/scsi.h> 321da177e4SLinus Torvalds #include <scsi/scsi_cmnd.h> 331da177e4SLinus Torvalds 341da177e4SLinus Torvalds #include "usb.h" 351da177e4SLinus Torvalds #include "transport.h" 361da177e4SLinus Torvalds #include "protocol.h" 371da177e4SLinus Torvalds #include "debug.h" 381da177e4SLinus Torvalds #include "sddr55.h" 391da177e4SLinus Torvalds 401da177e4SLinus Torvalds 411da177e4SLinus Torvalds #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) ) 421da177e4SLinus Torvalds #define LSB_of(s) ((s)&0xFF) 431da177e4SLinus Torvalds #define MSB_of(s) ((s)>>8) 441da177e4SLinus Torvalds #define PAGESIZE 512 451da177e4SLinus Torvalds 461da177e4SLinus Torvalds #define set_sense_info(sk, asc, ascq) \ 471da177e4SLinus Torvalds do { \ 481da177e4SLinus Torvalds info->sense_data[2] = sk; \ 491da177e4SLinus Torvalds info->sense_data[12] = asc; \ 501da177e4SLinus Torvalds info->sense_data[13] = ascq; \ 511da177e4SLinus Torvalds } while (0) 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds 541da177e4SLinus Torvalds struct sddr55_card_info { 551da177e4SLinus Torvalds unsigned long capacity; /* Size of card in bytes */ 561da177e4SLinus Torvalds int max_log_blks; /* maximum number of logical blocks */ 571da177e4SLinus Torvalds int pageshift; /* log2 of pagesize */ 581da177e4SLinus Torvalds int smallpageshift; /* 1 if pagesize == 256 */ 591da177e4SLinus Torvalds int blocksize; /* Size of block in pages */ 601da177e4SLinus Torvalds int blockshift; /* log2 of blocksize */ 611da177e4SLinus Torvalds int blockmask; /* 2^blockshift - 1 */ 621da177e4SLinus Torvalds int read_only; /* non zero if card is write protected */ 631da177e4SLinus Torvalds int force_read_only; /* non zero if we find a map error*/ 641da177e4SLinus Torvalds int *lba_to_pba; /* logical to physical map */ 651da177e4SLinus Torvalds int *pba_to_lba; /* physical to logical map */ 661da177e4SLinus Torvalds int fatal_error; /* set if we detect something nasty */ 671da177e4SLinus Torvalds unsigned long last_access; /* number of jiffies since we last talked to device */ 681da177e4SLinus Torvalds unsigned char sense_data[18]; 691da177e4SLinus Torvalds }; 701da177e4SLinus Torvalds 711da177e4SLinus Torvalds 721da177e4SLinus Torvalds #define NOT_ALLOCATED 0xffffffff 731da177e4SLinus Torvalds #define BAD_BLOCK 0xffff 741da177e4SLinus Torvalds #define CIS_BLOCK 0x400 751da177e4SLinus Torvalds #define UNUSED_BLOCK 0x3ff 761da177e4SLinus Torvalds 771da177e4SLinus Torvalds static int 781da177e4SLinus Torvalds sddr55_bulk_transport(struct us_data *us, int direction, 791da177e4SLinus Torvalds unsigned char *data, unsigned int len) { 801da177e4SLinus Torvalds struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; 811da177e4SLinus Torvalds unsigned int pipe = (direction == DMA_FROM_DEVICE) ? 821da177e4SLinus Torvalds us->recv_bulk_pipe : us->send_bulk_pipe; 831da177e4SLinus Torvalds 841da177e4SLinus Torvalds if (!len) 851da177e4SLinus Torvalds return USB_STOR_XFER_GOOD; 861da177e4SLinus Torvalds info->last_access = jiffies; 871da177e4SLinus Torvalds return usb_stor_bulk_transfer_buf(us, pipe, data, len, NULL); 881da177e4SLinus Torvalds } 891da177e4SLinus Torvalds 901da177e4SLinus Torvalds /* check if card inserted, if there is, update read_only status 911da177e4SLinus Torvalds * return non zero if no card 921da177e4SLinus Torvalds */ 931da177e4SLinus Torvalds 941da177e4SLinus Torvalds static int sddr55_status(struct us_data *us) 951da177e4SLinus Torvalds { 961da177e4SLinus Torvalds int result; 971da177e4SLinus Torvalds unsigned char *command = us->iobuf; 981da177e4SLinus Torvalds unsigned char *status = us->iobuf; 991da177e4SLinus Torvalds struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; 1001da177e4SLinus Torvalds 1011da177e4SLinus Torvalds /* send command */ 1021da177e4SLinus Torvalds memset(command, 0, 8); 1031da177e4SLinus Torvalds command[5] = 0xB0; 1041da177e4SLinus Torvalds command[7] = 0x80; 1051da177e4SLinus Torvalds result = sddr55_bulk_transport(us, 1061da177e4SLinus Torvalds DMA_TO_DEVICE, command, 8); 1071da177e4SLinus Torvalds 1081da177e4SLinus Torvalds US_DEBUGP("Result for send_command in status %d\n", 1091da177e4SLinus Torvalds result); 1101da177e4SLinus Torvalds 1111da177e4SLinus Torvalds if (result != USB_STOR_XFER_GOOD) { 1121da177e4SLinus Torvalds set_sense_info (4, 0, 0); /* hardware error */ 1131da177e4SLinus Torvalds return USB_STOR_TRANSPORT_ERROR; 1141da177e4SLinus Torvalds } 1151da177e4SLinus Torvalds 1161da177e4SLinus Torvalds result = sddr55_bulk_transport(us, 1171da177e4SLinus Torvalds DMA_FROM_DEVICE, status, 4); 1181da177e4SLinus Torvalds 1191da177e4SLinus Torvalds /* expect to get short transfer if no card fitted */ 1201da177e4SLinus Torvalds if (result == USB_STOR_XFER_SHORT || result == USB_STOR_XFER_STALLED) { 1211da177e4SLinus Torvalds /* had a short transfer, no card inserted, free map memory */ 1221da177e4SLinus Torvalds kfree(info->lba_to_pba); 1231da177e4SLinus Torvalds kfree(info->pba_to_lba); 1241da177e4SLinus Torvalds info->lba_to_pba = NULL; 1251da177e4SLinus Torvalds info->pba_to_lba = NULL; 1261da177e4SLinus Torvalds 1271da177e4SLinus Torvalds info->fatal_error = 0; 1281da177e4SLinus Torvalds info->force_read_only = 0; 1291da177e4SLinus Torvalds 1301da177e4SLinus Torvalds set_sense_info (2, 0x3a, 0); /* not ready, medium not present */ 1311da177e4SLinus Torvalds return USB_STOR_TRANSPORT_FAILED; 1321da177e4SLinus Torvalds } 1331da177e4SLinus Torvalds 1341da177e4SLinus Torvalds if (result != USB_STOR_XFER_GOOD) { 1351da177e4SLinus Torvalds set_sense_info (4, 0, 0); /* hardware error */ 1361da177e4SLinus Torvalds return USB_STOR_TRANSPORT_FAILED; 1371da177e4SLinus Torvalds } 1381da177e4SLinus Torvalds 1391da177e4SLinus Torvalds /* check write protect status */ 1401da177e4SLinus Torvalds info->read_only = (status[0] & 0x20); 1411da177e4SLinus Torvalds 1421da177e4SLinus Torvalds /* now read status */ 1431da177e4SLinus Torvalds result = sddr55_bulk_transport(us, 1441da177e4SLinus Torvalds DMA_FROM_DEVICE, status, 2); 1451da177e4SLinus Torvalds 1461da177e4SLinus Torvalds if (result != USB_STOR_XFER_GOOD) { 1471da177e4SLinus Torvalds set_sense_info (4, 0, 0); /* hardware error */ 1481da177e4SLinus Torvalds } 1491da177e4SLinus Torvalds 1501da177e4SLinus Torvalds return (result == USB_STOR_XFER_GOOD ? 1511da177e4SLinus Torvalds USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_FAILED); 1521da177e4SLinus Torvalds } 1531da177e4SLinus Torvalds 1541da177e4SLinus Torvalds 1551da177e4SLinus Torvalds static int sddr55_read_data(struct us_data *us, 1561da177e4SLinus Torvalds unsigned int lba, 1571da177e4SLinus Torvalds unsigned int page, 1581da177e4SLinus Torvalds unsigned short sectors) { 1591da177e4SLinus Torvalds 1601da177e4SLinus Torvalds int result = USB_STOR_TRANSPORT_GOOD; 1611da177e4SLinus Torvalds unsigned char *command = us->iobuf; 1621da177e4SLinus Torvalds unsigned char *status = us->iobuf; 1631da177e4SLinus Torvalds struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; 1641da177e4SLinus Torvalds unsigned char *buffer; 1651da177e4SLinus Torvalds 1661da177e4SLinus Torvalds unsigned int pba; 1671da177e4SLinus Torvalds unsigned long address; 1681da177e4SLinus Torvalds 1691da177e4SLinus Torvalds unsigned short pages; 1701da177e4SLinus Torvalds unsigned int len, index, offset; 1711da177e4SLinus Torvalds 1721da177e4SLinus Torvalds // Since we only read in one block at a time, we have to create 1731da177e4SLinus Torvalds // a bounce buffer and move the data a piece at a time between the 1741da177e4SLinus Torvalds // bounce buffer and the actual transfer buffer. 1751da177e4SLinus Torvalds 1761da177e4SLinus Torvalds len = min((unsigned int) sectors, (unsigned int) info->blocksize >> 1771da177e4SLinus Torvalds info->smallpageshift) * PAGESIZE; 1781da177e4SLinus Torvalds buffer = kmalloc(len, GFP_NOIO); 1791da177e4SLinus Torvalds if (buffer == NULL) 1801da177e4SLinus Torvalds return USB_STOR_TRANSPORT_ERROR; /* out of memory */ 1811da177e4SLinus Torvalds index = offset = 0; 1821da177e4SLinus Torvalds 1831da177e4SLinus Torvalds while (sectors>0) { 1841da177e4SLinus Torvalds 1851da177e4SLinus Torvalds /* have we got to end? */ 1861da177e4SLinus Torvalds if (lba >= info->max_log_blks) 1871da177e4SLinus Torvalds break; 1881da177e4SLinus Torvalds 1891da177e4SLinus Torvalds pba = info->lba_to_pba[lba]; 1901da177e4SLinus Torvalds 1911da177e4SLinus Torvalds // Read as many sectors as possible in this block 1921da177e4SLinus Torvalds 1931da177e4SLinus Torvalds pages = min((unsigned int) sectors << info->smallpageshift, 1941da177e4SLinus Torvalds info->blocksize - page); 1951da177e4SLinus Torvalds len = pages << info->pageshift; 1961da177e4SLinus Torvalds 1971da177e4SLinus Torvalds US_DEBUGP("Read %02X pages, from PBA %04X" 1981da177e4SLinus Torvalds " (LBA %04X) page %02X\n", 1991da177e4SLinus Torvalds pages, pba, lba, page); 2001da177e4SLinus Torvalds 2011da177e4SLinus Torvalds if (pba == NOT_ALLOCATED) { 2021da177e4SLinus Torvalds /* no pba for this lba, fill with zeroes */ 2031da177e4SLinus Torvalds memset (buffer, 0, len); 2041da177e4SLinus Torvalds } else { 2051da177e4SLinus Torvalds 2061da177e4SLinus Torvalds address = (pba << info->blockshift) + page; 2071da177e4SLinus Torvalds 2081da177e4SLinus Torvalds command[0] = 0; 2091da177e4SLinus Torvalds command[1] = LSB_of(address>>16); 2101da177e4SLinus Torvalds command[2] = LSB_of(address>>8); 2111da177e4SLinus Torvalds command[3] = LSB_of(address); 2121da177e4SLinus Torvalds 2131da177e4SLinus Torvalds command[4] = 0; 2141da177e4SLinus Torvalds command[5] = 0xB0; 2151da177e4SLinus Torvalds command[6] = LSB_of(pages << (1 - info->smallpageshift)); 2161da177e4SLinus Torvalds command[7] = 0x85; 2171da177e4SLinus Torvalds 2181da177e4SLinus Torvalds /* send command */ 2191da177e4SLinus Torvalds result = sddr55_bulk_transport(us, 2201da177e4SLinus Torvalds DMA_TO_DEVICE, command, 8); 2211da177e4SLinus Torvalds 2221da177e4SLinus Torvalds US_DEBUGP("Result for send_command in read_data %d\n", 2231da177e4SLinus Torvalds result); 2241da177e4SLinus Torvalds 2251da177e4SLinus Torvalds if (result != USB_STOR_XFER_GOOD) { 2261da177e4SLinus Torvalds result = USB_STOR_TRANSPORT_ERROR; 2271da177e4SLinus Torvalds goto leave; 2281da177e4SLinus Torvalds } 2291da177e4SLinus Torvalds 2301da177e4SLinus Torvalds /* read data */ 2311da177e4SLinus Torvalds result = sddr55_bulk_transport(us, 2321da177e4SLinus Torvalds DMA_FROM_DEVICE, buffer, len); 2331da177e4SLinus Torvalds 2341da177e4SLinus Torvalds if (result != USB_STOR_XFER_GOOD) { 2351da177e4SLinus Torvalds result = USB_STOR_TRANSPORT_ERROR; 2361da177e4SLinus Torvalds goto leave; 2371da177e4SLinus Torvalds } 2381da177e4SLinus Torvalds 2391da177e4SLinus Torvalds /* now read status */ 2401da177e4SLinus Torvalds result = sddr55_bulk_transport(us, 2411da177e4SLinus Torvalds DMA_FROM_DEVICE, status, 2); 2421da177e4SLinus Torvalds 2431da177e4SLinus Torvalds if (result != USB_STOR_XFER_GOOD) { 2441da177e4SLinus Torvalds result = USB_STOR_TRANSPORT_ERROR; 2451da177e4SLinus Torvalds goto leave; 2461da177e4SLinus Torvalds } 2471da177e4SLinus Torvalds 2481da177e4SLinus Torvalds /* check status for error */ 2491da177e4SLinus Torvalds if (status[0] == 0xff && status[1] == 0x4) { 2501da177e4SLinus Torvalds set_sense_info (3, 0x11, 0); 2511da177e4SLinus Torvalds result = USB_STOR_TRANSPORT_FAILED; 2521da177e4SLinus Torvalds goto leave; 2531da177e4SLinus Torvalds } 2541da177e4SLinus Torvalds } 2551da177e4SLinus Torvalds 2561da177e4SLinus Torvalds // Store the data in the transfer buffer 2571da177e4SLinus Torvalds usb_stor_access_xfer_buf(buffer, len, us->srb, 2581da177e4SLinus Torvalds &index, &offset, TO_XFER_BUF); 2591da177e4SLinus Torvalds 2601da177e4SLinus Torvalds page = 0; 2611da177e4SLinus Torvalds lba++; 2621da177e4SLinus Torvalds sectors -= pages >> info->smallpageshift; 2631da177e4SLinus Torvalds } 2641da177e4SLinus Torvalds 2651da177e4SLinus Torvalds result = USB_STOR_TRANSPORT_GOOD; 2661da177e4SLinus Torvalds 2671da177e4SLinus Torvalds leave: 2681da177e4SLinus Torvalds kfree(buffer); 2691da177e4SLinus Torvalds 2701da177e4SLinus Torvalds return result; 2711da177e4SLinus Torvalds } 2721da177e4SLinus Torvalds 2731da177e4SLinus Torvalds static int sddr55_write_data(struct us_data *us, 2741da177e4SLinus Torvalds unsigned int lba, 2751da177e4SLinus Torvalds unsigned int page, 2761da177e4SLinus Torvalds unsigned short sectors) { 2771da177e4SLinus Torvalds 2781da177e4SLinus Torvalds int result = USB_STOR_TRANSPORT_GOOD; 2791da177e4SLinus Torvalds unsigned char *command = us->iobuf; 2801da177e4SLinus Torvalds unsigned char *status = us->iobuf; 2811da177e4SLinus Torvalds struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; 2821da177e4SLinus Torvalds unsigned char *buffer; 2831da177e4SLinus Torvalds 2841da177e4SLinus Torvalds unsigned int pba; 2851da177e4SLinus Torvalds unsigned int new_pba; 2861da177e4SLinus Torvalds unsigned long address; 2871da177e4SLinus Torvalds 2881da177e4SLinus Torvalds unsigned short pages; 2891da177e4SLinus Torvalds int i; 2901da177e4SLinus Torvalds unsigned int len, index, offset; 2911da177e4SLinus Torvalds 2921da177e4SLinus Torvalds /* check if we are allowed to write */ 2931da177e4SLinus Torvalds if (info->read_only || info->force_read_only) { 2941da177e4SLinus Torvalds set_sense_info (7, 0x27, 0); /* read only */ 2951da177e4SLinus Torvalds return USB_STOR_TRANSPORT_FAILED; 2961da177e4SLinus Torvalds } 2971da177e4SLinus Torvalds 2981da177e4SLinus Torvalds // Since we only write one block at a time, we have to create 2991da177e4SLinus Torvalds // a bounce buffer and move the data a piece at a time between the 3001da177e4SLinus Torvalds // bounce buffer and the actual transfer buffer. 3011da177e4SLinus Torvalds 3021da177e4SLinus Torvalds len = min((unsigned int) sectors, (unsigned int) info->blocksize >> 3031da177e4SLinus Torvalds info->smallpageshift) * PAGESIZE; 3041da177e4SLinus Torvalds buffer = kmalloc(len, GFP_NOIO); 3051da177e4SLinus Torvalds if (buffer == NULL) 3061da177e4SLinus Torvalds return USB_STOR_TRANSPORT_ERROR; 3071da177e4SLinus Torvalds index = offset = 0; 3081da177e4SLinus Torvalds 3091da177e4SLinus Torvalds while (sectors > 0) { 3101da177e4SLinus Torvalds 3111da177e4SLinus Torvalds /* have we got to end? */ 3121da177e4SLinus Torvalds if (lba >= info->max_log_blks) 3131da177e4SLinus Torvalds break; 3141da177e4SLinus Torvalds 3151da177e4SLinus Torvalds pba = info->lba_to_pba[lba]; 3161da177e4SLinus Torvalds 3171da177e4SLinus Torvalds // Write as many sectors as possible in this block 3181da177e4SLinus Torvalds 3191da177e4SLinus Torvalds pages = min((unsigned int) sectors << info->smallpageshift, 3201da177e4SLinus Torvalds info->blocksize - page); 3211da177e4SLinus Torvalds len = pages << info->pageshift; 3221da177e4SLinus Torvalds 3231da177e4SLinus Torvalds // Get the data from the transfer buffer 3241da177e4SLinus Torvalds usb_stor_access_xfer_buf(buffer, len, us->srb, 3251da177e4SLinus Torvalds &index, &offset, FROM_XFER_BUF); 3261da177e4SLinus Torvalds 3271da177e4SLinus Torvalds US_DEBUGP("Write %02X pages, to PBA %04X" 3281da177e4SLinus Torvalds " (LBA %04X) page %02X\n", 3291da177e4SLinus Torvalds pages, pba, lba, page); 3301da177e4SLinus Torvalds 3311da177e4SLinus Torvalds command[4] = 0; 3321da177e4SLinus Torvalds 3331da177e4SLinus Torvalds if (pba == NOT_ALLOCATED) { 3341da177e4SLinus Torvalds /* no pba allocated for this lba, find a free pba to use */ 3351da177e4SLinus Torvalds 3361da177e4SLinus Torvalds int max_pba = (info->max_log_blks / 250 ) * 256; 3371da177e4SLinus Torvalds int found_count = 0; 3381da177e4SLinus Torvalds int found_pba = -1; 3391da177e4SLinus Torvalds 3401da177e4SLinus Torvalds /* set pba to first block in zone lba is in */ 3411da177e4SLinus Torvalds pba = (lba / 1000) * 1024; 3421da177e4SLinus Torvalds 3431da177e4SLinus Torvalds US_DEBUGP("No PBA for LBA %04X\n",lba); 3441da177e4SLinus Torvalds 3451da177e4SLinus Torvalds if (max_pba > 1024) 3461da177e4SLinus Torvalds max_pba = 1024; 3471da177e4SLinus Torvalds 3481da177e4SLinus Torvalds /* 3491da177e4SLinus Torvalds * Scan through the map looking for an unused block 3501da177e4SLinus Torvalds * leave 16 unused blocks at start (or as many as 3511da177e4SLinus Torvalds * possible) since the sddr55 seems to reuse a used 3521da177e4SLinus Torvalds * block when it shouldn't if we don't leave space. 3531da177e4SLinus Torvalds */ 3541da177e4SLinus Torvalds for (i = 0; i < max_pba; i++, pba++) { 3551da177e4SLinus Torvalds if (info->pba_to_lba[pba] == UNUSED_BLOCK) { 3561da177e4SLinus Torvalds found_pba = pba; 3571da177e4SLinus Torvalds if (found_count++ > 16) 3581da177e4SLinus Torvalds break; 3591da177e4SLinus Torvalds } 3601da177e4SLinus Torvalds } 3611da177e4SLinus Torvalds 3621da177e4SLinus Torvalds pba = found_pba; 3631da177e4SLinus Torvalds 3641da177e4SLinus Torvalds if (pba == -1) { 3651da177e4SLinus Torvalds /* oh dear */ 3661da177e4SLinus Torvalds US_DEBUGP("Couldn't find unallocated block\n"); 3671da177e4SLinus Torvalds 3681da177e4SLinus Torvalds set_sense_info (3, 0x31, 0); /* medium error */ 3691da177e4SLinus Torvalds result = USB_STOR_TRANSPORT_FAILED; 3701da177e4SLinus Torvalds goto leave; 3711da177e4SLinus Torvalds } 3721da177e4SLinus Torvalds 3731da177e4SLinus Torvalds US_DEBUGP("Allocating PBA %04X for LBA %04X\n", pba, lba); 3741da177e4SLinus Torvalds 3751da177e4SLinus Torvalds /* set writing to unallocated block flag */ 3761da177e4SLinus Torvalds command[4] = 0x40; 3771da177e4SLinus Torvalds } 3781da177e4SLinus Torvalds 3791da177e4SLinus Torvalds address = (pba << info->blockshift) + page; 3801da177e4SLinus Torvalds 3811da177e4SLinus Torvalds command[1] = LSB_of(address>>16); 3821da177e4SLinus Torvalds command[2] = LSB_of(address>>8); 3831da177e4SLinus Torvalds command[3] = LSB_of(address); 3841da177e4SLinus Torvalds 3851da177e4SLinus Torvalds /* set the lba into the command, modulo 1000 */ 3861da177e4SLinus Torvalds command[0] = LSB_of(lba % 1000); 3871da177e4SLinus Torvalds command[6] = MSB_of(lba % 1000); 3881da177e4SLinus Torvalds 3891da177e4SLinus Torvalds command[4] |= LSB_of(pages >> info->smallpageshift); 3901da177e4SLinus Torvalds command[5] = 0xB0; 3911da177e4SLinus Torvalds command[7] = 0x86; 3921da177e4SLinus Torvalds 3931da177e4SLinus Torvalds /* send command */ 3941da177e4SLinus Torvalds result = sddr55_bulk_transport(us, 3951da177e4SLinus Torvalds DMA_TO_DEVICE, command, 8); 3961da177e4SLinus Torvalds 3971da177e4SLinus Torvalds if (result != USB_STOR_XFER_GOOD) { 3981da177e4SLinus Torvalds US_DEBUGP("Result for send_command in write_data %d\n", 3991da177e4SLinus Torvalds result); 4001da177e4SLinus Torvalds 4011da177e4SLinus Torvalds /* set_sense_info is superfluous here? */ 4021da177e4SLinus Torvalds set_sense_info (3, 0x3, 0);/* peripheral write error */ 4031da177e4SLinus Torvalds result = USB_STOR_TRANSPORT_FAILED; 4041da177e4SLinus Torvalds goto leave; 4051da177e4SLinus Torvalds } 4061da177e4SLinus Torvalds 4071da177e4SLinus Torvalds /* send the data */ 4081da177e4SLinus Torvalds result = sddr55_bulk_transport(us, 4091da177e4SLinus Torvalds DMA_TO_DEVICE, buffer, len); 4101da177e4SLinus Torvalds 4111da177e4SLinus Torvalds if (result != USB_STOR_XFER_GOOD) { 4121da177e4SLinus Torvalds US_DEBUGP("Result for send_data in write_data %d\n", 4131da177e4SLinus Torvalds result); 4141da177e4SLinus Torvalds 4151da177e4SLinus Torvalds /* set_sense_info is superfluous here? */ 4161da177e4SLinus Torvalds set_sense_info (3, 0x3, 0);/* peripheral write error */ 4171da177e4SLinus Torvalds result = USB_STOR_TRANSPORT_FAILED; 4181da177e4SLinus Torvalds goto leave; 4191da177e4SLinus Torvalds } 4201da177e4SLinus Torvalds 4211da177e4SLinus Torvalds /* now read status */ 4221da177e4SLinus Torvalds result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, status, 6); 4231da177e4SLinus Torvalds 4241da177e4SLinus Torvalds if (result != USB_STOR_XFER_GOOD) { 4251da177e4SLinus Torvalds US_DEBUGP("Result for get_status in write_data %d\n", 4261da177e4SLinus Torvalds result); 4271da177e4SLinus Torvalds 4281da177e4SLinus Torvalds /* set_sense_info is superfluous here? */ 4291da177e4SLinus Torvalds set_sense_info (3, 0x3, 0);/* peripheral write error */ 4301da177e4SLinus Torvalds result = USB_STOR_TRANSPORT_FAILED; 4311da177e4SLinus Torvalds goto leave; 4321da177e4SLinus Torvalds } 4331da177e4SLinus Torvalds 4341da177e4SLinus Torvalds new_pba = (status[3] + (status[4] << 8) + (status[5] << 16)) 4351da177e4SLinus Torvalds >> info->blockshift; 4361da177e4SLinus Torvalds 4371da177e4SLinus Torvalds /* check status for error */ 4381da177e4SLinus Torvalds if (status[0] == 0xff && status[1] == 0x4) { 4391da177e4SLinus Torvalds info->pba_to_lba[new_pba] = BAD_BLOCK; 4401da177e4SLinus Torvalds 4411da177e4SLinus Torvalds set_sense_info (3, 0x0c, 0); 4421da177e4SLinus Torvalds result = USB_STOR_TRANSPORT_FAILED; 4431da177e4SLinus Torvalds goto leave; 4441da177e4SLinus Torvalds } 4451da177e4SLinus Torvalds 4461da177e4SLinus Torvalds US_DEBUGP("Updating maps for LBA %04X: old PBA %04X, new PBA %04X\n", 4471da177e4SLinus Torvalds lba, pba, new_pba); 4481da177e4SLinus Torvalds 4491da177e4SLinus Torvalds /* update the lba<->pba maps, note new_pba might be the same as pba */ 4501da177e4SLinus Torvalds info->lba_to_pba[lba] = new_pba; 4511da177e4SLinus Torvalds info->pba_to_lba[pba] = UNUSED_BLOCK; 4521da177e4SLinus Torvalds 4531da177e4SLinus Torvalds /* check that new_pba wasn't already being used */ 4541da177e4SLinus Torvalds if (info->pba_to_lba[new_pba] != UNUSED_BLOCK) { 4551da177e4SLinus Torvalds printk(KERN_ERR "sddr55 error: new PBA %04X already in use for LBA %04X\n", 4561da177e4SLinus Torvalds new_pba, info->pba_to_lba[new_pba]); 4571da177e4SLinus Torvalds info->fatal_error = 1; 4581da177e4SLinus Torvalds set_sense_info (3, 0x31, 0); 4591da177e4SLinus Torvalds result = USB_STOR_TRANSPORT_FAILED; 4601da177e4SLinus Torvalds goto leave; 4611da177e4SLinus Torvalds } 4621da177e4SLinus Torvalds 4631da177e4SLinus Torvalds /* update the pba<->lba maps for new_pba */ 4641da177e4SLinus Torvalds info->pba_to_lba[new_pba] = lba % 1000; 4651da177e4SLinus Torvalds 4661da177e4SLinus Torvalds page = 0; 4671da177e4SLinus Torvalds lba++; 4681da177e4SLinus Torvalds sectors -= pages >> info->smallpageshift; 4691da177e4SLinus Torvalds } 4701da177e4SLinus Torvalds result = USB_STOR_TRANSPORT_GOOD; 4711da177e4SLinus Torvalds 4721da177e4SLinus Torvalds leave: 4731da177e4SLinus Torvalds kfree(buffer); 4741da177e4SLinus Torvalds return result; 4751da177e4SLinus Torvalds } 4761da177e4SLinus Torvalds 4771da177e4SLinus Torvalds static int sddr55_read_deviceID(struct us_data *us, 4781da177e4SLinus Torvalds unsigned char *manufacturerID, 4791da177e4SLinus Torvalds unsigned char *deviceID) { 4801da177e4SLinus Torvalds 4811da177e4SLinus Torvalds int result; 4821da177e4SLinus Torvalds unsigned char *command = us->iobuf; 4831da177e4SLinus Torvalds unsigned char *content = us->iobuf; 4841da177e4SLinus Torvalds 4851da177e4SLinus Torvalds memset(command, 0, 8); 4861da177e4SLinus Torvalds command[5] = 0xB0; 4871da177e4SLinus Torvalds command[7] = 0x84; 4881da177e4SLinus Torvalds result = sddr55_bulk_transport(us, DMA_TO_DEVICE, command, 8); 4891da177e4SLinus Torvalds 4901da177e4SLinus Torvalds US_DEBUGP("Result of send_control for device ID is %d\n", 4911da177e4SLinus Torvalds result); 4921da177e4SLinus Torvalds 4931da177e4SLinus Torvalds if (result != USB_STOR_XFER_GOOD) 4941da177e4SLinus Torvalds return USB_STOR_TRANSPORT_ERROR; 4951da177e4SLinus Torvalds 4961da177e4SLinus Torvalds result = sddr55_bulk_transport(us, 4971da177e4SLinus Torvalds DMA_FROM_DEVICE, content, 4); 4981da177e4SLinus Torvalds 4991da177e4SLinus Torvalds if (result != USB_STOR_XFER_GOOD) 5001da177e4SLinus Torvalds return USB_STOR_TRANSPORT_ERROR; 5011da177e4SLinus Torvalds 5021da177e4SLinus Torvalds *manufacturerID = content[0]; 5031da177e4SLinus Torvalds *deviceID = content[1]; 5041da177e4SLinus Torvalds 5051da177e4SLinus Torvalds if (content[0] != 0xff) { 5061da177e4SLinus Torvalds result = sddr55_bulk_transport(us, 5071da177e4SLinus Torvalds DMA_FROM_DEVICE, content, 2); 5081da177e4SLinus Torvalds } 5091da177e4SLinus Torvalds 5101da177e4SLinus Torvalds return USB_STOR_TRANSPORT_GOOD; 5111da177e4SLinus Torvalds } 5121da177e4SLinus Torvalds 5131da177e4SLinus Torvalds 5141da177e4SLinus Torvalds int sddr55_reset(struct us_data *us) { 5151da177e4SLinus Torvalds return 0; 5161da177e4SLinus Torvalds } 5171da177e4SLinus Torvalds 5181da177e4SLinus Torvalds 5191da177e4SLinus Torvalds static unsigned long sddr55_get_capacity(struct us_data *us) { 5201da177e4SLinus Torvalds 5211da177e4SLinus Torvalds unsigned char manufacturerID; 5221da177e4SLinus Torvalds unsigned char deviceID; 5231da177e4SLinus Torvalds int result; 5241da177e4SLinus Torvalds struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; 5251da177e4SLinus Torvalds 5261da177e4SLinus Torvalds US_DEBUGP("Reading capacity...\n"); 5271da177e4SLinus Torvalds 5281da177e4SLinus Torvalds result = sddr55_read_deviceID(us, 5291da177e4SLinus Torvalds &manufacturerID, 5301da177e4SLinus Torvalds &deviceID); 5311da177e4SLinus Torvalds 5321da177e4SLinus Torvalds US_DEBUGP("Result of read_deviceID is %d\n", 5331da177e4SLinus Torvalds result); 5341da177e4SLinus Torvalds 5351da177e4SLinus Torvalds if (result != USB_STOR_XFER_GOOD) 5361da177e4SLinus Torvalds return 0; 5371da177e4SLinus Torvalds 5381da177e4SLinus Torvalds US_DEBUGP("Device ID = %02X\n", deviceID); 5391da177e4SLinus Torvalds US_DEBUGP("Manuf ID = %02X\n", manufacturerID); 5401da177e4SLinus Torvalds 5411da177e4SLinus Torvalds info->pageshift = 9; 5421da177e4SLinus Torvalds info->smallpageshift = 0; 5431da177e4SLinus Torvalds info->blocksize = 16; 5441da177e4SLinus Torvalds info->blockshift = 4; 5451da177e4SLinus Torvalds info->blockmask = 15; 5461da177e4SLinus Torvalds 5471da177e4SLinus Torvalds switch (deviceID) { 5481da177e4SLinus Torvalds 5491da177e4SLinus Torvalds case 0x6e: // 1MB 5501da177e4SLinus Torvalds case 0xe8: 5511da177e4SLinus Torvalds case 0xec: 5521da177e4SLinus Torvalds info->pageshift = 8; 5531da177e4SLinus Torvalds info->smallpageshift = 1; 5541da177e4SLinus Torvalds return 0x00100000; 5551da177e4SLinus Torvalds 5561da177e4SLinus Torvalds case 0xea: // 2MB 5571da177e4SLinus Torvalds case 0x64: 5581da177e4SLinus Torvalds info->pageshift = 8; 5591da177e4SLinus Torvalds info->smallpageshift = 1; 5601da177e4SLinus Torvalds case 0x5d: // 5d is a ROM card with pagesize 512. 5611da177e4SLinus Torvalds return 0x00200000; 5621da177e4SLinus Torvalds 5631da177e4SLinus Torvalds case 0xe3: // 4MB 5641da177e4SLinus Torvalds case 0xe5: 5651da177e4SLinus Torvalds case 0x6b: 5661da177e4SLinus Torvalds case 0xd5: 5671da177e4SLinus Torvalds return 0x00400000; 5681da177e4SLinus Torvalds 5691da177e4SLinus Torvalds case 0xe6: // 8MB 5701da177e4SLinus Torvalds case 0xd6: 5711da177e4SLinus Torvalds return 0x00800000; 5721da177e4SLinus Torvalds 5731da177e4SLinus Torvalds case 0x73: // 16MB 5741da177e4SLinus Torvalds info->blocksize = 32; 5751da177e4SLinus Torvalds info->blockshift = 5; 5761da177e4SLinus Torvalds info->blockmask = 31; 5771da177e4SLinus Torvalds return 0x01000000; 5781da177e4SLinus Torvalds 5791da177e4SLinus Torvalds case 0x75: // 32MB 5801da177e4SLinus Torvalds info->blocksize = 32; 5811da177e4SLinus Torvalds info->blockshift = 5; 5821da177e4SLinus Torvalds info->blockmask = 31; 5831da177e4SLinus Torvalds return 0x02000000; 5841da177e4SLinus Torvalds 5851da177e4SLinus Torvalds case 0x76: // 64MB 5861da177e4SLinus Torvalds info->blocksize = 32; 5871da177e4SLinus Torvalds info->blockshift = 5; 5881da177e4SLinus Torvalds info->blockmask = 31; 5891da177e4SLinus Torvalds return 0x04000000; 5901da177e4SLinus Torvalds 5911da177e4SLinus Torvalds case 0x79: // 128MB 5921da177e4SLinus Torvalds info->blocksize = 32; 5931da177e4SLinus Torvalds info->blockshift = 5; 5941da177e4SLinus Torvalds info->blockmask = 31; 5951da177e4SLinus Torvalds return 0x08000000; 5961da177e4SLinus Torvalds 5971da177e4SLinus Torvalds default: // unknown 5981da177e4SLinus Torvalds return 0; 5991da177e4SLinus Torvalds 6001da177e4SLinus Torvalds } 6011da177e4SLinus Torvalds } 6021da177e4SLinus Torvalds 6031da177e4SLinus Torvalds static int sddr55_read_map(struct us_data *us) { 6041da177e4SLinus Torvalds 6051da177e4SLinus Torvalds struct sddr55_card_info *info = (struct sddr55_card_info *)(us->extra); 6061da177e4SLinus Torvalds int numblocks; 6071da177e4SLinus Torvalds unsigned char *buffer; 6081da177e4SLinus Torvalds unsigned char *command = us->iobuf; 6091da177e4SLinus Torvalds int i; 6101da177e4SLinus Torvalds unsigned short lba; 6111da177e4SLinus Torvalds unsigned short max_lba; 6121da177e4SLinus Torvalds int result; 6131da177e4SLinus Torvalds 6141da177e4SLinus Torvalds if (!info->capacity) 6151da177e4SLinus Torvalds return -1; 6161da177e4SLinus Torvalds 6171da177e4SLinus Torvalds numblocks = info->capacity >> (info->blockshift + info->pageshift); 6181da177e4SLinus Torvalds 6191da177e4SLinus Torvalds buffer = kmalloc( numblocks * 2, GFP_NOIO ); 6201da177e4SLinus Torvalds 6211da177e4SLinus Torvalds if (!buffer) 6221da177e4SLinus Torvalds return -1; 6231da177e4SLinus Torvalds 6241da177e4SLinus Torvalds memset(command, 0, 8); 6251da177e4SLinus Torvalds command[5] = 0xB0; 6261da177e4SLinus Torvalds command[6] = numblocks * 2 / 256; 6271da177e4SLinus Torvalds command[7] = 0x8A; 6281da177e4SLinus Torvalds 6291da177e4SLinus Torvalds result = sddr55_bulk_transport(us, DMA_TO_DEVICE, command, 8); 6301da177e4SLinus Torvalds 6311da177e4SLinus Torvalds if ( result != USB_STOR_XFER_GOOD) { 6321da177e4SLinus Torvalds kfree (buffer); 6331da177e4SLinus Torvalds return -1; 6341da177e4SLinus Torvalds } 6351da177e4SLinus Torvalds 6361da177e4SLinus Torvalds result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, buffer, numblocks * 2); 6371da177e4SLinus Torvalds 6381da177e4SLinus Torvalds if ( result != USB_STOR_XFER_GOOD) { 6391da177e4SLinus Torvalds kfree (buffer); 6401da177e4SLinus Torvalds return -1; 6411da177e4SLinus Torvalds } 6421da177e4SLinus Torvalds 6431da177e4SLinus Torvalds result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, command, 2); 6441da177e4SLinus Torvalds 6451da177e4SLinus Torvalds if ( result != USB_STOR_XFER_GOOD) { 6461da177e4SLinus Torvalds kfree (buffer); 6471da177e4SLinus Torvalds return -1; 6481da177e4SLinus Torvalds } 6491da177e4SLinus Torvalds 6501da177e4SLinus Torvalds kfree(info->lba_to_pba); 6511da177e4SLinus Torvalds kfree(info->pba_to_lba); 6521da177e4SLinus Torvalds info->lba_to_pba = kmalloc(numblocks*sizeof(int), GFP_NOIO); 6531da177e4SLinus Torvalds info->pba_to_lba = kmalloc(numblocks*sizeof(int), GFP_NOIO); 6541da177e4SLinus Torvalds 6551da177e4SLinus Torvalds if (info->lba_to_pba == NULL || info->pba_to_lba == NULL) { 6561da177e4SLinus Torvalds kfree(info->lba_to_pba); 6571da177e4SLinus Torvalds kfree(info->pba_to_lba); 6581da177e4SLinus Torvalds info->lba_to_pba = NULL; 6591da177e4SLinus Torvalds info->pba_to_lba = NULL; 6601da177e4SLinus Torvalds kfree(buffer); 6611da177e4SLinus Torvalds return -1; 6621da177e4SLinus Torvalds } 6631da177e4SLinus Torvalds 6641da177e4SLinus Torvalds memset(info->lba_to_pba, 0xff, numblocks*sizeof(int)); 6651da177e4SLinus Torvalds memset(info->pba_to_lba, 0xff, numblocks*sizeof(int)); 6661da177e4SLinus Torvalds 6671da177e4SLinus Torvalds /* set maximum lba */ 6681da177e4SLinus Torvalds max_lba = info->max_log_blks; 6691da177e4SLinus Torvalds if (max_lba > 1000) 6701da177e4SLinus Torvalds max_lba = 1000; 6711da177e4SLinus Torvalds 6721da177e4SLinus Torvalds // Each block is 64 bytes of control data, so block i is located in 6731da177e4SLinus Torvalds // scatterlist block i*64/128k = i*(2^6)*(2^-17) = i*(2^-11) 6741da177e4SLinus Torvalds 6751da177e4SLinus Torvalds for (i=0; i<numblocks; i++) { 6761da177e4SLinus Torvalds int zone = i / 1024; 6771da177e4SLinus Torvalds 6781da177e4SLinus Torvalds lba = short_pack(buffer[i * 2], buffer[i * 2 + 1]); 6791da177e4SLinus Torvalds 6801da177e4SLinus Torvalds /* Every 1024 physical blocks ("zone"), the LBA numbers 6811da177e4SLinus Torvalds * go back to zero, but are within a higher 6821da177e4SLinus Torvalds * block of LBA's. Also, there is a maximum of 6831da177e4SLinus Torvalds * 1000 LBA's per zone. In other words, in PBA 6841da177e4SLinus Torvalds * 1024-2047 you will find LBA 0-999 which are 6851da177e4SLinus Torvalds * really LBA 1000-1999. Yes, this wastes 24 6861da177e4SLinus Torvalds * physical blocks per zone. Go figure. 6871da177e4SLinus Torvalds * These devices can have blocks go bad, so there 6881da177e4SLinus Torvalds * are 24 spare blocks to use when blocks do go bad. 6891da177e4SLinus Torvalds */ 6901da177e4SLinus Torvalds 6911da177e4SLinus Torvalds /* SDDR55 returns 0xffff for a bad block, and 0x400 for the 6921da177e4SLinus Torvalds * CIS block. (Is this true for cards 8MB or less??) 6931da177e4SLinus Torvalds * Record these in the physical to logical map 6941da177e4SLinus Torvalds */ 6951da177e4SLinus Torvalds 6961da177e4SLinus Torvalds info->pba_to_lba[i] = lba; 6971da177e4SLinus Torvalds 6981da177e4SLinus Torvalds if (lba >= max_lba) { 6991da177e4SLinus Torvalds continue; 7001da177e4SLinus Torvalds } 7011da177e4SLinus Torvalds 7021da177e4SLinus Torvalds if (info->lba_to_pba[lba + zone * 1000] != NOT_ALLOCATED && 7031da177e4SLinus Torvalds !info->force_read_only) { 7041da177e4SLinus Torvalds printk("sddr55: map inconsistency at LBA %04X\n", lba + zone * 1000); 7051da177e4SLinus Torvalds info->force_read_only = 1; 7061da177e4SLinus Torvalds } 7071da177e4SLinus Torvalds 7081da177e4SLinus Torvalds if (lba<0x10 || (lba>=0x3E0 && lba<0x3EF)) 7091da177e4SLinus Torvalds US_DEBUGP("LBA %04X <-> PBA %04X\n", lba, i); 7101da177e4SLinus Torvalds 7111da177e4SLinus Torvalds info->lba_to_pba[lba + zone * 1000] = i; 7121da177e4SLinus Torvalds } 7131da177e4SLinus Torvalds 7141da177e4SLinus Torvalds kfree(buffer); 7151da177e4SLinus Torvalds return 0; 7161da177e4SLinus Torvalds } 7171da177e4SLinus Torvalds 7181da177e4SLinus Torvalds 7191da177e4SLinus Torvalds static void sddr55_card_info_destructor(void *extra) { 7201da177e4SLinus Torvalds struct sddr55_card_info *info = (struct sddr55_card_info *)extra; 7211da177e4SLinus Torvalds 7221da177e4SLinus Torvalds if (!extra) 7231da177e4SLinus Torvalds return; 7241da177e4SLinus Torvalds 7251da177e4SLinus Torvalds kfree(info->lba_to_pba); 7261da177e4SLinus Torvalds kfree(info->pba_to_lba); 7271da177e4SLinus Torvalds } 7281da177e4SLinus Torvalds 7291da177e4SLinus Torvalds 7301da177e4SLinus Torvalds /* 7311da177e4SLinus Torvalds * Transport for the Sandisk SDDR-55 7321da177e4SLinus Torvalds */ 7331da177e4SLinus Torvalds int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us) 7341da177e4SLinus Torvalds { 7351da177e4SLinus Torvalds int result; 7361da177e4SLinus Torvalds static unsigned char inquiry_response[8] = { 7371da177e4SLinus Torvalds 0x00, 0x80, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x00 7381da177e4SLinus Torvalds }; 7391da177e4SLinus Torvalds // write-protected for now, no block descriptor support 7401da177e4SLinus Torvalds static unsigned char mode_page_01[20] = { 7411da177e4SLinus Torvalds 0x0, 0x12, 0x00, 0x80, 0x0, 0x0, 0x0, 0x0, 7421da177e4SLinus Torvalds 0x01, 0x0A, 7431da177e4SLinus Torvalds 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 7441da177e4SLinus Torvalds }; 7451da177e4SLinus Torvalds unsigned char *ptr = us->iobuf; 7461da177e4SLinus Torvalds unsigned long capacity; 7471da177e4SLinus Torvalds unsigned int lba; 7481da177e4SLinus Torvalds unsigned int pba; 7491da177e4SLinus Torvalds unsigned int page; 7501da177e4SLinus Torvalds unsigned short pages; 7511da177e4SLinus Torvalds struct sddr55_card_info *info; 7521da177e4SLinus Torvalds 7531da177e4SLinus Torvalds if (!us->extra) { 754887c2560SOliver Neukum us->extra = kzalloc( 7551da177e4SLinus Torvalds sizeof(struct sddr55_card_info), GFP_NOIO); 7561da177e4SLinus Torvalds if (!us->extra) 7571da177e4SLinus Torvalds return USB_STOR_TRANSPORT_ERROR; 7581da177e4SLinus Torvalds us->extra_destructor = sddr55_card_info_destructor; 7591da177e4SLinus Torvalds } 7601da177e4SLinus Torvalds 7611da177e4SLinus Torvalds info = (struct sddr55_card_info *)(us->extra); 7621da177e4SLinus Torvalds 7631da177e4SLinus Torvalds if (srb->cmnd[0] == REQUEST_SENSE) { 7641da177e4SLinus Torvalds US_DEBUGP("SDDR55: request sense %02x/%02x/%02x\n", info->sense_data[2], info->sense_data[12], info->sense_data[13]); 7651da177e4SLinus Torvalds 7661da177e4SLinus Torvalds memcpy (ptr, info->sense_data, sizeof info->sense_data); 7671da177e4SLinus Torvalds ptr[0] = 0x70; 7681da177e4SLinus Torvalds ptr[7] = 11; 7691da177e4SLinus Torvalds usb_stor_set_xfer_buf (ptr, sizeof info->sense_data, srb); 7701da177e4SLinus Torvalds memset (info->sense_data, 0, sizeof info->sense_data); 7711da177e4SLinus Torvalds 7721da177e4SLinus Torvalds return USB_STOR_TRANSPORT_GOOD; 7731da177e4SLinus Torvalds } 7741da177e4SLinus Torvalds 7751da177e4SLinus Torvalds memset (info->sense_data, 0, sizeof info->sense_data); 7761da177e4SLinus Torvalds 7771da177e4SLinus Torvalds /* Dummy up a response for INQUIRY since SDDR55 doesn't 7781da177e4SLinus Torvalds respond to INQUIRY commands */ 7791da177e4SLinus Torvalds 7801da177e4SLinus Torvalds if (srb->cmnd[0] == INQUIRY) { 7811da177e4SLinus Torvalds memcpy(ptr, inquiry_response, 8); 7821da177e4SLinus Torvalds fill_inquiry_response(us, ptr, 36); 7831da177e4SLinus Torvalds return USB_STOR_TRANSPORT_GOOD; 7841da177e4SLinus Torvalds } 7851da177e4SLinus Torvalds 7861da177e4SLinus Torvalds /* only check card status if the map isn't allocated, ie no card seen yet 7871da177e4SLinus Torvalds * or if it's been over half a second since we last accessed it 7881da177e4SLinus Torvalds */ 7891da177e4SLinus Torvalds if (info->lba_to_pba == NULL || time_after(jiffies, info->last_access + HZ/2)) { 7901da177e4SLinus Torvalds 7911da177e4SLinus Torvalds /* check to see if a card is fitted */ 7921da177e4SLinus Torvalds result = sddr55_status (us); 7931da177e4SLinus Torvalds if (result) { 7941da177e4SLinus Torvalds result = sddr55_status (us); 7951da177e4SLinus Torvalds if (!result) { 7961da177e4SLinus Torvalds set_sense_info (6, 0x28, 0); /* new media, set unit attention, not ready to ready */ 7971da177e4SLinus Torvalds } 7981da177e4SLinus Torvalds return USB_STOR_TRANSPORT_FAILED; 7991da177e4SLinus Torvalds } 8001da177e4SLinus Torvalds } 8011da177e4SLinus Torvalds 8021da177e4SLinus Torvalds /* if we detected a problem with the map when writing, 8031da177e4SLinus Torvalds don't allow any more access */ 8041da177e4SLinus Torvalds if (info->fatal_error) { 8051da177e4SLinus Torvalds 8061da177e4SLinus Torvalds set_sense_info (3, 0x31, 0); 8071da177e4SLinus Torvalds return USB_STOR_TRANSPORT_FAILED; 8081da177e4SLinus Torvalds } 8091da177e4SLinus Torvalds 8101da177e4SLinus Torvalds if (srb->cmnd[0] == READ_CAPACITY) { 8111da177e4SLinus Torvalds 8121da177e4SLinus Torvalds capacity = sddr55_get_capacity(us); 8131da177e4SLinus Torvalds 8141da177e4SLinus Torvalds if (!capacity) { 8151da177e4SLinus Torvalds set_sense_info (3, 0x30, 0); /* incompatible medium */ 8161da177e4SLinus Torvalds return USB_STOR_TRANSPORT_FAILED; 8171da177e4SLinus Torvalds } 8181da177e4SLinus Torvalds 8191da177e4SLinus Torvalds info->capacity = capacity; 8201da177e4SLinus Torvalds 8211da177e4SLinus Torvalds /* figure out the maximum logical block number, allowing for 8221da177e4SLinus Torvalds * the fact that only 250 out of every 256 are used */ 8231da177e4SLinus Torvalds info->max_log_blks = ((info->capacity >> (info->pageshift + info->blockshift)) / 256) * 250; 8241da177e4SLinus Torvalds 8251da177e4SLinus Torvalds /* Last page in the card, adjust as we only use 250 out of 8261da177e4SLinus Torvalds * every 256 pages */ 8271da177e4SLinus Torvalds capacity = (capacity / 256) * 250; 8281da177e4SLinus Torvalds 8291da177e4SLinus Torvalds capacity /= PAGESIZE; 8301da177e4SLinus Torvalds capacity--; 8311da177e4SLinus Torvalds 8321da177e4SLinus Torvalds ((__be32 *) ptr)[0] = cpu_to_be32(capacity); 8331da177e4SLinus Torvalds ((__be32 *) ptr)[1] = cpu_to_be32(PAGESIZE); 8341da177e4SLinus Torvalds usb_stor_set_xfer_buf(ptr, 8, srb); 8351da177e4SLinus Torvalds 8361da177e4SLinus Torvalds sddr55_read_map(us); 8371da177e4SLinus Torvalds 8381da177e4SLinus Torvalds return USB_STOR_TRANSPORT_GOOD; 8391da177e4SLinus Torvalds } 8401da177e4SLinus Torvalds 8411da177e4SLinus Torvalds if (srb->cmnd[0] == MODE_SENSE_10) { 8421da177e4SLinus Torvalds 8431da177e4SLinus Torvalds memcpy(ptr, mode_page_01, sizeof mode_page_01); 8441da177e4SLinus Torvalds ptr[3] = (info->read_only || info->force_read_only) ? 0x80 : 0; 8451da177e4SLinus Torvalds usb_stor_set_xfer_buf(ptr, sizeof(mode_page_01), srb); 8461da177e4SLinus Torvalds 8471da177e4SLinus Torvalds if ( (srb->cmnd[2] & 0x3F) == 0x01 ) { 8481da177e4SLinus Torvalds US_DEBUGP( 8491da177e4SLinus Torvalds "SDDR55: Dummy up request for mode page 1\n"); 8501da177e4SLinus Torvalds return USB_STOR_TRANSPORT_GOOD; 8511da177e4SLinus Torvalds 8521da177e4SLinus Torvalds } else if ( (srb->cmnd[2] & 0x3F) == 0x3F ) { 8531da177e4SLinus Torvalds US_DEBUGP( 8541da177e4SLinus Torvalds "SDDR55: Dummy up request for all mode pages\n"); 8551da177e4SLinus Torvalds return USB_STOR_TRANSPORT_GOOD; 8561da177e4SLinus Torvalds } 8571da177e4SLinus Torvalds 8581da177e4SLinus Torvalds set_sense_info (5, 0x24, 0); /* invalid field in command */ 8591da177e4SLinus Torvalds return USB_STOR_TRANSPORT_FAILED; 8601da177e4SLinus Torvalds } 8611da177e4SLinus Torvalds 8621da177e4SLinus Torvalds if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) { 8631da177e4SLinus Torvalds 8641da177e4SLinus Torvalds US_DEBUGP( 8651da177e4SLinus Torvalds "SDDR55: %s medium removal. Not that I can do" 8661da177e4SLinus Torvalds " anything about it...\n", 8671da177e4SLinus Torvalds (srb->cmnd[4]&0x03) ? "Prevent" : "Allow"); 8681da177e4SLinus Torvalds 8691da177e4SLinus Torvalds return USB_STOR_TRANSPORT_GOOD; 8701da177e4SLinus Torvalds 8711da177e4SLinus Torvalds } 8721da177e4SLinus Torvalds 8731da177e4SLinus Torvalds if (srb->cmnd[0] == READ_10 || srb->cmnd[0] == WRITE_10) { 8741da177e4SLinus Torvalds 8751da177e4SLinus Torvalds page = short_pack(srb->cmnd[3], srb->cmnd[2]); 8761da177e4SLinus Torvalds page <<= 16; 8771da177e4SLinus Torvalds page |= short_pack(srb->cmnd[5], srb->cmnd[4]); 8781da177e4SLinus Torvalds pages = short_pack(srb->cmnd[8], srb->cmnd[7]); 8791da177e4SLinus Torvalds 8801da177e4SLinus Torvalds page <<= info->smallpageshift; 8811da177e4SLinus Torvalds 8821da177e4SLinus Torvalds // convert page to block and page-within-block 8831da177e4SLinus Torvalds 8841da177e4SLinus Torvalds lba = page >> info->blockshift; 8851da177e4SLinus Torvalds page = page & info->blockmask; 8861da177e4SLinus Torvalds 8871da177e4SLinus Torvalds // locate physical block corresponding to logical block 8881da177e4SLinus Torvalds 8891da177e4SLinus Torvalds if (lba >= info->max_log_blks) { 8901da177e4SLinus Torvalds 8911da177e4SLinus Torvalds US_DEBUGP("Error: Requested LBA %04X exceeds maximum " 8921da177e4SLinus Torvalds "block %04X\n", lba, info->max_log_blks-1); 8931da177e4SLinus Torvalds 8941da177e4SLinus Torvalds set_sense_info (5, 0x24, 0); /* invalid field in command */ 8951da177e4SLinus Torvalds 8961da177e4SLinus Torvalds return USB_STOR_TRANSPORT_FAILED; 8971da177e4SLinus Torvalds } 8981da177e4SLinus Torvalds 8991da177e4SLinus Torvalds pba = info->lba_to_pba[lba]; 9001da177e4SLinus Torvalds 9011da177e4SLinus Torvalds if (srb->cmnd[0] == WRITE_10) { 9021da177e4SLinus Torvalds US_DEBUGP("WRITE_10: write block %04X (LBA %04X) page %01X" 9031da177e4SLinus Torvalds " pages %d\n", 9041da177e4SLinus Torvalds pba, lba, page, pages); 9051da177e4SLinus Torvalds 9061da177e4SLinus Torvalds return sddr55_write_data(us, lba, page, pages); 9071da177e4SLinus Torvalds } else { 9081da177e4SLinus Torvalds US_DEBUGP("READ_10: read block %04X (LBA %04X) page %01X" 9091da177e4SLinus Torvalds " pages %d\n", 9101da177e4SLinus Torvalds pba, lba, page, pages); 9111da177e4SLinus Torvalds 9121da177e4SLinus Torvalds return sddr55_read_data(us, lba, page, pages); 9131da177e4SLinus Torvalds } 9141da177e4SLinus Torvalds } 9151da177e4SLinus Torvalds 9161da177e4SLinus Torvalds 9171da177e4SLinus Torvalds if (srb->cmnd[0] == TEST_UNIT_READY) { 9181da177e4SLinus Torvalds return USB_STOR_TRANSPORT_GOOD; 9191da177e4SLinus Torvalds } 9201da177e4SLinus Torvalds 9211da177e4SLinus Torvalds if (srb->cmnd[0] == START_STOP) { 9221da177e4SLinus Torvalds return USB_STOR_TRANSPORT_GOOD; 9231da177e4SLinus Torvalds } 9241da177e4SLinus Torvalds 9251da177e4SLinus Torvalds set_sense_info (5, 0x20, 0); /* illegal command */ 9261da177e4SLinus Torvalds 9271da177e4SLinus Torvalds return USB_STOR_TRANSPORT_FAILED; // FIXME: sense buffer? 9281da177e4SLinus Torvalds } 9291da177e4SLinus Torvalds 930