Copyright ©1995 by NeXT Computer, Inc. All Rights Reserved.
IOSCSIControllerExported |
Adopted By: | IOSCSIController class | |
Declared In: | driverkit/scsiTypes.h |
Protocol Description |
Indirect device drivers for devices attached to SCSI controllers use the methods in this protocol to communicate with IOSCSIController. |
Method Types |
Allocating well-aligned buffers | allocateBufferOfLength:actualStart:actualLength: |
getDMAAlignment: |
Requesting I/O | executeRequest:buffer:client: |
maxTransfer |
Reserving SCSI targets | reserveTarget:lun:forOwner: |
releaseTarget:lun:forOwner: |
Resetting the SCSI bus | resetSCSIBus |
Getting the IOReturn equivalent of a sc_status_t value |
returnFromScStatus: |
Instance Methods |
allocateBufferOfLength:actualStart:actualLength: |
(void *)allocateBufferOfLength:(unsigned)length |
actualStart:(void **)actualStart actualLength:(unsigned *)actualLength |
Allocates and returns a pointer to some well-aligned memory. Well-aligned memory is necessary for calls to executeRequest:buffer:client:. You should use actualStart and actualLength when freeing the memory, as follows (italicized text delineated in angle brackets, that is << >>, is to be filled in with device-specific code): |
dataBuffer = [_controller allocateBufferOfLength:block_size
actualStart:&freePtr, actualLength:&freeLength];
<< Use the buffer... >>
IOFree(freePtr, freeLength);
Here's a typical use of this method: |
IODMAAlignment dmaAlign;
unsigned int alignment, alignedLength, freeLength;
void *alignedPtr = NULL;
unsigned int maxLength; /* Max length of the current transfer */
/* . . . */
[_controller getDMAAlignment:&dmaAlign];
if(<< we're doing a write >>)
alignment = dmaAlign.writeLength;
else
alignment = dmaAlign.readLength;
if(alignment > 1)
alignedLength = IOAlign(unsigned int, maxLength, alignment);
else
alignedLength = maxLength;
alignedPtr = [_controller allocateBufferOfLength:alignedLength
actualStart:&freePtr
actualLength:&freeLength];
<< If we're going to do a write, copy the data to alignedPtr.
Set up the request and submit it, as described in the
executeRequest:buffer:client: description. >>
<< Do any post-I/O processing that's necessary. >>
IOFree(freePtr, freeLength);
See also: getDMAAlignment: |
executeRequest:buffer:client: |
(sc_status_t)executeRequest:(IOSCSIRequest *)scsiRequest |
buffer:(void *)buffer client:(vm_task_t)client |
Executes the specified request. Indirect devices invoke this method whenever they need the IOSCSIController to perform I/O.
Subclasses of IOSCSIController must implement this method. A typical implementation of this method consists of the following: |
Using IOScheduleFunc() to schedule a timeout function to be called after scsiRequest->timeoutLength time has elapsed without I/O completion | ||
Sending the command descriptor block (CDB) specified in scsiRequest to the controller | ||
When the I/O has completed, unscheduling the timeout function |
This method should return scsiRequest->driverStatus, which should be set by the part of the driver that detected I/O completion or timeout.
Indirect devices use this method as shown below (italicized text delineated in angle brackets, that is << >>, is to be filled in with device-specific code): |
void *alignedPtr = NULL;
unsigned int alignedLength;
IOSCSIRequest request;
cdb_t cdb;
/* . . . */
if (<< we're going to be doing DMA >>) {
<< Ensure we have a well-aligned buffer that starts at alignedPtr
and continues for alignedLength bytes. See the
allocateBuffer: description for one way of doing this. >>
} else {
alignedLength = 0;
alignedPtr = 0;
}
bzero(&request, sizeof(request));
request.target = [self target];
request.lun = [self lun];
request.read = << YES if this is a read; NO otherwise >>;
request.maxTransfer = alignedLength;
request.timeoutLength = << some timeout length, in seconds >>;
request.disconnect = << 1 if allowed to disconnect; otherwise 0 >>;
request.cdb = cdb;
<< Set up the cdb (command descriptor block) field. The type of this
field, cdb_t, is defined and described in the header file
bsd/dev/scsireg.h. >>
rtn = [_controller executeRequest:&request
buffer:alignedPtr
client:IOVmTaskSelf()];
getDMAAlignment: |
(void)getDMAAlignment:(IODMAAlignment *)alignment |
Returns the DMA alignment requirements for the current architecture. IOSCSIController subclasses can override this method to specify any device-specific alignment requirements. See the description of allocateBufferOfLength:actualStart:actualLength: for an example of using this method.
See also: allocateBufferOfLength:actualStart:actualLength: |
maxTransfer |
(unsigned)maxTransfer |
Returns the maximum number of bytes per DMA transfer. This is the maximum transfer that can be requested in a call to executeRequest:buffer:client:. |
releaseTarget:lun:forOwner: |
(void)releaseTarget:(unsigned char)target |
lun:(unsigned char)lun forOwner:owner |
Releases the specified target/lun pair. If owner hasn't reserved the pair, this method uses IOLog to print an error message.
See also: reserveTarget:lun:forOwner: |
reserveTarget:lun:forOwner: |
(int)reserveTarget:(unsigned char)target |
lun:(unsigned char)lun forOwner:owner |
Reserves the specified target/lun pair, if it isn't already reserved. This method is invoked by a client (for example, a SCSIDisk instance) to mark a particular target/lun as being in use by that client. Usually, this happens at probe: time; however, the SCSIGeneric driver uses this method at other times.
This method returns a nonzero value if the target/lun pair is already reserved. Otherwise, it returns zero. See also: releaseTarget:lun:forOwner: |
resetSCSIBus |
(sc_status_t)resetSCSIBus |
Resets the SCSI bus. Subclasses of IOSCSIController must implement this method so that it resets the SCSI bus. The sc_status_t enumerated type is defined and described in the header file bsd/dev/scsireg.h. |
returnFromScStatus: |
(IOReturn)returnFromScStatus:(sc_status_t)sc_status |
Returns the IOReturn value corresponding to the specified sc_status_t value. The sc_status_t enumerated type is defined and described in the header file bsd/dev/scsireg.h. |