1*1da177e4SLinus Torvalds /* Driver for Lexar "Jumpshot" Compact Flash reader 2*1da177e4SLinus Torvalds * 3*1da177e4SLinus Torvalds * $Id: jumpshot.c,v 1.7 2002/02/25 00:40:13 mdharm Exp $ 4*1da177e4SLinus Torvalds * 5*1da177e4SLinus Torvalds * jumpshot driver v0.1: 6*1da177e4SLinus Torvalds * 7*1da177e4SLinus Torvalds * First release 8*1da177e4SLinus Torvalds * 9*1da177e4SLinus Torvalds * Current development and maintenance by: 10*1da177e4SLinus Torvalds * (c) 2000 Jimmie Mayfield (mayfield+usb@sackheads.org) 11*1da177e4SLinus Torvalds * 12*1da177e4SLinus Torvalds * Many thanks to Robert Baruch for the SanDisk SmartMedia reader driver 13*1da177e4SLinus Torvalds * which I used as a template for this driver. 14*1da177e4SLinus Torvalds * 15*1da177e4SLinus Torvalds * Some bugfixes and scatter-gather code by Gregory P. Smith 16*1da177e4SLinus Torvalds * (greg-usb@electricrain.com) 17*1da177e4SLinus Torvalds * 18*1da177e4SLinus Torvalds * Fix for media change by Joerg Schneider (js@joergschneider.com) 19*1da177e4SLinus Torvalds * 20*1da177e4SLinus Torvalds * Developed with the assistance of: 21*1da177e4SLinus Torvalds * 22*1da177e4SLinus Torvalds * (C) 2002 Alan Stern <stern@rowland.org> 23*1da177e4SLinus Torvalds * 24*1da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify it 25*1da177e4SLinus Torvalds * under the terms of the GNU General Public License as published by the 26*1da177e4SLinus Torvalds * Free Software Foundation; either version 2, or (at your option) any 27*1da177e4SLinus Torvalds * later version. 28*1da177e4SLinus Torvalds * 29*1da177e4SLinus Torvalds * This program is distributed in the hope that it will be useful, but 30*1da177e4SLinus Torvalds * WITHOUT ANY WARRANTY; without even the implied warranty of 31*1da177e4SLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 32*1da177e4SLinus Torvalds * General Public License for more details. 33*1da177e4SLinus Torvalds * 34*1da177e4SLinus Torvalds * You should have received a copy of the GNU General Public License along 35*1da177e4SLinus Torvalds * with this program; if not, write to the Free Software Foundation, Inc., 36*1da177e4SLinus Torvalds * 675 Mass Ave, Cambridge, MA 02139, USA. 37*1da177e4SLinus Torvalds */ 38*1da177e4SLinus Torvalds 39*1da177e4SLinus Torvalds /* 40*1da177e4SLinus Torvalds * This driver attempts to support the Lexar Jumpshot USB CompactFlash 41*1da177e4SLinus Torvalds * reader. Like many other USB CompactFlash readers, the Jumpshot contains 42*1da177e4SLinus Torvalds * a USB-to-ATA chip. 43*1da177e4SLinus Torvalds * 44*1da177e4SLinus Torvalds * This driver supports reading and writing. If you're truly paranoid, 45*1da177e4SLinus Torvalds * however, you can force the driver into a write-protected state by setting 46*1da177e4SLinus Torvalds * the WP enable bits in jumpshot_handle_mode_sense. See the comments 47*1da177e4SLinus Torvalds * in that routine. 48*1da177e4SLinus Torvalds */ 49*1da177e4SLinus Torvalds 50*1da177e4SLinus Torvalds #include <linux/sched.h> 51*1da177e4SLinus Torvalds #include <linux/errno.h> 52*1da177e4SLinus Torvalds #include <linux/slab.h> 53*1da177e4SLinus Torvalds 54*1da177e4SLinus Torvalds #include <scsi/scsi.h> 55*1da177e4SLinus Torvalds #include <scsi/scsi_cmnd.h> 56*1da177e4SLinus Torvalds 57*1da177e4SLinus Torvalds #include "usb.h" 58*1da177e4SLinus Torvalds #include "transport.h" 59*1da177e4SLinus Torvalds #include "protocol.h" 60*1da177e4SLinus Torvalds #include "debug.h" 61*1da177e4SLinus Torvalds #include "jumpshot.h" 62*1da177e4SLinus Torvalds 63*1da177e4SLinus Torvalds 64*1da177e4SLinus Torvalds static inline int jumpshot_bulk_read(struct us_data *us, 65*1da177e4SLinus Torvalds unsigned char *data, 66*1da177e4SLinus Torvalds unsigned int len) 67*1da177e4SLinus Torvalds { 68*1da177e4SLinus Torvalds if (len == 0) 69*1da177e4SLinus Torvalds return USB_STOR_XFER_GOOD; 70*1da177e4SLinus Torvalds 71*1da177e4SLinus Torvalds US_DEBUGP("jumpshot_bulk_read: len = %d\n", len); 72*1da177e4SLinus Torvalds return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, 73*1da177e4SLinus Torvalds data, len, NULL); 74*1da177e4SLinus Torvalds } 75*1da177e4SLinus Torvalds 76*1da177e4SLinus Torvalds 77*1da177e4SLinus Torvalds static inline int jumpshot_bulk_write(struct us_data *us, 78*1da177e4SLinus Torvalds unsigned char *data, 79*1da177e4SLinus Torvalds unsigned int len) 80*1da177e4SLinus Torvalds { 81*1da177e4SLinus Torvalds if (len == 0) 82*1da177e4SLinus Torvalds return USB_STOR_XFER_GOOD; 83*1da177e4SLinus Torvalds 84*1da177e4SLinus Torvalds US_DEBUGP("jumpshot_bulk_write: len = %d\n", len); 85*1da177e4SLinus Torvalds return usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, 86*1da177e4SLinus Torvalds data, len, NULL); 87*1da177e4SLinus Torvalds } 88*1da177e4SLinus Torvalds 89*1da177e4SLinus Torvalds 90*1da177e4SLinus Torvalds static int jumpshot_get_status(struct us_data *us) 91*1da177e4SLinus Torvalds { 92*1da177e4SLinus Torvalds int rc; 93*1da177e4SLinus Torvalds 94*1da177e4SLinus Torvalds if (!us) 95*1da177e4SLinus Torvalds return USB_STOR_TRANSPORT_ERROR; 96*1da177e4SLinus Torvalds 97*1da177e4SLinus Torvalds // send the setup 98*1da177e4SLinus Torvalds rc = usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe, 99*1da177e4SLinus Torvalds 0, 0xA0, 0, 7, us->iobuf, 1); 100*1da177e4SLinus Torvalds 101*1da177e4SLinus Torvalds if (rc != USB_STOR_XFER_GOOD) 102*1da177e4SLinus Torvalds return USB_STOR_TRANSPORT_ERROR; 103*1da177e4SLinus Torvalds 104*1da177e4SLinus Torvalds if (us->iobuf[0] != 0x50) { 105*1da177e4SLinus Torvalds US_DEBUGP("jumpshot_get_status: 0x%2x\n", 106*1da177e4SLinus Torvalds us->iobuf[0]); 107*1da177e4SLinus Torvalds return USB_STOR_TRANSPORT_ERROR; 108*1da177e4SLinus Torvalds } 109*1da177e4SLinus Torvalds 110*1da177e4SLinus Torvalds return USB_STOR_TRANSPORT_GOOD; 111*1da177e4SLinus Torvalds } 112*1da177e4SLinus Torvalds 113*1da177e4SLinus Torvalds static int jumpshot_read_data(struct us_data *us, 114*1da177e4SLinus Torvalds struct jumpshot_info *info, 115*1da177e4SLinus Torvalds u32 sector, 116*1da177e4SLinus Torvalds u32 sectors) 117*1da177e4SLinus Torvalds { 118*1da177e4SLinus Torvalds unsigned char *command = us->iobuf; 119*1da177e4SLinus Torvalds unsigned char *buffer; 120*1da177e4SLinus Torvalds unsigned char thistime; 121*1da177e4SLinus Torvalds unsigned int totallen, alloclen; 122*1da177e4SLinus Torvalds int len, result; 123*1da177e4SLinus Torvalds unsigned int sg_idx = 0, sg_offset = 0; 124*1da177e4SLinus Torvalds 125*1da177e4SLinus Torvalds // we're working in LBA mode. according to the ATA spec, 126*1da177e4SLinus Torvalds // we can support up to 28-bit addressing. I don't know if Jumpshot 127*1da177e4SLinus Torvalds // supports beyond 24-bit addressing. It's kind of hard to test 128*1da177e4SLinus Torvalds // since it requires > 8GB CF card. 129*1da177e4SLinus Torvalds 130*1da177e4SLinus Torvalds if (sector > 0x0FFFFFFF) 131*1da177e4SLinus Torvalds return USB_STOR_TRANSPORT_ERROR; 132*1da177e4SLinus Torvalds 133*1da177e4SLinus Torvalds totallen = sectors * info->ssize; 134*1da177e4SLinus Torvalds 135*1da177e4SLinus Torvalds // Since we don't read more than 64 KB at a time, we have to create 136*1da177e4SLinus Torvalds // a bounce buffer and move the data a piece at a time between the 137*1da177e4SLinus Torvalds // bounce buffer and the actual transfer buffer. 138*1da177e4SLinus Torvalds 139*1da177e4SLinus Torvalds alloclen = min(totallen, 65536u); 140*1da177e4SLinus Torvalds buffer = kmalloc(alloclen, GFP_NOIO); 141*1da177e4SLinus Torvalds if (buffer == NULL) 142*1da177e4SLinus Torvalds return USB_STOR_TRANSPORT_ERROR; 143*1da177e4SLinus Torvalds 144*1da177e4SLinus Torvalds do { 145*1da177e4SLinus Torvalds // loop, never allocate or transfer more than 64k at once 146*1da177e4SLinus Torvalds // (min(128k, 255*info->ssize) is the real limit) 147*1da177e4SLinus Torvalds len = min(totallen, alloclen); 148*1da177e4SLinus Torvalds thistime = (len / info->ssize) & 0xff; 149*1da177e4SLinus Torvalds 150*1da177e4SLinus Torvalds command[0] = 0; 151*1da177e4SLinus Torvalds command[1] = thistime; 152*1da177e4SLinus Torvalds command[2] = sector & 0xFF; 153*1da177e4SLinus Torvalds command[3] = (sector >> 8) & 0xFF; 154*1da177e4SLinus Torvalds command[4] = (sector >> 16) & 0xFF; 155*1da177e4SLinus Torvalds 156*1da177e4SLinus Torvalds command[5] = 0xE0 | ((sector >> 24) & 0x0F); 157*1da177e4SLinus Torvalds command[6] = 0x20; 158*1da177e4SLinus Torvalds 159*1da177e4SLinus Torvalds // send the setup + command 160*1da177e4SLinus Torvalds result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe, 161*1da177e4SLinus Torvalds 0, 0x20, 0, 1, command, 7); 162*1da177e4SLinus Torvalds if (result != USB_STOR_XFER_GOOD) 163*1da177e4SLinus Torvalds goto leave; 164*1da177e4SLinus Torvalds 165*1da177e4SLinus Torvalds // read the result 166*1da177e4SLinus Torvalds result = jumpshot_bulk_read(us, buffer, len); 167*1da177e4SLinus Torvalds if (result != USB_STOR_XFER_GOOD) 168*1da177e4SLinus Torvalds goto leave; 169*1da177e4SLinus Torvalds 170*1da177e4SLinus Torvalds US_DEBUGP("jumpshot_read_data: %d bytes\n", len); 171*1da177e4SLinus Torvalds 172*1da177e4SLinus Torvalds // Store the data in the transfer buffer 173*1da177e4SLinus Torvalds usb_stor_access_xfer_buf(buffer, len, us->srb, 174*1da177e4SLinus Torvalds &sg_idx, &sg_offset, TO_XFER_BUF); 175*1da177e4SLinus Torvalds 176*1da177e4SLinus Torvalds sector += thistime; 177*1da177e4SLinus Torvalds totallen -= len; 178*1da177e4SLinus Torvalds } while (totallen > 0); 179*1da177e4SLinus Torvalds 180*1da177e4SLinus Torvalds kfree(buffer); 181*1da177e4SLinus Torvalds return USB_STOR_TRANSPORT_GOOD; 182*1da177e4SLinus Torvalds 183*1da177e4SLinus Torvalds leave: 184*1da177e4SLinus Torvalds kfree(buffer); 185*1da177e4SLinus Torvalds return USB_STOR_TRANSPORT_ERROR; 186*1da177e4SLinus Torvalds } 187*1da177e4SLinus Torvalds 188*1da177e4SLinus Torvalds 189*1da177e4SLinus Torvalds static int jumpshot_write_data(struct us_data *us, 190*1da177e4SLinus Torvalds struct jumpshot_info *info, 191*1da177e4SLinus Torvalds u32 sector, 192*1da177e4SLinus Torvalds u32 sectors) 193*1da177e4SLinus Torvalds { 194*1da177e4SLinus Torvalds unsigned char *command = us->iobuf; 195*1da177e4SLinus Torvalds unsigned char *buffer; 196*1da177e4SLinus Torvalds unsigned char thistime; 197*1da177e4SLinus Torvalds unsigned int totallen, alloclen; 198*1da177e4SLinus Torvalds int len, result, waitcount; 199*1da177e4SLinus Torvalds unsigned int sg_idx = 0, sg_offset = 0; 200*1da177e4SLinus Torvalds 201*1da177e4SLinus Torvalds // we're working in LBA mode. according to the ATA spec, 202*1da177e4SLinus Torvalds // we can support up to 28-bit addressing. I don't know if Jumpshot 203*1da177e4SLinus Torvalds // supports beyond 24-bit addressing. It's kind of hard to test 204*1da177e4SLinus Torvalds // since it requires > 8GB CF card. 205*1da177e4SLinus Torvalds // 206*1da177e4SLinus Torvalds if (sector > 0x0FFFFFFF) 207*1da177e4SLinus Torvalds return USB_STOR_TRANSPORT_ERROR; 208*1da177e4SLinus Torvalds 209*1da177e4SLinus Torvalds totallen = sectors * info->ssize; 210*1da177e4SLinus Torvalds 211*1da177e4SLinus Torvalds // Since we don't write more than 64 KB at a time, we have to create 212*1da177e4SLinus Torvalds // a bounce buffer and move the data a piece at a time between the 213*1da177e4SLinus Torvalds // bounce buffer and the actual transfer buffer. 214*1da177e4SLinus Torvalds 215*1da177e4SLinus Torvalds alloclen = min(totallen, 65536u); 216*1da177e4SLinus Torvalds buffer = kmalloc(alloclen, GFP_NOIO); 217*1da177e4SLinus Torvalds if (buffer == NULL) 218*1da177e4SLinus Torvalds return USB_STOR_TRANSPORT_ERROR; 219*1da177e4SLinus Torvalds 220*1da177e4SLinus Torvalds do { 221*1da177e4SLinus Torvalds // loop, never allocate or transfer more than 64k at once 222*1da177e4SLinus Torvalds // (min(128k, 255*info->ssize) is the real limit) 223*1da177e4SLinus Torvalds 224*1da177e4SLinus Torvalds len = min(totallen, alloclen); 225*1da177e4SLinus Torvalds thistime = (len / info->ssize) & 0xff; 226*1da177e4SLinus Torvalds 227*1da177e4SLinus Torvalds // Get the data from the transfer buffer 228*1da177e4SLinus Torvalds usb_stor_access_xfer_buf(buffer, len, us->srb, 229*1da177e4SLinus Torvalds &sg_idx, &sg_offset, FROM_XFER_BUF); 230*1da177e4SLinus Torvalds 231*1da177e4SLinus Torvalds command[0] = 0; 232*1da177e4SLinus Torvalds command[1] = thistime; 233*1da177e4SLinus Torvalds command[2] = sector & 0xFF; 234*1da177e4SLinus Torvalds command[3] = (sector >> 8) & 0xFF; 235*1da177e4SLinus Torvalds command[4] = (sector >> 16) & 0xFF; 236*1da177e4SLinus Torvalds 237*1da177e4SLinus Torvalds command[5] = 0xE0 | ((sector >> 24) & 0x0F); 238*1da177e4SLinus Torvalds command[6] = 0x30; 239*1da177e4SLinus Torvalds 240*1da177e4SLinus Torvalds // send the setup + command 241*1da177e4SLinus Torvalds result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe, 242*1da177e4SLinus Torvalds 0, 0x20, 0, 1, command, 7); 243*1da177e4SLinus Torvalds if (result != USB_STOR_XFER_GOOD) 244*1da177e4SLinus Torvalds goto leave; 245*1da177e4SLinus Torvalds 246*1da177e4SLinus Torvalds // send the data 247*1da177e4SLinus Torvalds result = jumpshot_bulk_write(us, buffer, len); 248*1da177e4SLinus Torvalds if (result != USB_STOR_XFER_GOOD) 249*1da177e4SLinus Torvalds goto leave; 250*1da177e4SLinus Torvalds 251*1da177e4SLinus Torvalds // read the result. apparently the bulk write can complete 252*1da177e4SLinus Torvalds // before the jumpshot drive is finished writing. so we loop 253*1da177e4SLinus Torvalds // here until we get a good return code 254*1da177e4SLinus Torvalds waitcount = 0; 255*1da177e4SLinus Torvalds do { 256*1da177e4SLinus Torvalds result = jumpshot_get_status(us); 257*1da177e4SLinus Torvalds if (result != USB_STOR_TRANSPORT_GOOD) { 258*1da177e4SLinus Torvalds // I have not experimented to find the smallest value. 259*1da177e4SLinus Torvalds // 260*1da177e4SLinus Torvalds msleep(50); 261*1da177e4SLinus Torvalds } 262*1da177e4SLinus Torvalds } while ((result != USB_STOR_TRANSPORT_GOOD) && (waitcount < 10)); 263*1da177e4SLinus Torvalds 264*1da177e4SLinus Torvalds if (result != USB_STOR_TRANSPORT_GOOD) 265*1da177e4SLinus Torvalds US_DEBUGP("jumpshot_write_data: Gah! Waitcount = 10. Bad write!?\n"); 266*1da177e4SLinus Torvalds 267*1da177e4SLinus Torvalds sector += thistime; 268*1da177e4SLinus Torvalds totallen -= len; 269*1da177e4SLinus Torvalds } while (totallen > 0); 270*1da177e4SLinus Torvalds 271*1da177e4SLinus Torvalds kfree(buffer); 272*1da177e4SLinus Torvalds return result; 273*1da177e4SLinus Torvalds 274*1da177e4SLinus Torvalds leave: 275*1da177e4SLinus Torvalds kfree(buffer); 276*1da177e4SLinus Torvalds return USB_STOR_TRANSPORT_ERROR; 277*1da177e4SLinus Torvalds } 278*1da177e4SLinus Torvalds 279*1da177e4SLinus Torvalds static int jumpshot_id_device(struct us_data *us, 280*1da177e4SLinus Torvalds struct jumpshot_info *info) 281*1da177e4SLinus Torvalds { 282*1da177e4SLinus Torvalds unsigned char *command = us->iobuf; 283*1da177e4SLinus Torvalds unsigned char *reply; 284*1da177e4SLinus Torvalds int rc; 285*1da177e4SLinus Torvalds 286*1da177e4SLinus Torvalds if (!us || !info) 287*1da177e4SLinus Torvalds return USB_STOR_TRANSPORT_ERROR; 288*1da177e4SLinus Torvalds 289*1da177e4SLinus Torvalds command[0] = 0xE0; 290*1da177e4SLinus Torvalds command[1] = 0xEC; 291*1da177e4SLinus Torvalds reply = kmalloc(512, GFP_NOIO); 292*1da177e4SLinus Torvalds if (!reply) 293*1da177e4SLinus Torvalds return USB_STOR_TRANSPORT_ERROR; 294*1da177e4SLinus Torvalds 295*1da177e4SLinus Torvalds // send the setup 296*1da177e4SLinus Torvalds rc = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe, 297*1da177e4SLinus Torvalds 0, 0x20, 0, 6, command, 2); 298*1da177e4SLinus Torvalds 299*1da177e4SLinus Torvalds if (rc != USB_STOR_XFER_GOOD) { 300*1da177e4SLinus Torvalds US_DEBUGP("jumpshot_id_device: Gah! " 301*1da177e4SLinus Torvalds "send_control for read_capacity failed\n"); 302*1da177e4SLinus Torvalds rc = USB_STOR_TRANSPORT_ERROR; 303*1da177e4SLinus Torvalds goto leave; 304*1da177e4SLinus Torvalds } 305*1da177e4SLinus Torvalds 306*1da177e4SLinus Torvalds // read the reply 307*1da177e4SLinus Torvalds rc = jumpshot_bulk_read(us, reply, 512); 308*1da177e4SLinus Torvalds if (rc != USB_STOR_XFER_GOOD) { 309*1da177e4SLinus Torvalds rc = USB_STOR_TRANSPORT_ERROR; 310*1da177e4SLinus Torvalds goto leave; 311*1da177e4SLinus Torvalds } 312*1da177e4SLinus Torvalds 313*1da177e4SLinus Torvalds info->sectors = ((u32)(reply[117]) << 24) | 314*1da177e4SLinus Torvalds ((u32)(reply[116]) << 16) | 315*1da177e4SLinus Torvalds ((u32)(reply[115]) << 8) | 316*1da177e4SLinus Torvalds ((u32)(reply[114]) ); 317*1da177e4SLinus Torvalds 318*1da177e4SLinus Torvalds rc = USB_STOR_TRANSPORT_GOOD; 319*1da177e4SLinus Torvalds 320*1da177e4SLinus Torvalds leave: 321*1da177e4SLinus Torvalds kfree(reply); 322*1da177e4SLinus Torvalds return rc; 323*1da177e4SLinus Torvalds } 324*1da177e4SLinus Torvalds 325*1da177e4SLinus Torvalds static int jumpshot_handle_mode_sense(struct us_data *us, 326*1da177e4SLinus Torvalds struct scsi_cmnd * srb, 327*1da177e4SLinus Torvalds int sense_6) 328*1da177e4SLinus Torvalds { 329*1da177e4SLinus Torvalds static unsigned char rw_err_page[12] = { 330*1da177e4SLinus Torvalds 0x1, 0xA, 0x21, 1, 0, 0, 0, 0, 1, 0, 0, 0 331*1da177e4SLinus Torvalds }; 332*1da177e4SLinus Torvalds static unsigned char cache_page[12] = { 333*1da177e4SLinus Torvalds 0x8, 0xA, 0x1, 0, 0, 0, 0, 0, 0, 0, 0, 0 334*1da177e4SLinus Torvalds }; 335*1da177e4SLinus Torvalds static unsigned char rbac_page[12] = { 336*1da177e4SLinus Torvalds 0x1B, 0xA, 0, 0x81, 0, 0, 0, 0, 0, 0, 0, 0 337*1da177e4SLinus Torvalds }; 338*1da177e4SLinus Torvalds static unsigned char timer_page[8] = { 339*1da177e4SLinus Torvalds 0x1C, 0x6, 0, 0, 0, 0 340*1da177e4SLinus Torvalds }; 341*1da177e4SLinus Torvalds unsigned char pc, page_code; 342*1da177e4SLinus Torvalds unsigned int i = 0; 343*1da177e4SLinus Torvalds struct jumpshot_info *info = (struct jumpshot_info *) (us->extra); 344*1da177e4SLinus Torvalds unsigned char *ptr = us->iobuf; 345*1da177e4SLinus Torvalds 346*1da177e4SLinus Torvalds pc = srb->cmnd[2] >> 6; 347*1da177e4SLinus Torvalds page_code = srb->cmnd[2] & 0x3F; 348*1da177e4SLinus Torvalds 349*1da177e4SLinus Torvalds switch (pc) { 350*1da177e4SLinus Torvalds case 0x0: 351*1da177e4SLinus Torvalds US_DEBUGP("jumpshot_handle_mode_sense: Current values\n"); 352*1da177e4SLinus Torvalds break; 353*1da177e4SLinus Torvalds case 0x1: 354*1da177e4SLinus Torvalds US_DEBUGP("jumpshot_handle_mode_sense: Changeable values\n"); 355*1da177e4SLinus Torvalds break; 356*1da177e4SLinus Torvalds case 0x2: 357*1da177e4SLinus Torvalds US_DEBUGP("jumpshot_handle_mode_sense: Default values\n"); 358*1da177e4SLinus Torvalds break; 359*1da177e4SLinus Torvalds case 0x3: 360*1da177e4SLinus Torvalds US_DEBUGP("jumpshot_handle_mode_sense: Saves values\n"); 361*1da177e4SLinus Torvalds break; 362*1da177e4SLinus Torvalds } 363*1da177e4SLinus Torvalds 364*1da177e4SLinus Torvalds memset(ptr, 0, 8); 365*1da177e4SLinus Torvalds if (sense_6) { 366*1da177e4SLinus Torvalds ptr[2] = 0x00; // WP enable: 0x80 367*1da177e4SLinus Torvalds i = 4; 368*1da177e4SLinus Torvalds } else { 369*1da177e4SLinus Torvalds ptr[3] = 0x00; // WP enable: 0x80 370*1da177e4SLinus Torvalds i = 8; 371*1da177e4SLinus Torvalds } 372*1da177e4SLinus Torvalds 373*1da177e4SLinus Torvalds switch (page_code) { 374*1da177e4SLinus Torvalds case 0x0: 375*1da177e4SLinus Torvalds // vendor-specific mode 376*1da177e4SLinus Torvalds info->sense_key = 0x05; 377*1da177e4SLinus Torvalds info->sense_asc = 0x24; 378*1da177e4SLinus Torvalds info->sense_ascq = 0x00; 379*1da177e4SLinus Torvalds return USB_STOR_TRANSPORT_FAILED; 380*1da177e4SLinus Torvalds 381*1da177e4SLinus Torvalds case 0x1: 382*1da177e4SLinus Torvalds memcpy(ptr + i, rw_err_page, sizeof(rw_err_page)); 383*1da177e4SLinus Torvalds i += sizeof(rw_err_page); 384*1da177e4SLinus Torvalds break; 385*1da177e4SLinus Torvalds 386*1da177e4SLinus Torvalds case 0x8: 387*1da177e4SLinus Torvalds memcpy(ptr + i, cache_page, sizeof(cache_page)); 388*1da177e4SLinus Torvalds i += sizeof(cache_page); 389*1da177e4SLinus Torvalds break; 390*1da177e4SLinus Torvalds 391*1da177e4SLinus Torvalds case 0x1B: 392*1da177e4SLinus Torvalds memcpy(ptr + i, rbac_page, sizeof(rbac_page)); 393*1da177e4SLinus Torvalds i += sizeof(rbac_page); 394*1da177e4SLinus Torvalds break; 395*1da177e4SLinus Torvalds 396*1da177e4SLinus Torvalds case 0x1C: 397*1da177e4SLinus Torvalds memcpy(ptr + i, timer_page, sizeof(timer_page)); 398*1da177e4SLinus Torvalds i += sizeof(timer_page); 399*1da177e4SLinus Torvalds break; 400*1da177e4SLinus Torvalds 401*1da177e4SLinus Torvalds case 0x3F: 402*1da177e4SLinus Torvalds memcpy(ptr + i, timer_page, sizeof(timer_page)); 403*1da177e4SLinus Torvalds i += sizeof(timer_page); 404*1da177e4SLinus Torvalds memcpy(ptr + i, rbac_page, sizeof(rbac_page)); 405*1da177e4SLinus Torvalds i += sizeof(rbac_page); 406*1da177e4SLinus Torvalds memcpy(ptr + i, cache_page, sizeof(cache_page)); 407*1da177e4SLinus Torvalds i += sizeof(cache_page); 408*1da177e4SLinus Torvalds memcpy(ptr + i, rw_err_page, sizeof(rw_err_page)); 409*1da177e4SLinus Torvalds i += sizeof(rw_err_page); 410*1da177e4SLinus Torvalds break; 411*1da177e4SLinus Torvalds } 412*1da177e4SLinus Torvalds 413*1da177e4SLinus Torvalds if (sense_6) 414*1da177e4SLinus Torvalds ptr[0] = i - 1; 415*1da177e4SLinus Torvalds else 416*1da177e4SLinus Torvalds ((__be16 *) ptr)[0] = cpu_to_be16(i - 2); 417*1da177e4SLinus Torvalds usb_stor_set_xfer_buf(ptr, i, srb); 418*1da177e4SLinus Torvalds 419*1da177e4SLinus Torvalds return USB_STOR_TRANSPORT_GOOD; 420*1da177e4SLinus Torvalds } 421*1da177e4SLinus Torvalds 422*1da177e4SLinus Torvalds 423*1da177e4SLinus Torvalds static void jumpshot_info_destructor(void *extra) 424*1da177e4SLinus Torvalds { 425*1da177e4SLinus Torvalds // this routine is a placeholder... 426*1da177e4SLinus Torvalds // currently, we don't allocate any extra blocks so we're okay 427*1da177e4SLinus Torvalds } 428*1da177e4SLinus Torvalds 429*1da177e4SLinus Torvalds 430*1da177e4SLinus Torvalds 431*1da177e4SLinus Torvalds // Transport for the Lexar 'Jumpshot' 432*1da177e4SLinus Torvalds // 433*1da177e4SLinus Torvalds int jumpshot_transport(struct scsi_cmnd * srb, struct us_data *us) 434*1da177e4SLinus Torvalds { 435*1da177e4SLinus Torvalds struct jumpshot_info *info; 436*1da177e4SLinus Torvalds int rc; 437*1da177e4SLinus Torvalds unsigned long block, blocks; 438*1da177e4SLinus Torvalds unsigned char *ptr = us->iobuf; 439*1da177e4SLinus Torvalds static unsigned char inquiry_response[8] = { 440*1da177e4SLinus Torvalds 0x00, 0x80, 0x00, 0x01, 0x1F, 0x00, 0x00, 0x00 441*1da177e4SLinus Torvalds }; 442*1da177e4SLinus Torvalds 443*1da177e4SLinus Torvalds if (!us->extra) { 444*1da177e4SLinus Torvalds us->extra = kmalloc(sizeof(struct jumpshot_info), GFP_NOIO); 445*1da177e4SLinus Torvalds if (!us->extra) { 446*1da177e4SLinus Torvalds US_DEBUGP("jumpshot_transport: Gah! Can't allocate storage for jumpshot info struct!\n"); 447*1da177e4SLinus Torvalds return USB_STOR_TRANSPORT_ERROR; 448*1da177e4SLinus Torvalds } 449*1da177e4SLinus Torvalds memset(us->extra, 0, sizeof(struct jumpshot_info)); 450*1da177e4SLinus Torvalds us->extra_destructor = jumpshot_info_destructor; 451*1da177e4SLinus Torvalds } 452*1da177e4SLinus Torvalds 453*1da177e4SLinus Torvalds info = (struct jumpshot_info *) (us->extra); 454*1da177e4SLinus Torvalds 455*1da177e4SLinus Torvalds if (srb->cmnd[0] == INQUIRY) { 456*1da177e4SLinus Torvalds US_DEBUGP("jumpshot_transport: INQUIRY. Returning bogus response.\n"); 457*1da177e4SLinus Torvalds memcpy(ptr, inquiry_response, sizeof(inquiry_response)); 458*1da177e4SLinus Torvalds fill_inquiry_response(us, ptr, 36); 459*1da177e4SLinus Torvalds return USB_STOR_TRANSPORT_GOOD; 460*1da177e4SLinus Torvalds } 461*1da177e4SLinus Torvalds 462*1da177e4SLinus Torvalds if (srb->cmnd[0] == READ_CAPACITY) { 463*1da177e4SLinus Torvalds info->ssize = 0x200; // hard coded 512 byte sectors as per ATA spec 464*1da177e4SLinus Torvalds 465*1da177e4SLinus Torvalds rc = jumpshot_get_status(us); 466*1da177e4SLinus Torvalds if (rc != USB_STOR_TRANSPORT_GOOD) 467*1da177e4SLinus Torvalds return rc; 468*1da177e4SLinus Torvalds 469*1da177e4SLinus Torvalds rc = jumpshot_id_device(us, info); 470*1da177e4SLinus Torvalds if (rc != USB_STOR_TRANSPORT_GOOD) 471*1da177e4SLinus Torvalds return rc; 472*1da177e4SLinus Torvalds 473*1da177e4SLinus Torvalds US_DEBUGP("jumpshot_transport: READ_CAPACITY: %ld sectors, %ld bytes per sector\n", 474*1da177e4SLinus Torvalds info->sectors, info->ssize); 475*1da177e4SLinus Torvalds 476*1da177e4SLinus Torvalds // build the reply 477*1da177e4SLinus Torvalds // 478*1da177e4SLinus Torvalds ((__be32 *) ptr)[0] = cpu_to_be32(info->sectors - 1); 479*1da177e4SLinus Torvalds ((__be32 *) ptr)[1] = cpu_to_be32(info->ssize); 480*1da177e4SLinus Torvalds usb_stor_set_xfer_buf(ptr, 8, srb); 481*1da177e4SLinus Torvalds 482*1da177e4SLinus Torvalds return USB_STOR_TRANSPORT_GOOD; 483*1da177e4SLinus Torvalds } 484*1da177e4SLinus Torvalds 485*1da177e4SLinus Torvalds if (srb->cmnd[0] == MODE_SELECT_10) { 486*1da177e4SLinus Torvalds US_DEBUGP("jumpshot_transport: Gah! MODE_SELECT_10.\n"); 487*1da177e4SLinus Torvalds return USB_STOR_TRANSPORT_ERROR; 488*1da177e4SLinus Torvalds } 489*1da177e4SLinus Torvalds 490*1da177e4SLinus Torvalds if (srb->cmnd[0] == READ_10) { 491*1da177e4SLinus Torvalds block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) | 492*1da177e4SLinus Torvalds ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5])); 493*1da177e4SLinus Torvalds 494*1da177e4SLinus Torvalds blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8])); 495*1da177e4SLinus Torvalds 496*1da177e4SLinus Torvalds US_DEBUGP("jumpshot_transport: READ_10: read block 0x%04lx count %ld\n", block, blocks); 497*1da177e4SLinus Torvalds return jumpshot_read_data(us, info, block, blocks); 498*1da177e4SLinus Torvalds } 499*1da177e4SLinus Torvalds 500*1da177e4SLinus Torvalds if (srb->cmnd[0] == READ_12) { 501*1da177e4SLinus Torvalds // I don't think we'll ever see a READ_12 but support it anyway... 502*1da177e4SLinus Torvalds // 503*1da177e4SLinus Torvalds block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) | 504*1da177e4SLinus Torvalds ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5])); 505*1da177e4SLinus Torvalds 506*1da177e4SLinus Torvalds blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) | 507*1da177e4SLinus Torvalds ((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9])); 508*1da177e4SLinus Torvalds 509*1da177e4SLinus Torvalds US_DEBUGP("jumpshot_transport: READ_12: read block 0x%04lx count %ld\n", block, blocks); 510*1da177e4SLinus Torvalds return jumpshot_read_data(us, info, block, blocks); 511*1da177e4SLinus Torvalds } 512*1da177e4SLinus Torvalds 513*1da177e4SLinus Torvalds if (srb->cmnd[0] == WRITE_10) { 514*1da177e4SLinus Torvalds block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) | 515*1da177e4SLinus Torvalds ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5])); 516*1da177e4SLinus Torvalds 517*1da177e4SLinus Torvalds blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8])); 518*1da177e4SLinus Torvalds 519*1da177e4SLinus Torvalds US_DEBUGP("jumpshot_transport: WRITE_10: write block 0x%04lx count %ld\n", block, blocks); 520*1da177e4SLinus Torvalds return jumpshot_write_data(us, info, block, blocks); 521*1da177e4SLinus Torvalds } 522*1da177e4SLinus Torvalds 523*1da177e4SLinus Torvalds if (srb->cmnd[0] == WRITE_12) { 524*1da177e4SLinus Torvalds // I don't think we'll ever see a WRITE_12 but support it anyway... 525*1da177e4SLinus Torvalds // 526*1da177e4SLinus Torvalds block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) | 527*1da177e4SLinus Torvalds ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5])); 528*1da177e4SLinus Torvalds 529*1da177e4SLinus Torvalds blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) | 530*1da177e4SLinus Torvalds ((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9])); 531*1da177e4SLinus Torvalds 532*1da177e4SLinus Torvalds US_DEBUGP("jumpshot_transport: WRITE_12: write block 0x%04lx count %ld\n", block, blocks); 533*1da177e4SLinus Torvalds return jumpshot_write_data(us, info, block, blocks); 534*1da177e4SLinus Torvalds } 535*1da177e4SLinus Torvalds 536*1da177e4SLinus Torvalds 537*1da177e4SLinus Torvalds if (srb->cmnd[0] == TEST_UNIT_READY) { 538*1da177e4SLinus Torvalds US_DEBUGP("jumpshot_transport: TEST_UNIT_READY.\n"); 539*1da177e4SLinus Torvalds return jumpshot_get_status(us); 540*1da177e4SLinus Torvalds } 541*1da177e4SLinus Torvalds 542*1da177e4SLinus Torvalds if (srb->cmnd[0] == REQUEST_SENSE) { 543*1da177e4SLinus Torvalds US_DEBUGP("jumpshot_transport: REQUEST_SENSE.\n"); 544*1da177e4SLinus Torvalds 545*1da177e4SLinus Torvalds memset(ptr, 0, 18); 546*1da177e4SLinus Torvalds ptr[0] = 0xF0; 547*1da177e4SLinus Torvalds ptr[2] = info->sense_key; 548*1da177e4SLinus Torvalds ptr[7] = 11; 549*1da177e4SLinus Torvalds ptr[12] = info->sense_asc; 550*1da177e4SLinus Torvalds ptr[13] = info->sense_ascq; 551*1da177e4SLinus Torvalds usb_stor_set_xfer_buf(ptr, 18, srb); 552*1da177e4SLinus Torvalds 553*1da177e4SLinus Torvalds return USB_STOR_TRANSPORT_GOOD; 554*1da177e4SLinus Torvalds } 555*1da177e4SLinus Torvalds 556*1da177e4SLinus Torvalds if (srb->cmnd[0] == MODE_SENSE) { 557*1da177e4SLinus Torvalds US_DEBUGP("jumpshot_transport: MODE_SENSE_6 detected\n"); 558*1da177e4SLinus Torvalds return jumpshot_handle_mode_sense(us, srb, 1); 559*1da177e4SLinus Torvalds } 560*1da177e4SLinus Torvalds 561*1da177e4SLinus Torvalds if (srb->cmnd[0] == MODE_SENSE_10) { 562*1da177e4SLinus Torvalds US_DEBUGP("jumpshot_transport: MODE_SENSE_10 detected\n"); 563*1da177e4SLinus Torvalds return jumpshot_handle_mode_sense(us, srb, 0); 564*1da177e4SLinus Torvalds } 565*1da177e4SLinus Torvalds 566*1da177e4SLinus Torvalds if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) { 567*1da177e4SLinus Torvalds // sure. whatever. not like we can stop the user from popping 568*1da177e4SLinus Torvalds // the media out of the device (no locking doors, etc) 569*1da177e4SLinus Torvalds // 570*1da177e4SLinus Torvalds return USB_STOR_TRANSPORT_GOOD; 571*1da177e4SLinus Torvalds } 572*1da177e4SLinus Torvalds 573*1da177e4SLinus Torvalds if (srb->cmnd[0] == START_STOP) { 574*1da177e4SLinus Torvalds /* this is used by sd.c'check_scsidisk_media_change to detect 575*1da177e4SLinus Torvalds media change */ 576*1da177e4SLinus Torvalds US_DEBUGP("jumpshot_transport: START_STOP.\n"); 577*1da177e4SLinus Torvalds /* the first jumpshot_id_device after a media change returns 578*1da177e4SLinus Torvalds an error (determined experimentally) */ 579*1da177e4SLinus Torvalds rc = jumpshot_id_device(us, info); 580*1da177e4SLinus Torvalds if (rc == USB_STOR_TRANSPORT_GOOD) { 581*1da177e4SLinus Torvalds info->sense_key = NO_SENSE; 582*1da177e4SLinus Torvalds srb->result = SUCCESS; 583*1da177e4SLinus Torvalds } else { 584*1da177e4SLinus Torvalds info->sense_key = UNIT_ATTENTION; 585*1da177e4SLinus Torvalds srb->result = SAM_STAT_CHECK_CONDITION; 586*1da177e4SLinus Torvalds } 587*1da177e4SLinus Torvalds return rc; 588*1da177e4SLinus Torvalds } 589*1da177e4SLinus Torvalds 590*1da177e4SLinus Torvalds US_DEBUGP("jumpshot_transport: Gah! Unknown command: %d (0x%x)\n", 591*1da177e4SLinus Torvalds srb->cmnd[0], srb->cmnd[0]); 592*1da177e4SLinus Torvalds info->sense_key = 0x05; 593*1da177e4SLinus Torvalds info->sense_asc = 0x20; 594*1da177e4SLinus Torvalds info->sense_ascq = 0x00; 595*1da177e4SLinus Torvalds return USB_STOR_TRANSPORT_FAILED; 596*1da177e4SLinus Torvalds } 597