Annotation of XNU/iokit/IOKit/storage/scsi/IOBasicSCSI.h, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.