Advanced SCSI Programming Interface (ASPI) OS/2 Specification

This chapter describes the function of ASPI, gives an overview of the steps involved in programming ASPI for OS/2, and discusses the SCSI request block and ASPI command codes executed by the ASPI manager.

Introduction to ASPI
ASPI is an application interface that allows easier access to SCSI devices. When running DOS, users typically load an ASPI manager that routes all requests directly to the hardware. ASPI drivers (such as ASPIDISK and ASPICD) send requests to the ASPI manager, which then sends the command to the appropriate device.

The device driver model used by OS/2 is layered (similar to ASPI) so that an adapter device driver (ADD) is responsible for knowing about the hardware dependencies of a particular SCSI adapter. Applications that want to send ASPI requests do so by routing these requests to a device manager (OS2ASPI.DMD) and then converts them into requests recognizable to any ADD.

The ASPI support currently embedded within OS/2 2.x allows any OS/2 application to send commands to a SCSI device. However, there are a large number of DOS and Windows applications that could be supported if the commands were routed to OS2ASPI.DMD.

VASPI.SYS is a virtual device driver that allows DOS applications to issue SCSI commands that will be handled by OS2ASPI.DMD. If you have an existing DOS or Windows ASPI application, it should now be able to run in a virtual DOS session under OS/2 2.x.

Accessing ASPI
Device drivers that need to access ASPIN, must determine the address of the ASPI entry point through an OS/2 Attach DevHelp call as follows: SCSIMGR$             DB   'SCSIMGR$',0 Return_Data_Buffer   DB   12      DUP     (?) MOV BX,OFFSET SCSIMGR MOV DI,OFFSET Return_Data_Buffer MOV DL,DevHlp_AttachDD CALL [DevHlp] On return from the Attach DevHelp call, a clear-carry flag indicates that the SCSI manager SCSIMGR$ was found and the return data is valid. A set-carry flag indicates that the SCSI manager was not found. The return data buffer has the following format:
 * Note:ASPI_Real and Real_DS are used by OS/2 1.x only. Information returned under OS/2 2.x is irrelevant.

Calling ASPI
When the ASPI entry-point parameters have been successfully determined, calling ASPI uses the values appropriate to the mode of the processor. The address of the ASPI request block and the DS of the ASPI entry point must be pushed onto the stack before making a FAR call. The following is an example of how to call ASPI:

Accessing ASPI At Initialization Time
At initialization time, an OS/2 device driver lacks the privilege level for making a FAR call to the ASPI interface. To circumvent this restriction, the SCSI manager provides a special IOCtl which can be used by a driver to pass an ASPI request. To use the IOCtl, the driver must first use a DosOpen call to get a file handle for the SCSI manager. Having completed this successfully, the driver can call ASPI at initialization time as follows: When the driver has returned from initialization, this access method is no longer valid.

ASPI and OS/2 2.x
The device driver architecture for OS/2 2.x is divided into several basic layers. The Device Manager Drivers (DMD) receive requests from the file systems and other device drivers. These requests are passed on to an Adapter Device Driver (ADD), which then sends the appropriate command to the host adapter.

ASPI for OS/2 2.x is a translation layer, and has been implemented as a device driver (OS2ASPI.DMD). An application can send SRBs to any SCSI adapter which has an ADD installed. It is no longer possible to set host adapter parameters because OS2ASPI has no direct control over the host adapter.



Target Allocation With OS/2 2.x
The device driver architecture for OS/2 2.x is structured so that targets controlled by an ADD must be allocated to an individual (DMD). For example, when the system boots, OS2DASD.DMD is usually the first device manager loaded, and it automatically searches for all available hard drives and permanently allocates them for use by the file systems. Other DMDs usually do something similar with targets that they assume should be controlled by them.

The standard method for preventing a DMD from allocating a particular target is through the use of command line switches on the ADD that handles the device. If you are planning to use ASPI to control a device that may be allocated by a DMD that loads before OS2ASPI.DMD, be sure to specify that the device manager in question is not allowed access to it.


 * If you are writing an ASPI application for a magneto-optical drive (target 6 on an AHA-1540) that returns device type 0 (DASD) in the Inquiry data, you must be sure to prevent OS2DASD from accessing it by adding the parameter /!DM6 to disable ID 6. See the following example: BASEDEV=AHA154X.ADD /A:0 /!DM:6
 * If you are writing an ASPI application for a device that also may be controlled by a device driver through os2scsi.dmd (target 6 on an AHA-1540), you can also prevent OS2SCSI from accessing it by adding the parameter /!SM6 for ID 6. See the following example: BASEDEV=AHA154X.ADD /A:0 /!SM:6

Currently, only OS2DASD.DMD and OS2SCSI.DMD can be controlled in this manner because they are the only DMDs to be mentioned in IBM's specification for ADDs. For a complete explanation of command line switches supported by the ADD that are provided with OS/2 2.1, search for SCSI in the OS/2 Command Line Reference. Device managers can handle allocations in one of two ways: wait for a device driver to issue an allocation request (OS2SCSI.DMD performs this) or permanently allocate the device during system boot (OS2DASD.DMD and OS2CDROM.DMD perform this function).

Typically, OS2ASPI will not allocate a device until the first execute I/O command is issued. This command allows it to scan for devices and not interfere with them until an application decides to issue a command. However, once this allocation takes place, OS2ASPI will not release the device because it can never be sure when the application is finished with it.

OS2ASPI.DMD can be used without any command line switches, but there are usually two situations that can arise that OS2ASPI must address: The previous two problems can be solved by the use of optional command line switches such as the following:
 * A user wants to utilize two applications by way of different interfaces (such as OS2ASPI and OS2SCSI) and both need to access the device. In this case, if the application using OS2SCSI is well-behaved, it will release the device when it is finished and OS2ASPI will be able to allocate it. If OS2ASPI does not release the device, the OS2SCSI application will not be able to access the device until the system is rebooted and the device allocation information is reset.
 * A user wants to access a device that has been permanently allocated by another device manager, such as a diagnostic that reports information about the system configuration. However, if the devices are allocated to another manager, the application will never be able to see them.
 * /ALL - This switch instructs OS2ASPI.DMD to allow commands to be issued to ANY device on the SCSI bus, even those allocated by other managers.
 * Warning: Commands should be issued to devices under the control of other managers with extreme caution. If you are using the /ALL switch and plan to issue commands to devices that are shared with another manager, try and limit them to non-destructive commands such as Inquiry and Test Unity Ready.
 * /SHARE - This switch instructs OS2ASPI.DMD to release any target after each command, allowing multiple managers to access a target at different times. Because this requires more commands to be issued to the driver, there will be a slight performance penalty when this switch is used.
 * Warning: When sharing devices and sending multiple concurrent requests, it is possible that allocation/deallocation of the device will cause a command to be rejected. This switch is best suited for use when you have applications that require different managers, but will not be used simultaneously.

BASEDEV=OS2ASPI.DMD /SHARE BASEDEV=OS2ASPI.DMD /ALL

SCSI Request Block (SRB)
A SCSI Request Block (SRB) contains the command to be executed by the ASPI manager and is used by both drivers and application programs. An SRB consists of an SRB header followed by additional fields dependent on the command code. All request blocks have an 8-byte header.
 * The R/W column indicates whether the field is sent to ASPI (W), returned from ASPI (R), or reserved (-).
 * Command Code: The Command Code field indicates which of the ASPI services is being accessed. Refer to ASPI Command Codes.
 * Status: The Status Byte field is used to post the status of the command. Refer to ASPI Status Bytes.
 * Host Adapter Number: The Host Adapter Number field specifies which installed host adapter the request is intended for. Host adapter numbers are always assigned by the SCSI manager layer beginning with zero.
 * SCSI Request Flags: The SCSI Request Flags field definition is command-code specific.
 * Reserved for Expansion: The last four bytes of the header are reserved and must be zero.

ASPI Command Codes
The ASPI Command Codes, including valid ASPI command codes and ASPI status bytes and their descriptions are given as follows.

ASPI Command Code = 0: Host Adapter Inquiry

 * The R/W column indicates whether the field is sent to ASPI (W), returned from ASPI (R), or reserved (-).

The status byte always returns with a non-zero status. A SCSI Request Completed Without Error (01h) status indicates that the remaining fields are valid. An Invalid Host Adapter Number (81h) status indicates that the specified host adapter is not installed.

This function gets information on the installed host adapter hardware, including number of host adapters installed. It can be issued once with host adapter zero specified, to get the number of host adapters. If further information is desired, it can be issued for each individual host adapter.
 * The SCSI Request Flags field is currently undefined for this command and should be zeroed.
 * The SCSI Manager ID field contains a 16-byte ASCII string describing the SCSI manager.
 * The Host Adapter ID field contains a 16-byte ASCII string describing the SCSI host adapter.
 * The definition of the Host Adapter Unique Parameters field is left to implementation notes, specific to a particular host adapter.

ASPI Command Code = 1: Get Device Type

 * The R/W column indicates whether the field is sent to ASPI (W), returned from ASPI (R), or reserved (-).

This command always returns with a non-zero status.

A SCSI Request Completed Without Error (01h) status indicates that the specified device is installed and the peripheral device type field is valid. A SCSI Device Not Installed Error (82h) indicates that the peripheral device type field is not valid.

This command is intended for use by various drivers, during initialization, for identifying the targets that they need to support. A CD-ROM driver, for example, can scan each Target/LUN on each installed host adapter looking for the device type corresponding to CD-ROM devices. This eliminates the need for each driver to duplicate the effort of scanning the SCSI bus for devices.

The peripheral device type is determined by sending a SCSI Inquiry command to the given target. Refer to any SCSI specification to learn more about the Inquiry command. The SCSI Request Flags field is currently undefined for this command and should be zeroed.

ASPI Command Code = 2: Execute SCSI I/O Command

 * The R/W column indicates whether the field is sent to ASPI (W), returned from ASPI (R), or reserved (-).
 * Used by OS/2 1.x only. Fields are not used under OS/2 2.x.

This command usually returns with zero status indicating that the request was queued successfully. Command completion can be determined by polling for non-zero status or through the use of the Post Routine Address field. If you are going to use polling, interrupts must be enabled. The SCSI Request Flags byte is defined as follows: The Post bit specifies whether posting is enabled (bit 0 = 1) or disabled ( bit 0 = 0). The Link bit specifies whether linking is enabled (bit 1 = 1) or disabled (bit 1 = 0). The Direction Bits specify the direction of the transfer:
 * 00 - Direction determined by SCSI command. Length not checked.
 * 01 - Transfer from SCSI target to host. Length checked.
 * 10 - Transfer from host to SCSI target. Length checked.
 * 11 - No data transfer.

The Scatter/Gather Enable (SGE) bit specifies whether scatter/gather is enabled (bit 5=1) or disabled (bit 5=0). The Target ID and LUN fields are used to specify the peripheral device involved in the I/O.

The Data Allocation Length field indicates the number of bytes to be transferred. If the SCSI command to be executed does not transfer data (such as Rewind, Start Unit, and so forth) the data allocation length must be set to zero.

The Length of Scatter/Gather List field is valid only when the scatter/gather enable bit in the flags is set. It contains the number of descriptors in the array pointed by the Data Buffer Pointer field.

The Sense Allocation Length field indicates the number of bytes allocated at the end of the SRB for sense data. A request sense is automatically generated if a check condition is presented at the end of a SCSI command.

The Data Buffer Pointer field is a pointer to the I/O data buffer. When scatter/gather is enabled, this field is a physical pointer to a scatter/ gather list. A scatter/gather list is made up of one or more descriptors of the following format: |DWORD Buffer Pointer | |-| | DWORD Buffer Size  | The SRB Link Pointer field is a pointer to the next SRB in a chain. See the SCSI Command Linking With ASPI for more information.

The SCSI CDB Length field establishes the length, in bytes, of the SCSI Command Descriptor Block (CDB).

The Host Adapter Status field reports the host adapter status, as follows:
 * 00h - Host adapter did not detect any error
 * 11h - Selection timeout
 * 12h - Data overrun/underrun
 * 13h - Unexpected bus free
 * 14h - Target bus phase sequence failure

The Target Status field reports the target's SCSI status, including:
 * 00h - No target status
 * 02h - Check status (sense data is in sense allocation area)
 * 08h - Specified target/LUN is busy
 * 18h - Reservation conflict


 * Note: The host adapter status and the target status are valid only when the status byte is either 2 or 4.

The Post Routine Address field, if specified, is called when the I/O is completed.

The SCSI Command Descriptor Block (CDB) field contains the CDB as defined by the target's SCSI command set. The length of the SCSI CDB is specified in the SCSI Command Length field.

The Sense Allocation Area is filled with sense data on a check condition. The maximum length of this field is specified in the Sense Allocation Length field. The target can return fewer than the number of sense bytes requested.

SCSI Command Linking With ASPI
ASPI provides the ability to use SCSI linking to guarantee the sequential execution of several commands. This feature requires that the involved target(s) support SCSI linking.

To use SCSI linking, a chain of SRBs is built with the SRB link pointer used to link the elements together. The link bit should be set in the SCSI request flags byte of all SRBs except the last in the chain. When a SCSI target returns indicating that the linked command is complete, the next SRB is immediately processed, and the appropriate CDB is dispatched. When using SCSI linking, make sure that the linking flags in the SCSI CDB agree with the link bit in the SCSI request flags. Inconsistencies can cause unpredictable results. For example, setting the CDB up for linking but failing to set the link bit may result in a random address being used for the next SRB pointer.

Any error returned from the target on a linked command will break the chain. Note that if linking without tags is used, as defined in SCSI, posting may not occur on any elements in the chain until the chain is complete. If you have the post bit set in each SRB's SCSI request flags byte, then each SRB's post routine will be called.


 * Note: Do not use SCSI linking. Many SCSI targets, as well as SCSI host adapters, do not handle SCSI linking and will not work with your ASPI module.

ASPI Command Posting
Posting refers to the SCSI manager making a FAR call to a post routine as specified in the SRB. This can be used by a driver much like a hardware interrupt might be used. Post routines have all the same privileges and restrictions as a hardware-interrupt service routine in OS/2. Posting is optional, but should almost always be used in OS/2.

To use Posting, the post bit must be set in the SCSI request flags. The post routine is called to indicate that the requested I/O is complete. The specific SRB completed is indicated by the four-byte SRB pointer on the stack. The DS of the post routine as specified in the SRB is also passed to the stack. The post routine will be called with interrupts enabled. It is assumed that all registers are preserved by the post routine. ASPI_Post         proc         far push        bp             ;Use bp as a reference mov         bp,sp pusha                      ;Save all registers push        es             ;Save ES                    mov          bx,[bp+6]      ;Load DS of POST routine mov         ax,[bp+10]     ;Physical address of SRB--&gt;AX:BX mov         ax,[bp+8] .                                .                                 .                    pop          es             ;Restore registers popa pop         ds                    pop          bp                    retf ASPI_Post                      endp

When your post routine is first entered, the stack looks like this: /--\ Top of Stack [SP+0] > | Return Address (Offset)  | |--|              [SP+2] > | Return Address (Segment) | |--|              [SP+4] > | SRB Pointer (Offset)     | |--|              [SP+6] > | SRB Pointer (Segment)    | |--|                       |        . . .             |                        |--|                        |        . . .             |                        |--|                        |        . . .             |                        |                          |                        \--/ You can issue any ASPI command from within your post routine except for an abort command. Your post routine should get in and out as quickly as possible.

ASPI Command Code = 3: Abort SCSI I/O Request

 * The R/W column indicates whether the field is sent to ASPI (W), returned from ASPI (R), or reserved (-).

This command is used to request that an SRB be aborted. It should be issued on any I/O request that has not completed if the driver wishes to timeout on that request. Success of the Abort command is never assured.

This command always returns with SCSI Request Completed Without Error, but the actual failure or success of the abort operation is indicated by the status eventually returned in the SRB specified.

The SCSI Request Flags field is currently undefined for this command and should be zeroed. The SRB Pointer to Abort field contains a pointer to the SRB which is to be aborted.


 * Note: An abort command should not be issued during a post routine.

ASPI Command Code = 4: Reset SCSI Device

 * The R/W column indicates whether the field is sent to ASPI (W), returned from ASPI (R), or reserved (-). **Used by OS/2 1.x only. Fields are not used under OS/2 2.x.

This command is used to reset a specific SCSI target. Note that the structure passed is almost identical to the execute SCSI I/O SRB except that some of the fields are not used.

This command usually returns with zero status indicating that the request was queued successfully. Command completion can be determined by polling for non-zero status or through the use of posting. The SCSI Request Flags byte is defined as follows: The Post bit specifies whether posting is enabled (bit 0 = 1) or disabled ( bit 0 = 0).

ASPI Command Code = 5: Set Host Adapter Parameters

 * The R/W column indicates whether the field is sent to ASPI (W), returned from ASPI (R), or reserved (-).

The definition of the host adapter unique parameters is left to implementation notes specific to a particular host adapter.