ASPI For DOS Specification About This Chapter Read this chapter to find out: - An overview of the steps involved in programming ASPI for DOS - Accessing and calling ASPI - The SCSI request block and ASPI command codes executed by the ASPI manager Using ASPI – An Overview There are two steps involved in order for a driver to make use of ASPI: - Obtaining the ASPI entry point - Calling ASPI Typically the entry point is obtained once and ASPI calls are made multiple times within a device driver. ASPI function calls are used to return data about the ASPI -manager, host adapter, and SCSI devices, but are mainly used to execute SCSI I/O -requests. The ASPI layer is re-entrant and can accept function calls before previous calls have completed. A call will normally return immediately with zero status indicating that the request has been successfully queued. In order to continue program flow after the function completes, the driver either polls ASPI status or enables the post bit which turns control over to a specified routine upon completion of the ASPI call. Note: When a program makes a call to an ASPI manager, the manager uses the caller's stack. It is therefore necessary for the program to allocate enough stack memory for itself as well as the ASPI manager. There is no fixed amount of stack needed by all ASPI managers; a programmer needs to be aware of this constraint and test code with individual managers for compatibility. Accessing ASPI Device drivers wishing to access ASPI must open the driver by performing a DOS Int 21h function call OPEN A FILE as follows: On Entry: AX = 3D00h DS:DX = Pointer to SCSIMGR$, 0 On Return: AX = File handle if carry flag is not set Error code if carry flag is set Getting The ASPI Entry Point Device drivers can get the entry point to ASPI by performing a DOS Int 21h function call IOCTL READ as follows: On Entry: AX = 4402h DS:DX = Pointer to data returned (4 bytes) CX = 4 BX = File handle On Return: AX = Nothing Data returned in DS:DX contains the ASPI entry point: Byte 0-1: ASPI Entry Point Offset Byte 2-3: ASPI Entry Point Segment Closing ASPI Device drivers wishing to close ASPI must do it by performing a DOS Int 21h -function call CLOSE A FILE as follows: On Entry: AH = 3Eh BX = File handle On Return: AX = Error code if carry flag is set Nothing if carry flag is not set Calling ASPI The following is an example of how to call the ASPI manager: .MODEL SMALL .STACK 100h ;100h byte stack .DATA SCSIMgrString db “SCSIMGR$” dw 0 ;NULL-terminate string ASPI_Entry db 4 dup (?) SRB db 58 dup (0) ;Initialize SRB for Host ; Adapter Inquiry .CODE start: mov ax,@DATA mov ds,ax ;Init DS mov ax,03D00h lea dx,SCSIMgrString int 21h ;Open ASPI Manager jc NoASPIManager ;Branch if none found push ax ;Save ASPI File Handle mov bx,ax ;BX = File Handle mov ax,4402h lea dx,ASPI_Entry ;Store entry point here mov cx,4 ;Four bytes to transfer int 21h ;Get ASPI entry point mov ah,03Eh pop bx ;BX = ASPI File Handle int 21h ;Close ASPI Manager push ds ;Push SRB's segment lea bx,SRB push bx ;Push SRB's offset lea bx,ASPI_Entry call DWORD PTR [bx] ;Call ASPI add sp,4 ;Restore the stack . ASPI_Exit: mov ax,4C00h ;Exit to DOS int 21h ret NoASPIManager: . ;No ASPI Manager found!! jmp ASPI_Exit ;Handle it. END As shown in this sample code, the SRB's segment is first pushed onto the stack -followed by its offset. ASPI is then called directly. 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 eight-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 is used to indicate which of the ASPI services is being accessed. Refer to Valid ASPI Command Codes on page 2-7. Status The Status Byte field is used to post the status of the command. Refer to ASPI Status Bytes on page 2-7. 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 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 Get Disk Drive Information 07h-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) 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 will always return 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 is used to get 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) Peripheeral Device Type of Target/LU R *The R/W column indicates whether the field is sent to ASPI (W), returned from ASPI (R), or reserved (—). This command will always return with 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) 04h (04) 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) 02h (02) Data Buffer Pointer (Offset) W 11h (17) 02h (02) Data Buffer Pointer (Segment) W 13h (19) 02h (02) SRB Link Pointer (Offset) W 15h (21) 02h (02) SRB Link Pointer (Segment) 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) Post Routine Address (Offset) W 1Ch (28) 02h (02) Post Routine Address (Segment) W 1Eh (30) 22h (34) 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 (—). This command will usually return 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 (discussed later). Keep in mind that 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 Rsvd Direction Bits Rsvd 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 which direction the transfer is: 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 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 (i.e., Rewind, Start Unit, etc.) the Data Allocation Length must be set to zero. The Sense Allocation Length field indicates, in bytes, 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. You place the -logical address here. ASPI will convert it to the physical address in the case of a bus master or DMA transfer. The SRB Link Pointer field is a pointer to the next SRB in a chain. See the -discussion on linking 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 is used to report 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 is used to report 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 The POST Routine Address field, if specified, is called when the I/O is completed. See the discussion on posting for more information. 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. Note that 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. Note that the use of this feature requires the involved target(s) to 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: It is strongly recommended that you do not use SCSI linking. There are many SCSI targets, as well as SCSI host adapters, which do not handle SCSI linking and will not work with your ASPI module. ASPI Command Posting To use Posting, the post bit must be set in the SCSI request flags. Posting refers to the SCSI manager making a FAR call to a post routine as specified in the SRB. The post -routine is called to indicate that the SRB is complete. The specific SRB completed is indicated by a four-byte SRB pointer on the stack. It is assumed that all -registers are preserved by the post routine. The ASPI manager will first push the completed SRB's two-byte segment onto the stack followed by its two-byte offset. The following is a sample ASPI post handler: ASPI_Post proc far push bp mov bp,sp pusha ;Save all registers push ds push es mov bx,[bp+6] ;BX = SRBs offset mov es,[bp+8] ;ES = SRBs segment . ;ES:BX points to SRB . . pop es pop ds popa pop bp ;Restore all registers retf ; and return to ASPI ASPI_Post endp When your post routine is first entered, the stack will look as follows: Top of Stack [SP+0] —> Return Address (Offset) [SP+2] —> Return Address (Segment) [SP+4] —> SRB Pointer (Offset) [SP+6] —> SRB Pointer (Segment) ... ... ... You may 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. Posting can be used by device drivers and Terminate and Stay Resident (TSR) programs which need to operate in an interrupt driven fashion. ASPI Command Code = 3: Abort SCSI I/O Command 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) 02h (02) SRB Pointer to Abort (Offset) W 0Ah (10) 02h (12) SRB Pointer to Abort (Segment) 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) POST Routine Address (Offset) W 1Ch (28) 02h (02) POST Routine Address (Segment) W 1Eh (30) 02h (02) Reserved for ASPI Workspace — *The R/W column indicates whether the field is sent to ASPI (W), returned from ASPI (R), or reserved (—). This command is used to reset a specific SCSI target. Note that the structure passed is nearly 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 Reserved 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. ASPI Command Code = 6: Get Disk Drive Information Offset # Bytes Description R/W* 00h (00) 01h (01) Command Code = 6 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) Drive Flags R 0Bh (11) 01h (01) Int 13h Drive R 0Ch (12) 01h (01) Preferred Head Translation R 0Dh (13) 01h (01) Preferred Sector Translation R 0Eh (14) 0Ah (10) Reserved for Expansion = 0 — *The R/W column indicates whether the field is sent to ASPI (W), returned from ASPI (R), or reserved (—). ASPI managers that support this command code always return with a status of SCSI Request Completed Without Error (01h). ASPI managers that do not support this -command code always return with a status of Invalid SCSI Request (80h). This command is intended for use by SCSI disk drivers that need to determine which disk drives are already being controlled by some BIOS/DOS, and which disk drives are available for use by the disk driver. It also provides a means to determine which drives are not under control of the BIOS/DOS, yet still accessible via Int 13h. This is useful because many disk caching utilities will cache Int 13h requests, but not any disk driver requests. There are also some disk utility programs which will allow the user to access physical sectors on a disk via Int 13h. The SCSI Requests Flags field is currently undefined for this command and should be zero. The Drive Flags byte is defined as follows: 7 6 5 4 3 2 1 0 Rsvd Rsvd Rsvd Rsvd Rsvd Rsvd Int 13 Info All Rsvd bits will return zeroed. The Int 13 Info bits return information pertaining to the Int 13h drive field: 00 - The given drive (HA #/Target/LUN) is not accessible via Int 13h. If you wish to read/write to this drive, you will need to send ASPI read/write requests to the drive. The Int 13h Drive field is invalid. 01 - The given drive (HA #/Target/LUN) is accessible via Int 13h. The Int 13h Drive field contains the drive's Int 13h drive number. This drive is under the control of DOS. 10 - The given drive (HA #/Target/LUN) is accessible via Int 13h. The Int 13h Drive field contains the drive's Int 13h drive number. This drive is not under control of DOS and can be used, for example, by a SCSI Disk Driver. 11 - Invalid. The Int 13h Drive field returns the Int 13 drive number for the given host adapter -number, target ID, and LUN. Valid Int 13 drive numbers range for 00-FFh. The Preferred Head Translation field indicates the given host adapter's/disk drive's preferred head translation method. A typical value will be 64 heads. The Preferred Sector Translation field indicates the given host adapter's/disk drive's preferred sector translation method. A typical value will be 32 sectors per track. ASPI Under Windows 3.x Windows is a graphical user interface which runs under DOS as an application; -however, writing a device driver or application capable of making ASPI calls in a -Windows environment is not as simple as in the strictly DOS case. The problem arises because ASPI for DOS uses a Real Mode interface and Windows uses the DOS -Protected Mode Interface (DPMI). Whereas ASPI expects a Real Mode segment and -offset for the SRB and the entry point of ASPI, Windows uses a Selector and offset to -address data and code. In order to program correctly in this environment a consortium of companies, Microsoft“ and Intel“ among them, have written a specification called the DOS Protected Mode Interface Specification. The details of the specification are too complex to go into detail here, but it is recommended that a copy be obtained from the DPMI committee for programming purposes; however, as a brief overview two steps need to be followed to access ASPI for DOS from a Windows application: 1 Allocate all SRBs and buffers down in Real Mode memory. This can be -accomplished using Window's GlobalDosAlloc routine or using DPMI interrupt 31h, function 100h. This makes it possible for the ASPI module and manager to locate the SRB and data buffers using segments and offsets. 2 Call the Real Mode procedure with Far Return Frame Function (interrupt 31h, -function 0301h). This makes it possible to call the ASPI manager which is a Real Mode -procedure. For more information on programming ASPI in the Windows environment, refer to the ASPI For Windows Specification.