Mac Developer Library

Developer

IOBlockStorageDriver Class Reference

Options
Deployment Target:

On This Page
Language:

IOBlockStorageDriver

Inheritance


  • IOBlockStorageDriver

Conforms To


Not Applicable

Import Statement


Not Applicable

Objective-C

@import Kernel;

Availability


Available in OS X v10.6 and later.

The common base class for generic block storage drivers.

The IOBlockStorageDriver class is the common base class for generic block storage drivers. It matches and communicates via an IOBlockStorageDevice interface, and connects to the remainder of the storage framework via the IOStorage protocol. It extends the IOStorage protocol by implementing the appropriate open and close semantics, deblocking for unaligned transfers, polling for ejectable media, locking and ejection policies, media object creation and tear-down, and statistics gathering and reporting.

Block storage drivers are split into two parts: the generic driver handles all generic device issues, independent of the lower-level transport mechanism (e.g. SCSI, ATA, USB, FireWire). All storage operations at the generic driver level are translated into a series of generic device operations. These operations are passed via the IOBlockStorageDevice nub to a transport driver, which implements the appropriate transport-dependent protocol to execute these operations.

To determine the write-protect state of a device (or media), for example, the generic driver would issue a call to the Transport Driver's reportWriteProtection method. If this were a SCSI device, its transport driver would issue a Mode Sense command to extract the write-protection status bit. The transport driver then reports true or false to the generic driver.

The generic driver therefore has no knowledge of, or involvement with, the actual commands and mechanisms used to communicate with the device. It is expected that the generic driver will rarely, if ever, need to be subclassed to handle device idiosyncrasies; rather, the transport driver should be changed via overrides.

A generic driver could be subclassed to create a different type of generic device. The generic driver IOCDBlockStorageDriver class is a subclass of IOBlockStorageDriver, adding CD functions.

  • React to new media insertion.

    Declaration

    C++

    virtual IOReturn acceptNewMedia( void);

    Discussion

    This method logs the media block size and block count, then calls instantiateMediaObject to get a media object instantiated. The media object is then attached above us and registered.

    This method can be overridden to control what happens when new media is inserted. The default implementation deals with one IOMedia object.

  • Declaration

    C++

    virtual void addToBytesTransferred( UInt64bytesTransferred, UInt64totalTime, UInt64latentTime, boolisWrite);

    Parameters

    bytesTransferred

    Number of bytes transferred in this operation.

    totalTime

    Nanoseconds spent performing this operation.

    latentTime

    Nanoseconds of latency during this operation.

    isWrite

    Indicates whether this operation was a write, otherwise is was a read.

    Discussion

    Update the total number of bytes transferred, the total transfer time, and the total latency time -- used for statistics.

    This method's implementation is not typically overridden.

  • Declaration

    C++

    virtual Context * allocateContext();

    Return Value

    Context structure.

    Discussion

    Allocate a context structure for a read/write operation.

  • Declaration

    C++

    #ifdef __LP64__ virtual void breakUpRequest( UInt64 byteStart, IOMemoryDescriptor *buffer, IOStorageAttributes *attributes, IOStorageCompletion *completion, Context *context); #else /* !__LP64__ */ virtual void breakUpRequest( UInt64 byteStart, IOMemoryDescriptor *buffer, IOStorageCompletion completion, Context *context); #endif /* !__LP64__ */

    Parameters

    byteStart

    Starting byte offset for the data transfer.

    buffer

    Buffer for the data transfer. The size of the buffer implies the size of the data transfer.

    attributes

    Attributes of the data transfer. See IOStorageAttributes. It is the responsibility of the callee to maintain the information for the duration of the data transfer, as necessary.

    completion

    Completion routine to call once the data transfer is complete. It is the responsibility of the callee to maintain the information for the duration of the data transfer, as necessary.

    context

    Additional context information for the data transfer (e.g. block size).

    Discussion

    The breakUpRequest method checks to see if the incoming request exceeds our transfer constraints, and if so, breaks up the request into smaller sub-requests.

    This method is part of a sequence of methods invoked for each read/write request. The first is prepareRequest, which allocates and prepares some context for the transfer; the second is deblockRequest, which aligns the transfer at the media's block boundaries; third is breakUpRequest, which breaks up the transfer into multiple sub-transfers when certain hardware constraints are exceeded; fourth is executeRequest, which implements the actual transfer from the block storage device.

    This method's implementation is not typically overridden.

  • Check if media has newly arrived or disappeared.

    Declaration

    C++

    virtual IOReturn checkForMedia( void);

    Discussion

    This method does most of the work in polling for media, first calling the block storage device's reportMediaState method. If reportMediaState reports no change in the media state, kIOReturnSuccess is returned. If the media state has indeed changed, a call is made to mediaStateHasChanged to act on the event.

  • Constrain the byte count for this IO to device limits.

    Declaration

    C++

    virtual UInt64 constrainByteCount( UInt64requestedCount, boolisWrite);

    Parameters

    requestedCount

    The requested byte count for the next read or write operation.

    isWrite

    True if the operation will be a write; False if the operation will be a read.

    Discussion

    This function should be called prior to each read or write operation, so that the driver can constrain the requested byte count, as necessary, to meet current device limits. Such limits could be imposed by the device depending on operating modes, media types, or transport protocol (e.g. ATA, SCSI).

    At present, this method is not used.

  • Declaration

    C++

    virtual IOStorage * copyPhysicalExtent( IOService *client, UInt64 *byteStart, UInt64 *byteCount);

    Parameters

    client

    Client requesting the operation.

    byteStart

    Starting byte offset for the operation. Returns a physical byte offset, relative to the physical storage object, on success.

    byteCount

    Size of the operation. Returns the actual number of bytes which can be transferred, relative to the physical storage object, on success.

    Return Value

    A reference to the physical storage object, which should be released by the caller, or a null on error.

    Discussion

    Convert the specified byte offset into a physical byte offset, relative to a physical storage object. This call should only be made within the context of lockPhysicalExtents().

  • Declaration

    C++

    #ifdef __LP64__ virtual void deblockRequest( UInt64 byteStart, IOMemoryDescriptor *buffer, IOStorageAttributes *attributes, IOStorageCompletion *completion, Context *context); #else /* !__LP64__ */ virtual void deblockRequest( UInt64 byteStart, IOMemoryDescriptor *buffer, IOStorageCompletion completion, Context *context); #endif /* !__LP64__ */

    Parameters

    byteStart

    Starting byte offset for the data transfer.

    buffer

    Buffer for the data transfer. The size of the buffer implies the size of the data transfer.

    attributes

    Attributes of the data transfer. See IOStorageAttributes. It is the responsibility of the callee to maintain the information for the duration of the data transfer, as necessary.

    completion

    Completion routine to call once the data transfer is complete. It is the responsibility of the callee to maintain the information for the duration of the data transfer, as necessary.

    context

    Additional context information for the data transfer (e.g. block size).

    Discussion

    The deblockRequest method checks to see if the incoming request rests on the media's block boundaries, and if not, deblocks it. Deblocking involves rounding out the request to the nearest block boundaries and transferring the excess bytes into a scratch buffer.

    This method is part of a sequence of methods invoked for each read/write request. The first is prepareRequest, which allocates and prepares some context for the transfer; the second is deblockRequest, which aligns the transfer at the media's block boundaries; third is breakUpRequest, which breaks up the transfer into multiple sub-transfers when certain hardware constraints are exceeded; fourth is executeRequest, which implements the actual transfer from the block storage device.

    This method's implementation is not typically overridden.

  • Decommission an existing piece of media that has gone away.

    Declaration

    C++

    virtual IOReturn decommissionMedia( boolforcible);

    Parameters

    forcible

    True to force forgetting of the media object even if terminate reports that there was an active client.

    Discussion

    This method wraps a call to terminate, to tear down the stack and the IOMedia object for the media. If "forcible" is true, the media object will be forgotten, and initMediaState will be called. A forcible decommission would occur when an unrecoverable error happens during tear-down (e.g. perhaps a client is still open), but we must still forget about the media.

  • Declaration

    C++

    virtual void deleteContext( Context *context);

    Parameters

    context

    Context structure to be deleted.

    Discussion

    Delete a context structure from a read/write operation.

  • Declaration

    C++

    virtual IOReturn ejectMedia();

    Return Value

    An IOReturn code.

    Discussion

    Eject the media from the device. The driver is responsible for tearing down the media object it created before proceeding with the eject. If the tear-down fails, an error should be returned.

  • Declaration

    C++

    #ifdef __LP64__ virtual void executeRequest( UInt64 byteStart, IOMemoryDescriptor *buffer, IOStorageAttributes *attributes, IOStorageCompletion *completion, Context *context); #else /* !__LP64__ */ virtual void executeRequest( UInt64 byteStart, IOMemoryDescriptor *buffer, IOStorageCompletion completion, Context *context); #endif /* !__LP64__ */

    Parameters

    byteStart

    Starting byte offset for the data transfer.

    buffer

    Buffer for the data transfer. The size of the buffer implies the size of the data transfer.

    attributes

    Attributes of the data transfer. See IOStorageAttributes. It is the responsibility of the callee to maintain the information for the duration of the data transfer, as necessary.

    completion

    Completion routine to call once the data transfer is complete. It is the responsibility of the callee to maintain the information for the duration of the data transfer, as necessary.

    context

    Additional context information for the data transfer (e.g. block size).

    Discussion

    Execute an asynchronous storage request. The request is guaranteed to be block-aligned.

    This method is part of a sequence of methods invoked for each read/write request. The first is prepareRequest, which allocates and prepares some context for the transfer; the second is deblockRequest, which aligns the transfer at the media's block boundaries; third is breakUpRequest, which breaks up the transfer into multiple sub-transfers when certain hardware constraints are exceeded; fourth is executeRequest, which implements the actual transfer from the block storage device.

  • Declaration

    C++

    virtual IOReturn formatMedia( UInt64byteCapacity);

    Parameters

    byteCapacity

    Number of bytes to format media to.

    Return Value

    An IOReturn code.

    Discussion

    Format the media with the specified byte capacity. The driver is responsible for tearing down the media object and recreating it.

  • Return the desired device name.

    Declaration

    C++

    virtual const char * getDeviceTypeName( void);

    Discussion

    This method returns a string, used to compare the kIOBlockStorageDeviceTypeKey of our provider. This method is called from probe.

    The default implementation of this method returns kIOBlockStorageDeviceTypeGeneric.

  • Declaration

    C++

    virtual UInt32 getFormatCapacities( UInt64 *capacities, UInt32capacitiesMaxCount) const;

    Parameters

    capacities

    Buffer that will receive the UInt64 capacity values.

    capacitiesMaxCount

    Maximum number of capacity values that can be held in the buffer.

    Return Value

    Actual number of capacity values copied to the buffer, or if no buffer is given, the total number of capacity values available.

    Discussion

    Ask the driver to report the feasible formatting capacities for the inserted media (in bytes). This routine fills the caller's buffer, up to the maximum count specified if the real number of capacities would overflow the buffer. The return value indicates the actual number of capacities copied to the buffer.

    If the capacities buffer is not supplied or if the maximum count is zero, the routine returns the proposed count of capacities instead.

  • Declaration

    C++

    virtual UInt64 getMediaBlockSize() const;

    Return Value

    Natural block size, in bytes.

    Discussion

    Ask the driver about the media's natural block size.

  • Declaration

    C++

    virtual IOMediaState getMediaState() const;

    Return Value

    An IOMediaState value.

    Discussion

    Ask the driver about the media's current state.

  • Declaration

    C++

    virtual UInt64 getStatistic( Statisticsstatistic) const;

    Parameters

    statistic

    Statistic index (an IOBlockStorageDriver::Statistics index).

    Return Value

    Statistic value.

    Discussion

    Ask the driver to report one of its operating statistics.

  • Declaration

    C++

    virtual UInt32 getStatistics( UInt64 *statistics, UInt32statisticsMaxCount) const;

    Parameters

    statistics

    Buffer that will receive the UInt64 statistic values.

    statisticsMaxCount

    Maximum number of statistic values that can be held in the buffer.

    Return Value

    Actual number of statistic values copied to the buffer, or if no buffer is given, the total number of statistic values available.

    Discussion

    Ask the driver to report its operating statistics.

    The statistics are each indexed by IOBlockStorageDriver::Statistics indices. This routine fills the caller's buffer, up to the maximum count specified if the real number of statistics would overflow the buffer. The return value indicates the actual number of statistics copied to the buffer.

    If the statistics buffer is not supplied or if the maximum count is zero, the routine returns the proposed count of statistics instead.

  • Declaration

    C++

    virtual void handleClose( IOService *client, IOOptionBitsoptions);

    Parameters

    client

    Client requesting the close.

    options

    Options for the close. Set to zero.

    Discussion

    The handleClose method closes the client's access to this object.

    This implementation replaces the IOService definition of handleIsOpen().

  • Declaration

    C++

    virtual bool handleIsOpen( const IOService *client) const;

    Parameters

    client

    Client to check the open state of. Set to zero to check the open state of all clients.

    Return Value

    Returns true if the client was (or clients were) open, false otherwise.

    Discussion

    The handleIsOpen method determines whether the specified client, or any client if none is specified, presently has an open on this object.

    This implementation replaces the IOService definition of handleIsOpen().

  • Declaration

    C++

    virtual bool handleOpen( IOService *client, IOOptionBitsoptions, void *access);

    Parameters

    client

    Client requesting the open.

    options

    Options for the open. Set to zero.

    access

    Access level for the open. Set to kIOStorageAccessReader or kIOStorageAccessReaderWriter.

    Return Value

    Returns true if the open was successful, false otherwise.

    Discussion

    The handleOpen method grants or denies permission to access this object to an interested client. The argument is an IOStorageAccess value that specifies the level of access desired -- reader or reader-writer.

    This method can be invoked to upgrade or downgrade the access level for an existing client as well. The previous access level will prevail for upgrades that fail, of course. A downgrade should never fail. If the new access level should be the same as the old for a given client, this method will do nothing and return success. In all cases, one, singular close-per-client is expected for all opens-per-client received.

    This implementation replaces the IOService definition of handleIsOpen().

  • Declaration

    C++

    virtual bool handleStart( IOService *provider);

    Parameters

    provider

    This object's provider.

    Return Value

    Returns true on success, false otherwise.

    Discussion

    Prepare the block storage driver for operation.

    This is where a media object needs to be created for fixed media, and optionally for removable media.

    Note that this method is called from within the start() routine; if this method returns successfully, it should be prepared to accept any of IOBlockStorageDriver's APIs.

  • Declaration

    C++

    virtual void incrementErrors( boolisWrite);

    Parameters

    isWrite

    Indicates whether this operation was a write, otherwise is was a read.

    Discussion

    Update the total error count -- used for statistics.

    This method's implementation is not typically overridden.

  • Declaration

    C++

    virtual void incrementRetries( boolisWrite);

    Parameters

    isWrite

    Indicates whether this operation was a write, otherwise is was a read.

    Discussion

    Update the total retry count -- used for statistics.

    This method's implementation is not typically overridden.

  • Initialize media-related instance variables.

    Declaration

    C++

    virtual void initMediaState( void);

    Discussion

    Called when media is not present, this method marks the device state as not having media present, not spun up, and write-enabled.

  • Create an IOMedia object for media.

    Declaration

    C++

    virtual IOMedia * instantiateDesiredMediaObject( void);

    Discussion

    This method creates the exact type of IOMedia object desired. It is called by instantiateMediaObject. A subclass may override this one-line method to change the type of media object actually instantiated.

  • Create an IOMedia object for media.

    Declaration

    C++

    virtual IOMedia * instantiateMediaObject( UInt64base, UInt64byteSize, UInt32blockSize, char *mediaName);

    Parameters

    base

    Byte number of beginning of active data area of the media. Usually zero.

    byteSize

    Size of the data area of the media, in bytes.

    blockSize

    Block size of the media, in bytes.

    mediaName

    Name of the IOMedia object.

    Return Value

    A pointer to the created IOMedia object, or a null on error.

    Discussion

    This method creates an IOMedia object from the supplied parameters. It is a convenience method to wrap the handful of steps to do the job.

  • Declaration

    C++

    virtual bool isMediaEjectable() const;

    Return Value

    Returns true if the media is ejectable, false otherwise.

    Discussion

    Ask the driver whether the media is ejectable.

  • Declaration

    C++

    virtual bool isMediaRemovable() const;

    Return Value

    Returns true if the media is ejectable, false otherwise.

    Discussion

    Ask the driver whether the media is ejectable.

  • Declaration

    C++

    virtual bool isMediaWritable() const;

    Return Value

    Returns true if the media is writable, false otherwise.

    Discussion

    Ask the driver whether the media is writable.

  • Declaration

    C++

    virtual bool lockPhysicalExtents( IOService *client);

    Parameters

    client

    Client requesting the operation.

    Return Value

    Returns true if the lock was successful, false otherwise.

    Discussion

    Lock the contents of the storage object against relocation temporarily, for the purpose of getting physical extents.

  • React to a new media insertion or a media removal.

    Declaration

    C++

    virtual IOReturn mediaStateHasChanged( IOMediaState state);

    Discussion

    This method is called on a media state change, that is, an arrival or removal. If media has just become available, calls are made to recordMediaParameters and acceptNewMedia. If media has just gone away, a call is made to decommissionMedia, with the forcible parameter set to true. The forcible tear-down is needed to enforce the disappearance of media, regardless of interested clients.

  • Declaration

    C++

    virtual void prepareRequest( UInt64byteStart, IOMemoryDescriptor *buffer, IOStorageAttributes *attributes, IOStorageCompletion *completion);

    Parameters

    byteStart

    Starting byte offset for the data transfer.

    buffer

    Buffer for the data transfer. The size of the buffer implies the size of the data transfer.

    attributes

    Attributes of the data transfer. See IOStorageAttributes. It is the responsibility of the callee to maintain the information for the duration of the data transfer, as necessary.

    completion

    Completion routine to call once the data transfer is complete. It is the responsibility of the callee to maintain the information for the duration of the data transfer, as necessary.

    Discussion

    The prepareRequest method allocates and prepares state for the transfer.

    This method is part of a sequence of methods invoked for each read/write request. The first is prepareRequest, which allocates and prepares some context for the transfer; the second is deblockRequest, which aligns the transfer at the media's block boundaries; third is breakUpRequest, which breaks up the transfer into multiple sub-transfers when certain hardware constraints are exceeded; fourth is executeRequest, which implements the actual transfer from the block storage device.

    This method's implementation is not typically overridden.

  • Declaration

    C++

    virtual void read( IOService *client, UInt64byteStart, IOMemoryDescriptor *buffer, IOStorageAttributes *attributes, IOStorageCompletion *completion);

    Parameters

    client

    Client requesting the read.

    byteStart

    Starting byte offset for the data transfer.

    buffer

    Buffer for the data transfer. The size of the buffer implies the size of the data transfer.

    attributes

    Attributes of the data transfer. See IOStorageAttributes. It is the responsibility of the callee to maintain the information for the duration of the data transfer, as necessary.

    completion

    Completion routine to call once the data transfer is complete. It is the responsibility of the callee to maintain the information for the duration of the data transfer, as necessary.

    Discussion

    The read method is the receiving end for all read requests from the storage framework (through the media object created by this driver).

    This method initiates a sequence of methods (stages) for each read/write request. The first is prepareRequest, which allocates and prepares some context for the transfer; the second is deblockRequest, which aligns the transfer at the media's block boundaries; third is breakUpRequest, which breaks up the transfer into multiple sub-transfers when certain hardware constraints are exceeded; fourth is executeRequest, which implements the actual transfer from the block storage device.

    This method's implementation is not typically overridden.

  • Obtain media-related parameters on media insertion.

    Declaration

    C++

    virtual IOReturn recordMediaParameters( void);

    Discussion

    This method obtains media-related parameters via calls to the Transport Driver's reportBlockSize, reportMaxValidBlock, and reportWriteProtection methods.

  • Reject new media.

    Declaration

    C++

    virtual void rejectMedia( void);

    Discussion

    This method will be called if validateNewMedia returns False (thus rejecting the new media. A vendor may choose to override this method to control behavior when media is rejected.

    The default implementation simply calls ejectMedia.

  • Request that the device enter an idle state.

    Declaration

    C++

    virtual IOReturn requestIdle( void);

    Discussion

    Request that the device enter an idle state. The device will exit this state on the next read or write request, or as it sees necessary. One example is for a DVD drive to spin down when it enters such an idle state, and spin up on the next read request from the system.

  • Declaration

    C++

    virtual IOReturn synchronizeCache( IOService *client);

    Parameters

    client

    Client requesting the cache synchronization.

    Return Value

    Returns the status of the cache synchronization.

    Discussion

    Flush the cached data in the storage object, if any, synchronously.

  • Declaration

    C++

    virtual void unlockPhysicalExtents( IOService *client);

    Parameters

    client

    Client requesting the operation.

    Discussion

    Unlock the contents of the storage object for relocation again. This call must balance a successful call to lockPhysicalExtents().

  • Declaration

    C++

    virtual IOReturn unmap( IOService *client, IOStorageExtent *extents, UInt32extentsCount, UInt32 options = 0);

    Parameters

    client

    Client requesting the operation.

    extents

    List of extents. See IOStorageExtent. It is legal for the callee to overwrite the contents of this buffer in order to satisfy the request.

    extentsCount

    Number of extents.

    Return Value

    Returns the status of the operation.

    Discussion

    Delete unused data from the storage object at the specified byte offsets, synchronously.

  • Verify that new media is acceptable.

    Declaration

    C++

    virtual bool validateNewMedia( void);

    Discussion

    This method will be called whenever new media is detected. Return true to accept the media, or false to reject it (and call rejectMedia). Vendors might override this method to handle password-protection for new media.

    The default implementation always returns True, indicating media is accepted.

  • Declaration

    C++

    virtual void write( IOService *client, UInt64byteStart, IOMemoryDescriptor *buffer, IOStorageAttributes *attributes, IOStorageCompletion *completion);

    Parameters

    client

    Client requesting the write.

    byteStart

    Starting byte offset for the data transfer.

    buffer

    Buffer for the data transfer. The size of the buffer implies the size of the data transfer.

    attributes

    Attributes of the data transfer. See IOStorageAttributes. It is the responsibility of the callee to maintain the information for the duration of the data transfer, as necessary.

    completion

    Completion routine to call once the data transfer is complete. It is the responsibility of the callee to maintain the information for the duration of the data transfer, as necessary.

    Discussion

    The write method is the receiving end for all write requests from the storage framework (through the media object created by this driver).

    This method initiates a sequence of methods (stages) for each read/write request. The first is prepareRequest, which allocates and prepares some context for the transfer; the second is deblockRequest, which aligns the transfer at the media's block boundaries; third is breakUpRequest, which breaks up the transfer into multiple sub-transfers when certain hardware constraints are exceeded; fourth is executeRequest, which implements the actual transfer from the block storage device.

    This method's implementation is not typically overridden.

Instance Variables

  • True if the media is write-protected; False if not.

    Declaration

    C++

    bool _writeProtected;

  • True if the media is removable; False if it is fixed (not removable).

    Declaration

    C++

    bool _removable;

  • Type of the media (can be used to differentiate between the different types of CD media, DVD media, etc).

    Declaration

    C++

    UInt32 _mediaType;

  • A pointer to the media object we have instantiated (if any).

    Declaration

    C++

    IOMedia * _mediaObject;

  • The block size of the media, in bytes.

    Declaration

    C++

    UInt64 _mediaBlockSize;

  • The maximum byte transfer allowed for write operations.

    Declaration

    C++

    UInt64 _maxWriteByteTransfer;

  • The maximum byte transfer allowed for read operations.

    Declaration

    C++

    UInt64 _maxReadByteTransfer;

  • The maximum allowable block number for the media, zero-based.

    Declaration

    C++

    UInt64 _maxBlockNumber;

  • True if the media is ejectable under software control.

    Declaration

    C++

    bool _ejectable;