1/* Driver for USB Mass Storage compliant devices 2 * SCSI layer glue code 3 * 4 * $Id: scsiglue.c,v 1.1.1.1 2008/10/15 03:27:04 james26_jang Exp $ 5 * 6 * Current development and maintenance by: 7 * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) 8 * 9 * Developed with the assistance of: 10 * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org) 11 * (c) 2000 Stephen J. Gowdy (SGowdy@lbl.gov) 12 * 13 * Initial work by: 14 * (c) 1999 Michael Gee (michael@linuxspecific.com) 15 * 16 * This driver is based on the 'USB Mass Storage Class' document. This 17 * describes in detail the protocol used to communicate with such 18 * devices. Clearly, the designers had SCSI and ATAPI commands in 19 * mind when they created this document. The commands are all very 20 * similar to commands in the SCSI-II and ATAPI specifications. 21 * 22 * It is important to note that in a number of cases this class 23 * exhibits class-specific exemptions from the USB specification. 24 * Notably the usage of NAK, STALL and ACK differs from the norm, in 25 * that they are used to communicate wait, failed and OK on commands. 26 * 27 * Also, for certain devices, the interrupt endpoint is used to convey 28 * status of a command. 29 * 30 * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more 31 * information about this driver. 32 * 33 * This program is free software; you can redistribute it and/or modify it 34 * under the terms of the GNU General Public License as published by the 35 * Free Software Foundation; either version 2, or (at your option) any 36 * later version. 37 * 38 * This program is distributed in the hope that it will be useful, but 39 * WITHOUT ANY WARRANTY; without even the implied warranty of 40 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 41 * General Public License for more details. 42 * 43 * You should have received a copy of the GNU General Public License along 44 * with this program; if not, write to the Free Software Foundation, Inc., 45 * 675 Mass Ave, Cambridge, MA 02139, USA. 46 */ 47#include "scsiglue.h" 48#include "usb.h" 49#include "debug.h" 50#include "transport.h" 51 52#include <linux/slab.h> 53 54/* 55 * kernel thread actions 56 */ 57 58#define US_ACT_COMMAND 1 59#define US_ACT_DEVICE_RESET 2 60#define US_ACT_BUS_RESET 3 61#define US_ACT_HOST_RESET 4 62#define US_ACT_EXIT 5 63 64/*********************************************************************** 65 * Host functions 66 ***********************************************************************/ 67 68static const char* host_info(struct Scsi_Host *host) 69{ 70 return "SCSI emulation for USB Mass Storage devices"; 71} 72 73/* detect a virtual adapter (always works) */ 74static int detect(struct SHT *sht) 75{ 76 struct us_data *us; 77 char local_name[32]; 78 /* Note: this function gets called with io_request_lock spinlock helt! */ 79 /* This is not nice at all, but how else are we to get the 80 * data here? */ 81 us = (struct us_data *)sht->proc_dir; 82 83 /* set up the name of our subdirectory under /proc/scsi/ */ 84 sprintf(local_name, "usb-storage-%d", us->host_number); 85 sht->proc_name = kmalloc (strlen(local_name) + 1, GFP_ATOMIC); 86 if (!sht->proc_name) 87 return 0; 88 strcpy(sht->proc_name, local_name); 89 90 /* we start with no /proc directory entry */ 91 sht->proc_dir = NULL; 92 93 /* register the host */ 94 us->host = scsi_register(sht, sizeof(us)); 95 if (us->host) { 96 us->host->hostdata[0] = (unsigned long)us; 97 us->host_no = us->host->host_no; 98 return 1; 99 } 100 101 /* odd... didn't register properly. Abort and free pointers */ 102 kfree(sht->proc_name); 103 sht->proc_name = NULL; 104 return 0; 105} 106 107/* Release all resources used by the virtual host 108 * 109 * NOTE: There is no contention here, because we're already deregistered 110 * the driver and we're doing each virtual host in turn, not in parallel 111 */ 112static int release(struct Scsi_Host *psh) 113{ 114 struct us_data *us = (struct us_data *)psh->hostdata[0]; 115 116 US_DEBUGP("release() called for host %s\n", us->htmplt.name); 117printk("release() called for host %s\n", us->htmplt.name); 118 119 /* Kill the control threads 120 * 121 * Enqueue the command, wake up the thread, and wait for 122 * notification that it's exited. 123 */ 124 US_DEBUGP("-- sending US_ACT_EXIT command to thread\n"); 125 us->action = US_ACT_EXIT; 126 127 up(&(us->sema)); 128 wait_for_completion(&(us->notify)); 129 130 /* remove the pointer to the data structure we were using */ 131 (struct us_data*)psh->hostdata[0] = NULL; 132 133 /* we always have a successful release */ 134 return 0; 135} 136 137/* run command */ 138static int command( Scsi_Cmnd *srb ) 139{ 140 US_DEBUGP("Bad use of us_command\n"); 141 142 return DID_BAD_TARGET << 16; 143} 144 145/* run command */ 146static int queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *)) 147{ 148 struct us_data *us = (struct us_data *)srb->host->hostdata[0]; 149 unsigned long flags; 150 151 US_DEBUGP("queuecommand() called\n"); 152 srb->host_scribble = (unsigned char *)us; 153 154 /* get exclusive access to the structures we want */ 155 spin_lock_irqsave(&(us->queue_exclusion), flags); 156 157 /* enqueue the command */ 158 us->queue_srb = srb; 159 srb->scsi_done = done; 160 us->action = US_ACT_COMMAND; 161 162 /* release the lock on the structure */ 163 spin_unlock_irqrestore(&(us->queue_exclusion), flags); 164 165 /* wake up the process task */ 166 up(&(us->sema)); 167 168 return 0; 169} 170 171/*********************************************************************** 172 * Error handling functions 173 ***********************************************************************/ 174 175/* Command abort */ 176static int command_abort( Scsi_Cmnd *srb ) 177{ 178 struct us_data *us = (struct us_data *)srb->host->hostdata[0]; 179 180 US_DEBUGP("command_abort() called\n"); 181 182 /* if we're stuck waiting for an IRQ, simulate it */ 183 if (atomic_read(us->ip_wanted)) { 184 US_DEBUGP("-- simulating missing IRQ\n"); 185 up(&(us->ip_waitq)); 186 } 187 188 /* if the device has been removed, this worked */ 189 if (!us->pusb_dev) { 190 US_DEBUGP("-- device removed already\n"); 191 return SUCCESS; 192 } 193 194 /* if we have an urb pending, let's wake the control thread up */ 195 if (!us->current_done.done) { 196 atomic_inc(&us->abortcnt); 197 spin_unlock_irq(&io_request_lock); 198 /* cancel the URB -- this will automatically wake the thread */ 199 usb_unlink_urb(us->current_urb); 200 201 /* wait for us to be done */ 202 wait_for_completion(&(us->notify)); 203 spin_lock_irq(&io_request_lock); 204 atomic_dec(&us->abortcnt); 205 return SUCCESS; 206 } 207 208 US_DEBUGP ("-- nothing to abort\n"); 209 return FAILED; 210} 211 212/* This invokes the transport reset mechanism to reset the state of the 213 * device */ 214static int device_reset( Scsi_Cmnd *srb ) 215{ 216 struct us_data *us = (struct us_data *)srb->host->hostdata[0]; 217 int rc; 218 219 US_DEBUGP("device_reset() called\n" ); 220 221 spin_unlock_irq(&io_request_lock); 222 rc = us->transport_reset(us); 223 spin_lock_irq(&io_request_lock); 224 return rc; 225} 226 227/* This resets the device port, and simulates the device 228 * disconnect/reconnect for all drivers which have claimed other 229 * interfaces. */ 230static int bus_reset( Scsi_Cmnd *srb ) 231{ 232 struct us_data *us = (struct us_data *)srb->host->hostdata[0]; 233 int i; 234 int result; 235 236 /* we use the usb_reset_device() function to handle this for us */ 237 US_DEBUGP("bus_reset() called\n"); 238 239 /* if the device has been removed, this worked */ 240 if (!us->pusb_dev) { 241 US_DEBUGP("-- device removed already\n"); 242 return SUCCESS; 243 } 244 245 spin_unlock_irq(&io_request_lock); 246 247 /* release the IRQ, if we have one */ 248 down(&(us->irq_urb_sem)); 249 if (us->irq_urb) { 250 US_DEBUGP("-- releasing irq URB\n"); 251 result = usb_unlink_urb(us->irq_urb); 252 US_DEBUGP("-- usb_unlink_urb() returned %d\n", result); 253 } 254 up(&(us->irq_urb_sem)); 255 256 /* attempt to reset the port */ 257 if (usb_reset_device(us->pusb_dev) < 0) { 258 spin_lock_irq(&io_request_lock); 259 return FAILED; 260 } 261 262 /* FIXME: This needs to lock out driver probing while it's working 263 * or we can have race conditions */ 264 for (i = 0; i < us->pusb_dev->actconfig->bNumInterfaces; i++) { 265 struct usb_interface *intf = 266 &us->pusb_dev->actconfig->interface[i]; 267 const struct usb_device_id *id; 268 269 /* if this is an unclaimed interface, skip it */ 270 if (!intf->driver) { 271 continue; 272 } 273 274 US_DEBUGP("Examinging driver %s...", intf->driver->name); 275 /* skip interfaces which we've claimed */ 276 if (intf->driver == &usb_storage_driver) { 277 US_DEBUGPX("skipping ourselves.\n"); 278 continue; 279 } 280 281 /* simulate a disconnect and reconnect for all interfaces */ 282 US_DEBUGPX("simulating disconnect/reconnect.\n"); 283 down(&intf->driver->serialize); 284 intf->driver->disconnect(us->pusb_dev, intf->private_data); 285 id = usb_match_id(us->pusb_dev, intf, intf->driver->id_table); 286 intf->driver->probe(us->pusb_dev, i, id); 287 up(&intf->driver->serialize); 288 } 289 290 /* re-allocate the IRQ URB and submit it to restore connectivity 291 * for CBI devices 292 */ 293 if (us->protocol == US_PR_CBI) { 294 down(&(us->irq_urb_sem)); 295 us->irq_urb->dev = us->pusb_dev; 296 result = usb_submit_urb(us->irq_urb); 297 US_DEBUGP("usb_submit_urb() returns %d\n", result); 298 up(&(us->irq_urb_sem)); 299 } 300 301 spin_lock_irq(&io_request_lock); 302 303 US_DEBUGP("bus_reset() complete\n"); 304 return SUCCESS; 305} 306 307/* FIXME: This doesn't do anything right now */ 308static int host_reset( Scsi_Cmnd *srb ) 309{ 310 printk(KERN_CRIT "usb-storage: host_reset() requested but not implemented\n" ); 311 return FAILED; 312} 313 314/*********************************************************************** 315 * /proc/scsi/ functions 316 ***********************************************************************/ 317 318/* we use this macro to help us write into the buffer */ 319#undef SPRINTF 320#define SPRINTF(args...) \ 321 do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0) 322 323static int proc_info (char *buffer, char **start, off_t offset, int length, 324 int hostno, int inout) 325{ 326 struct us_data *us; 327 char *pos = buffer; 328 329 /* if someone is sending us data, just throw it away */ 330 if (inout) 331 { 332 printk("Some one is sending us data\n"); 333 return length; 334 } 335 /* lock the data structures */ 336 down(&us_list_semaphore); 337 338 /* find our data from hostno */ 339 us = us_list; 340 while (us) { 341 if (us->host_no == hostno) 342 break; 343 us = us->next; 344 } 345 346 /* release our lock on the data structures */ 347 up(&us_list_semaphore); 348 349 /* if we couldn't find it, we return an error */ 350 if (!us) { 351 printk("Can not find it %x\n", hostno); 352 return -ESRCH; 353 } 354 355 /* print the controller name */ 356 SPRINTF(" Host scsi%d: usb-storage\n", hostno); 357 358 if(us->vendor) 359 /* print product, vendor, and serial number strings */ 360 SPRINTF(" Vendor: %s\n", us->vendor); 361 362 if(us->product) 363 SPRINTF(" Product: %s\n", us->product); 364 365 if(us->serial) 366 SPRINTF("Serial Number: %s\n", us->serial); 367 368 if(us->protocol_name) 369 /* show the protocol and transport */ 370 SPRINTF(" Protocol: %s\n", us->protocol_name); 371 372 if(us->transport_name) 373 SPRINTF(" Transport: %s\n", us->transport_name); 374 375 /* show the GUID of the device */ 376 SPRINTF(" GUID: " GUID_FORMAT "\n", GUID_ARGS(us->guid)); 377 378 if(us->pusb_dev) 379 SPRINTF(" Attached: %s\n", us->pusb_dev ? "Yes" : "No"); 380 381 if(us->pusb_dev && us->pusb_dev->devpath) 382 { 383 SPRINTF(" Port: %s\n", us->pusb_dev->devpath ); 384 385 if(us->pusb_dev && us->pusb_dev->devpath && us->pusb_dev->bus && us->pusb_dev->bus->bus_name) 386 SPRINTF(" Bus: %s-%s\n", us->pusb_dev->bus->bus_name, us->pusb_dev->devpath); 387 } 388 389 /* 390 * Calculate start of next buffer, and return value. 391 */ 392 *start = buffer + offset; 393 394 if ((pos - buffer) < offset) 395 { 396 return (0); 397 } 398 else if ((pos - buffer - offset) < length) 399 { 400 return (pos - buffer - offset); 401 } 402 else 403 { 404 return (length); 405 } 406} 407 408/* 409 * this defines our 'host' 410 */ 411 412Scsi_Host_Template usb_stor_host_template = { 413 name: "usb-storage", 414 proc_info: proc_info, 415 info: host_info, 416 417 detect: detect, 418 release: release, 419 command: command, 420 queuecommand: queuecommand, 421 422 eh_abort_handler: command_abort, 423 eh_device_reset_handler:device_reset, 424 eh_bus_reset_handler: bus_reset, 425 eh_host_reset_handler: host_reset, 426 427 can_queue: 1, 428 this_id: -1, 429 430 sg_tablesize: SG_ALL, 431 cmd_per_lun: 1, 432 present: 0, 433 unchecked_isa_dma: FALSE, 434 use_clustering: TRUE, 435 use_new_eh_code: TRUE, 436 emulated: TRUE 437}; 438 439unsigned char usb_stor_sense_notready[18] = { 440 [0] = 0x70, /* current error */ 441 [2] = 0x02, /* not ready */ 442 [5] = 0x0a, /* additional length */ 443 [10] = 0x04, /* not ready */ 444 [11] = 0x03 /* manual intervention */ 445}; 446 447#define USB_STOR_SCSI_SENSE_HDRSZ 4 448#define USB_STOR_SCSI_SENSE_10_HDRSZ 8 449 450struct usb_stor_scsi_sense_hdr 451{ 452 __u8* dataLength; 453 __u8* mediumType; 454 __u8* devSpecParms; 455 __u8* blkDescLength; 456}; 457 458typedef struct usb_stor_scsi_sense_hdr Usb_Stor_Scsi_Sense_Hdr; 459 460union usb_stor_scsi_sense_hdr_u 461{ 462 Usb_Stor_Scsi_Sense_Hdr hdr; 463 __u8* array[USB_STOR_SCSI_SENSE_HDRSZ]; 464}; 465 466typedef union usb_stor_scsi_sense_hdr_u Usb_Stor_Scsi_Sense_Hdr_u; 467 468struct usb_stor_scsi_sense_hdr_10 469{ 470 __u8* dataLengthMSB; 471 __u8* dataLengthLSB; 472 __u8* mediumType; 473 __u8* devSpecParms; 474 __u8* reserved1; 475 __u8* reserved2; 476 __u8* blkDescLengthMSB; 477 __u8* blkDescLengthLSB; 478}; 479 480typedef struct usb_stor_scsi_sense_hdr_10 Usb_Stor_Scsi_Sense_Hdr_10; 481 482union usb_stor_scsi_sense_hdr_10_u 483{ 484 Usb_Stor_Scsi_Sense_Hdr_10 hdr; 485 __u8* array[USB_STOR_SCSI_SENSE_10_HDRSZ]; 486}; 487 488typedef union usb_stor_scsi_sense_hdr_10_u Usb_Stor_Scsi_Sense_Hdr_10_u; 489 490void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* , Usb_Stor_Scsi_Sense_Hdr_u*, 491 Usb_Stor_Scsi_Sense_Hdr_10_u*, int* ); 492 493int usb_stor_scsiSense10to6( Scsi_Cmnd* the10 ) 494{ 495 __u8 *buffer=0; 496 int outputBufferSize = 0; 497 int length=0; 498 struct scatterlist *sg = 0; 499 int i=0, j=0, element=0; 500 Usb_Stor_Scsi_Sense_Hdr_u the6Locations; 501 Usb_Stor_Scsi_Sense_Hdr_10_u the10Locations; 502 int sb=0,si=0,db=0,di=0; 503 int sgLength=0; 504 505 US_DEBUGP("-- converting 10 byte sense data to 6 byte\n"); 506 the10->cmnd[0] = the10->cmnd[0] & 0xBF; 507 508 /* Determine buffer locations */ 509 usb_stor_scsiSenseParseBuffer( the10, &the6Locations, &the10Locations, 510 &length ); 511 512 /* Work out minimum buffer to output */ 513 outputBufferSize = *the10Locations.hdr.dataLengthLSB; 514 outputBufferSize += USB_STOR_SCSI_SENSE_HDRSZ; 515 516 /* Check to see if we need to trucate the output */ 517 if ( outputBufferSize > length ) 518 { 519 printk( KERN_WARNING USB_STORAGE 520 "Had to truncate MODE_SENSE_10 buffer into MODE_SENSE.\n" ); 521 printk( KERN_WARNING USB_STORAGE 522 "outputBufferSize is %d and length is %d.\n", 523 outputBufferSize, length ); 524 } 525 outputBufferSize = length; 526 527 /* Data length */ 528 if ( *the10Locations.hdr.dataLengthMSB != 0 ) /* MSB must be zero */ 529 { 530 printk( KERN_WARNING USB_STORAGE 531 "Command will be truncated to fit in SENSE6 buffer.\n" ); 532 *the6Locations.hdr.dataLength = 0xff; 533 } 534 else 535 { 536 *the6Locations.hdr.dataLength = *the10Locations.hdr.dataLengthLSB; 537 } 538 539 /* Medium type and DevSpecific parms */ 540 *the6Locations.hdr.mediumType = *the10Locations.hdr.mediumType; 541 *the6Locations.hdr.devSpecParms = *the10Locations.hdr.devSpecParms; 542 543 /* Block descriptor length */ 544 if ( *the10Locations.hdr.blkDescLengthMSB != 0 ) /* MSB must be zero */ 545 { 546 printk( KERN_WARNING USB_STORAGE 547 "Command will be truncated to fit in SENSE6 buffer.\n" ); 548 *the6Locations.hdr.blkDescLength = 0xff; 549 } 550 else 551 { 552 *the6Locations.hdr.blkDescLength = *the10Locations.hdr.blkDescLengthLSB; 553 } 554 555 if ( the10->use_sg == 0 ) 556 { 557 buffer = the10->request_buffer; 558 /* Copy the rest of the data */ 559 memmove( &(buffer[USB_STOR_SCSI_SENSE_HDRSZ]), 560 &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]), 561 outputBufferSize - USB_STOR_SCSI_SENSE_HDRSZ ); 562 /* initialise last bytes left in buffer due to smaller header */ 563 memset( &(buffer[outputBufferSize 564 -(USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ)]), 565 0, 566 USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ ); 567 } 568 else 569 { 570 sg = (struct scatterlist *) the10->request_buffer; 571 /* scan through this scatterlist and figure out starting positions */ 572 for ( i=0; i < the10->use_sg; i++) 573 { 574 sgLength = sg[i].length; 575 for ( j=0; j<sgLength; j++ ) 576 { 577 /* get to end of header */ 578 if ( element == USB_STOR_SCSI_SENSE_HDRSZ ) 579 { 580 db=i; 581 di=j; 582 } 583 if ( element == USB_STOR_SCSI_SENSE_10_HDRSZ ) 584 { 585 sb=i; 586 si=j; 587 /* we've found both sets now, exit loops */ 588 j=sgLength; 589 i=the10->use_sg; 590 } 591 element++; 592 } 593 } 594 595 /* Now we know where to start the copy from */ 596 element = USB_STOR_SCSI_SENSE_HDRSZ; 597 while ( element < outputBufferSize 598 -(USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ) ) 599 { 600 /* check limits */ 601 if ( sb >= the10->use_sg || 602 si >= sg[sb].length || 603 db >= the10->use_sg || 604 di >= sg[db].length ) 605 { 606 printk( KERN_ERR USB_STORAGE 607 "Buffer overrun averted, this shouldn't happen!\n" ); 608 break; 609 } 610 611 /* copy one byte */ 612 sg[db].address[di] = sg[sb].address[si]; 613 614 /* get next destination */ 615 if ( sg[db].length-1 == di ) 616 { 617 db++; 618 di=0; 619 } 620 else 621 { 622 di++; 623 } 624 625 /* get next source */ 626 if ( sg[sb].length-1 == si ) 627 { 628 sb++; 629 si=0; 630 } 631 else 632 { 633 si++; 634 } 635 636 element++; 637 } 638 /* zero the remaining bytes */ 639 while ( element < outputBufferSize ) 640 { 641 /* check limits */ 642 if ( db >= the10->use_sg || 643 di >= sg[db].length ) 644 { 645 printk( KERN_ERR USB_STORAGE 646 "Buffer overrun averted, this shouldn't happen!\n" ); 647 break; 648 } 649 650 sg[db].address[di] = 0; 651 652 /* get next destination */ 653 if ( sg[db].length-1 == di ) 654 { 655 db++; 656 di=0; 657 } 658 else 659 { 660 di++; 661 } 662 element++; 663 } 664 } 665 666 /* All done any everything was fine */ 667 return 0; 668} 669 670int usb_stor_scsiSense6to10( Scsi_Cmnd* the6 ) 671{ 672 /* will be used to store part of buffer */ 673 __u8 tempBuffer[USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ], 674 *buffer=0; 675 int outputBufferSize = 0; 676 int length=0; 677 struct scatterlist *sg = 0; 678 int i=0, j=0, element=0; 679 Usb_Stor_Scsi_Sense_Hdr_u the6Locations; 680 Usb_Stor_Scsi_Sense_Hdr_10_u the10Locations; 681 int sb=0,si=0,db=0,di=0; 682 int lsb=0,lsi=0,ldb=0,ldi=0; 683 684 US_DEBUGP("-- converting 6 byte sense data to 10 byte\n"); 685 the6->cmnd[0] = the6->cmnd[0] | 0x40; 686 687 /* Determine buffer locations */ 688 usb_stor_scsiSenseParseBuffer( the6, &the6Locations, &the10Locations, 689 &length ); 690 691 /* Work out minimum buffer to output */ 692 outputBufferSize = *the6Locations.hdr.dataLength; 693 outputBufferSize += USB_STOR_SCSI_SENSE_10_HDRSZ; 694 695 /* Check to see if we need to trucate the output */ 696 if ( outputBufferSize > length ) 697 { 698 printk( KERN_WARNING USB_STORAGE 699 "Had to truncate MODE_SENSE into MODE_SENSE_10 buffer.\n" ); 700 printk( KERN_WARNING USB_STORAGE 701 "outputBufferSize is %d and length is %d.\n", 702 outputBufferSize, length ); 703 } 704 outputBufferSize = length; 705 706 /* Block descriptor length - save these before overwriting */ 707 tempBuffer[2] = *the10Locations.hdr.blkDescLengthMSB; 708 tempBuffer[3] = *the10Locations.hdr.blkDescLengthLSB; 709 *the10Locations.hdr.blkDescLengthLSB = *the6Locations.hdr.blkDescLength; 710 *the10Locations.hdr.blkDescLengthMSB = 0; 711 712 /* reserved - save these before overwriting */ 713 tempBuffer[0] = *the10Locations.hdr.reserved1; 714 tempBuffer[1] = *the10Locations.hdr.reserved2; 715 *the10Locations.hdr.reserved1 = *the10Locations.hdr.reserved2 = 0; 716 717 /* Medium type and DevSpecific parms */ 718 *the10Locations.hdr.devSpecParms = *the6Locations.hdr.devSpecParms; 719 *the10Locations.hdr.mediumType = *the6Locations.hdr.mediumType; 720 721 /* Data length */ 722 *the10Locations.hdr.dataLengthLSB = *the6Locations.hdr.dataLength; 723 *the10Locations.hdr.dataLengthMSB = 0; 724 725 if ( !the6->use_sg ) 726 { 727 buffer = the6->request_buffer; 728 /* Copy the rest of the data */ 729 memmove( &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]), 730 &(buffer[USB_STOR_SCSI_SENSE_HDRSZ]), 731 outputBufferSize-USB_STOR_SCSI_SENSE_10_HDRSZ ); 732 /* Put the first four bytes (after header) in place */ 733 memcpy( &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]), 734 tempBuffer, 735 USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ ); 736 } 737 else 738 { 739 sg = (struct scatterlist *) the6->request_buffer; 740 /* scan through this scatterlist and figure out ending positions */ 741 for ( i=0; i < the6->use_sg; i++) 742 { 743 for ( j=0; j<sg[i].length; j++ ) 744 { 745 /* get to end of header */ 746 if ( element == USB_STOR_SCSI_SENSE_HDRSZ ) 747 { 748 ldb=i; 749 ldi=j; 750 } 751 if ( element == USB_STOR_SCSI_SENSE_10_HDRSZ ) 752 { 753 lsb=i; 754 lsi=j; 755 /* we've found both sets now, exit loops */ 756 j=sg[i].length; 757 i=the6->use_sg; 758 break; 759 } 760 element++; 761 } 762 } 763 /* scan through this scatterlist and figure out starting positions */ 764 element = length-1; 765 /* destination is the last element */ 766 db=the6->use_sg-1; 767 di=sg[db].length-1; 768 for ( i=the6->use_sg-1; i >= 0; i--) 769 { 770 for ( j=sg[i].length-1; j>=0; j-- ) 771 { 772 /* get to end of header and find source for copy */ 773 if ( element == length - 1 774 - (USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ) ) 775 { 776 sb=i; 777 si=j; 778 /* we've found both sets now, exit loops */ 779 j=-1; 780 i=-1; 781 } 782 element--; 783 } 784 } 785 /* Now we know where to start the copy from */ 786 element = length-1 787 - (USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ); 788 while ( element >= USB_STOR_SCSI_SENSE_10_HDRSZ ) 789 { 790 /* check limits */ 791 if ( ( sb <= lsb && si < lsi ) || 792 ( db <= ldb && di < ldi ) ) 793 { 794 printk( KERN_ERR USB_STORAGE 795 "Buffer overrun averted, this shouldn't happen!\n" ); 796 break; 797 } 798 799 /* copy one byte */ 800 sg[db].address[di] = sg[sb].address[si]; 801 802 /* get next destination */ 803 if ( di == 0 ) 804 { 805 db--; 806 di=sg[db].length-1; 807 } 808 else 809 { 810 di--; 811 } 812 813 /* get next source */ 814 if ( si == 0 ) 815 { 816 sb--; 817 si=sg[sb].length-1; 818 } 819 else 820 { 821 si--; 822 } 823 824 element--; 825 } 826 /* copy the remaining four bytes */ 827 while ( element >= USB_STOR_SCSI_SENSE_HDRSZ ) 828 { 829 /* check limits */ 830 if ( db <= ldb && di < ldi ) 831 { 832 printk( KERN_ERR USB_STORAGE 833 "Buffer overrun averted, this shouldn't happen!\n" ); 834 break; 835 } 836 837 sg[db].address[di] = tempBuffer[element-USB_STOR_SCSI_SENSE_HDRSZ]; 838 839 /* get next destination */ 840 if ( di == 0 ) 841 { 842 db--; 843 di=sg[db].length-1; 844 } 845 else 846 { 847 di--; 848 } 849 element--; 850 } 851 } 852 853 /* All done and everything was fine */ 854 return 0; 855} 856 857void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* srb, Usb_Stor_Scsi_Sense_Hdr_u* the6, 858 Usb_Stor_Scsi_Sense_Hdr_10_u* the10, 859 int* length_p ) 860 861{ 862 int i = 0, j=0, element=0; 863 struct scatterlist *sg = 0; 864 int length = 0; 865 __u8* buffer=0; 866 867 /* are we scatter-gathering? */ 868 if ( srb->use_sg != 0 ) 869 { 870 /* loop over all the scatter gather structures and 871 * get pointer to the data members in the headers 872 * (also work out the length while we're here) 873 */ 874 sg = (struct scatterlist *) srb->request_buffer; 875 for (i = 0; i < srb->use_sg; i++) 876 { 877 length += sg[i].length; 878 /* We only do the inner loop for the headers */ 879 if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ ) 880 { 881 /* scan through this scatterlist */ 882 for ( j=0; j<sg[i].length; j++ ) 883 { 884 if ( element < USB_STOR_SCSI_SENSE_HDRSZ ) 885 { 886 /* fill in the pointers for both header types */ 887 the6->array[element] = &(sg[i].address[j]); 888 the10->array[element] = &(sg[i].address[j]); 889 } 890 else if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ ) 891 { 892 /* only the longer headers still cares now */ 893 the10->array[element] = &(sg[i].address[j]); 894 } 895 /* increase element counter */ 896 element++; 897 } 898 } 899 } 900 } 901 else 902 { 903 length = srb->request_bufflen; 904 buffer = srb->request_buffer; 905 if ( length < USB_STOR_SCSI_SENSE_10_HDRSZ ) 906 printk( KERN_ERR USB_STORAGE 907 "Buffer length smaller than header!!" ); 908 for( i=0; i<USB_STOR_SCSI_SENSE_10_HDRSZ; i++ ) 909 { 910 if ( i < USB_STOR_SCSI_SENSE_HDRSZ ) 911 { 912 the6->array[i] = &(buffer[i]); 913 the10->array[i] = &(buffer[i]); 914 } 915 else 916 { 917 the10->array[i] = &(buffer[i]); 918 } 919 } 920 } 921 922 /* Set value of length passed in */ 923 *length_p = length; 924} 925 926