|
|
1.1 ! root 1: /* ! 2: * Copyright (C) 2006 Michael Brown <[email protected]>. ! 3: * ! 4: * This program is free software; you can redistribute it and/or ! 5: * modify it under the terms of the GNU General Public License as ! 6: * published by the Free Software Foundation; either version 2 of the ! 7: * License, or any later version. ! 8: * ! 9: * This program is distributed in the hope that it will be useful, but ! 10: * WITHOUT ANY WARRANTY; without even the implied warranty of ! 11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 12: * General Public License for more details. ! 13: * ! 14: * You should have received a copy of the GNU General Public License ! 15: * along with this program; if not, write to the Free Software ! 16: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ! 17: */ ! 18: ! 19: FILE_LICENCE ( GPL2_OR_LATER ); ! 20: ! 21: #include <stddef.h> ! 22: #include <stdlib.h> ! 23: #include <string.h> ! 24: #include <byteswap.h> ! 25: #include <errno.h> ! 26: #include <ipxe/list.h> ! 27: #include <ipxe/process.h> ! 28: #include <ipxe/xfer.h> ! 29: #include <ipxe/blockdev.h> ! 30: #include <ipxe/scsi.h> ! 31: ! 32: /** @file ! 33: * ! 34: * SCSI block device ! 35: * ! 36: */ ! 37: ! 38: /** Maximum number of command retries */ ! 39: #define SCSICMD_MAX_RETRIES 10 ! 40: ! 41: /* Error numbers generated by SCSI sense data */ ! 42: #define EIO_NO_SENSE __einfo_error ( EINFO_EIO_NO_SENSE ) ! 43: #define EINFO_EIO_NO_SENSE \ ! 44: __einfo_uniqify ( EINFO_EIO, 0x00, "No sense" ) ! 45: #define EIO_RECOVERED_ERROR __einfo_error ( EINFO_EIO_RECOVERED_ERROR ) ! 46: #define EINFO_EIO_RECOVERED_ERROR \ ! 47: __einfo_uniqify ( EINFO_EIO, 0x01, "Recovered error" ) ! 48: #define EIO_NOT_READY __einfo_error ( EINFO_EIO_NOT_READY ) ! 49: #define EINFO_EIO_NOT_READY \ ! 50: __einfo_uniqify ( EINFO_EIO, 0x02, "Not ready" ) ! 51: #define EIO_MEDIUM_ERROR __einfo_error ( EINFO_EIO_MEDIUM_ERROR ) ! 52: #define EINFO_EIO_MEDIUM_ERROR \ ! 53: __einfo_uniqify ( EINFO_EIO, 0x03, "Medium error" ) ! 54: #define EIO_HARDWARE_ERROR __einfo_error ( EINFO_EIO_HARDWARE_ERROR ) ! 55: #define EINFO_EIO_HARDWARE_ERROR \ ! 56: __einfo_uniqify ( EINFO_EIO, 0x04, "Hardware error" ) ! 57: #define EIO_ILLEGAL_REQUEST __einfo_error ( EINFO_EIO_ILLEGAL_REQUEST ) ! 58: #define EINFO_EIO_ILLEGAL_REQUEST \ ! 59: __einfo_uniqify ( EINFO_EIO, 0x05, "Illegal request" ) ! 60: #define EIO_UNIT_ATTENTION __einfo_error ( EINFO_EIO_UNIT_ATTENTION ) ! 61: #define EINFO_EIO_UNIT_ATTENTION \ ! 62: __einfo_uniqify ( EINFO_EIO, 0x06, "Unit attention" ) ! 63: #define EIO_DATA_PROTECT __einfo_error ( EINFO_EIO_DATA_PROTECT ) ! 64: #define EINFO_EIO_DATA_PROTECT \ ! 65: __einfo_uniqify ( EINFO_EIO, 0x07, "Data protect" ) ! 66: #define EIO_BLANK_CHECK __einfo_error ( EINFO_EIO_BLANK_CHECK ) ! 67: #define EINFO_EIO_BLANK_CHECK \ ! 68: __einfo_uniqify ( EINFO_EIO, 0x08, "Blank check" ) ! 69: #define EIO_VENDOR_SPECIFIC __einfo_error ( EINFO_EIO_VENDOR_SPECIFIC ) ! 70: #define EINFO_EIO_VENDOR_SPECIFIC \ ! 71: __einfo_uniqify ( EINFO_EIO, 0x09, "Vendor specific" ) ! 72: #define EIO_COPY_ABORTED __einfo_error ( EINFO_EIO_COPY_ABORTED ) ! 73: #define EINFO_EIO_COPY_ABORTED \ ! 74: __einfo_uniqify ( EINFO_EIO, 0x0a, "Copy aborted" ) ! 75: #define EIO_ABORTED_COMMAND __einfo_error ( EINFO_EIO_ABORTED_COMMAND ) ! 76: #define EINFO_EIO_ABORTED_COMMAND \ ! 77: __einfo_uniqify ( EINFO_EIO, 0x0b, "Aborted command" ) ! 78: #define EIO_RESERVED __einfo_error ( EINFO_EIO_RESERVED ) ! 79: #define EINFO_EIO_RESERVED \ ! 80: __einfo_uniqify ( EINFO_EIO, 0x0c, "Reserved" ) ! 81: #define EIO_VOLUME_OVERFLOW __einfo_error ( EINFO_EIO_VOLUME_OVERFLOW ) ! 82: #define EINFO_EIO_VOLUME_OVERFLOW \ ! 83: __einfo_uniqify ( EINFO_EIO, 0x0d, "Volume overflow" ) ! 84: #define EIO_MISCOMPARE __einfo_error ( EINFO_EIO_MISCOMPARE ) ! 85: #define EINFO_EIO_MISCOMPARE \ ! 86: __einfo_uniqify ( EINFO_EIO, 0x0e, "Miscompare" ) ! 87: #define EIO_COMPLETED __einfo_error ( EINFO_EIO_COMPLETED ) ! 88: #define EINFO_EIO_COMPLETED \ ! 89: __einfo_uniqify ( EINFO_EIO, 0x0f, "Completed" ) ! 90: #define EIO_SENSE( key ) \ ! 91: EUNIQ ( EIO, (key), EIO_NO_SENSE, EIO_RECOVERED_ERROR, \ ! 92: EIO_NOT_READY, EIO_MEDIUM_ERROR, EIO_HARDWARE_ERROR, \ ! 93: EIO_ILLEGAL_REQUEST, EIO_UNIT_ATTENTION, \ ! 94: EIO_DATA_PROTECT, EIO_BLANK_CHECK, EIO_VENDOR_SPECIFIC, \ ! 95: EIO_COPY_ABORTED, EIO_ABORTED_COMMAND, EIO_RESERVED, \ ! 96: EIO_VOLUME_OVERFLOW, EIO_MISCOMPARE, EIO_COMPLETED ) ! 97: ! 98: /****************************************************************************** ! 99: * ! 100: * Utility functions ! 101: * ! 102: ****************************************************************************** ! 103: */ ! 104: ! 105: /** ! 106: * Parse SCSI LUN ! 107: * ! 108: * @v lun_string LUN string representation ! 109: * @v lun LUN to fill in ! 110: * @ret rc Return status code ! 111: */ ! 112: int scsi_parse_lun ( const char *lun_string, struct scsi_lun *lun ) { ! 113: char *p; ! 114: int i; ! 115: ! 116: memset ( lun, 0, sizeof ( *lun ) ); ! 117: if ( lun_string ) { ! 118: p = ( char * ) lun_string; ! 119: for ( i = 0 ; i < 4 ; i++ ) { ! 120: lun->u16[i] = htons ( strtoul ( p, &p, 16 ) ); ! 121: if ( *p == '\0' ) ! 122: break; ! 123: if ( *p != '-' ) ! 124: return -EINVAL; ! 125: p++; ! 126: } ! 127: if ( *p ) ! 128: return -EINVAL; ! 129: } ! 130: ! 131: return 0; ! 132: } ! 133: ! 134: /****************************************************************************** ! 135: * ! 136: * Interface methods ! 137: * ! 138: ****************************************************************************** ! 139: */ ! 140: ! 141: /** ! 142: * Issue SCSI command ! 143: * ! 144: * @v control SCSI control interface ! 145: * @v data SCSI data interface ! 146: * @v command SCSI command ! 147: * @ret tag Command tag, or negative error ! 148: */ ! 149: int scsi_command ( struct interface *control, struct interface *data, ! 150: struct scsi_cmd *command ) { ! 151: struct interface *dest; ! 152: scsi_command_TYPE ( void * ) *op = ! 153: intf_get_dest_op ( control, scsi_command, &dest ); ! 154: void *object = intf_object ( dest ); ! 155: int tap; ! 156: ! 157: if ( op ) { ! 158: tap = op ( object, data, command ); ! 159: } else { ! 160: /* Default is to fail to issue the command */ ! 161: tap = -EOPNOTSUPP; ! 162: } ! 163: ! 164: intf_put ( dest ); ! 165: return tap; ! 166: } ! 167: ! 168: /** ! 169: * Report SCSI response ! 170: * ! 171: * @v interface SCSI command interface ! 172: * @v response SCSI response ! 173: */ ! 174: void scsi_response ( struct interface *intf, struct scsi_rsp *response ) { ! 175: struct interface *dest; ! 176: scsi_response_TYPE ( void * ) *op = ! 177: intf_get_dest_op ( intf, scsi_response, &dest ); ! 178: void *object = intf_object ( dest ); ! 179: ! 180: if ( op ) { ! 181: op ( object, response ); ! 182: } else { ! 183: /* Default is to ignore the response */ ! 184: } ! 185: ! 186: intf_put ( dest ); ! 187: } ! 188: ! 189: /****************************************************************************** ! 190: * ! 191: * SCSI devices and commands ! 192: * ! 193: ****************************************************************************** ! 194: */ ! 195: ! 196: /** A SCSI device */ ! 197: struct scsi_device { ! 198: /** Reference count */ ! 199: struct refcnt refcnt; ! 200: /** Block control interface */ ! 201: struct interface block; ! 202: /** SCSI control interface */ ! 203: struct interface scsi; ! 204: ! 205: /** SCSI LUN */ ! 206: struct scsi_lun lun; ! 207: /** Flags */ ! 208: unsigned int flags; ! 209: ! 210: /** TEST UNIT READY interface */ ! 211: struct interface ready; ! 212: /** TEST UNIT READY process */ ! 213: struct process process; ! 214: ! 215: /** List of commands */ ! 216: struct list_head cmds; ! 217: }; ! 218: ! 219: /** SCSI device flags */ ! 220: enum scsi_device_flags { ! 221: /** Unit is ready */ ! 222: SCSIDEV_UNIT_READY = 0x0001, ! 223: }; ! 224: ! 225: /** A SCSI command */ ! 226: struct scsi_command { ! 227: /** Reference count */ ! 228: struct refcnt refcnt; ! 229: /** SCSI device */ ! 230: struct scsi_device *scsidev; ! 231: /** List of SCSI commands */ ! 232: struct list_head list; ! 233: ! 234: /** Block data interface */ ! 235: struct interface block; ! 236: /** SCSI data interface */ ! 237: struct interface scsi; ! 238: ! 239: /** Command type */ ! 240: struct scsi_command_type *type; ! 241: /** Starting logical block address */ ! 242: uint64_t lba; ! 243: /** Number of blocks */ ! 244: unsigned int count; ! 245: /** Data buffer */ ! 246: userptr_t buffer; ! 247: /** Length of data buffer */ ! 248: size_t len; ! 249: /** Command tag */ ! 250: uint32_t tag; ! 251: ! 252: /** Retry count */ ! 253: unsigned int retries; ! 254: ! 255: /** Private data */ ! 256: uint8_t priv[0]; ! 257: }; ! 258: ! 259: /** A SCSI command type */ ! 260: struct scsi_command_type { ! 261: /** Name */ ! 262: const char *name; ! 263: /** Additional working space */ ! 264: size_t priv_len; ! 265: /** ! 266: * Construct SCSI command IU ! 267: * ! 268: * @v scsicmd SCSI command ! 269: * @v command SCSI command IU ! 270: */ ! 271: void ( * cmd ) ( struct scsi_command *scsicmd, ! 272: struct scsi_cmd *command ); ! 273: /** ! 274: * Handle SCSI command completion ! 275: * ! 276: * @v scsicmd SCSI command ! 277: * @v rc Reason for completion ! 278: */ ! 279: void ( * done ) ( struct scsi_command *scsicmd, int rc ); ! 280: }; ! 281: ! 282: /** ! 283: * Get reference to SCSI device ! 284: * ! 285: * @v scsidev SCSI device ! 286: * @ret scsidev SCSI device ! 287: */ ! 288: static inline __attribute__ (( always_inline )) struct scsi_device * ! 289: scsidev_get ( struct scsi_device *scsidev ) { ! 290: ref_get ( &scsidev->refcnt ); ! 291: return scsidev; ! 292: } ! 293: ! 294: /** ! 295: * Drop reference to SCSI device ! 296: * ! 297: * @v scsidev SCSI device ! 298: */ ! 299: static inline __attribute__ (( always_inline )) void ! 300: scsidev_put ( struct scsi_device *scsidev ) { ! 301: ref_put ( &scsidev->refcnt ); ! 302: } ! 303: ! 304: /** ! 305: * Get reference to SCSI command ! 306: * ! 307: * @v scsicmd SCSI command ! 308: * @ret scsicmd SCSI command ! 309: */ ! 310: static inline __attribute__ (( always_inline )) struct scsi_command * ! 311: scsicmd_get ( struct scsi_command *scsicmd ) { ! 312: ref_get ( &scsicmd->refcnt ); ! 313: return scsicmd; ! 314: } ! 315: ! 316: /** ! 317: * Drop reference to SCSI command ! 318: * ! 319: * @v scsicmd SCSI command ! 320: */ ! 321: static inline __attribute__ (( always_inline )) void ! 322: scsicmd_put ( struct scsi_command *scsicmd ) { ! 323: ref_put ( &scsicmd->refcnt ); ! 324: } ! 325: ! 326: /** ! 327: * Get SCSI command private data ! 328: * ! 329: * @v scsicmd SCSI command ! 330: * @ret priv Private data ! 331: */ ! 332: static inline __attribute__ (( always_inline )) void * ! 333: scsicmd_priv ( struct scsi_command *scsicmd ) { ! 334: return scsicmd->priv; ! 335: } ! 336: ! 337: /** ! 338: * Free SCSI command ! 339: * ! 340: * @v refcnt Reference count ! 341: */ ! 342: static void scsicmd_free ( struct refcnt *refcnt ) { ! 343: struct scsi_command *scsicmd = ! 344: container_of ( refcnt, struct scsi_command, refcnt ); ! 345: ! 346: /* Remove from list of commands */ ! 347: list_del ( &scsicmd->list ); ! 348: scsidev_put ( scsicmd->scsidev ); ! 349: ! 350: /* Free command */ ! 351: free ( scsicmd ); ! 352: } ! 353: ! 354: /** ! 355: * Close SCSI command ! 356: * ! 357: * @v scsicmd SCSI command ! 358: * @v rc Reason for close ! 359: */ ! 360: static void scsicmd_close ( struct scsi_command *scsicmd, int rc ) { ! 361: struct scsi_device *scsidev = scsicmd->scsidev; ! 362: ! 363: if ( rc != 0 ) { ! 364: DBGC ( scsidev, "SCSI %p tag %08x closed: %s\n", ! 365: scsidev, scsicmd->tag, strerror ( rc ) ); ! 366: } ! 367: ! 368: /* Shut down interfaces */ ! 369: intf_shutdown ( &scsicmd->scsi, rc ); ! 370: intf_shutdown ( &scsicmd->block, rc ); ! 371: } ! 372: ! 373: /** ! 374: * Construct and issue SCSI command ! 375: * ! 376: * @ret rc Return status code ! 377: */ ! 378: static int scsicmd_command ( struct scsi_command *scsicmd ) { ! 379: struct scsi_device *scsidev = scsicmd->scsidev; ! 380: struct scsi_cmd command; ! 381: int tag; ! 382: int rc; ! 383: ! 384: /* Construct command */ ! 385: memset ( &command, 0, sizeof ( command ) ); ! 386: memcpy ( &command.lun, &scsidev->lun, sizeof ( command.lun ) ); ! 387: scsicmd->type->cmd ( scsicmd, &command ); ! 388: ! 389: /* Issue command */ ! 390: if ( ( tag = scsi_command ( &scsidev->scsi, &scsicmd->scsi, ! 391: &command ) ) < 0 ) { ! 392: rc = tag; ! 393: DBGC ( scsidev, "SCSI %p could not issue command: %s\n", ! 394: scsidev, strerror ( rc ) ); ! 395: return rc; ! 396: } ! 397: ! 398: /* Record tag */ ! 399: if ( scsicmd->tag ) { ! 400: DBGC ( scsidev, "SCSI %p tag %08x is now tag %08x\n", ! 401: scsidev, scsicmd->tag, tag ); ! 402: } ! 403: scsicmd->tag = tag; ! 404: DBGC2 ( scsidev, "SCSI %p tag %08x %s " SCSI_CDB_FORMAT "\n", ! 405: scsidev, scsicmd->tag, scsicmd->type->name, ! 406: SCSI_CDB_DATA ( command.cdb ) ); ! 407: ! 408: return 0; ! 409: } ! 410: ! 411: /** ! 412: * Handle SCSI command completion ! 413: * ! 414: * @v scsicmd SCSI command ! 415: * @v rc Reason for close ! 416: */ ! 417: static void scsicmd_done ( struct scsi_command *scsicmd, int rc ) { ! 418: struct scsi_device *scsidev = scsicmd->scsidev; ! 419: ! 420: /* Restart SCSI interface */ ! 421: intf_restart ( &scsicmd->scsi, rc ); ! 422: ! 423: /* SCSI targets have an annoying habit of returning occasional ! 424: * pointless "error" messages such as "power-on occurred", so ! 425: * we have to be prepared to retry commands. ! 426: */ ! 427: if ( ( rc != 0 ) && ( scsicmd->retries++ < SCSICMD_MAX_RETRIES ) ) { ! 428: /* Retry command */ ! 429: DBGC ( scsidev, "SCSI %p tag %08x failed: %s\n", ! 430: scsidev, scsicmd->tag, strerror ( rc ) ); ! 431: DBGC ( scsidev, "SCSI %p tag %08x retrying (retry %d)\n", ! 432: scsidev, scsicmd->tag, scsicmd->retries ); ! 433: if ( ( rc = scsicmd_command ( scsicmd ) ) == 0 ) ! 434: return; ! 435: } ! 436: ! 437: /* If we didn't (successfully) reissue the command, hand over ! 438: * to the command completion handler. ! 439: */ ! 440: scsicmd->type->done ( scsicmd, rc ); ! 441: } ! 442: ! 443: /** ! 444: * Handle SCSI response ! 445: * ! 446: * @v scsicmd SCSI command ! 447: * @v response SCSI response ! 448: */ ! 449: static void scsicmd_response ( struct scsi_command *scsicmd, ! 450: struct scsi_rsp *response ) { ! 451: struct scsi_device *scsidev = scsicmd->scsidev; ! 452: size_t overrun; ! 453: size_t underrun; ! 454: int rc; ! 455: ! 456: if ( response->status == 0 ) { ! 457: scsicmd_done ( scsicmd, 0 ); ! 458: } else { ! 459: DBGC ( scsidev, "SCSI %p tag %08x status %02x", ! 460: scsidev, scsicmd->tag, response->status ); ! 461: if ( response->overrun > 0 ) { ! 462: overrun = response->overrun; ! 463: DBGC ( scsidev, " overrun +%zd", overrun ); ! 464: } else if ( response->overrun < 0 ) { ! 465: underrun = -(response->overrun); ! 466: DBGC ( scsidev, " underrun -%zd", underrun ); ! 467: } ! 468: DBGC ( scsidev, " sense %02x:%02x:%08x\n", ! 469: response->sense.code, response->sense.key, ! 470: ntohl ( response->sense.info ) ); ! 471: ! 472: /* Construct error number from sense data */ ! 473: rc = -EIO_SENSE ( response->sense.key & SCSI_SENSE_KEY_MASK ); ! 474: scsicmd_done ( scsicmd, rc ); ! 475: } ! 476: } ! 477: ! 478: /** ! 479: * Construct SCSI READ command ! 480: * ! 481: * @v scsicmd SCSI command ! 482: * @v command SCSI command IU ! 483: */ ! 484: static void scsicmd_read_cmd ( struct scsi_command *scsicmd, ! 485: struct scsi_cmd *command ) { ! 486: ! 487: if ( ( scsicmd->lba + scsicmd->count ) > SCSI_MAX_BLOCK_10 ) { ! 488: /* Use READ (16) */ ! 489: command->cdb.read16.opcode = SCSI_OPCODE_READ_16; ! 490: command->cdb.read16.lba = cpu_to_be64 ( scsicmd->lba ); ! 491: command->cdb.read16.len = cpu_to_be32 ( scsicmd->count ); ! 492: } else { ! 493: /* Use READ (10) */ ! 494: command->cdb.read10.opcode = SCSI_OPCODE_READ_10; ! 495: command->cdb.read10.lba = cpu_to_be32 ( scsicmd->lba ); ! 496: command->cdb.read10.len = cpu_to_be16 ( scsicmd->count ); ! 497: } ! 498: command->data_in = scsicmd->buffer; ! 499: command->data_in_len = scsicmd->len; ! 500: } ! 501: ! 502: /** SCSI READ command type */ ! 503: static struct scsi_command_type scsicmd_read = { ! 504: .name = "READ", ! 505: .cmd = scsicmd_read_cmd, ! 506: .done = scsicmd_close, ! 507: }; ! 508: ! 509: /** ! 510: * Construct SCSI WRITE command ! 511: * ! 512: * @v scsicmd SCSI command ! 513: * @v command SCSI command IU ! 514: */ ! 515: static void scsicmd_write_cmd ( struct scsi_command *scsicmd, ! 516: struct scsi_cmd *command ) { ! 517: ! 518: if ( ( scsicmd->lba + scsicmd->count ) > SCSI_MAX_BLOCK_10 ) { ! 519: /* Use WRITE (16) */ ! 520: command->cdb.write16.opcode = SCSI_OPCODE_WRITE_16; ! 521: command->cdb.write16.lba = cpu_to_be64 ( scsicmd->lba ); ! 522: command->cdb.write16.len = cpu_to_be32 ( scsicmd->count ); ! 523: } else { ! 524: /* Use WRITE (10) */ ! 525: command->cdb.write10.opcode = SCSI_OPCODE_WRITE_10; ! 526: command->cdb.write10.lba = cpu_to_be32 ( scsicmd->lba ); ! 527: command->cdb.write10.len = cpu_to_be16 ( scsicmd->count ); ! 528: } ! 529: command->data_out = scsicmd->buffer; ! 530: command->data_out_len = scsicmd->len; ! 531: } ! 532: ! 533: /** SCSI WRITE command type */ ! 534: static struct scsi_command_type scsicmd_write = { ! 535: .name = "WRITE", ! 536: .cmd = scsicmd_write_cmd, ! 537: .done = scsicmd_close, ! 538: }; ! 539: ! 540: /** SCSI READ CAPACITY private data */ ! 541: struct scsi_read_capacity_private { ! 542: /** Use READ CAPACITY (16) */ ! 543: int use16; ! 544: /** Data buffer for READ CAPACITY commands */ ! 545: union { ! 546: /** Data buffer for READ CAPACITY (10) */ ! 547: struct scsi_capacity_10 capacity10; ! 548: /** Data buffer for READ CAPACITY (16) */ ! 549: struct scsi_capacity_16 capacity16; ! 550: } capacity; ! 551: }; ! 552: ! 553: /** ! 554: * Construct SCSI READ CAPACITY command ! 555: * ! 556: * @v scsicmd SCSI command ! 557: * @v command SCSI command IU ! 558: */ ! 559: static void scsicmd_read_capacity_cmd ( struct scsi_command *scsicmd, ! 560: struct scsi_cmd *command ) { ! 561: struct scsi_read_capacity_private *priv = scsicmd_priv ( scsicmd ); ! 562: struct scsi_cdb_read_capacity_16 *readcap16 = &command->cdb.readcap16; ! 563: struct scsi_cdb_read_capacity_10 *readcap10 = &command->cdb.readcap10; ! 564: struct scsi_capacity_16 *capacity16 = &priv->capacity.capacity16; ! 565: struct scsi_capacity_10 *capacity10 = &priv->capacity.capacity10; ! 566: ! 567: if ( priv->use16 ) { ! 568: /* Use READ CAPACITY (16) */ ! 569: readcap16->opcode = SCSI_OPCODE_SERVICE_ACTION_IN; ! 570: readcap16->service_action = ! 571: SCSI_SERVICE_ACTION_READ_CAPACITY_16; ! 572: readcap16->len = cpu_to_be32 ( sizeof ( *capacity16 ) ); ! 573: command->data_in = virt_to_user ( capacity16 ); ! 574: command->data_in_len = sizeof ( *capacity16 ); ! 575: } else { ! 576: /* Use READ CAPACITY (10) */ ! 577: readcap10->opcode = SCSI_OPCODE_READ_CAPACITY_10; ! 578: command->data_in = virt_to_user ( capacity10 ); ! 579: command->data_in_len = sizeof ( *capacity10 ); ! 580: } ! 581: } ! 582: ! 583: /** ! 584: * Handle SCSI READ CAPACITY command completion ! 585: * ! 586: * @v scsicmd SCSI command ! 587: * @v rc Reason for completion ! 588: */ ! 589: static void scsicmd_read_capacity_done ( struct scsi_command *scsicmd, ! 590: int rc ) { ! 591: struct scsi_read_capacity_private *priv = scsicmd_priv ( scsicmd ); ! 592: struct scsi_capacity_16 *capacity16 = &priv->capacity.capacity16; ! 593: struct scsi_capacity_10 *capacity10 = &priv->capacity.capacity10; ! 594: struct block_device_capacity capacity; ! 595: ! 596: /* Close if command failed */ ! 597: if ( rc != 0 ) { ! 598: scsicmd_close ( scsicmd, rc ); ! 599: return; ! 600: } ! 601: ! 602: /* Extract capacity */ ! 603: if ( priv->use16 ) { ! 604: capacity.blocks = ( be64_to_cpu ( capacity16->lba ) + 1 ); ! 605: capacity.blksize = be32_to_cpu ( capacity16->blksize ); ! 606: } else { ! 607: capacity.blocks = ( be32_to_cpu ( capacity10->lba ) + 1 ); ! 608: capacity.blksize = be32_to_cpu ( capacity10->blksize ); ! 609: ! 610: /* If capacity range was exceeded (i.e. capacity.lba ! 611: * was 0xffffffff, meaning that blockdev->blocks is ! 612: * now zero), use READ CAPACITY (16) instead. READ ! 613: * CAPACITY (16) is not mandatory, so we can't just ! 614: * use it straight off. ! 615: */ ! 616: if ( capacity.blocks == 0 ) { ! 617: priv->use16 = 1; ! 618: if ( ( rc = scsicmd_command ( scsicmd ) ) != 0 ) { ! 619: scsicmd_close ( scsicmd, rc ); ! 620: return; ! 621: } ! 622: return; ! 623: } ! 624: } ! 625: capacity.max_count = -1U; ! 626: ! 627: /* Return capacity to caller */ ! 628: block_capacity ( &scsicmd->block, &capacity ); ! 629: ! 630: /* Close command */ ! 631: scsicmd_close ( scsicmd, 0 ); ! 632: } ! 633: ! 634: /** SCSI READ CAPACITY command type */ ! 635: static struct scsi_command_type scsicmd_read_capacity = { ! 636: .name = "READ CAPACITY", ! 637: .priv_len = sizeof ( struct scsi_read_capacity_private ), ! 638: .cmd = scsicmd_read_capacity_cmd, ! 639: .done = scsicmd_read_capacity_done, ! 640: }; ! 641: ! 642: /** ! 643: * Construct SCSI TEST UNIT READY command ! 644: * ! 645: * @v scsicmd SCSI command ! 646: * @v command SCSI command IU ! 647: */ ! 648: static void scsicmd_test_unit_ready_cmd ( struct scsi_command *scsicmd __unused, ! 649: struct scsi_cmd *command ) { ! 650: struct scsi_cdb_test_unit_ready *testready = &command->cdb.testready; ! 651: ! 652: testready->opcode = SCSI_OPCODE_TEST_UNIT_READY; ! 653: } ! 654: ! 655: /** SCSI TEST UNIT READY command type */ ! 656: static struct scsi_command_type scsicmd_test_unit_ready = { ! 657: .name = "TEST UNIT READY", ! 658: .cmd = scsicmd_test_unit_ready_cmd, ! 659: .done = scsicmd_close, ! 660: }; ! 661: ! 662: /** SCSI command block interface operations */ ! 663: static struct interface_operation scsicmd_block_op[] = { ! 664: INTF_OP ( intf_close, struct scsi_command *, scsicmd_close ), ! 665: }; ! 666: ! 667: /** SCSI command block interface descriptor */ ! 668: static struct interface_descriptor scsicmd_block_desc = ! 669: INTF_DESC_PASSTHRU ( struct scsi_command, block, ! 670: scsicmd_block_op, scsi ); ! 671: ! 672: /** SCSI command SCSI interface operations */ ! 673: static struct interface_operation scsicmd_scsi_op[] = { ! 674: INTF_OP ( intf_close, struct scsi_command *, scsicmd_done ), ! 675: INTF_OP ( scsi_response, struct scsi_command *, scsicmd_response ), ! 676: }; ! 677: ! 678: /** SCSI command SCSI interface descriptor */ ! 679: static struct interface_descriptor scsicmd_scsi_desc = ! 680: INTF_DESC_PASSTHRU ( struct scsi_command, scsi, ! 681: scsicmd_scsi_op, block ); ! 682: ! 683: /** ! 684: * Create SCSI command ! 685: * ! 686: * @v scsidev SCSI device ! 687: * @v block Block data interface ! 688: * @v type SCSI command type ! 689: * @v lba Starting logical block address ! 690: * @v count Number of blocks to transfer ! 691: * @v buffer Data buffer ! 692: * @v len Length of data buffer ! 693: * @ret rc Return status code ! 694: */ ! 695: static int scsidev_command ( struct scsi_device *scsidev, ! 696: struct interface *block, ! 697: struct scsi_command_type *type, ! 698: uint64_t lba, unsigned int count, ! 699: userptr_t buffer, size_t len ) { ! 700: struct scsi_command *scsicmd; ! 701: int rc; ! 702: ! 703: /* Allocate and initialise structure */ ! 704: scsicmd = zalloc ( sizeof ( *scsicmd ) + type->priv_len ); ! 705: if ( ! scsicmd ) { ! 706: rc = -ENOMEM; ! 707: goto err_zalloc; ! 708: } ! 709: ref_init ( &scsicmd->refcnt, scsicmd_free ); ! 710: intf_init ( &scsicmd->block, &scsicmd_block_desc, &scsicmd->refcnt ); ! 711: intf_init ( &scsicmd->scsi, &scsicmd_scsi_desc, ! 712: &scsicmd->refcnt ); ! 713: scsicmd->scsidev = scsidev_get ( scsidev ); ! 714: list_add ( &scsicmd->list, &scsidev->cmds ); ! 715: scsicmd->type = type; ! 716: scsicmd->lba = lba; ! 717: scsicmd->count = count; ! 718: scsicmd->buffer = buffer; ! 719: scsicmd->len = len; ! 720: ! 721: /* Issue SCSI command */ ! 722: if ( ( rc = scsicmd_command ( scsicmd ) ) != 0 ) ! 723: goto err_command; ! 724: ! 725: /* Attach to parent interface, mortalise self, and return */ ! 726: intf_plug_plug ( &scsicmd->block, block ); ! 727: ref_put ( &scsicmd->refcnt ); ! 728: return 0; ! 729: ! 730: err_command: ! 731: scsicmd_close ( scsicmd, rc ); ! 732: ref_put ( &scsicmd->refcnt ); ! 733: err_zalloc: ! 734: return rc; ! 735: } ! 736: ! 737: /** ! 738: * Issue SCSI block read ! 739: * ! 740: * @v scsidev SCSI device ! 741: * @v block Block data interface ! 742: * @v lba Starting logical block address ! 743: * @v count Number of blocks to transfer ! 744: * @v buffer Data buffer ! 745: * @v len Length of data buffer ! 746: * @ret rc Return status code ! 747: ! 748: */ ! 749: static int scsidev_read ( struct scsi_device *scsidev, ! 750: struct interface *block, ! 751: uint64_t lba, unsigned int count, ! 752: userptr_t buffer, size_t len ) { ! 753: return scsidev_command ( scsidev, block, &scsicmd_read, ! 754: lba, count, buffer, len ); ! 755: } ! 756: ! 757: /** ! 758: * Issue SCSI block write ! 759: * ! 760: * @v scsidev SCSI device ! 761: * @v block Block data interface ! 762: * @v lba Starting logical block address ! 763: * @v count Number of blocks to transfer ! 764: * @v buffer Data buffer ! 765: * @v len Length of data buffer ! 766: * @ret rc Return status code ! 767: */ ! 768: static int scsidev_write ( struct scsi_device *scsidev, ! 769: struct interface *block, ! 770: uint64_t lba, unsigned int count, ! 771: userptr_t buffer, size_t len ) { ! 772: return scsidev_command ( scsidev, block, &scsicmd_write, ! 773: lba, count, buffer, len ); ! 774: } ! 775: ! 776: /** ! 777: * Read SCSI device capacity ! 778: * ! 779: * @v scsidev SCSI device ! 780: * @v block Block data interface ! 781: * @ret rc Return status code ! 782: */ ! 783: static int scsidev_read_capacity ( struct scsi_device *scsidev, ! 784: struct interface *block ) { ! 785: return scsidev_command ( scsidev, block, &scsicmd_read_capacity, ! 786: 0, 0, UNULL, 0 ); ! 787: } ! 788: ! 789: /** ! 790: * Test to see if SCSI device is ready ! 791: * ! 792: * @v scsidev SCSI device ! 793: * @v block Block data interface ! 794: * @ret rc Return status code ! 795: */ ! 796: static int scsidev_test_unit_ready ( struct scsi_device *scsidev, ! 797: struct interface *block ) { ! 798: return scsidev_command ( scsidev, block, &scsicmd_test_unit_ready, ! 799: 0, 0, UNULL, 0 ); ! 800: } ! 801: ! 802: /** ! 803: * Check SCSI device flow-control window ! 804: * ! 805: * @v scsidev SCSI device ! 806: * @ret len Length of window ! 807: */ ! 808: static size_t scsidev_window ( struct scsi_device *scsidev ) { ! 809: ! 810: /* Refuse commands until unit is confirmed ready */ ! 811: if ( ! ( scsidev->flags & SCSIDEV_UNIT_READY ) ) ! 812: return 0; ! 813: ! 814: return xfer_window ( &scsidev->scsi ); ! 815: } ! 816: ! 817: /** ! 818: * Close SCSI device ! 819: * ! 820: * @v scsidev SCSI device ! 821: * @v rc Reason for close ! 822: */ ! 823: static void scsidev_close ( struct scsi_device *scsidev, int rc ) { ! 824: struct scsi_command *scsicmd; ! 825: struct scsi_command *tmp; ! 826: ! 827: /* Stop process */ ! 828: process_del ( &scsidev->process ); ! 829: ! 830: /* Shut down interfaces */ ! 831: intf_shutdown ( &scsidev->block, rc ); ! 832: intf_shutdown ( &scsidev->scsi, rc ); ! 833: intf_shutdown ( &scsidev->ready, rc ); ! 834: ! 835: /* Shut down any remaining commands */ ! 836: list_for_each_entry_safe ( scsicmd, tmp, &scsidev->cmds, list ) { ! 837: scsicmd_get ( scsicmd ); ! 838: scsicmd_close ( scsicmd, rc ); ! 839: scsicmd_put ( scsicmd ); ! 840: } ! 841: } ! 842: ! 843: /** SCSI device block interface operations */ ! 844: static struct interface_operation scsidev_block_op[] = { ! 845: INTF_OP ( xfer_window, struct scsi_device *, scsidev_window ), ! 846: INTF_OP ( block_read, struct scsi_device *, scsidev_read ), ! 847: INTF_OP ( block_write, struct scsi_device *, scsidev_write ), ! 848: INTF_OP ( block_read_capacity, struct scsi_device *, ! 849: scsidev_read_capacity ), ! 850: INTF_OP ( intf_close, struct scsi_device *, scsidev_close ), ! 851: }; ! 852: ! 853: /** SCSI device block interface descriptor */ ! 854: static struct interface_descriptor scsidev_block_desc = ! 855: INTF_DESC_PASSTHRU ( struct scsi_device, block, ! 856: scsidev_block_op, scsi ); ! 857: ! 858: /** ! 859: * Handle SCSI TEST UNIT READY response ! 860: * ! 861: * @v scsidev SCSI device ! 862: * @v rc Reason for close ! 863: */ ! 864: static void scsidev_ready ( struct scsi_device *scsidev, int rc ) { ! 865: ! 866: /* Shut down interface */ ! 867: intf_shutdown ( &scsidev->ready, rc ); ! 868: ! 869: /* Close device on failure */ ! 870: if ( rc != 0 ) { ! 871: DBGC ( scsidev, "SCSI %p not ready: %s\n", ! 872: scsidev, strerror ( rc ) ); ! 873: scsidev_close ( scsidev, rc ); ! 874: return; ! 875: } ! 876: ! 877: /* Mark device as ready */ ! 878: scsidev->flags |= SCSIDEV_UNIT_READY; ! 879: xfer_window_changed ( &scsidev->block ); ! 880: DBGC ( scsidev, "SCSI %p unit is ready\n", scsidev ); ! 881: } ! 882: ! 883: /** SCSI device TEST UNIT READY interface operations */ ! 884: static struct interface_operation scsidev_ready_op[] = { ! 885: INTF_OP ( intf_close, struct scsi_device *, scsidev_ready ), ! 886: }; ! 887: ! 888: /** SCSI device TEST UNIT READY interface descriptor */ ! 889: static struct interface_descriptor scsidev_ready_desc = ! 890: INTF_DESC ( struct scsi_device, ready, scsidev_ready_op ); ! 891: ! 892: /** ! 893: * SCSI TEST UNIT READY process ! 894: * ! 895: * @v process Process ! 896: */ ! 897: static void scsidev_step ( struct process *process ) { ! 898: struct scsi_device *scsidev = ! 899: container_of ( process, struct scsi_device, process ); ! 900: int rc; ! 901: ! 902: /* Wait until underlying SCSI device is ready */ ! 903: if ( xfer_window ( &scsidev->scsi ) == 0 ) ! 904: return; ! 905: ! 906: /* Stop process */ ! 907: process_del ( &scsidev->process ); ! 908: ! 909: DBGC ( scsidev, "SCSI %p waiting for unit to become ready\n", ! 910: scsidev ); ! 911: ! 912: /* Issue TEST UNIT READY command */ ! 913: if ( ( rc = scsidev_test_unit_ready ( scsidev, &scsidev->ready )) !=0){ ! 914: scsidev_close ( scsidev, rc ); ! 915: return; ! 916: } ! 917: } ! 918: ! 919: /** SCSI device SCSI interface operations */ ! 920: static struct interface_operation scsidev_scsi_op[] = { ! 921: INTF_OP ( intf_close, struct scsi_device *, scsidev_close ), ! 922: }; ! 923: ! 924: /** SCSI device SCSI interface descriptor */ ! 925: static struct interface_descriptor scsidev_scsi_desc = ! 926: INTF_DESC_PASSTHRU ( struct scsi_device, scsi, ! 927: scsidev_scsi_op, block ); ! 928: ! 929: /** ! 930: * Open SCSI device ! 931: * ! 932: * @v block Block control interface ! 933: * @v scsi SCSI control interface ! 934: * @v lun SCSI LUN ! 935: * @ret rc Return status code ! 936: */ ! 937: int scsi_open ( struct interface *block, struct interface *scsi, ! 938: struct scsi_lun *lun ) { ! 939: struct scsi_device *scsidev; ! 940: ! 941: /* Allocate and initialise structure */ ! 942: scsidev = zalloc ( sizeof ( *scsidev ) ); ! 943: if ( ! scsidev ) ! 944: return -ENOMEM; ! 945: ref_init ( &scsidev->refcnt, NULL ); ! 946: intf_init ( &scsidev->block, &scsidev_block_desc, &scsidev->refcnt ); ! 947: intf_init ( &scsidev->scsi, &scsidev_scsi_desc, &scsidev->refcnt ); ! 948: intf_init ( &scsidev->ready, &scsidev_ready_desc, &scsidev->refcnt ); ! 949: process_init ( &scsidev->process, scsidev_step, &scsidev->refcnt ); ! 950: INIT_LIST_HEAD ( &scsidev->cmds ); ! 951: memcpy ( &scsidev->lun, lun, sizeof ( scsidev->lun ) ); ! 952: DBGC ( scsidev, "SCSI %p created for LUN " SCSI_LUN_FORMAT "\n", ! 953: scsidev, SCSI_LUN_DATA ( scsidev->lun ) ); ! 954: ! 955: /* Attach to SCSI and parent interfaces, mortalise self, and return */ ! 956: intf_plug_plug ( &scsidev->scsi, scsi ); ! 957: intf_plug_plug ( &scsidev->block, block ); ! 958: ref_put ( &scsidev->refcnt ); ! 959: return 0; ! 960: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.