ASPI for Win16 Specification Read this specification to find out about * An overview of the steps involved in programming ASPI for Win16 * ASPI for Win16 commands * Polling and posting of ASPI for Win16 SCSI requests * Important information for ASPI for Win16 developers * The scanscsi.exe application, which scans the SCSI bus and displays the device name of each target * A summary of the error codes and messages returned by ASPI routines ------------------------------------------------------------------------------- Using ASPI for Win16 - An Overview ASPI for Win16 is implemented as a Dynamic Link Library (DLL). The name of this file is winaspi.dll. ASPI function calls are used to return information about the ASPI manager, host adapter, and SCSI devices, but are mainly used to execute SCSI I/O requests. The ASPI for Win16 layer is fully multitasking and can accept function calls before previous calls have completed. Two functions must be imported from winaspi.dll into your Windows application: Function Description ------------------ ------------------------------------------------------- GetASPISupportInfo This function returns the number of host adapters installed and other miscellaneous information. You should call this function to make sure that ASPI is properly initialized before calling the SendASPICommand function. SendASPICommand This function allows you to send an ASPI for Win16 command. ------------------ ------------------------------------------------------- All SRBs and data buffers must be in locked memory before they are passed to ASPI. This is covered in greater detail in the Miscellaneous section at the end of the document. ------------------------------------------------------------------------------- ASPI Managers For Windows This document does not define the protocol between winaspi.dll and any DOS ASPI managers that may be loaded. There are many reasons for this, including: * Some hardware companies may write ASPI for Win16 managers that do not include concurrent ASPI for DOS support. * Some hardware companies may decide to have winaspi.dll communicate with a Windows 386 Enhanced Mode Virtual Device Driver (VxD). * Some hardware companies may decide to only support Windows 3.1, which may or may not have improved hardware support. It is also not the intent of this specification to define which modes of Windows should be supported. We anticipate that most hardware companies will support ASPI for Win16 in Standard and 386 Enhanced Modes and will not support Real Mode. ------------------------------------------------------------------------------- GetASPISupportInfo Function Prototype: WORD GetASPISupportInfo( VOID ); The GetASPISupportInfo function returns the number of host adapters installed and other miscellaneous information. This function should be called first before issuing an ASPI command to ensure that ASPI has been properly initialized. This function call does not perform any initialization itself; instead, it confirms that everything is ready for processing. The return value specifies the outcome of the function. The LOBYTE returns the number of host adapters installed if the HIBYTE value equals SS_COMP. The HIBYTE returns whether ASPI for Win16 is ready to accept ASPI commands. Refer to the example code. The HIBYTE is defined as follows: Table 1: Return Values from GetASPISupportInfo Function Status Value Description ---------------- ----- -------------------------------------------------- SS_COMP 01h SCSI Request Completed Without Error SS_OLD_MANAGER E1h One or more ASPI for DOS managers are loaded which do not support ASPI for Win16. SS_ILLEGAL_MODE E2h This ASPI manager does not support this mode of Windows. You typically see this error code when running Windows in Real Mode. SS_NO_ASPI E3h No ASPI managers are loaded. This typically occurs when a DOS ASPI manager is not resident in memory. SS_FAILED_INIT E4h For some reason, other than SS_OLD_MANAGER, SS_ILLEGAL_MODE or SS_NO_ASPI, ASPI for Win16 could not properly initialize itself. This may be caused by a lack of system resources. ---------------- ----- -------------------------------------------------- Example The following example returns the current status of ASPI for Win16: WORD ASPIStatus; BYTE NumAdapters; HWND hwnd; . . ASPIStatus = GetASPISupportInfo(); switch ( HIBYTE(ASPIStatus) ) { case SS_COMP: //ASPI for Windows is properly initialized NumAdapters = LOBYTE(ASPIStatus); break; case SS_NO_ASPI: MessageBox( hwnd, "No ASPI managers were found!!", NULL, MB_ICONSTOP ); return 0; case SS_ILLEGAL_MODE: MessageBox( hwnd, "ASPI for Windows does not support this mode!!", NULL, MB_ICONSTOP ); return 0; case SS_OLD_MANAGER: MessageBox( hwnd, "An ASPI manager which does not support Windows" "is resident!!", NULL, MB_ICONSTOP ); return 0; default: MessageBox( hwnd, " ASPI for Windows is not initialized!!", NULL, MB_ICONSTOP ); return 0; } . . ------------------------------------------------------------------------------- Host Adapter Inquiry Command Prototype: WORD SendASPICommand( LPSRB lpSRB ); The SendASPICommand function with command code SC_HA_INQUIRY (00h) is used to get information on the installed host adapter hardware, including number of host adapters installed. lpSRB is a pointer to the following structure: Table 2: Host Adapter Inquiry Command typedef struct { BYTE SRB_Cmd; // ASPI command code = SC_HA_INQUIRY BYTE SRB_Status; // ASPI command status byte BYTE SRB_HaId; // ASPI host adapter number BYTE SRB_Flags; // ASPI request flags WORD SRB_55AASignature; // Extended signature bytes WORD SRB_ExtBufferSize; // Extended buffer length BYTE HA_Count; // Number of host adapters present BYTE HA_SCSI_ID; // SCSI ID of host adapter BYTE HA_ManagerId[16]; // String describing the manager BYTE HA_Identifier[16]; // String describing the host adapter BYTE HA_Unique[16]; // Host Adapter Unique parameters BYTE HA_ExtBuffer[4]; // Extended buffer area } SRB_HAInquiry; Offset # Bytes Description R/W -------- -------- ---------------------------------------------------- --- 00h (00) 01h (01) Command Code = SC_HA_INQUIRY (00h) W 01h (01) 01h (01) Command Status. This byte always returns with a R non-zero status. A SCSI Request Completed Without Error (01h) status indicates that the remaining fields are valid. See the table below for other return codes for this command. 02h (02) 01h (01) Host Adapter Number. This field specifies which W installed host adapter the request is intended for. Host adapter numbers are assigned by the SCSI manager layer, beginning with 0. An Invalid Host Adapter Number (81h) status indicates that the specified host adapter is not installed. 03h (03) 01h (01) SCSI Request Flags. This field is currently - undefined for this command and should be zeroed. R/W 04h (04) 02h (02) Extended Request Signature. This field is set to AA55h (55 in byte 4) by the ASPI client. If the extended request mechanism is supported by the device driver, this signature is reversed to 55AAh when returned. This word is reserved for older drivers that do not support the extended request and will be returned unchanged. 06h (06) 02h (02) Extended Buffer Length. The ASPI client specifies R/W the number of extended-buffer bytes desired. Currently, 4 bytes are defined. When returned, this field contains the number of bytes that contain valid information. In no case will the length returned be greater than the length specified on input. 08h (08) 01h (01) Number of Host Adapters. The ASPI manager sets this R field with the number of host adapters installed under ASPI. For example, a return value of 2 indicates that host adapters #0 and #1 are valid. To determine the total number of host adapters in the system the SRB_HaId field (offset 02h) should be set to 0, or GetASPISupportInfo can be used. 09h (09) 01h (01) Host Adapter SCSI ID. The ASPI manager sets this R field with the SCSI ID of the given host adapter. 0Ah (10) 10h (16) SCSI Manager ID. This field contains a 16-byte R ASCII string describing the SCSI manager. 1Ah (26) 10h (16) Host Adapter Identifier. This field contains a R 16-byte ASCII string describing the SCSI host adapter. 2Ah (42) 10h (16) Host Adapter Unique Parameters. The definition of this field is left to implementation notes specific to a particular host adapter. 3Ah (58) 02h (02) Supported Extensions. R Bit 15-4 Reserved Bit 3 0 = Not a Wide SCSI 32-bit host adapter 1 = Wide SCSI 32-bit host adapter Bit 2 0 = Not a Wide SCSI 16-bit host adapter 1 = Wide SCSI 16-bit host adapter Bit 1 0 = Residual byte length not reported 1 = Residual byte length reported. See section on Residual Byte Length below. Bit 0 Reserved -------- -------- ---------------------------------------------------- --- The return value specifies the outcome of the function. One of the following values is returned by ASPI for Win16: Table 3: Return Values from Host Adapter Inquiry Command Status Value Description ---------------- ----- -------------------------------------------------- SS_COMP 01h SCSI Request Completed Without Error SS_INVALID_HA 81h Invalid Host Adapter Number SS_INVALID_SRB E0h One or more parameters in the SCSI Request Block (SRB) are set incorrectly. ---------------- ----- -------------------------------------------------- Residual Byte Length Residual byte length is the number of bytes not transferred to, or received from, the target SCSI device. For example, if the ASPI buffer length for a SCSI Inquiry command is set for 100 bytes, but the target only returns 36 bytes; the residual length is 64 bytes. Another example: if the ASPI buffer length for a SCSI Write command is set for 514 bytes but the target only takes 512 bytes, the residual length is 2 bytes. ASPI modules can determine if the loaded ASPI manager supports residual byte length by issuing an Extended Host Adapter Inquiry command, as described in the previous section. Example The following example retrieves host adapter hardware information from adapter #0: SRB_HAInquiry MySRB; WORD ASPI_Status; . . MySRB.SRB_Cmd = SC_HA_INQUIRY; MySRB.SRB_HaId = 0; MySRB.SRB_Flags = 0; MySRB.SRB_Hdr_Rsvd = 0; ASPI_Status = SendASPICommand ( (LPSRB) &MySRB ); . . ------------------------------------------------------------------------------- Get Device Type Command Prototype: WORD SendASPICommand( LPSRB lpSRB ); The SendASPICommand function with command code SC_GET_DEV_TYPE (01h) is used by Windows applications to identify the targets which they need to support. For example, a Windows tape backup package can scan each Target/LUN on each installed host adapter looking for the device type corresponding to sequential access devices. This eliminates the need for each Windows application to duplicate the effort of scanning the SCSI bus for devices. Note: Some Windows applications may scan the SCSI bus themselves instead of using this command. This allows them to detect SCSI devices that were powered up after ASPI initialization. lpSRB is a pointer to the following structure: Table 4: Get Device Type Command typedef struct { BYTE SRB_Cmd; // ASPI command code = SC_GET_DEV_TYPE BYTE SRB_Status; // ASPI command status byte BYTE SRB_HaId; // ASPI host adapter number BYTE SRB_Flags; // ASPI request flags DWORD SRB_Hdr_Rsvd; // Reserved, MUST = 0 BYTE SRB_Target; // Target's SCSI ID BYTE SRB_Lun; // Target's LUN number BYTE SRB_DeviceType; // Target's peripheral device type } SRB_GDEVBlock; Offset # Bytes Description R/W -------- -------- ---------------------------------------------------- --- 00h (00) 01h (01) Command Code = SC_GET_DEV_TYPE (01h) W 01h (01) 01h (01) Command Status. This byte always returns with a R 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. 02h (02) 01h (01) Host Adapter Number. This field specifies which W installed host adapter the request is intended for. Host adapter numbers are assigned by the SCSI manager layer, beginning with 0. An Invalid Host Adapter Number (81h) status indicates that the specified host adapter is not installed. 03h (03) 01h (01) SCSI Request Flags. This field is currently - undefined for this command and should be zeroed. 04h (04) 04h (04) Reserved for Expansion = 0 - 08h (08) 01h (01) Target ID. This field indicates the SCSI ID of the W target device. 09h (09) 01h (01) LUN. This field indicates the Logical Unit Number W (LUN) of the device. 0Ah (10) 01h (01) Peripheral Device Type of Target/LUN. The ASPI R manager fills this field with the peripheral device type, as previously reported by the SCSI Inquiry command. Refer to any SCSI specification to learn more about the SCSI Inquiry command. -------- -------- ---------------------------------------------------- --- The return value specifies the outcome of the function. One of the following values is returned by ASPI for Win16: Table 5: Return Values from Get Device Type Command Status Value Description ---------------- ----- -------------------------------------------------- SS_COMP 01h SCSI Request Completed Without Error SS_INVALID_HA 81h Invalid Host Adapter Number SS_NO_DEVICE 82h SCSI Device Not Installed SS_INVALID_SRB E0h One or more parameters in the SCSI Request Block (SRB) are set incorrectly. ---------------- ----- -------------------------------------------------- Example The following example retrieves the peripheral device type from host adapter #0, target ID #4, and LUN #0. SRB_GDEVBlock MySRB; WORD ASPI_Status; . . MySRB.SRB_Cmd = SC_GET_DEV_TYPE; MySRB.SRB_HaId = 0; MySRB.SRB_Flags = 0; MySRB.SRB_Hdr_Rsvd = 0; MySRB.SRB_Target = 4; MySRB.SRB_Lun = 0; ASPI_Status = SendASPICommand ( (LPSRB) &MySRB ); . /***************************************************/ /* If ASPI_Status == SS_COMP, MySRB.SRB_DeviceType */ /* will contain the peripheral device type. */ /***************************************************/ . . ------------------------------------------------------------------------------- Execute SCSI I/O Command Prototype: WORD SendASPICommand( LPSRB lpSRB ); The SendASPICommand function with command code SC_EXEC_SCSI_CMD (02h) is used to execute a SCSI command: for example, sending a SCSI Test Unit Ready command to a tape drive. lpSRB is a pointer to the following structure: Table 6: Execute SCSI I/O Command typedef struct { // Structure for 6-byte CDBs BYTE SRB_Cmd; // ASPI command code = SC_EXEC_SCSI_CMD BYTE SRB_Status; // ASPI command status byte BYTE SRB_HaId; // ASPI host adapter number BYTE SRB_Flags; // ASPI request flags DWORD SRB_Hdr_Rsvd; // Reserved, MUST = 0 BYTE SRB_Target; // Target's SCSI ID BYTE SRB_Lun; // Target's LUN number DWORD SRB_BufLen; // Data Allocation LengthPG BYTE SRB_SenseLen; // Sense Allocation Length BYTE far *SRB_BufPointer; // Data Buffer Pointer DWORD SRB_Rsvd1; // Reserved, MUST = 0 BYTE SRB_CDBLen; // CDB Length = 6 BYTE SRB_HaStat; // Host Adapter Status BYTE SRB_TargStat; // Target Status FARPROC SRB_PostProc; // Post routine BYTE SRB_Rsvd2[34]; // Reserved, MUST = 0 BYTE CDBByte[6]; // SCSI CDB BYTE SenseArea6[SENSE_LEN]; // Request Sense buffer } SRB_ExecSCSICmd6; typedef struct { // Structure for 10-byte CDBs BYTE SRB_Cmd; // ASPI command code = SC_EXEC_SCSI_CMD BYTE SRB_Status; // ASPI command status byte BYTE SRB_HaId; // ASPI host adapter number BYTE SRB_Flags; // ASPI request flags DWORD SRB_Hdr_Rsvd; // Reserved, MUST = 0 BYTE SRB_Target; // Target's SCSI ID BYTE SRB_Lun; // Target's LUN number DWORD SRB_BufLen; // Data Allocation Length BYTE SRB_SenseLen; // Sense Allocation Length BYTE far *SRB_BufPointer; // Data Buffer Pointer DWORD SRB_Rsvd1; // Reserved, MUST = 0 BYTE SRB_CDBLen; // CDB Length = 10 BYTE SRB_HaStat; // Host Adapter Status BYTE SRB_TargStat; // Target Status FARPROC SRB_PostProc; // Post routine BYTE SRB_Rsvd2[34]; // Reserved, MUST = 0 BYTE CDBByte[10]; // SCSI CDB BYTE SenseArea10[SENSE_LEN]; // Request Sense buffer } SRB_ExecSCSICmd10; Note: You can easily create a new structure for non-standard CDB lengths. Offset # Bytes Description R/W -------- -------- ---------------------------------------------------- --- 00h (00) 01h (01) Command Code = SC_EXEC_SCSI_CMD (02h) W 01h (01) 01h (01) Command Status. R 02h (02) 01h (01) Host Adapter Number. This field specifies which W installed host adapter the request is intended for. Host adapter numbers are assigned by the SCSI manager layer, beginning with 0. An Invalid Host Adapter Number (81h) status indicates that the specified host adapter is not installed. 03h (03) 01h (01) SCSI Request Flags. W Bits 7-5 Reserved Bits 4-3 00 = Transfer direction determined by SCSI command. Length not checked. 01 = Transfer direction from SCSI target to host. Length checked. 10 = Transfer direction from host to SCSI target. Length checked. 11 = No data transfer. Bit 2 0 = Residual byte length reporting disabled 1 = Residual byte length reporting enabled (if the ASPI manager supports it) Bit 1 0 = Linking disabled 1 = Linking enabled. This bit should be cleared if scatter/gather is enabled. Bit 0 0 = Posting disabled 1 = Posting enabled 04h (04) 04h (04) Reserved = 0 - 08h (08) 01h (01) Target ID. This field specifies the target ID of W the peripheral device involved in the I/O operation. 09h (09) 01h (01) LUN. This field specifies the LUN of the peripheral W device involved in the I/O operation. 0Ah (10) 04h (04) Data Allocation Length. This field indicates the W 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. If residual byte length is supported and selected, this field is returned with the residual number of bytes (usually 0). See Residual Byte Length on page 2-7. 0Eh (14) 01h (01) Sense Allocation Length (N). This field indicates W 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. 0Fh (15) 02h (02) Data Buffer Pointer (Offset). This field is a W pointer to the I/O data buffer. You place the logical address here. ASPI converts it to the physical address in the case of a bus master or DMA transfer. 11h (17) 02h (02) Data Buffer Pointer (Segment) W 13h (19) 02h (02) SRB Link Pointer (Offset). This field is a pointer W to the next SRB in a chain. See SCSI Command Linking on page 2-9 for more information. 15h (21) 02h (02) SRB Link Pointer (Segment) W 17h (23) 01h (01) SCSI CDB Length (M). This field establishes the W length, in bytes, of the SCSI Command Descriptor Block (CDB). 18h (24) 01h (01) Host Adapter Status. R 00h - Host adapter did not detect any error 11h - Selection time-out 12h - Data overrun/underrun 13h - Unexpected Bus Free 14h - Target Bus phase sequence failure 19h (25) 01h (01) Target Status. R 00h - No target status 02h - Check status (sense data is in sense allocation area) 08h - Specified target/LUN is busy 18h - Reservation conflict 1Ah (26) 02h (02) Post Routine Address (Offset). This field, if W specified, is called when the I/O is completed. See ASPI Command Posting on page 2-10 for more information. 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). This field W 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. 40h+M N Sense Allocation Area. This field is filled with R 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. -------- -------- ---------------------------------------------------- --- The return value specifies the outcome of the function. ASPI for Win16 returns one of the following values: Table 7: Return Values from Execute SCSI I/O Command Status Value Description ---------------- ----- -------------------------------------------------- SS_PENDING 00h SCSI request is in progress. SS_COMP 01h SCSI/ASPI request has completed without error. SS_ABORTED 02h SCSI command has been aborted. SS_ERR 04h SCSI command has completed with an error. SS_INVALID_HA 81h Invalid Host Adapter Number SS_INVALID_SRB E0h One or more parameters in the SCSI Request Block (SRB) are set incorrectly. SS_ASPI_IS_BUSY E5h The ASPI manager cannot handle the request at this time. This error generally occurs if the ASPI manager is already using up all of his resources to execute other requests. Try resending the command later. SS_BUFFER_TO_BIG E6h The ASPI manager cannot handle the given transfer size. Refer to Miscellaneous for more information. ---------------- ----- -------------------------------------------------- Example The following example sends a SCSI Inquiry command to host adapter #0, target #0, and LUN #0: SRB_ExecSCSICmd6 MySRB; char InquiryBuffer[32]; FARPROC lpfnPostProcedure; . . lpfnPostProcedure = MakeProcInstance( PostProcedure, hInstance ); . . MySRB.SRB_Cmd = SC_EXEC_SCSI_CMD; MySRB.SRB_HaId = 0; MySRB.SRB_Flags = SRB_DIR_SCSI | SRB_POSTING; MySRB.SRB_Hdr_Rsvd = 0; MySRB.SRB_Target = 0; MySRB.SRB_Lun = 0; MySRB.SRB_BufLen = 32; MySRB.SRB_SenseLen = SENSE_LEN; MySRB.SRB_BufPointer = InquiryBuffer; MySRB.SRB_CDBLen = 6; MySRB.SRB_PostProc = lpfnPostProcedure; MySRB.CDBByte[0] = SCSI_INQUIRY; MySRB.CDBByte[1] = 0; MySRB.CDBByte[2] = 0; MySRB.CDBByte[3] = 0; MySRB.CDBByte[4] = 32; MySRB.CDBByte[5] = 0; . /**************************************************/ /* Make sure all other reserved fields are zeroed */ /* before passing the SRB to ASPI for Windows */ /**************************************************/ . SendASPICommand ( (LPSRB) &MySRB ); . . ------------------------------------------------------------------------------- Abort SCSI I/O Command Prototype: WORD SendASPICommand( LPSRB lpSRB ); The SendASPICommand function with command code SC_ABORT_SRB is used to request that an SRB be aborted. It should be issued on any I/O request that has not completed if the application wishes to time-out on that request. Success of the Abort command is never assured. lpSRB is a pointer to the following structure: Table 8: Abort SCSI I/O Command typedef struct { BYTE SRB_Cmd; // ASPI command code = SC_ABORT_SRB BYTE SRB_Status; // ASPI command status byte BYTE SRB_HaId; // ASPI host adapter number BYTE SRB_Flags; // ASPI request flags DWORD SRB_Hdr_Rsvd; // Reserved, MUST = 0 LPSRB SRB_ToAbort; // Pointer to SRB to abort } SRB_Abort; Offset # Bytes Description R/W -------- -------- ---------------------------------------------------- --- 00h (00) 01h (01) Command Code = SC_ARORT_SRB (03h) W 01h (01) 01h (01) Command Status. This byte always returns with a R non-zero status. A SCSI Request Completed Without Error (01h) status indicates that the remaining fields are valid, and the abort will be attempted. 02h (02) 01h (01) Host Adapter Number. This field specifies which W installed host adapter the request is intended for. Host adapter numbers are assigned by the SCSI manager layer, beginning with 0. An Invalid Host Adapter Number (81h) status indicates that the specified host adapter is not installed. 03h (03) 01h (01) SCSI Request Flags. This field is currently - undefined for this command and should be zeroed. 04h (04) 04h (04) Reserved for Expansion = 0 - 08h (08) 02h (02) SRB Pointer to Abort (Offset). This field contains W a pointer to the SRB which is to be aborted. 0Ah (10) 02h (02) SRB Pointer to Abort (Segment) W -------- -------- ---------------------------------------------------- --- The return value specifies the outcome of the function. One of the following values is returned by ASPI for Win16: Table 9: Return Values from Abort SCSI I/O Command Status Value Description ---------------- ----- -------------------------------------------------- SS_COMP 01h SCSI/ASPI request has completed without error. SS_INVALID_HA 81h Invalid Host Adapter Number SS_INVALID_SRB E0h One or more parameters in the SCSI Request Block (SRB) are set incorrectly. ---------------- ----- -------------------------------------------------- Example The following example shows how to abort a stuck SCSI I/O: SRB_ExecSCSICmd6 StuckSRB; SRB_Abort AbortSRB; WORD ASPI_Status; . . AbortSRB.SRB_Cmd = SC_ABORT_SRB; AbortSRB.SRB_HaId = 0; AbortSRB.SRB_Flags = 0; AbortSRB.SRB_Hdr_Rsvd = 0; AbortSRB.SRB_ToAbort = (LPSRB) &StuckSRB; ASPI_Status = SendASPICommand ( (LPSRB) &AbortSRB ); . . while (StuckSRB.SRB_Status==SS_PENDING); . . /**************************************************/ /* This sample code has no error handling, time- */ /* out code, nor does it free up the processor. */ /* Your application should be more robust. */ /**************************************************/ ------------------------------------------------------------------------------- Reset SCSI Device Command Prototype: WORD SendASPICommand( LPSRB lpSRB ); The SendASPICommand function with command code SC_RESET_DEV is used to send a SCSI Bus Device reset to the specified target. lpSRB is a pointer to the following structure: Table 10: Reset SCSI Device Command typedef struct { BYTE SRB_Cmd; // ASPI command code = SC_RESET_DEV BYTE SRB_Status; // ASPI command status byte BYTE SRB_HaId; // ASPI host adapter number BYTE SRB_Flags; // ASPI request flags DWORD SRB_Hdr_Rsvd; // Reserved, MUST = 0 BYTE SRB_Target; // Target's SCSI ID BYTE SRB_Lun; // Target's LUN number BYTE SRB_ResetRsvd1[14]; // Reserved, MUST = 0 BYTE SRB_HaStat; // Host Adapter Status BYTE SRB_TargStat; // Target Status FARPROC SRB_PostProc; // Post routine BYTE SRB_ResetRsvd2[34]; // Reserved, MUST = 0 } SRB_BusDeviceReset; Offset # Bytes Description R/W -------- -------- ---------------------------------------------------- --- 00h (00) 01h (01) Command Code = SC_RESET_DEV (04h) W 01h (01) 01h (01) Command Status. R 02h (02) 01h (01) Host Adapter Number. This field specifies which W installed host adapter the request is intended for. Host adapter numbers are assigned by the SCSI manager layer, beginning with 0. An Invalid Host Adapter Number (81h) status indicates that the specified host adapter is not installed. 03h (03) 01h (01) SCSI Request Flags W Bit 7-1 Reserved Bit 0 1 = Posting enabled 0 = Posting disabled 04h (04) 04h (04) Reserved = 0 - 08h (08) 01h (01) Target ID W 09h (09) 01h (01) LUN W 0Ah (10) 0Eh (14) Reserved = 0 - 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 - -------- -------- ---------------------------------------------------- --- Upon completion of the SCSI command, the ASPI manager sets this field with the host adapter status as follows: Table 11: Reset SCSI Device Command Status, HA Status, Target Status Command Status Value Description ---------------- ----- -------------------------------------------------- SS_COMP 01h SCSI/ASPI request has completed without error. SS_INVALID_HA 81h Invalid Host Adapter Number SS_INVALID_SRB E0h One or more parameters in the SCSI Request Block (SRB) are set incorrectly. SS_ASPI_IS_BUSY E5h The ASPI manager cannot handle the request at this time. This error generally occurs if the ASPI manager is already using up all of his resources to execute other requests. Try resending the command later. ---------------- ----- -------------------------------------------------- HA Status Value Description ---------------- ----- -------------------------------------------------- HASTAT_OK 00h Host adapter did not detect an error HASTAT_SEL_TO 11h Selection time-out HASTAT_DO_DU 12h Data overrun/underrun HASTAT_BUS_FREE 13h Unexpected Bus Free HASTAT_PHASE_ERR 14h Target Bus phase sequence failure ---------------- ----- -------------------------------------------------- Target Status Value Description ---------------- ----- -------------------------------------------------- STATUS_GOOD 00h No target status STATUS_CHKCOND 02h Check status (sense data is in SenseArea) STATUS_BUSY 08h Specified Target/LUN is busy STATUS_RESCONF 18h Reservation conflict ---------------- ----- -------------------------------------------------- Example The following example issues a SCSI Bus Device reset to host adapter #0, target #5: SRB_BusDeviceReset MySRB; WORD ASPI_Status; . . MySRB.SRB_Cmd = SC_RESET_DEV; MySRB.SRB_HaId = 0; MySRB.SRB_Flags = 0; MySRB.SRB_Hdr_Rsvd = 0; MySRB.SRB_Target = 5; MySRB.SRB_Lun = 0; ASPI_Status = SendASPICommand ( (LPSRB) &MySRB ); . /**************************************************/ /* Make sure all other reserved fields are zeroed */ /* before passing the SRB to ASPI for Windows */ /**************************************************/ . while (MySRB.SRB_Status==SS_PENDING); . . /**************************************************/ /* This sample code has no error handling, time- */ /* out code, nor does it free up the processor. */ /* Your application should be more robust. */ /**************************************************/ ASPI Polling Once you send an ASPI for Win16 SCSI request, you have two ways of being notified that the SCSI request has completed. The first and simplest method is called polling. After the command is sent, and ASPI for Win16 returns control to your program, you can poll the status byte waiting for the command to complete. For example, the following code segment sends a SCSI Inquiry command to target #2. SRB_ExecSCSICmd6 MySRB; char InquiryBuffer[32]; . . /**************************************************/ /* Code is entered with 'MySRB' zeroed. */ /**************************************************/ MySRB.SRB_Cmd = SC_EXEC_SCSI_CMD; MySRB.SRB_Flags = SRB_DIR_SCSI; MySRB.SRB_Target = 2; MySRB.SRB_BufLen = 32; MySRB.SRB_SenseLen = SENSE_LEN; MySRB.SRB_BufPointer = InquiryBuffer; MySRB.SRB_CDBLen = 6; MySRB.CDBByte[0] = SCSI_INQUIRY; MySRB.CDBByte[4] = 32; . . SendASPICommand ( (LPSRB) &MySRB ); // Send Inquiry command while ( MySRB.SRB_Status == SS_PENDING ); // Wait till it's finished /**************************************************/ /* At this point, the SCSI command has completed */ /* with or without an error. */ /**************************************************/ if ( MySRB.SRB_Status == SS_COMP ) ; // Command completed without error else ; // Command completed with error Since Windows is currently a non-preemptive multitasking operating system, you should use polling with caution. The example above is not a good example of freeing up the processor, nor does it have any time-out handler. ASPI Posting Most applications use posting, rather than polling, to be notified that a SCSI request has completed. When posting is enabled, ASPI for Win16 posts completion by calling your callback function. For example, the following code segment sends a SCSI Inquiry command to target #2 during the WM_CREATE message. long FAR PASCAL WndProc (HWND, WORD, WORD, LONG); void FAR PASCAL ASPIPostProc ( LPSRB ); HWND PostHWND; HANDLE hInstance; . . . // ************************************************************************ // // Function: ASPIPostProc // // Description: If POSTING is enabled, this function is called by ASPI // for Windows when the SCSI request has completed. This // sample function simply posts a message to our Window // handle to indicate that the SCSI request has completed. // // DoneSRB This parameter points to the ASPI SCSI Request Block (SRB) // which has completed. // // Returns Nothing // // ************************************************************************ #ifdef WIN32 void ASPIPostProc( PSRB_ExecSCSICmd DoneSRB ) { PostMessage( PostHWND, WM_ASPIPOST, 0, (LPARAM)DoneSRB ); return; } #else void _loadds __far __pascal ASPIPostProc( LPSRB DoneSRB ) { PostMessage(PostHWND,WM_ASPIPOST, (WORD)((SRB_ExecSCSICmd6 far *)DoneSRB)->SRB_Status, (DWORD)DoneSRB); return; } #endif // ************************************************************************ // // Functioin: WndProc() // // ************************************************************************ #ifdef WIN32 LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) #else long __far __pascal _export WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) #endif { HDC hdc; PAINTSTRUCT ps; TEXTMETRIC tm; HMENU hMenu; static short cxClient, cyClient; int i=0; WORD status; #ifdef WIN32 SRB_ExecSCSICmd *SRBPtr; #else SRB_ExecSCSICmd6 far *SRBPtr; #endif switch (message) { case WM_CREATE: hdc = GetDC(hwnd); SelectObject(hdc,GetStockObject(SYSTEM_FIXED_FONT)); GetTextMetrics(hdc,&tm); cxChar = tm.tmAveCharWidth; cyChar = tm.tmHeight; ReleaseDC(hwnd,hdc); rect.top = 0; return 0; case WM_PAINT: InvalidateRect(hwnd,NULL,TRUE); hdc = BeginPaint(hwnd,&ps) ; EndPaint (hwnd,&ps) ; return 0 ; case WM_SIZE: cxClient = LOWORD(lParam); cyClient = HIWORD(lParam); rect.right = LOWORD(lParam); rect.bottom = HIWORD(lParam); UpdateWindow(hwnd); return 0; case WM_COMMAND: hMenu = GetMenu(hwnd); switch (wParam) { case ID_FILE_EXIT: SendMessage(hwnd,WM_CLOSE,0,0L); return 0; default: // 10 = target #0 // 11 = target #1 // 12 = target #2 // 13 = target #3 // 14 = target #4 // 15 = target #5 // 16 = target #6 // 17 = target #7 // Toggle the SCSI target scan status(ENABLED/DISABELD) if ((wParam >= 10 && wParam <= 17) || (wParam >= 20 && wParam <= 27)) { status = GetMenuState(hMenu,wParam,MF_BYCOMMAND) & MF_CHECKED; CheckMenuItem(hMenu,wParam,MF_BYCOMMAND | ((status) ? MF_UNCHECKED:MF_CHECKED)); } return 0; } case WM_ASPIPOST: #ifdef WIN32 SRBPtr = (PSRB_ExecSCSICmd)lParam; #else SRBPtr = (SRB_ExecSCSICmd6 far *)lParam; #endif DisplaySCSIID(hwnd,SRBPtr); ScanNextTarget(hwnd); return 0; case WM_DESTROY: PostQuitMessage(0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; } When the post routine is called, the sample post handler fills the wParam field and contains the status of ASPI command (SRB_Status), while the lParam field contains a far pointer to the SRB which has completed. ------------------------------------------------------------------------------- Miscellaneous This section contains important information about using ASPI for Win16. * All structures must be "packed" onto byte aligments. To do this using Microsoft compilers use the "#pragma pack(1)" command within your source code or use the /Zp1 command line option. Please check your documentation for the proper commands or pragmas for other compilers. * All of the ASPI functions use 'C' style name decoration. If using a 'C++' compiler then make sure to include your function prototypes within an "extern "C" {}" block. * Your ASPI for Win16 program should never exit with pending SCSI I/Os. Doing so could lead to system instability. Send an ASPI Abort command if necessary. * Your SRBs and data buffers must be in page-locked memory. Most SCSI host adapters are bus masters. This means that the data buffer must not move while the transfer is taking place. We recommend that you allocate your buffers using GlobalAlloc and lock it first with GlobalLock and then with GlobalPageLock. This technique can overcome some quirks that Windows 3.x seems to have with locking down buffers. Note: This is no longer a requirement if you are writing to the ASPI for Win32 interface. * At a minimum, all ASPI for Win16 managers must support transfers of 64 KBytes or less. It is not possible for all SCSI host adapters to transfer data blocks larger than this. If the ASPI manager cannot support the requested transfer size, the SS_BUFFER_TOO_BIG error is returned from the SendASPICommand routine. No posting occurs. If this happens, break the transfer down into 64 KByte transfers or less. For maximum compatibility, we recommend that you do not request transfer sizes larger than 64 KBytes. * Do not forget to support the SS_ASPI_IS_BUSY return status when sending a SCSI command. Under extreme loads, some ASPI for Win16 managers may not have enough resources to service each request. * If you send an ASPI request with posting enabled, and the return value is not equal to SS_PENDING (in other words, the request is not in progress), then ASPI for Win16 does not post completion to your specified window handle. (Refer to the specific return value for more information about why the request is not in progress.) * ASPI for Win16 is fully multitasking. You can send a request to ASPI while another request is executing. Make sure you use a separate SRB for each ASPI request. We also recommend that you only send one SRB at a time per target. * If you use posting, your post routine will most likely be called during interrupt time. Since most Windows routines are non-reentrant, you should call Windows routines with caution. You can call PostMessage during interrupt time, however. * Make sure that you zero out all reserved fields before passing the SRB to ASPI for Win16. ------------------------------------------------------------------------------- Error Codes and Messages All ASPI for Win16 calls can fail. This specification has already defined which error codes can be returned by each ASPI routine. The following table summarizes all of the error codes returned by ASPI routines. Code Value Description ---------------- ----- -------------------------------------------------- SS_PENDING 00h SCSI request is in progress. SS_COMP 01h SCSI/ASPI request has completed without error. SS_ABORTED 02h SCSI command has been aborted. SS_ERR 04h SCSI command has completed with an error. SS_INVALID_CMD 80h Invalid ASPI command code. SS_INVALID_HA 81h Invalid Host Adapter Number. SS_NO_DEVICE 82h SCSI device not installed at passed address. SS_INVALID_SRB E0h One or more parameters in the SCSI Request Block (SRB) are set incorrectly. SS_OLD_MANAGER E1h One or more ASPI for DOS managers are loaded which do not support ASPI for Win16. SS_ILLEGAL_MODE E2h This ASPI manager does not support this mode of Windows. You typically see this error code when running Windows in Real Mode. SS_NO_ASPI E3h No ASPI managers are loaded. This typically occurs when a DOS ASPI manager is not resident in memory. SS_FAILED_INIT E4h For some reason, other than SS_OLD_MANAGER, SS_ILLEGAL_MODE or SS_NO_ASPI, ASPI for Win16 could not properly initialize itself. This may be caused by a lack of system resources. SS_ASPI_IS_BUSY E5h The ASPI manager cannot handle the request at this time. This error generally occurs if the ASPI manager is already using up all of his resources to execute other requests. Try resending the command later. SS_BUFFER_TO_BIG E6h The ASPI manager cannot handle the given transfer size. Refer to Miscellaneous for more information. ---------------- ----- --------------------------------------------------