ADC Home > Reference Library > Reference > Darwin > Kernel Framework Reference

 


IOBlockStorageDriver

Inherits from:
Declared In:

Overview

The common base class for generic block storage drivers.

Discussion

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.



Functions

acceptNewMedia

React to new media insertion.

addToBytesTransferred
allocateContext
breakUpRequest
checkForMedia

Check if media has newly arrived or disappeared.

constrainByteCount

Constrain the byte count for this IO to device limits.

deblockRequest
decommissionMedia

Decommission an existing piece of media that has gone away.

deleteContext
ejectMedia
executeRequest
formatMedia
getDeviceTypeName

Return the desired device name.

getFormatCapacities
getMediaBlockSize
getMediaState
getStatistic
getStatistics
handleClose
handleIsOpen
handleOpen
handleStart
handleYield
incrementErrors
incrementRetries
initMediaState

Initialize media-related instance variables.

instantiateDesiredMediaObject

Create an IOMedia object for media.

instantiateMediaObject

Create an IOMedia object for media.

isMediaEjectable
isMediaPollExpensive
isMediaPollRequired
lockMedia
mediaStateHasChanged

React to a new media insertion or a media removal.

pollMedia
prepareRequest
read
recordMediaParameters

Obtain media-related parameters on media insertion.

rejectMedia

Reject new media.

synchronizeCache
validateNewMedia

Verify that new media is acceptable.

write

acceptNewMedia


React to new media insertion.

protected

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.


addToBytesTransferred


protected

virtual void addToBytesTransferred( UInt64 bytesTransferred, UInt64 totalTime, UInt64 latentTime, bool isWrite);
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.


allocateContext


protected

virtual Context * allocateContext();
Return Value

Context structure.

Discussion

Allocate a context structure for a read/write operation.


breakUpRequest


protected

virtual void breakUpRequest( UInt64 byteStart, IOMemoryDescriptor *buffer, IOStorageCompletion completion, Context *context);
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.

completion

Completion routine to call once the data transfer is complete.

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.


checkForMedia


Check if media has newly arrived or disappeared.

protected

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.


constrainByteCount


Constrain the byte count for this IO to device limits.

protected

virtual UInt64 constrainByteCount( UInt64 requestedCount, bool isWrite);
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.


deblockRequest


protected

virtual void deblockRequest( UInt64 byteStart, IOMemoryDescriptor *buffer, IOStorageCompletion completion, Context *context);
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.

completion

Completion routine to call once the data transfer is complete.

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.


decommissionMedia


Decommission an existing piece of media that has gone away.

protected

virtual IOReturn decommissionMedia( bool forcible);
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.


deleteContext


protected

virtual void deleteContext( Context *context);
Parameters
context

Context structure to be deleted.

Discussion

Delete a context structure from a read/write operation.


ejectMedia


public

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.


executeRequest


protected

virtual void executeRequest( UInt64 byteStart, IOMemoryDescriptor *buffer, IOStorageCompletion completion, Context *context);
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.

completion

Completion routine to call once the data transfer is complete.

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.


formatMedia


public

virtual IOReturn formatMedia( UInt64 byteCapacity);
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.


getDeviceTypeName


Return the desired device name.

protected

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.


getFormatCapacities


public

virtual UInt32 getFormatCapacities( UInt64 *capacities, UInt32 capacitiesMaxCount) 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.


getMediaBlockSize


protected

virtual UInt64 getMediaBlockSize() const;
Return Value

Natural block size, in bytes.

Discussion

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


getMediaState


public

virtual IOMediaState getMediaState() const;
Return Value

An IOMediaState value.

Discussion

Ask the driver about the media's current state.


getStatistic


public

virtual UInt64 getStatistic( Statistics statistic) const;
Parameters
statistic

Statistic index (an IOBlockStorageDriver::Statistics index).

Return Value

Statistic value.

Discussion

Ask the driver to report one of its operating statistics.


getStatistics


public

virtual UInt32 getStatistics( UInt64 *statistics, UInt32 statisticsMaxCount) 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.


handleClose


protected

virtual void handleClose( IOService *client, IOOptionBits options);
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().


handleIsOpen


protected

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().


handleOpen


protected

virtual bool handleOpen( IOService *client, IOOptionBits options, 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().


handleStart


protected

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.


handleYield


protected

virtual bool handleYield( IOService *provider, IOOptionBits options = 0, void *argument = 0);
Parameters
provider

This object's provider.

Discussion

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);
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.


incrementRetries


protected

virtual void incrementRetries( bool isWrite);
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.


initMediaState


Initialize media-related instance variables.

protected

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.


instantiateDesiredMediaObject


Create an IOMedia object for media.

protected

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.


instantiateMediaObject


Create an IOMedia object for media.

protected

virtual IOMedia * instantiateMediaObject( UInt64 base, UInt64 byteSize, UInt32 blockSize, 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.


isMediaEjectable


public

virtual bool isMediaEjectable() const;
Return Value

Returns true if the media is ejectable, false otherwise.

Discussion

Ask the driver whether the media is ejectable.


isMediaPollExpensive


public

virtual bool isMediaPollExpensive() const;
Return Value

Returns true if polling the media is expensive, false otherwise.

Discussion

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;
Return Value

Returns true if polling the media is required, false otherwise.

Discussion

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);
Parameters
lock

Pass true to lock the media, otherwise pass false to unlock the media.

Return Value

An IOReturn code.

Discussion

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);
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.


pollMedia


public

virtual IOReturn pollMedia();
Return Value

An IOReturn code.

Discussion

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, 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.


read


public

virtual void read( IOService *client, UInt64 byteStart, 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.


recordMediaParameters


Obtain media-related parameters on media insertion.

protected

virtual IOReturn recordMediaParameters( void);
Discussion

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);
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.


synchronizeCache


public

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.


validateNewMedia


Verify that new media is acceptable.

protected

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.


write


public

virtual void write( IOService *client, UInt64 byteStart, 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.

Member Data


_ejectable


protected

bool _ejectable;
Discussion

True if the media is ejectable under software control.


_lockable


protected

bool _lockable;
Discussion

True if the media can be locked in the device under software control.


_maxBlockNumber


protected

UInt64 _maxBlockNumber;
Discussion

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


_maxReadByteTransfer


protected

UInt64 _maxReadByteTransfer;
Discussion

The maximum byte transfer allowed for read operations.


_maxWriteByteTransfer


protected

UInt64 _maxWriteByteTransfer;
Discussion

The maximum byte transfer allowed for write operations.


_mediaBlockSize


protected

UInt64 _mediaBlockSize;
Discussion

The block size of the media, in bytes.


_mediaObject


protected

IOMedia * _mediaObject;
Discussion

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


_mediaPresent


protected

bool _mediaPresent;
Discussion

True if media is present in the device; False if not.


_mediaStateLock


private

IOLock * _mediaStateLock;
Discussion

A lock used to protect during media checks.


_mediaType


protected

UInt32 _mediaType;
Discussion

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


_pollIsExpensive


protected

bool _pollIsExpensive;
Discussion

True if polling is expensive; False if not.


_pollIsRequired


protected

bool _pollIsRequired;
Discussion

True if we must poll to detect media insertion or removal.


_removable


protected

bool _removable;
Discussion

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


_writeProtected


protected

bool _writeProtected;
Discussion

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

Enumerations


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 };
Constants
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.


Did this document help you?
Yes: Tell us what works for you.
It’s good, but: Report typos, inaccuracies, and so forth.
It wasn’t helpful: Tell us what would have helped.

 

Last Updated: 2008-12-19