|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ============================================================================= ! 23: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 24: * ! 25: * IOBasicSCSI.h ! 26: * ! 27: * This class implements generic SCSI functionality. ! 28: */ ! 29: ! 30: #ifndef _IOBASICSCSI_H ! 31: #define _IOBASICSCSI_H ! 32: ! 33: #include <IOKit/IOTypes.h> ! 34: #include <IOKit/IOService.h> ! 35: #include <IOKit/IOSyncer.h> ! 36: #include <IOKit/scsi/IOSCSIDeviceInterface.h> ! 37: #include <IOKit/storage/IOHDTypes.h> ! 38: ! 39: const int kMinInqSize = 5; /* minimal, supported by all devs */ ! 40: const int kReadCapSize = 8; ! 41: const int kModeSenseSize = 64; ! 42: const int kMaxInqSize = 256; ! 43: ! 44: const int kCheckCondition = 0x02; ! 45: const int kUnitAttention = 0x06; ! 46: ! 47: /* SCSI operation codes: */ ! 48: ! 49: const UInt8 SOP_TUR = 0x00; /* test unit ready */ ! 50: const UInt8 SOP_INQUIRY = 0x12; /* inquiry */ ! 51: const UInt8 SOP_MODESELECT = 0x15; /* mode select */ ! 52: const UInt8 SOP_MODESENSE = 0x1a; /* mode sense */ ! 53: const UInt8 SOP_READCAP = 0x25; /* read capacity */ ! 54: const UInt8 SOP_READ10 = 0x28; /* read (10-byte) */ ! 55: const UInt8 SOP_WRITE10 = 0x2a; /* write (10-byte) */ ! 56: ! 57: struct IOTURcdb { ! 58: UInt8 opcode; ! 59: UInt8 lunbits; ! 60: UInt8 reserved1; ! 61: UInt8 reserved2; ! 62: UInt8 reserved3; ! 63: UInt8 ctlbyte; ! 64: }; ! 65: ! 66: struct IORWcdb { /* CDB for read and write */ ! 67: UInt8 opcode; /* read=0x28, write=0x2a */ ! 68: UInt8 lunbits; /* lun and control bits */ ! 69: UInt8 lba_3; /* logical block address: msb */ ! 70: UInt8 lba_2; ! 71: UInt8 lba_1; ! 72: UInt8 lba_0; /* logical block address: lsb */ ! 73: UInt8 reserved; ! 74: UInt8 count_msb; /* block count: msb */ ! 75: UInt8 count_lsb; /* block count: lsb */ ! 76: UInt8 ctlbyte; ! 77: }; ! 78: ! 79: struct IOInquirycdb { /* inquiry */ ! 80: UInt8 opcode; /* 0x12 */ ! 81: UInt8 lunbits; /* lun and control bits */ ! 82: UInt8 pagecode; /* page code/op code */ ! 83: UInt8 reserved; ! 84: UInt8 len; /* allocation length */ ! 85: UInt8 ctlbyte; ! 86: }; ! 87: ! 88: struct IOReadCapcdb { ! 89: UInt8 opcode; ! 90: UInt8 lunbits; ! 91: UInt8 lba_3; ! 92: UInt8 lba_2; ! 93: UInt8 lba_1; ! 94: UInt8 lba_0; ! 95: UInt8 reserved1; ! 96: UInt8 reserved2; ! 97: UInt8 reserved3; ! 98: UInt8 ctlbyte; ! 99: }; ! 100: ! 101: struct IOModeSensecdb { ! 102: UInt8 opcode; ! 103: UInt8 lunbits; /* lun and control bits */ ! 104: UInt8 pagecode; ! 105: UInt8 reserved; ! 106: UInt8 len; /* allocation length */ ! 107: UInt8 ctlbyte; ! 108: }; ! 109: ! 110: struct IOModeSelectcdb { ! 111: UInt8 opcode; ! 112: UInt8 lunbits; ! 113: UInt8 reserved1; ! 114: UInt8 reserved2; ! 115: UInt8 paramlen; ! 116: UInt8 ctlbyte; ! 117: }; ! 118: ! 119: /*! ! 120: * @enum stateValues ! 121: * @discussion ! 122: * These state values are used to determin the state of an IO operation. ! 123: * Some are simply for debugging use. ! 124: * @constant kNone ! 125: * Nothing happening. ! 126: * @constant kAsyncReadWrite ! 127: * Doing an asynchronous IO operation. ! 128: * @constant kSimpleSynchIO ! 129: * Doing a simple synchronous IO operation. ! 130: * @constant kHandlingUnitAttention ! 131: * Currently handling a Unit-Attention condition. ! 132: * @constant kDoneHandlingUnitAttention ! 133: * Done handling Unit Attention; command should be reissued. ! 134: * @constant kAwaitingPower ! 135: * Awaiting power. ! 136: * @constant kMaxValidState ! 137: * The maximum valid state value. ! 138: * @constant kMaxStateValue ! 139: * The maximum state value possible. ! 140: */ ! 141: enum stateValues { ! 142: kNone = 0, ! 143: kAsyncReadWrite = 1, ! 144: kSimpleSynchIO = 2, ! 145: kHandlingUnitAttention = 3, ! 146: kDoneHandlingUnitAttention = 4, ! 147: kAwaitingPower = 5, ! 148: ! 149: kMaxValidState = kAwaitingPower, ! 150: ! 151: kMaxStateValue = 255 ! 152: }; ! 153: /*! ! 154: * @typedef statevalue ! 155: * @discussion ! 156: * Shorthand for enum StateValues. ! 157: */ ! 158: typedef enum stateValues stateValue; ! 159: ! 160: const bool kSync = true; /* type info for requests awaiting power */ ! 161: const bool kAsync = false; ! 162: ! 163: /*! ! 164: * @class ! 165: * IOBasicSCSI : public IOService ! 166: * @abstract ! 167: * Basic SCSI support functions. ! 168: * @discussion ! 169: * IOBasicSCSI provides a set of basic SCSI functions and support ! 170: * utilities. It is intended to be the base class for a SCSI Transport ! 171: * Driver. ! 172: */ ! 173: ! 174: class IOBasicSCSI : public IOService { ! 175: ! 176: OSDeclareAbstractStructors(IOBasicSCSI) ! 177: ! 178: public: ! 179: ! 180: /*! ! 181: * @struct completion ! 182: * @field action ! 183: * The C function called upon completion of the operation. ! 184: * @field target ! 185: * The C++ class pointer, passed to tha action function. ! 186: * @field param ! 187: * A value passed to the action function. This value is not touched. ! 188: */ ! 189: /*! ! 190: * @struct context ! 191: * @discussion ! 192: * The context structure contains all persistent information needed for a ! 193: * synchronous or asynchronous IO operation. ! 194: * @field completion ! 195: * The completion information for an asynchronous read or write operation. ! 196: * @field state ! 197: * The current state of the operation. ! 198: * @field step ! 199: * The current step value, if we are handling a Unit Attention. ! 200: * @field originalContext ! 201: * A pointer to the context for the command that caused the Unit Attention ! 202: * condition. ! 203: * @field scsireq ! 204: * A pointer to the IOSCSIRequest object. ! 205: * @field memory ! 206: * The data buffer for the operation. A pointer to an IOMemoryDescriptor. ! 207: * @field scsiresult ! 208: * A pointer to the IOSCSIResult object. ! 209: * @field desiredPower ! 210: * The desired power level for the operation to execute. ! 211: * @field isSync ! 212: * True if synchronous; False if asynchronous. ! 213: * @field next ! 214: * A pointer to a context structure, used as a queue forward-link. ! 215: * @field sync ! 216: * A syncer used to block a thread awaiting a power level, or for completion ! 217: * of a synchronous operation. ! 218: */ ! 219: struct context { ! 220: ! 221: /* Completion information for our client, used only for async operations. ! 222: * Typically this information will only be used by subclasses. ! 223: */ ! 224: ! 225: struct { ! 226: gdCompletionFunction action; /* function to call */ ! 227: IOService *target; /* client object ("this") */ ! 228: void *param; /* client's parameter */ ! 229: } completion; ! 230: ! 231: /* Parameters used during an IO retry: */ ! 232: ! 233: stateValue state; /* what state we're in */ ! 234: UInt32 step; ! 235: struct context *originalIOContext; /* original SCSI IO if doing a retry */ ! 236: ! 237: IOMemoryDescriptor *memory; ! 238: ! 239: UInt32 desiredPower; /* desired power level state */ ! 240: bool isSync; /* true if sync, false if async */ ! 241: struct context *next; /* for queue of requests pending power */ ! 242: /* Parameters to hand off to the SCSI provider: */ ! 243: ! 244: IOSCSICommand *scsireq; ! 245: SCSISenseData *senseData; ! 246: IOMemoryDescriptor *senseDataDesc; ! 247: ! 248: IOSyncer *sync; /* to wait for completion */ ! 249: }; ! 250: ! 251: /* Overrides from IOService: */ ! 252: ! 253: virtual void free(void); ! 254: ! 255: virtual bool init(OSDictionary * properties); ! 256: ! 257: /*! ! 258: * @function probe ! 259: * @abstract ! 260: * Determine if device matches expected type. ! 261: * @discussion ! 262: * This method is responsible for matching the device type. It calls ! 263: * doInquiry to issue a SCSI Inquiry command to the device, then calls ! 264: * deviceTypeMatches to ensure that the device type matches the expected ! 265: * type. If the device type matches, then the Vendor, Product, and ! 266: * Revision strings are copied from the inquiry data, and "this" is ! 267: * returned. If the device type does not match, NULL is returned. ! 268: * ! 269: * The default implementation ignores the score parameter, though that ! 270: * parameter is passed to the superclass probe method. ! 271: */ ! 272: virtual IOService * probe(IOService * provider,SInt32 * score); ! 273: ! 274: /* --- end of IOService overrides --- */ ! 275: ! 276: /*! ! 277: * @function deviceTypeMatches ! 278: * @abstract ! 279: * Determine if device type matches expected type. ! 280: * @discussion ! 281: * This method must be implemented by a device-specific subclass. ! 282: * @param inqBuf ! 283: * A pointer to the SCSI inquiry data for the device. ! 284: * @param inqLen ! 285: * The size of the data in the inquiry buffer. ! 286: * @result ! 287: * True indicates a match; False indicates a failure. ! 288: */ ! 289: virtual bool deviceTypeMatches(UInt8 inqBuf[],UInt32 inqLen) = 0; ! 290: ! 291: /*! ! 292: * @function executeCdb ! 293: * Issue the client's cdb as a pass-through. ! 294: * @discussion This method is provided to allow developers to issue arbitrary commands ! 295: * to the device (via the Transport Driver). Expected uses might include vendor-specific ! 296: * commands to support device-based password-protection, or for other vendor features. ! 297: * ! 298: * This method may not be supported by all Transport Drivers. For example, ATA devices ! 299: * do not have a CDB concept; those Transport Drivers will return kIOReturnUnsupported. ! 300: * @param params ! 301: * See IOHDTypes.h for the layout of this data structure. ! 302: */ ! 303: virtual IOReturn executeCdb(struct cdbParams *params); ! 304: ! 305: /*! ! 306: * @function getAdditionalDeviceInfoString ! 307: * @abstract ! 308: * Return additional informational string for the device. ! 309: * @result ! 310: * A pointer to a static character string. The default implementation ! 311: * returns "[SCSI]" . ! 312: */ ! 313: virtual char * getAdditionalDeviceInfoString(void); ! 314: ! 315: /*! ! 316: * @function getVendorString ! 317: * @abstract ! 318: * Return Vendor Name string ! 319: * @result ! 320: * A pointer to a static character string, copied from the inquiry data. ! 321: */ ! 322: virtual char * getVendorString(void); ! 323: ! 324: /*! ! 325: * @function getProductString ! 326: * @abstract ! 327: * Return Product Name string for the device. ! 328: * @result ! 329: A pointer to a static character string, copied from the inquiry data. ! 330: */ ! 331: virtual char * getProductString(void); ! 332: ! 333: /*! ! 334: * @function getRevisionString ! 335: * @abstract ! 336: * Return Product Revision string for the device. ! 337: * @result ! 338: * A pointer to a static character string, copied from the inquiry data. ! 339: */ ! 340: virtual char * getRevisionString(void); ! 341: ! 342: /*! ! 343: * @function reportBlockSize ! 344: * @abstract ! 345: * Report the block size for the device, in bytes. ! 346: * @discussion ! 347: * This method returns the block size for the media. The default ! 348: * implementation obtains the block size from the SCSI Read Capacity ! 349: * command. Since the result of the Read Capacity is used by this ! 350: * method and reportMaxValidBlock, this method either returns a cached ! 351: * value or calls doReadCapacity to issue the command and cache both ! 352: * values. ! 353: * @param blockSize ! 354: * Pointer to returned block size value. ! 355: */ ! 356: virtual IOReturn reportBlockSize(UInt64 *blockSize); ! 357: ! 358: /*! ! 359: * @function reportEjectability ! 360: * @abstract ! 361: * Report if the media is ejectable under software control. ! 362: * @discussion ! 363: * This method reports whether the media is ejectable under software ! 364: * control. The default implementation always reports that removable ! 365: * media is ejectable. ! 366: * ! 367: * This method should only be called if the media is known to be removable. ! 368: * @param isEjectable ! 369: * Pointer to returned result. True indicates the media is ejectable, False indicates ! 370: * the media cannot be ejected under software control. ! 371: */ ! 372: virtual IOReturn reportEjectability(bool *isEjectable); ! 373: ! 374: /*! ! 375: * @function reportLockability ! 376: * @abstract ! 377: * Report if the media is lockable under software control. ! 378: * @discussion ! 379: * This method reports whether the media can be locked under software ! 380: * control, to prevent the user from removing the media manually, e.g. ! 381: * by pressing a button on the drive. This method is only called by ! 382: * the generic driver when the media is known to be removable. The ! 383: * default implementation always returns true. ! 384: * ! 385: * This method should only be called if the media is known to be removable. ! 386: * @param isLockable ! 387: * Pointer to returned result. True indicates the media can be locked in place; False ! 388: * indicates the media cannot be locked by software. ! 389: */ ! 390: virtual IOReturn reportLockability(bool *isLockable); ! 391: ! 392: /*! ! 393: * @function reportMaxReadTransfer ! 394: * @abstract ! 395: * Report the maximum allowed byte transfer for read operations. ! 396: * @discussion ! 397: * Some devices impose a maximum data transfer size. Because this limit ! 398: * may be determined by the size of a block-count field in a command, the limit may ! 399: * depend on the block size of the transfer. ! 400: * The default implementation reports blocksize * 65536, which is the maximum ! 401: * number of bytes that can be transferred ! 402: * in a SCSI command with a standard 16-bit block count field. ! 403: * @param blockSize ! 404: * The block size desired for the transfer. ! 405: * @param max ! 406: * Pointer to returned result. ! 407: */ ! 408: virtual IOReturn reportMaxReadTransfer (UInt64 blocksize,UInt64 *max); ! 409: ! 410: /*! ! 411: * @function reportMaxValidBlock ! 412: * @abstract ! 413: * Report the highest valid block for the device. ! 414: * @discussion ! 415: * This method reports the maximum allowable block number. The default ! 416: * implementation obtains the block number from the SCSI Read Capacity ! 417: * command. Since the result of the Read Capacity is used by this ! 418: * method and reportBlockSize, this method either returns a cached ! 419: * value or calls doReadCapacity to issue the command and cache both ! 420: * values. ! 421: * @param maxBlock ! 422: * Pointer to returned result ! 423: */ ! 424: virtual IOReturn reportMaxValidBlock(UInt64 *maxBlock); ! 425: ! 426: /*! ! 427: * @function reportMaxWriteTransfer ! 428: * @abstract ! 429: * Report the maximum allowed byte transfer for write operations. ! 430: * @discussion ! 431: * Some devices impose a maximum data transfer size. Because this limit ! 432: * may be determined by the size of a block-count field in a command, the limit may ! 433: * depend on the block size of the transfer. ! 434: * The default implementation reports blocksize * 65536, which is the maximum ! 435: * number of bytes that can be transferred ! 436: * in a SCSI command with a standard 16-bit block count field. ! 437: * @param blockSize ! 438: * The block size desired for the transfer. ! 439: * @param max ! 440: * Pointer to returned result. ! 441: */ ! 442: virtual IOReturn reportMaxWriteTransfer(UInt64 blocksize,UInt64 *max); ! 443: ! 444: /*! ! 445: * @function reportPollRequirements ! 446: * @abstract ! 447: * Report if it's necessary to poll for media insertion, and if polling is expensive. ! 448: * @discussion ! 449: * This method reports whether the device must be polled to detect media ! 450: * insertion, and whether a poll is expensive to perform. ! 451: * ! 452: * The term "expensive" typically implies a device that must be spun-up to detect media, ! 453: * as on a PC floppy. Most devices can detect media inexpensively. ! 454: * ! 455: * The default implementation of this method always reports an ! 456: * inexpensive poll (pollIsExpensive = false), and that all removable ! 457: * media must be polled. ! 458: * @param pollRequired ! 459: * Pointer to returned result. True indicates that polling is required; False indicates ! 460: * that polling is not required to detect media. ! 461: * @param pollIsExpensive ! 462: * Pointer to returned result. True indicates that the polling operation is expensive; ! 463: * False indicates that the polling operation is cheap. ! 464: */ ! 465: virtual IOReturn reportPollRequirements(bool *pollRequired,bool *pollIsExpensive); ! 466: ! 467: /*! ! 468: * @function reportRemovability ! 469: * @abstract ! 470: * Report whether the media is removable or not. ! 471: * @discussion ! 472: * This method reports whether the media is removable, but it does not ! 473: * provide detailed information regarding software eject or lock/unlock capability. ! 474: * ! 475: * The default implementation of this method examines the cached ! 476: * Inquiry data to determine if media is removable. If the RMB bit ! 477: * (0x80 of Inquiry data byte 1) is set, the media is removable. If ! 478: * there is no Inquiry data, the media is reported to be nonremovable. ! 479: * ! 480: * This method also sets the instance variable _removable. ! 481: * @param isRemovable ! 482: * Pointer to returned result. True indicates that the media is removable; False ! 483: * indicates the media is not removable. ! 484: */ ! 485: virtual IOReturn reportRemovability(bool *isRemovable); ! 486: ! 487: /*! ! 488: * @function reportWriteProtection ! 489: * @abstract ! 490: * Report whether the media is write-protected or not. ! 491: * @discussion ! 492: * The default implementation of this method issues a SCSI Mode Sense ! 493: * command to test the WP bit( 0x80 of byte 2 of the Mode Sense Header ! 494: * data). A request is made for Mode Sense Page 1, though any valid ! 495: * page will return a header. If the bit is set, the media is considered ! 496: * write-protected. ! 497: * @param isWriteProtected ! 498: * Pointer to returned result. True indicates that the media is write-protected (it ! 499: * cannot be written); False indicates that the media is not write-protected (it ! 500: * is permissible to write). ! 501: */ ! 502: virtual IOReturn reportWriteProtection(bool *isWriteProtected); ! 503: ! 504: protected: ! 505: ! 506: /*! ! 507: * @function createReadCdb ! 508: * @abstract ! 509: * Create a SCSI CDB for a read operation. ! 510: * @discussion ! 511: * Override this to control the cdb created for a read operation. ! 512: * The default implementation creates a 10-byte read command with ! 513: * disconnect allowed, 8-byte autosense, and a 2-second timeout. ! 514: * @param cdb ! 515: * A pointer to the CDB bytes. ! 516: * @param cdbLength ! 517: * The length of the CDB in bytes. ! 518: * @param block ! 519: * The device block to be read. ! 520: * @param nblks ! 521: * The number of blocks to be transferred. ! 522: * @param maxAutoSenseLength ! 523: * The maximum size of the autosense data, in bytes. A value of zero ! 524: * will disable autosense. ! 525: * @param timeoutSeconds ! 526: * The command timeout in seconds. ! 527: * @result ! 528: * The IOSCSICommandOptions returned will be used to issue the command. ! 529: */ ! 530: virtual UInt32 createReadCdb( ! 531: UInt8 *cdb, /* in */ ! 532: UInt32 *cdbLength, /* out */ ! 533: UInt32 block, /* in */ ! 534: UInt32 nblks, /* in */ ! 535: UInt32 *maxAutoSenseLength, /* out */ ! 536: UInt32 *timeoutSeconds); /* out */ ! 537: ! 538: /*! ! 539: * @function createWriteCdb ! 540: * @abstract ! 541: * Create a SCSI CDB for a write operation. ! 542: * @discussion ! 543: * Override this to control the cdb created for a write operation. ! 544: * The default implementation creates a 10-byte write command with ! 545: * disconnect allowed, 8-byte autosense, and a 2-second timeout. ! 546: * @param cdb ! 547: * A pointer to the CDB bytes. ! 548: * @param cdbLength ! 549: * The length of the CDB in bytes. ! 550: * @param block ! 551: * The device block to be written. ! 552: * @param nblks ! 553: * The number of blocks to be transferred. ! 554: * @param maxAutoSenseLength ! 555: * The maximum size of the autosense data, in bytes. A value of zero ! 556: * will disable autosense. ! 557: * @param timeoutSeconds ! 558: * The command timeout in seconds. ! 559: * @result ! 560: * The IOSCSICommandOptions returned will be used to issue the command. ! 561: */ ! 562: virtual UInt32 createWriteCdb( ! 563: UInt8 *cdb, /* in */ ! 564: UInt32 *cdbLength, /* out */ ! 565: UInt32 block, /* in */ ! 566: UInt32 nblks, /* in */ ! 567: UInt32 *maxAutoSenseLength, /* out */ ! 568: UInt32 *timeoutSeconds); /* out */ ! 569: ! 570: ! 571: /*! ! 572: * @function doInquiry ! 573: * @abstract ! 574: * Obtain SCSI Inquiry data from the device. ! 575: * @discussion ! 576: * This method issues a SCSI Inquiry command to the device, to obtain ! 577: * the result in the supplied buffer. The method first issues an ! 578: * inquiry with a 5-byte length, to obtain the full length of the ! 579: * devices inquiry data. The second Inquiry command is issued to get ! 580: * the full inquiry data (limited to maxLen, of course). ! 581: * @param inqBuf ! 582: * A pointer to the buffer. ! 583: * @param maxLen ! 584: * The maximum number of bytes the buffer can contain. ! 585: * @param actualLen ! 586: * A pointer to the returned byte count actually transferred. ! 587: */ ! 588: virtual IOReturn doInquiry(UInt8 *inqBuf,UInt32 maxLen,UInt32 *actualLen); ! 589: ! 590: /*! ! 591: * @function handleUnitAttention ! 592: * @abstract ! 593: * @discussion ! 594: * Override this to perform any special processing required when ! 595: * a Unit-Attention condition is detected. The cx->step value starts at 1 and ! 596: * is incremented as each subsequent command is executed. HandleUnitAttention ! 597: * is then called again duirng the command completion, until cx->state is ! 598: * changed to kDoneHandlingUnitAttention. This repeated calling behavior allows ! 599: * handleUnitAttention to issue several commands to the device to recover from ! 600: * the Unit-Attention condition. Note that since handleUnitAttention is called ! 601: * on the SCSI completion thread, it must not issue blocking operations, but ! 602: * should instead call simpleAsyncIO. ! 603: * ! 604: * The default implementation merely sets the state to ! 605: * kDoneHandlingUnitAttention, to allow the original command to be ! 606: * reissued. ! 607: * @param cx ! 608: * Pointer to context for the current command. ! 609: */ ! 610: virtual void handleUnitAttention(struct context *cx); ! 611: ! 612: /* Internally used methods. */ ! 613: ! 614: /* ! 615: * @group ! 616: * Internally Used Methods ! 617: * @discussion ! 618: * These methods are used internally, and will not generally be modified. ! 619: */ ! 620: ! 621: /*! ! 622: * @function allocateContext ! 623: * @abstract ! 624: * Allocate a context structure for use with the current IO operation. ! 625: */ ! 626: virtual struct context * allocateContext(void); ! 627: ! 628: /*! ! 629: * @function allocateInquiryBuffer ! 630: * @abstract ! 631: * Allocate an inquiry buffer. ! 632: * @param buf ! 633: * A pointer for the returned buffer pointer. ! 634: * @param size ! 635: * The requested size of the buffer, in bytes. ! 636: */ ! 637: virtual IOReturn allocateInquiryBuffer(UInt8 **buf,UInt32 size); ! 638: ! 639: /*! ! 640: * @function allocateTempBuffer ! 641: * @abstract ! 642: * Allocate a buffer for temporary use. ! 643: * @param buf ! 644: * A pointer for the returned buffer pointer. ! 645: * @param size ! 646: * The requested size of the buffer, in bytes. ! 647: */ ! 648: virtual IOReturn allocateTempBuffer(UInt8 **buf,UInt32 size); ! 649: ! 650: /*! ! 651: * @function allocateReadCapacityBuffer ! 652: * @abstract ! 653: * Allocate a buffer for Read-Capacity data. ! 654: * @param buf ! 655: * A pointer for the returned buffer pointer. ! 656: * @param size ! 657: * The requested size of the buffer, in bytes. ! 658: */ ! 659: virtual IOReturn allocateReadCapacityBuffer(UInt8 **buf,UInt8 size); ! 660: ! 661: /*! ! 662: * @function deleteContext ! 663: * @abstract ! 664: * Delete a context structure. ! 665: * @discussion ! 666: * This method also issues a "release" for the IO buffer and/or lock, if any. ! 667: * @param cx ! 668: * A pointer to the context structure to be deleted. ! 669: */ ! 670: virtual void deleteContext(struct context *cx); ! 671: ! 672: /*! ! 673: * @function deleteInquiryBuffer ! 674: * @abstract ! 675: * Delete an inquiry data buffer. ! 676: * @param buf ! 677: * A pointer to the buffer. ! 678: * @param size ! 679: * The requested size of the buffer, in bytes. ! 680: */ ! 681: virtual void deleteInquiryBuffer(UInt8 *buf,UInt32 size); ! 682: ! 683: /*! ! 684: * @function deleteTempBuffer ! 685: * @abstract ! 686: * Delete a temporary data buffer. ! 687: * @param buf ! 688: * A pointer to the buffer. ! 689: * @param len ! 690: * The requested size of the buffer, in bytes. ! 691: */ ! 692: virtual void deleteTempBuffer(UInt8 *buf,UInt32 len); ! 693: ! 694: /*! ! 695: * @function deleteReadCapacityBuffer ! 696: * @abstract ! 697: * Delete a Read-Capacity data buffer. ! 698: * @param buf ! 699: * A pointer to the buffer. ! 700: * @param len ! 701: * The requested size of the buffer, in bytes. ! 702: */ ! 703: virtual void deleteReadCapacityBuffer(UInt8 *buf,UInt32 len); ! 704: ! 705: /*! ! 706: * @function doReadCapacity ! 707: * @abstract ! 708: * @discussion ! 709: * The default implementation of this method issues a standard SCSI ! 710: * Read Capacity command. The block size and maximum valid block are ! 711: * extracted from the returned data in an endian-neutral way. ! 712: * @param blockSize ! 713: * A pointer to the returned block size value. ! 714: * @param maxBlock ! 715: * A pointer to the returned maximum block number. ! 716: */ ! 717: virtual IOReturn doReadCapacity(UInt64 *blockSize,UInt64 *maxBlock); ! 718: ! 719: /*! ! 720: * @function getBlockSize ! 721: * @abstract ! 722: * Return the device block size. ! 723: * @discussion ! 724: * This method obtains the block size from the Read-Capacity data. If RC data is ! 725: * not yet cached, a call is made to doReadCapacity to obtain the data. ! 726: */ ! 727: virtual UInt64 getBlockSize(void); ! 728: ! 729: ! 730: /*! ! 731: * @function dequeueCommands ! 732: * @abstract ! 733: * Dequeue commands previously enqueued awaiting the proper device power level. ! 734: * @discussion ! 735: * This method is called when a command is queued (from queueCommand), when a call ! 736: * completes (from RWCompletion), and when the device power level changes. All commands ! 737: * for which the device power level is proper are immediately dequeued. ! 738: * ! 739: * Queued synchronous commands are simply "awakened" by unlocking a lock. The originating ! 740: * thread then continues and issues the command. Asynchronous commands are immediately ! 741: * dispatched via a call to standardAsyncReadWriteExecute. ! 742: */ ! 743: virtual void dequeueCommands(void); ! 744: ! 745: /*! ! 746: * @function queueCommand ! 747: * @abstract ! 748: * Queue commands awaiting the proper device power level. ! 749: * @discussion ! 750: * This method is called prior to issuing any IO command, so that each command can ! 751: * be enqueued awaiting its desired device power level. After queuing the command, a ! 752: * call is made to dequeueCommands to attempt to dequeue any available command that can ! 753: * be executed (including the one just queued). Putting commands into the queue ensures ! 754: * that the proper sequence is maintained. ! 755: * @param cx ! 756: * The context for the command being queued. ! 757: * @param isSync ! 758: * True if the command is synchronous; False if the command is asynchronous. ! 759: * @param desiredPower ! 760: * The device power level needed before the command can execute. ! 761: */ ! 762: virtual void queueCommand(struct context *cx,bool isSync,UInt32 desiredPower); ! 763: ! 764: /*! ! 765: * @function RWCompletion ! 766: * @abstract ! 767: * Asynchronous read/write completion routine. ! 768: * @discussion ! 769: * A subclass must implement the read-write completion, called upon completion ! 770: * of an IO started by doAsyncReadWrite. ! 771: * @param cx ! 772: * A pointer to the context structure for the completing command. ! 773: */ ! 774: virtual void RWCompletion(struct context *cx) = 0; ! 775: ! 776: /*! ! 777: * @function simpleSynchIO ! 778: * @abstract ! 779: * Issue a simple synchronous SCSI command. ! 780: * @discussion ! 781: * This method issues a single SCSI command and waits for the command ! 782: * to complete. The SCSI command must already be set up in the context ! 783: * structure. ! 784: * @param cx ! 785: * A pointer to the context structure for the command. ! 786: */ ! 787: virtual IOReturn simpleSynchIO(struct context *cx); ! 788: ! 789: /*! ! 790: * @function standardAsyncReadWrite ! 791: * @abstract ! 792: * Start an asynchronous read or write operation. ! 793: * @discussion ! 794: * This method starts an asynchronous read or write operation. No ! 795: * incoming parameters are validated. The default implementation ! 796: * calls createReadCdb or createWriteCdb, ! 797: * then issues a SCSI command to IOSCSIDevice. If the command is ! 798: * accepted, then the completion will be called at some future time. ! 799: * @result ! 800: * The only possible returns from this method are: ! 801: * ! 802: * kIOReturnSuccess, meaning that the IO was accepted by the transport ! 803: * drivers provider (e.g. IOSCSIDevice), and that the completion ! 804: * function will be called when the IO completes, i.e. target->action(param). ! 805: * ! 806: * kIOReturnNoMemory, meaning that memory allocation failed. ! 807: * ! 808: * Other kIOReturn codes from the provider which occurred ! 809: * because the IO was not accepted in that provider's queue. This ! 810: * might indicate a full queue or bad parameter. ! 811: * @param buffer ! 812: * An IOMemoryDescriptor describing the data-transfer buffer. The data direction ! 813: * is contained in the IOMemoryDescriptor. Responsiblity for releasing the descriptor ! 814: * rests with the caller. ! 815: * @param block ! 816: * The starting block number of the data transfer. ! 817: * @param nblks ! 818: * The integral number of blocks to be transferred. ! 819: * @param action ! 820: * The C function called upon completion of the data transfer. ! 821: * @param target ! 822: * The C++ class "this" pointer, passed as an argument to "action." ! 823: * @param param ! 824: * This value is passed as an argument to "action." It is not validated or modified. ! 825: */ ! 826: virtual IOReturn standardAsyncReadWrite(IOMemoryDescriptor *buffer, ! 827: UInt32 block,UInt32 nblks, ! 828: gdCompletionFunction action, ! 829: IOService *target,void *param); ! 830: ! 831: /*! ! 832: * @function standardAsyncReadWriteExecute ! 833: * @abstract ! 834: * Issue an asynchronous read/write operation after dequeuing. ! 835: * @param cx ! 836: * A pointer to the context structure for the command. ! 837: */ ! 838: virtual IOReturn standardAsyncReadWriteExecute(struct context *cx); ! 839: ! 840: /*! ! 841: * @function standardSyncReadWrite ! 842: * Perform a synchronous read or write operation. ! 843: * @param buffer ! 844: * An IOMemoryDescriptor describing the data-transfer buffer. The data direction ! 845: * is contained in the IOMemoryDescriptor. Responsiblity for releasing the descriptor ! 846: * rests with the caller. ! 847: * @param block ! 848: * The starting block number of the data transfer. ! 849: * @param nblks ! 850: * The integral number of blocks to be transferred. ! 851: */ ! 852: virtual IOReturn standardSyncReadWrite(IOMemoryDescriptor *buffer,UInt32 block,UInt32 nblks); ! 853: ! 854: /*! ! 855: * @function stringFromState ! 856: * @abstract ! 857: * Return a string description of a state value. ! 858: * @discussion ! 859: * Used for debugging. ! 860: * @param state ! 861: * The state to be converted to a string description. ! 862: */ ! 863: virtual char * stringFromState(stateValue state); ! 864: ! 865: public: ! 866: ! 867: /*! ! 868: * @function genericCompletion ! 869: * @abstract ! 870: * Generic IO completion function. ! 871: * @discussion ! 872: * This method handles completion of a SCSI command. It implements a ! 873: * simple state machine to handle a Unit Attention condition on a ! 874: * command. ! 875: * ! 876: * This method must be public so we can reach it from ! 877: * the C-language callback "glue" routine. It should not be called ! 878: * from outside this class. ! 879: * ! 880: * ! 881: * ! 882: * If a Unit Attention condition occurs, we set the state to ! 883: * kHandlingUnitAttention and call handleUnitAttention to do whatever ! 884: * is necessary to clear the condition. Eventually, handleUnitAttention ! 885: * resets the state to kDoneHandlingUnitAttention, which will allow ! 886: * the state machine to reissue the original command. ! 887: * ! 888: * If we are already processing a Unit Attention, then genericCompletion ! 889: * increments a step counter and calls handleUnitAttention. The step ! 890: * counter allows handleUnitAttention to issue multiple SCSI commands ! 891: * to clear the condition. The handleUnitAttention method is called ! 892: * repeatedly, until the state is set to kDoneHandlingUnitAttention. ! 893: * ! 894: * If this operation is a normal asynchronous read or write (usually ! 895: * started by standardAsyncReadWrite, though this is not required), ! 896: * then a call is made to RWCompletion, followed by deletion of the ! 897: * context structure for the command. RWCompletion is implemented by ! 898: * the subclass of IOBasicSCSI, for example in IOSCSIHDDrive. ! 899: * @param cx ! 900: * A pointer to the context structure for the command. ! 901: */ ! 902: virtual void genericCompletion(struct context *cx); ! 903: ! 904: /* ! 905: * @endgroup ! 906: */ ! 907: ! 908: protected: ! 909: ! 910: /* ! 911: * @group ! 912: * Power Management Methods ! 913: * @discussion ! 914: * A subclass must implement these to report the power level required to do various commands. ! 915: */ ! 916: ! 917: /*! ! 918: * @function getExecuteCDBPowerState ! 919: * @abstract ! 920: * Return the required device power level to execute a client CDB. ! 921: */ ! 922: virtual UInt32 getExecuteCDBPowerState(void) = 0; ! 923: ! 924: /*! ! 925: * @function getInquiryPowerState ! 926: * @abstract ! 927: * Return the required device power level to issue an Inquiry command. ! 928: */ ! 929: virtual UInt32 getInquiryPowerState(void) = 0; ! 930: ! 931: /*! ! 932: * @function getReadCapacityPowerState ! 933: * @abstract ! 934: * Return the required device power level to issue a Read Capacity command. ! 935: */ ! 936: virtual UInt32 getReadCapacityPowerState(void) = 0; ! 937: ! 938: /*! ! 939: * @function getReadWritePowerState ! 940: * @abstract ! 941: * Return the required device power level to issue a data read or write. ! 942: */ ! 943: virtual UInt32 getReadWritePowerState(void) = 0; ! 944: ! 945: /*! ! 946: * @function getReportWriteProtectionPowerState ! 947: * @abstract ! 948: * Return the required device power level to determine media write protection. ! 949: */ ! 950: virtual UInt32 getReportWriteProtectionPowerState(void) = 0; ! 951: ! 952: /*! ! 953: * @function powerTickle ! 954: * @abstract ! 955: * Check for the device power state currently being in the desired state. ! 956: * @discussion ! 957: * A subclass must implement powerTickle, which is called when we desire power to ! 958: * execute a command. PowerTickle may handle generic or a subclass-expanded set of ! 959: * power states. The implementation will usually relay the call to the Power Management ! 960: * subsystem function activityTickle. For a device without power management capability, ! 961: * the implementation should always return True. ! 962: * @param desiredState ! 963: * The desired device power level. ! 964: * @result ! 965: * True if power is in the desired state (or better); False if the caller must wait ! 966: * until power is available. ! 967: */ ! 968: virtual bool powerTickle(UInt32 desiredState) = 0; ! 969: ! 970: /* ! 971: * @endgroup ! 972: */ ! 973: ! 974: /*! ! 975: * @var _provider ! 976: * A pointer to our provider. ! 977: */ ! 978: IOSCSIDevice * _provider; ! 979: ! 980: /* Device information : */ ! 981: ! 982: /*! ! 983: * @var _inqBuf ! 984: * A pointer to the allocate Inquiry Data buffer. ! 985: */ ! 986: UInt8 * _inqBuf; /* the Inquiry data buffer */ ! 987: ! 988: /*! ! 989: * @var _inqBufSize ! 990: * The size of the inquiry data buffer, in bytes. ! 991: */ ! 992: UInt32 _inqBufSize; /* size of the buffer */ ! 993: ! 994: /*! ! 995: * @var _inqLen ! 996: * The number of valid bytes of inquiry data. ! 997: */ ! 998: UInt32 _inqLen; /* valid bytes in buffer */ ! 999: ! 1000: /*! ! 1001: * @var _vendor ! 1002: * The Vendor Name string from the inquiry data, null-terminated. ! 1003: */ ! 1004: char _vendor[9]; /* info from Inquiry data */ ! 1005: ! 1006: /*! ! 1007: * @var _product ! 1008: * The Product Name string from the inquiry data, null-terminated. ! 1009: */ ! 1010: char _product[17]; ! 1011: ! 1012: /*! ! 1013: * @var _rev ! 1014: * The Product Revision string from the inquiry data, null-terminated. ! 1015: */ ! 1016: char _rev[5]; ! 1017: ! 1018: /* Since we get both of these items from the same command, we ! 1019: * just cache both values if we get either call, so we only ! 1020: * have to issue the command once. ! 1021: */ ! 1022: ! 1023: /*! ! 1024: * @var _readCapDone ! 1025: * True if we have issued a Read-Capacity command to obtain the ! 1026: * values for _maxBlock and _blockSize. ! 1027: */ ! 1028: bool _readCapDone; ! 1029: ! 1030: /*! ! 1031: * @var _removable ! 1032: * True if the media is removable; False if the media is fixed. ! 1033: */ ! 1034: bool _removable; ! 1035: ! 1036: /*! ! 1037: * @var _maxBlock ! 1038: * The highest valid block on the media, relative to zero. ! 1039: */ ! 1040: UInt64 _maxBlock; ! 1041: ! 1042: /*! ! 1043: * @var _blockSize ! 1044: * The block size of the media in bytes. ! 1045: */ ! 1046: UInt64 _blockSize; ! 1047: ! 1048: /* The queue of pending requests awaiting power: */ ! 1049: ! 1050: /*! ! 1051: * @struct queue ! 1052: * @discussion ! 1053: * A data structure for a queue. ! 1054: * @field head ! 1055: * A pointer to the head item. ! 1056: * @field tail ! 1057: * A pointer to the tail item. ! 1058: * @field lock ! 1059: * A lock used to protect the queue during changes. ! 1060: */ ! 1061: /*! ! 1062: * @var _powerQueue ! 1063: * A queue structure containing operations queued awaiting power level. ! 1064: */ ! 1065: struct queue { ! 1066: struct context * head; ! 1067: struct context * tail; ! 1068: IOLock * lock; ! 1069: } _powerQueue; ! 1070: ! 1071: }; ! 1072: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.