1 /* Driver for Freecom USB/IDE adaptor 2 * 3 * $Id: freecom.c,v 1.22 2002/04/22 03:39:43 mdharm Exp $ 4 * 5 * Freecom v0.1: 6 * 7 * First release 8 * 9 * Current development and maintenance by: 10 * (C) 2000 David Brown <usb-storage@davidb.org> 11 * 12 * This program is free software; you can redistribute it and/or modify it 13 * under the terms of the GNU General Public License as published by the 14 * Free Software Foundation; either version 2, or (at your option) any 15 * later version. 16 * 17 * This program is distributed in the hope that it will be useful, but 18 * WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 * General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License along 23 * with this program; if not, write to the Free Software Foundation, Inc., 24 * 675 Mass Ave, Cambridge, MA 02139, USA. 25 * 26 * This driver was developed with information provided in FREECOM's USB 27 * Programmers Reference Guide. For further information contact Freecom 28 * (http://www.freecom.de/) 29 */ 30 31 #include <linux/config.h> 32 #include <linux/hdreg.h> 33 34 #include <scsi/scsi.h> 35 #include <scsi/scsi_cmnd.h> 36 37 #include "usb.h" 38 #include "transport.h" 39 #include "protocol.h" 40 #include "debug.h" 41 #include "freecom.h" 42 43 #ifdef CONFIG_USB_STORAGE_DEBUG 44 static void pdump (void *, int); 45 #endif 46 47 /* Bits of HD_STATUS */ 48 #define ERR_STAT 0x01 49 #define DRQ_STAT 0x08 50 51 /* All of the outgoing packets are 64 bytes long. */ 52 struct freecom_cb_wrap { 53 u8 Type; /* Command type. */ 54 u8 Timeout; /* Timeout in seconds. */ 55 u8 Atapi[12]; /* An ATAPI packet. */ 56 u8 Filler[50]; /* Padding Data. */ 57 }; 58 59 struct freecom_xfer_wrap { 60 u8 Type; /* Command type. */ 61 u8 Timeout; /* Timeout in seconds. */ 62 __le32 Count; /* Number of bytes to transfer. */ 63 u8 Pad[58]; 64 } __attribute__ ((packed)); 65 66 struct freecom_ide_out { 67 u8 Type; /* Type + IDE register. */ 68 u8 Pad; 69 __le16 Value; /* Value to write. */ 70 u8 Pad2[60]; 71 }; 72 73 struct freecom_ide_in { 74 u8 Type; /* Type | IDE register. */ 75 u8 Pad[63]; 76 }; 77 78 struct freecom_status { 79 u8 Status; 80 u8 Reason; 81 __le16 Count; 82 u8 Pad[60]; 83 }; 84 85 /* Freecom stuffs the interrupt status in the INDEX_STAT bit of the ide 86 * register. */ 87 #define FCM_INT_STATUS 0x02 /* INDEX_STAT */ 88 #define FCM_STATUS_BUSY 0x80 89 90 /* These are the packet types. The low bit indicates that this command 91 * should wait for an interrupt. */ 92 #define FCM_PACKET_ATAPI 0x21 93 #define FCM_PACKET_STATUS 0x20 94 95 /* Receive data from the IDE interface. The ATAPI packet has already 96 * waited, so the data should be immediately available. */ 97 #define FCM_PACKET_INPUT 0x81 98 99 /* Send data to the IDE interface. */ 100 #define FCM_PACKET_OUTPUT 0x01 101 102 /* Write a value to an ide register. Or the ide register to write after 103 * munging the address a bit. */ 104 #define FCM_PACKET_IDE_WRITE 0x40 105 #define FCM_PACKET_IDE_READ 0xC0 106 107 /* All packets (except for status) are 64 bytes long. */ 108 #define FCM_PACKET_LENGTH 64 109 #define FCM_STATUS_PACKET_LENGTH 4 110 111 static int 112 freecom_readdata (struct scsi_cmnd *srb, struct us_data *us, 113 unsigned int ipipe, unsigned int opipe, int count) 114 { 115 struct freecom_xfer_wrap *fxfr = 116 (struct freecom_xfer_wrap *) us->iobuf; 117 int result; 118 119 fxfr->Type = FCM_PACKET_INPUT | 0x00; 120 fxfr->Timeout = 0; /* Short timeout for debugging. */ 121 fxfr->Count = cpu_to_le32 (count); 122 memset (fxfr->Pad, 0, sizeof (fxfr->Pad)); 123 124 US_DEBUGP("Read data Freecom! (c=%d)\n", count); 125 126 /* Issue the transfer command. */ 127 result = usb_stor_bulk_transfer_buf (us, opipe, fxfr, 128 FCM_PACKET_LENGTH, NULL); 129 if (result != USB_STOR_XFER_GOOD) { 130 US_DEBUGP ("Freecom readdata transport error\n"); 131 return USB_STOR_TRANSPORT_ERROR; 132 } 133 134 /* Now transfer all of our blocks. */ 135 US_DEBUGP("Start of read\n"); 136 result = usb_stor_bulk_transfer_sg(us, ipipe, srb->request_buffer, 137 count, srb->use_sg, &srb->resid); 138 US_DEBUGP("freecom_readdata done!\n"); 139 140 if (result > USB_STOR_XFER_SHORT) 141 return USB_STOR_TRANSPORT_ERROR; 142 return USB_STOR_TRANSPORT_GOOD; 143 } 144 145 static int 146 freecom_writedata (struct scsi_cmnd *srb, struct us_data *us, 147 int unsigned ipipe, unsigned int opipe, int count) 148 { 149 struct freecom_xfer_wrap *fxfr = 150 (struct freecom_xfer_wrap *) us->iobuf; 151 int result; 152 153 fxfr->Type = FCM_PACKET_OUTPUT | 0x00; 154 fxfr->Timeout = 0; /* Short timeout for debugging. */ 155 fxfr->Count = cpu_to_le32 (count); 156 memset (fxfr->Pad, 0, sizeof (fxfr->Pad)); 157 158 US_DEBUGP("Write data Freecom! (c=%d)\n", count); 159 160 /* Issue the transfer command. */ 161 result = usb_stor_bulk_transfer_buf (us, opipe, fxfr, 162 FCM_PACKET_LENGTH, NULL); 163 if (result != USB_STOR_XFER_GOOD) { 164 US_DEBUGP ("Freecom writedata transport error\n"); 165 return USB_STOR_TRANSPORT_ERROR; 166 } 167 168 /* Now transfer all of our blocks. */ 169 US_DEBUGP("Start of write\n"); 170 result = usb_stor_bulk_transfer_sg(us, opipe, srb->request_buffer, 171 count, srb->use_sg, &srb->resid); 172 173 US_DEBUGP("freecom_writedata done!\n"); 174 if (result > USB_STOR_XFER_SHORT) 175 return USB_STOR_TRANSPORT_ERROR; 176 return USB_STOR_TRANSPORT_GOOD; 177 } 178 179 /* 180 * Transport for the Freecom USB/IDE adaptor. 181 * 182 */ 183 int freecom_transport(struct scsi_cmnd *srb, struct us_data *us) 184 { 185 struct freecom_cb_wrap *fcb; 186 struct freecom_status *fst; 187 unsigned int ipipe, opipe; /* We need both pipes. */ 188 int result; 189 unsigned int partial; 190 int length; 191 192 fcb = (struct freecom_cb_wrap *) us->iobuf; 193 fst = (struct freecom_status *) us->iobuf; 194 195 US_DEBUGP("Freecom TRANSPORT STARTED\n"); 196 197 /* Get handles for both transports. */ 198 opipe = us->send_bulk_pipe; 199 ipipe = us->recv_bulk_pipe; 200 201 /* The ATAPI Command always goes out first. */ 202 fcb->Type = FCM_PACKET_ATAPI | 0x00; 203 fcb->Timeout = 0; 204 memcpy (fcb->Atapi, srb->cmnd, 12); 205 memset (fcb->Filler, 0, sizeof (fcb->Filler)); 206 207 US_DEBUG(pdump (srb->cmnd, 12)); 208 209 /* Send it out. */ 210 result = usb_stor_bulk_transfer_buf (us, opipe, fcb, 211 FCM_PACKET_LENGTH, NULL); 212 213 /* The Freecom device will only fail if there is something wrong in 214 * USB land. It returns the status in its own registers, which 215 * come back in the bulk pipe. */ 216 if (result != USB_STOR_XFER_GOOD) { 217 US_DEBUGP ("freecom transport error\n"); 218 return USB_STOR_TRANSPORT_ERROR; 219 } 220 221 /* There are times we can optimize out this status read, but it 222 * doesn't hurt us to always do it now. */ 223 result = usb_stor_bulk_transfer_buf (us, ipipe, fst, 224 FCM_STATUS_PACKET_LENGTH, &partial); 225 US_DEBUGP("foo Status result %d %u\n", result, partial); 226 if (result != USB_STOR_XFER_GOOD) 227 return USB_STOR_TRANSPORT_ERROR; 228 229 US_DEBUG(pdump ((void *) fst, partial)); 230 231 /* The firmware will time-out commands after 20 seconds. Some commands 232 * can legitimately take longer than this, so we use a different 233 * command that only waits for the interrupt and then sends status, 234 * without having to send a new ATAPI command to the device. 235 * 236 * NOTE: There is some indication that a data transfer after a timeout 237 * may not work, but that is a condition that should never happen. 238 */ 239 while (fst->Status & FCM_STATUS_BUSY) { 240 US_DEBUGP("20 second USB/ATAPI bridge TIMEOUT occurred!\n"); 241 US_DEBUGP("fst->Status is %x\n", fst->Status); 242 243 /* Get the status again */ 244 fcb->Type = FCM_PACKET_STATUS; 245 fcb->Timeout = 0; 246 memset (fcb->Atapi, 0, sizeof(fcb->Atapi)); 247 memset (fcb->Filler, 0, sizeof (fcb->Filler)); 248 249 /* Send it out. */ 250 result = usb_stor_bulk_transfer_buf (us, opipe, fcb, 251 FCM_PACKET_LENGTH, NULL); 252 253 /* The Freecom device will only fail if there is something 254 * wrong in USB land. It returns the status in its own 255 * registers, which come back in the bulk pipe. 256 */ 257 if (result != USB_STOR_XFER_GOOD) { 258 US_DEBUGP ("freecom transport error\n"); 259 return USB_STOR_TRANSPORT_ERROR; 260 } 261 262 /* get the data */ 263 result = usb_stor_bulk_transfer_buf (us, ipipe, fst, 264 FCM_STATUS_PACKET_LENGTH, &partial); 265 266 US_DEBUGP("bar Status result %d %u\n", result, partial); 267 if (result != USB_STOR_XFER_GOOD) 268 return USB_STOR_TRANSPORT_ERROR; 269 270 US_DEBUG(pdump ((void *) fst, partial)); 271 } 272 273 if (partial != 4) 274 return USB_STOR_TRANSPORT_ERROR; 275 if ((fst->Status & 1) != 0) { 276 US_DEBUGP("operation failed\n"); 277 return USB_STOR_TRANSPORT_FAILED; 278 } 279 280 /* The device might not have as much data available as we 281 * requested. If you ask for more than the device has, this reads 282 * and such will hang. */ 283 US_DEBUGP("Device indicates that it has %d bytes available\n", 284 le16_to_cpu (fst->Count)); 285 US_DEBUGP("SCSI requested %d\n", srb->request_bufflen); 286 287 /* Find the length we desire to read. */ 288 switch (srb->cmnd[0]) { 289 case INQUIRY: 290 case REQUEST_SENSE: /* 16 or 18 bytes? spec says 18, lots of devices only have 16 */ 291 case MODE_SENSE: 292 case MODE_SENSE_10: 293 length = le16_to_cpu(fst->Count); 294 break; 295 default: 296 length = srb->request_bufflen; 297 } 298 299 /* verify that this amount is legal */ 300 if (length > srb->request_bufflen) { 301 length = srb->request_bufflen; 302 US_DEBUGP("Truncating request to match buffer length: %d\n", length); 303 } 304 305 /* What we do now depends on what direction the data is supposed to 306 * move in. */ 307 308 switch (us->srb->sc_data_direction) { 309 case DMA_FROM_DEVICE: 310 /* catch bogus "read 0 length" case */ 311 if (!length) 312 break; 313 /* Make sure that the status indicates that the device 314 * wants data as well. */ 315 if ((fst->Status & DRQ_STAT) == 0 || (fst->Reason & 3) != 2) { 316 US_DEBUGP("SCSI wants data, drive doesn't have any\n"); 317 return USB_STOR_TRANSPORT_FAILED; 318 } 319 result = freecom_readdata (srb, us, ipipe, opipe, length); 320 if (result != USB_STOR_TRANSPORT_GOOD) 321 return result; 322 323 US_DEBUGP("FCM: Waiting for status\n"); 324 result = usb_stor_bulk_transfer_buf (us, ipipe, fst, 325 FCM_PACKET_LENGTH, &partial); 326 US_DEBUG(pdump ((void *) fst, partial)); 327 328 if (partial != 4 || result > USB_STOR_XFER_SHORT) 329 return USB_STOR_TRANSPORT_ERROR; 330 if ((fst->Status & ERR_STAT) != 0) { 331 US_DEBUGP("operation failed\n"); 332 return USB_STOR_TRANSPORT_FAILED; 333 } 334 if ((fst->Reason & 3) != 3) { 335 US_DEBUGP("Drive seems still hungry\n"); 336 return USB_STOR_TRANSPORT_FAILED; 337 } 338 US_DEBUGP("Transfer happy\n"); 339 break; 340 341 case DMA_TO_DEVICE: 342 /* catch bogus "write 0 length" case */ 343 if (!length) 344 break; 345 /* Make sure the status indicates that the device wants to 346 * send us data. */ 347 /* !!IMPLEMENT!! */ 348 result = freecom_writedata (srb, us, ipipe, opipe, length); 349 if (result != USB_STOR_TRANSPORT_GOOD) 350 return result; 351 352 US_DEBUGP("FCM: Waiting for status\n"); 353 result = usb_stor_bulk_transfer_buf (us, ipipe, fst, 354 FCM_PACKET_LENGTH, &partial); 355 356 if (partial != 4 || result > USB_STOR_XFER_SHORT) 357 return USB_STOR_TRANSPORT_ERROR; 358 if ((fst->Status & ERR_STAT) != 0) { 359 US_DEBUGP("operation failed\n"); 360 return USB_STOR_TRANSPORT_FAILED; 361 } 362 if ((fst->Reason & 3) != 3) { 363 US_DEBUGP("Drive seems still hungry\n"); 364 return USB_STOR_TRANSPORT_FAILED; 365 } 366 367 US_DEBUGP("Transfer happy\n"); 368 break; 369 370 371 case DMA_NONE: 372 /* Easy, do nothing. */ 373 break; 374 375 default: 376 /* should never hit here -- filtered in usb.c */ 377 US_DEBUGP ("freecom unimplemented direction: %d\n", 378 us->srb->sc_data_direction); 379 // Return fail, SCSI seems to handle this better. 380 return USB_STOR_TRANSPORT_FAILED; 381 break; 382 } 383 384 return USB_STOR_TRANSPORT_GOOD; 385 } 386 387 int 388 freecom_init (struct us_data *us) 389 { 390 int result; 391 char *buffer = us->iobuf; 392 393 /* The DMA-mapped I/O buffer is 64 bytes long, just right for 394 * all our packets. No need to allocate any extra buffer space. 395 */ 396 397 result = usb_stor_control_msg(us, us->recv_ctrl_pipe, 398 0x4c, 0xc0, 0x4346, 0x0, buffer, 0x20, 3*HZ); 399 buffer[32] = '\0'; 400 US_DEBUGP("String returned from FC init is: %s\n", buffer); 401 402 /* Special thanks to the people at Freecom for providing me with 403 * this "magic sequence", which they use in their Windows and MacOS 404 * drivers to make sure that all the attached perhiperals are 405 * properly reset. 406 */ 407 408 /* send reset */ 409 result = usb_stor_control_msg(us, us->send_ctrl_pipe, 410 0x4d, 0x40, 0x24d8, 0x0, NULL, 0x0, 3*HZ); 411 US_DEBUGP("result from activate reset is %d\n", result); 412 413 /* wait 250ms */ 414 mdelay(250); 415 416 /* clear reset */ 417 result = usb_stor_control_msg(us, us->send_ctrl_pipe, 418 0x4d, 0x40, 0x24f8, 0x0, NULL, 0x0, 3*HZ); 419 US_DEBUGP("result from clear reset is %d\n", result); 420 421 /* wait 3 seconds */ 422 mdelay(3 * 1000); 423 424 return USB_STOR_TRANSPORT_GOOD; 425 } 426 427 int usb_stor_freecom_reset(struct us_data *us) 428 { 429 printk (KERN_CRIT "freecom reset called\n"); 430 431 /* We don't really have this feature. */ 432 return FAILED; 433 } 434 435 #ifdef CONFIG_USB_STORAGE_DEBUG 436 static void pdump (void *ibuffer, int length) 437 { 438 static char line[80]; 439 int offset = 0; 440 unsigned char *buffer = (unsigned char *) ibuffer; 441 int i, j; 442 int from, base; 443 444 offset = 0; 445 for (i = 0; i < length; i++) { 446 if ((i & 15) == 0) { 447 if (i > 0) { 448 offset += sprintf (line+offset, " - "); 449 for (j = i - 16; j < i; j++) { 450 if (buffer[j] >= 32 && buffer[j] <= 126) 451 line[offset++] = buffer[j]; 452 else 453 line[offset++] = '.'; 454 } 455 line[offset] = 0; 456 US_DEBUGP("%s\n", line); 457 offset = 0; 458 } 459 offset += sprintf (line+offset, "%08x:", i); 460 } 461 else if ((i & 7) == 0) { 462 offset += sprintf (line+offset, " -"); 463 } 464 offset += sprintf (line+offset, " %02x", buffer[i] & 0xff); 465 } 466 467 /* Add the last "chunk" of data. */ 468 from = (length - 1) % 16; 469 base = ((length - 1) / 16) * 16; 470 471 for (i = from + 1; i < 16; i++) 472 offset += sprintf (line+offset, " "); 473 if (from < 8) 474 offset += sprintf (line+offset, " "); 475 offset += sprintf (line+offset, " - "); 476 477 for (i = 0; i <= from; i++) { 478 if (buffer[base+i] >= 32 && buffer[base+i] <= 126) 479 line[offset++] = buffer[base+i]; 480 else 481 line[offset++] = '.'; 482 } 483 line[offset] = 0; 484 US_DEBUGP("%s\n", line); 485 offset = 0; 486 } 487 #endif 488 489