ADC Home > Reference Library > Reference > Hardware & Drivers > I/O Kit Framework Reference
|
IOBlockStorageDriver |
Inherits from: | |
Declared In: |
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.
Check if media has newly arrived or disappeared.
Constrain the byte count for this IO to device limits.
Decommission an existing piece of media that has gone away.
Return the desired device name.
Initialize media-related instance variables.
Create an IOMedia object for media.
Create an IOMedia object for media.
React to a new media insertion or a media removal.
Obtain media-related parameters on media insertion.
Reject new media.
Verify that new media is acceptable.
acceptNewMedia |
React to new media insertion.
protected
virtual IOReturn acceptNewMedia( void);
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.
addToBytesTransferred |
protected
virtual void addToBytesTransferred( UInt64 bytesTransferred, UInt64 totalTime, UInt64 latentTime, bool isWrite);
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.
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.
allocateContext |
protected
virtual Context * allocateContext();
Context structure.
Allocate a context structure for a read/write operation.
breakUpRequest |
protected
virtual void breakUpRequest( UInt64 byteStart, IOMemoryDescriptor *buffer, IOStorageCompletion completion, Context *context);
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.
completion
Completion routine to call once the data transfer is complete.
context
Additional context information for the data transfer (e.g. block size).
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.
checkForMedia |
Check if media has newly arrived or disappeared.
protected
virtual IOReturn checkForMedia( void);
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.
constrainByteCount |
Constrain the byte count for this IO to device limits.
protected
virtual UInt64 constrainByteCount( UInt64 requestedCount, bool isWrite);
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.
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.
deblockRequest |
protected
virtual void deblockRequest( UInt64 byteStart, IOMemoryDescriptor *buffer, IOStorageCompletion completion, Context *context);
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.
completion
Completion routine to call once the data transfer is complete.
context
Additional context information for the data transfer (e.g. block size).
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.
decommissionMedia |
Decommission an existing piece of media that has gone away.
protected
virtual IOReturn decommissionMedia( bool forcible);
forcible
True to force forgetting of the media object even if terminate reports that there was an active client.
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.
deleteContext |
protected
virtual void deleteContext( Context *context);
context
Context structure to be deleted.
Delete a context structure from a read/write operation.
ejectMedia |
public
virtual IOReturn ejectMedia();
An IOReturn code.
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.
executeRequest |
protected
virtual void executeRequest( UInt64 byteStart, IOMemoryDescriptor *buffer, IOStorageCompletion completion, Context *context);
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.
completion
Completion routine to call once the data transfer is complete.
context
Additional context information for the data transfer (e.g. block size).
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.
formatMedia |
public
virtual IOReturn formatMedia( UInt64 byteCapacity);
byteCapacity
Number of bytes to format media to.
An IOReturn code.
Format the media with the specified byte capacity. The driver is responsible for tearing down the media object and recreating it.
getDeviceTypeName |
Return the desired device name.
protected
virtual const char * getDeviceTypeName(void);
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.
getFormatCapacities |
public
virtual UInt32 getFormatCapacities( UInt64 *capacities, UInt32 capacitiesMaxCount) const;
capacities
Buffer that will receive the UInt64 capacity values.
capacitiesMaxCount
Maximum number of capacity values that can be held in the buffer.
Actual number of capacity values copied to the buffer, or if no buffer is given, the total number of capacity values available.
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.
getMediaBlockSize |
protected
virtual UInt64 getMediaBlockSize() const;
Natural block size, in bytes.
Ask the driver about the media's natural block size.
getMediaState |
public
virtual IOMediaState getMediaState() const;
An IOMediaState value.
Ask the driver about the media's current state.
getStatistic |
public
virtual UInt64 getStatistic( Statistics statistic) const;
statistic
Statistic index (an IOBlockStorageDriver::Statistics index).
Statistic value.
Ask the driver to report one of its operating statistics.
getStatistics |
public
virtual UInt32 getStatistics( UInt64 *statistics, UInt32 statisticsMaxCount) const;
statistics
Buffer that will receive the UInt64 statistic values.
statisticsMaxCount
Maximum number of statistic values that can be held in the buffer.
Actual number of statistic values copied to the buffer, or if no buffer is given, the total number of statistic values available.
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.
handleClose |
protected
virtual void handleClose( IOService *client, IOOptionBits options);
client
Client requesting the close.
options
Options for the close. Set to zero.
The handleClose method closes the client's access to this object.
This implementation replaces the IOService definition of handleIsOpen().
handleIsOpen |
protected
virtual bool handleIsOpen( const IOService * client) const;
client
Client to check the open state of. Set to zero to check the open state of all clients.
Returns true if the client was (or clients were) open, false otherwise.
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().
handleOpen |
protected
virtual bool handleOpen( IOService *client, IOOptionBits options, void *access);
client
Client requesting the open.
options
Options for the open. Set to zero.
access
Access level for the open. Set to kIOStorageAccessReader or kIOStorageAccessReaderWriter.
Returns true if the open was successful, false otherwise.
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().
handleStart |
protected
virtual bool handleStart( IOService *provider);
provider
This object's provider.
Returns true on success, false otherwise.
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.
handleYield |
protected
virtual bool handleYield( IOService *provider, IOOptionBits options = 0, void *argument = 0);
provider
This object's provider.
Stop the block storage driver.
This method is called as a result of a kIOMessageServiceIsRequestingClose provider message. The argument is passed in as-is from the message. The options are unused.
This is where the driver should clean up its state in preparation for removal from the system.
Note that this method is called from within the yield() routine.
This method is called with the arbitration lock held.
incrementErrors |
protected
virtual void incrementErrors( bool isWrite);
isWrite
Indicates whether this operation was a write, otherwise is was a read.
Update the total error count -- used for statistics.
This method's implementation is not typically overridden.
incrementRetries |
protected
virtual void incrementRetries( bool isWrite);
isWrite
Indicates whether this operation was a write, otherwise is was a read.
Update the total retry count -- used for statistics.
This method's implementation is not typically overridden.
initMediaState |
Initialize media-related instance variables.
protected
virtual void initMediaState( void);
Called when media is not present, this method marks the device state as not having media present, not spun up, and write-enabled.
instantiateDesiredMediaObject |
Create an IOMedia object for media.
protected
virtual IOMedia * instantiateDesiredMediaObject( void);
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.
instantiateMediaObject |
Create an IOMedia object for media.
protected
virtual IOMedia * instantiateMediaObject( UInt64 base, UInt64 byteSize, UInt32 blockSize, char *mediaName);
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.
A pointer to the created IOMedia object, or a null on error.
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.
isMediaEjectable |
public
virtual bool isMediaEjectable() const;
Returns true if the media is ejectable, false otherwise.
Ask the driver whether the media is ejectable.
isMediaPollExpensive |
public
virtual bool isMediaPollExpensive() const;
Returns true if polling the media is expensive, false otherwise.
Ask the driver whether a pollMedia() would be an expensive operation, that is, one that requires the device to spin up or delay for a while.
isMediaPollRequired |
public
virtual bool isMediaPollRequired() const;
Returns true if polling the media is required, false otherwise.
Ask the driver whether the block storage device requires polling, which is typically required for devices without the ability to asynchronously detect the arrival or departure of the media.
lockMedia |
public
virtual IOReturn lockMedia( bool lock);
lock
Pass true to lock the media, otherwise pass false to unlock the media.
An IOReturn code.
Lock or unlock the ejectable media in the device, that is, prevent it from manual ejection or allow its manual ejection.
mediaStateHasChanged |
React to a new media insertion or a media removal.
protected
virtual IOReturn mediaStateHasChanged( IOMediaState state);
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.
pollMedia |
public
virtual IOReturn pollMedia();
An IOReturn code.
Poll for the presence of media in the device. The driver is responsible for tearing down the media object it created should the media have been removed since the last poll, and vice-versa, creating the media object should new media have arrived since the last poll.
prepareRequest |
protected
virtual void prepareRequest( UInt64 byteStart, IOMemoryDescriptor *buffer, IOStorageCompletion completion);
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.
completion
Completion routine to call once the data transfer is complete.
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.
read |
public
virtual void read( IOService *client, UInt64 byteStart, IOMemoryDescriptor *buffer, IOStorageCompletion completion);
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.
completion
Completion routine to call once the data transfer is complete.
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.
recordMediaParameters |
Obtain media-related parameters on media insertion.
protected
virtual IOReturn recordMediaParameters( void);
This method obtains media-related parameters via calls to the Transport Driver's reportBlockSize, reportMaxValidBlock, reportMaxReadTransfer, reportMaxWriteTransfer, and reportWriteProtection methods.
rejectMedia |
Reject new media.
protected
virtual void rejectMedia( void);
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.
synchronizeCache |
public
virtual IOReturn synchronizeCache( IOService *client);
client
Client requesting the cache synchronization.
Returns the status of the cache synchronization.
Flush the cached data in the storage object, if any, synchronously.
validateNewMedia |
Verify that new media is acceptable.
protected
virtual bool validateNewMedia( void);
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.
write |
public
virtual void write( IOService *client, UInt64 byteStart, IOMemoryDescriptor *buffer, IOStorageCompletion completion);
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.
completion
Completion routine to call once the data transfer is complete.
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.
_ejectable |
protected
bool _ejectable;
True if the media is ejectable under software control.
_lockable |
protected
bool _lockable;
True if the media can be locked in the device under software control.
_maxBlockNumber |
protected
UInt64 _maxBlockNumber;
The maximum allowable block number for the media, zero-based.
_maxReadByteTransfer |
protected
UInt64 _maxReadByteTransfer;
The maximum byte transfer allowed for read operations.
_maxWriteByteTransfer |
protected
UInt64 _maxWriteByteTransfer;
The maximum byte transfer allowed for write operations.
_mediaBlockSize |
protected
UInt64 _mediaBlockSize;
The block size of the media, in bytes.
_mediaObject |
protected
IOMedia * _mediaObject;
A pointer to the media object we have instantiated (if any).
_mediaPresent |
protected
bool _mediaPresent;
True if media is present in the device; False if not.
_mediaStateLock |
private
IOLock * _mediaStateLock;
A lock used to protect during media checks.
_mediaType |
protected
UInt32 _mediaType;
Type of the media (can be used to differentiate between the different types of CD media, DVD media, etc).
_pollIsExpensive |
protected
bool _pollIsExpensive;
True if polling is expensive; False if not.
_pollIsRequired |
protected
bool _pollIsRequired;
True if we must poll to detect media insertion or removal.
_removable |
protected
bool _removable;
True if the media is removable; False if it is fixed (not removable).
_writeProtected |
protected
bool _writeProtected;
True if the media is write-protected; False if not.
Statistics |
Indices for the different statistics that getStatistics() can report.
public
enum Statistics { kStatisticsReads, kStatisticsBytesRead, kStatisticsTotalReadTime, kStatisticsLatentReadTime, kStatisticsReadRetries, kStatisticsReadErrors, kStatisticsWrites, kStatisticsSingleBlockWrites, kStatisticsBytesWritten, kStatisticsTotalWriteTime, kStatisticsLatentWriteTime, kStatisticsWriteRetries, kStatisticsWriteErrors };
kStatisticsReads
Number of read operations thus far.
kStatisticsBytesRead
Number of bytes read thus far.
kStatisticsTotalReadTime
Nanoseconds spent performing reads thus far.
kStatisticsLatentReadTime
Nanoseconds of latency during reads thus far.
kStatisticsReadRetries
Number of read retries thus far.
kStatisticsReadErrors
Number of read errors thus far.
kStatisticsWrites
Number of write operations thus far.
kStatisticsSingleBlockWrites
Number of write operations for a single block thus far.
kStatisticsBytesWritten
Number of bytes written thus far.
kStatisticsTotalWriteTime
Nanoseconds spent performing writes thus far.
kStatisticsLatentWriteTime
Nanoseconds of latency during writes thus far.
kStatisticsWriteRetries
Number of write retries thus far.
kStatisticsWriteErrors
Number of write errors thus far.
|
Last Updated: 2009-02-23