Advanced SCSI Programming Interface (ASPI) OS/2 Specification

From EDM2
Jump to: navigation, search
Storage Device Driver Reference
  1. About This Book
  2. Introduction to DASD, SCSI, and CD-ROM Programming Interfaces
  3. Installation of OS/2, DASD, SCSI, and CD-ROM Device Drivers
  4. Adapter Device Driver Development Considerations
  5. DASD, SCSI, and CD-ROM Device Manager Interface Specification
  6. Error Handling
  7. Adapter Device Driver Command-Line Parameters
  8. DASD IOCtl Device Driver Test Tool
  9. Optical IOCtl Device Driver Test Tool
  10. Using Filter Device Drivers
  11. Library and Services
  12. CD-ROM Device Manager Interface Specification
  13. CD-ROM Device Driver Test Tool
  14. Building an OS/2 Virtual Disk Driver
  15. OS2DASD.DMD - Technical Reference
  16. Boot Record Architecture
  17. Extended Device Driver Interface Specification
  18. I/O Request Block - C Definitions
  19. OS/2 SCSI Device Driver Interface Specification
  20. Advanced SCSI Programming Interface (ASPI) OS/2 Specification
  21. Adapter Device Driver Interface Questions and Answers
  22. Device Driver Test Tool (DDTT)
  23. Glossary

Reprint Courtesy of International Business Machines Corporation, © International Business Machines Corporation

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:

 ASPI_Real       DW              Real Mode offset of ASPI entry point
                 DW              Real Mode CS segment of ASPI entry point
 Real_DS         DW              Real Mode DS of ASPI entry point
 ASPI_Prot       DW              Protected Mode offset of ASPI entry point
                 DW              Protected Mode CS selector of ASPI entry point
 Prot_DS         DW              Protected Mode DS of ASPI entry point

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:

               PUSH      AX                  ;Save AX
               PUSH      @ASPI_SRB           ;Push pointer to ASPI SRB
               SMSW      AX                  ;Check mode of processor
               TEST      AX,PROTECT_MODE
               JNZ       PROT_CALL

               PUSH      Real_DS
               CALL      [ASPI_REAL]
               JMP       CALL_DONE

PROT_CALL:     PUSH      Prot_DS
               CALL      [ASPI_PROT]

CALL_DONE:     ADD       SP,6                ;Restore the stack
               POP       AX

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:

   PUSH    @DATA_BUFFER            ;Not Applicable
   PUSH    @REQUEST_BLOCK          ;Parameter List = SRB
   PUSH    40H                     ;Function Code
   PUSH    80H                     ;Function Category
   PUSH    ASPI_Handle             ;File handle from DosOpen
   CALL    DOSDEVIOCTL

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.

Storage-img3.gif

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:

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

The previous two problems can be solved by the use of optional command line switches such as the following:

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

Offset # Bytes Description R/W*
00h (00) 01h (01) Command Code W
01h (01) 01h (01) Status R
02h (02) 01h (01) Host Adapter Number W
03h (03) 01h (01) SCSI Request Flags W
04h (04) 04h (04) Reserved for Expansion = 0 -
  • 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.

Valid ASPI Command Codes
Command Code Description
00h Host Adapter Inquiry
01h Get Device Type
02h Execute SCSI I/O Command
03h Abort SCSI I/O Command
04h Reset SCSI Device
05h Set Host Adapter Parameters
06h-7Fh Reserved for Future Expansion
80h-FFh Reserved for Vendor Unique

ASPI Status Bytes

Status Byte Description
00h SCSI Request In Progress
01h SCSI Request Completed Without Error
02h SCSI Request Aborted By Host
04h SCSI Request Completed With Error
80h Invalid SCSI Request
81h Invalid Host Adapter Number
82h SCSI Device Not Installed

ASPI Command Code = 0: Host Adapter Inquiry

Offset # Bytes Description R/W*
00h (00) 01h (01) Command Code = 0 W
01h (01) 01h (01) Status R
02h (02) 01h (01) Host Adapter Number W
03h (03) 01h (01) SCSI Request Flags W
04h (04) 04h (04) Reserved for Expansion = 0 -
08h (08) 01h (01) Number of Host Adapters R
09h (09) 01h (01) Target ID of Host Adapter R
0Ah (10) 10h (16) SCSI Manager ID R
1Ah (26) 10h (16) Host Adapter ID R
2Ah (42) 10h (16) Host Adapter Unique Parameters R
  • 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

Offset # Bytes Description R/W*
00h (00) 01h (01) Command Code = 1 W
01h (01) 01h (01) Status R
02h (02) 01h (01) Host Adapter Number W
03h (03) 01h (01) SCSI Request Flags W
04h (04) 04h (04) Reserved for Expansion = 0 -
08h (08) 01h (01) Target ID W
09h (09) 01h (01) LUN W
0Ah (10) 01h (01) Peripheral Device Type of Target/LUN R
  • 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

Offset # Bytes Description R/W*
00h (00) 01h (01) Command Code = 2 W
01h (01) 01h (01) Status R
02h (02) 01h (01) Host Adapter Number W
03h (03) 01h (01) SCSI Request Flags W
04h (04) 02h (02) Length of Scatter/Gather List W
06h (06) 02h (02) Reserved for Expansion = 0 -
08h (08) 01h (01) Target ID W
09h (09) 01h (01) LUN W
0Ah (10) 04h (04) Data Allocation Length W
0Eh (14) 01h (01) Sense Allocation Length (N) W
0Fh (15) 04h (04) Data Buffer Pointer W
13h (19) 04h (04) SRB Link Pointer W
17h (23) 01h (01) SCSI CDB Length (M) W
18h (24) 01h (01) Host Adapter Status R
19h (25) 01h (01) Target Status R
1Ah (26) 02h (02) Real Mode Post Routine Offset** W
1Ch (28) 02h (02) Real Mode Post Routine CS** W
1Eh (30) 02h (02) Real Mode Post Routine DS** W
20h (32) 02h (02) Protected Mode Post Routine Offset W
22h (34) 02h (02) Protected Mode Post Routine CS W
24h (36) 02h (02) W
26h (38) 04h (04) Physical Address of SRB W
2Ah (42) 16h (22) Reserved for ASPI Workspace -
40h (64) M SCSI Command Descriptor Block (CDB) W
40h+M N Sense Allocation Area R
  • 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:

7 6 5 4 3 2 1 0
Rsvd Rsvd SGE Direction Bits Direction Bits Reserved Link Post

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

Offset # Bytes Description R/W*
00h (00) 01h (01) Command Code = 3 W
01h (01) 01h (01) Status R
02h (02) 01h (01) Host Adapter Number W
03h (03) 01h (01) SCSI Request Flags W
04h (04) 04h (04) Reserved for Expansion = 0 -
08h (08) 04h (04) Physical SRB Pointer W
  • 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

Offset # Bytes Description R/W*
00h (00) 01h (01) Command Code = 4 W
01h (01) 01h (01) Status R
02h (02) 01h (01) Host Adapter Number W
03h (03) 01h (01) SCSI Request Flags W
04h (04) 04h (04) Reserved for Expansion = 0 -
08h (08) 01h (01) Target ID W
09h (09) 01h (01) LUN W
0Ah (10) 0Eh (14) Reserved -
18h (24) 01h (01) Host Adapter Status R
19h (25) 01h (01) Target Status R
1Ah (26) 02h (02) Real Mode POST Routine Offset** W
1Ch (28) 02h (02) Real Mode POST Routine CS** W
1Eh (30) 02h (02) Real Mode POST Routine DS** W
20h (32) 02h (02) Protected Mode POST Routine Offset W
22h (34) 02h (02) Protected Mode POST Routine CS W
24h (36) 02h (02) Protected Mode POST Routine DS W
26h (38) 16h (22) Reserved for ASPI Workspace -
  • 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:

7 6 5 4 3 2 1 0
Rsvd Rsvd Rsvd Rsvd Rsvd Rsvd Rsvd Post

The Post bit specifies whether posting is enabled (bit 0 = 1) or disabled ( bit 0 = 0).

ASPI Command Code = 5: Set Host Adapter Parameters

Offset # Bytes Description R/W*
00h (00) 01h (01) Command Code = 5 W
01h (01) 01h (01) Status R
02h (02) 01h (01) Host Adapter Number W
03h (03) 01h (01) SCSI Request Flags W
04h (04) 04h (04) Reserved for Expansion = 0 -
08h (08) 10h (16) Host Adapter Unique Parameters W
  • 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.