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.