ASPI For OS/2 Specification About This Chapter Read this chapter to find out: - An overview of the steps involved in programming ASPI for OS/2 - The SCSI request block and ASPI command codes executed by the ASPI manager - The ASPIAPP application that scans the SCSI bus and displays information about the targets it finds - The ASPIDRV sample device driver Accessing ASPI Device drivers wishing to access ASPI must determine the address of the ASPI entry point through an OS/2 Attach Device Help 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 Device Help call, a clear carry flag indicates that the SCSI manager SCSIMGR$ was found and that 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 Once the ASPI entry point parameters have been successfully determined, calling ASPI is a matter of using 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 Once 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. 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 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 normally the first device manager loaded and it will automatically search for all available hard drives and permanently allocate 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 on using ASPI to control a device that may be allocated by a DMD that loads before os2aspi.dmd, be sure and specify that the device manager in question is not allowed access to it. 1 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: BASEDEV=AHA154X.ADD /A:0 /!DM:6 2 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: 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, please consult the on-line help for SCSI. The current ASPI specification does not provide a method for allocating targets and there are no command line switches for os2aspi.dmd that can be used with the current ADD. The target for each SRB will be allocated and deallocated on a command basis until the first Execute I/O SRB is sent. At this point, the target will be permanently -allocated to os2aspi.dmd and other DMDs will no longer have access to the target. Sample Code for OS/2 2.x The SDK includes sample code for designing ASPI applications and device drivers to be used with OS/2 2.x. ASPIAPP is a simple program that scans the SCSI bus and displays information about any targets that it finds on adapters in the system. This application is a single-threaded, character based application intended to show you how ASPI can be used. ASPIDRV is a simple device driver that passes requests from ASPIAPP to os2aspi.dmd after converting any virtual addresses to physical addresses. This driver is intended for handling single-threaded requests that are small enough not to require a scatter/gather list. If you are transferring large blocks of data you may have to convert the virtual address of the buffer into a page table that can be used as a scatter/gather list. 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 5-8. Status The Status Byte field is used to post the status of the command. Refer to ASPI Status Bytes on page 5-8. 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-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 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) 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) Protected Mode Post Routine DS 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 (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 SGE 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 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 (i.e., Rewind, Start Unit, etc.) 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, 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. 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 -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 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. 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 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 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. 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 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. ASPIAPP.C //***************************************************************************** // // Copyright 1993 Adaptec, Inc., All Rights Reserved. // // This software contains the valuable trade secrets of Adaptec. The // software is protected under copyright laws as an unpublished work of // Adaptec. Notice is for informational purposes only and does not imply // publication. The user of this software may make copies of the software // for use with parts manufactured by Adaptec or under license from Adaptec // and for no other use. // //********************************************************************* *******/ //****************************************************************************** // // Driver Name: ASPIAPP.EXE // // Version: 1.0 // // Source Code: ASPIAPP.C ASPI.H MAKEFILE // // Base Code #: // // Description: This application, ASPIAPP.EXE is a sample application that // sends SRBs to OS2ASPI.DMD via the device driver ASPIDRV.SYS. // // - This is a simple full screen text application that scans for // SCSI adapters and displays information about all targets that // are found. // // History: // // 06/15/93 - JHL - v1.0 submitted. // //****************************************************************************/ #define INCL_DOSDEVICES #include #include #include #include #include #include #include "aspi.h" #define ASPI_REQ 0x80 #define MAX_CDB_LENGTH 12 #define MAX_SENSE_LENGTH 18 void main() { HFILE aspiDriverHandle; ULONG action; USHORT currentAdapter; USHORT currentTarget; ASPI_SRB_INQUIRY inquirySRB; ASPI_SRB_DEVICE_TYPE deviceSRB; PASPI_SRB_EXECUTE_IO executeSRB; UCHAR inquiryData[50]; UCHAR inquiryOutput[20]; UCHAR *adapterString = "Adapter:"; UCHAR *targetString = "Target:"; UCHAR *deviceString = "Device Type:"; UCHAR *noDriver = "Driver NOT found"; UCHAR *SRBError = "Error executing SRB"; UCHAR *vendorInformation = "Device Name:"; //Attempt to open the driver for calls to OS2ASPI.DMD if (DosOpen((PSZ)"ASPIDRV$", (PHFILE) &aspiDriverHandle, (PULONG) &action, 0L, 0L, FILE_OPEN, OPEN_SHARE_DENYNONE | OPEN_FLAGS_FAIL_ON_ERROR | OPEN_ACCESS_READ WRITE, 0L)) printf("%s\n",noDriver); else { //Initialize the SRB memset(&inquirySRB, 0, sizeof(inquirySRB)); //The driver was opened, so send a command to it DosDevIOCtl(aspiDriverHandle, // DevHandle ASPI_REQ, // ulCategory ASPI_CMD_ADAPTER_INQUIRY, // ulFunction (PCHAR) &inquirySRB, // pParmList sizeof(inquirySRB), // ulParmLengthMax NULL, // pParmLengthInOut NULL, // pDataArea 0, // ulDataLengthMax NULL); // pDataLengthInOut // If some adapters were found, display their targets if ((inquirySRB.SRBHdr.ASPIStatus == ASPI_STATUS_NO_ERROR) && (inquirySRB.AdapterCount)) { for (currentAdapter = 0; currentAdapter < inquirySRB.AdapterCount; currentAdapter++) { for (currentTarget = 0; currentTarget < 8; currentTarget++) { //Initialize the SRB memset(&deviceSRB, 0, sizeof(deviceSRB)); deviceSRB.SRBHdr.CommandCode = ASPI_CMD_GET_DEVICE_TYPE; deviceSRB.SRBHdr.AdapterIndex = currentAdapter; deviceSRB.DeviceTargetID = currentTarget; DosDevIOCtl(aspiDriverHandle, // DevHandle ASPI_REQ, // ulCategory ASPI_CMD_GET_DEVICE_TYPE, // ulFunction (PCHAR) &deviceSRB, // pParmList sizeof(deviceSRB), // ulParmLengthMax NULL, // pParmLengthInOut NULL, // pDataArea 0, // ulDataLengthMax NULL); // pDataLengthInOut // If the target was found, issue an INQUIRY and display // the results. if (deviceSRB.SRBHdr.ASPIStatus == ASPI_STATUS_NO_ERROR) { printf("%s %d %s %d %s %d ", adapterString, currentAdapter, targetString, currentTarget, deviceString, deviceSRB.DeviceType); //Initialize the SRB executeSRB = malloc(sizeof(ASPI_SRB_EXECUTE_IO) + MAX_CDB_LENGTH + MAX_SENSE_LENGTH); memset(executeSRB, 0, sizeof(ASPI_SRB_EXECUTE_IO) + MAX_CDB_LENGTH + MAX_SENSE_LENGTH) ; //Set up the SRB, and pass the data buffer pointer as //part of the IOCtl executeSRB->SRBHdr.CommandCode = ASPI_CMD_EXECUTE_IO; executeSRB->SRBHdr.ASPIReqFlags = ASPI_REQFLAG_DIR_TO_HOST | ASPI_REQFLAG_POST_ENABLE; executeSRB->SRBHdr.AdapterIndex = currentAdapter; executeSRB->DeviceTargetID = currentTarget; executeSRB->DataXferLen = 50; executeSRB->SenseDataLen = MAX_SENSE_LENGTH; executeSRB->SCSICDBLen = 6; executeSRB->SCSICDBStart[0] = 0x12; executeSRB->SCSICDBStart[4] = 50; DosDevIOCtl(aspiDriverHandle, // DevHandle ASPI_REQ, // ulCategory ASPI_CMD_EXECUTE_IO, // ulFunction (PCHAR) executeSRB, // pParmList sizeof(ASPI_SRB_EXECUTE_IO) + MAX_CDB_LENGTH + MAX_SENSE_LENGTH), // ulParmLengthMax NULL, // pParmLengthInOut (PCHAR) inquiryData, // pDataArea sizeof (inquiryData), // ulDataLengthMax NULL); // pDataLengthInOut // If the command completed, display the data if (executeSRB->SRBHdr.ASPIStatus == ASPI_STATUS_NO_ERROR) { strncpy(inquiryOutput,inquiryData + 8,19); inquiryOutput[19] = '\0'; printf("%s\n",vendorInformation,inquiryOutput); } else printf("%s\n",SRBError); free(executeSRB); } } } } DosClose(aspiDriverHandle); } } ASPI.H //-------------------------// // ASPI SRB Header // //-------------------------// typedef struct _ASPI_SRBHDR { /* ASHD */ UCHAR CommandCode; UCHAR ASPIStatus; UCHAR AdapterIndex; UCHAR ASPIReqFlags; } ASPI_SRB_HEADER,*NPASPI_SRB_HEADER, FAR *PASPI_SRB_HEADER; //-------------------------------------------------// // Command Values in ASPI_SRB_HEADER->CommandCode // //-------------------------------------------------// #define ASPI_CMD_ADAPTER_INQUIRY 0x00 #define ASPI_CMD_GET_DEVICE_TYPE 0x01 #define ASPI_CMD_EXECUTE_IO 0x02 #define ASPI_CMD_ABORT_IO 0x03 #define ASPI_CMD_RESET_DEVICE 0x04 #define ASPI_CMD_SET_ADAPTER_PARMS 0x05 //-------------------------------------------------------// // ASPI Status Values in ASPI_SRB_HEADER->ASPIStatus // //-------------------------------------------------------// #define ASPI_STATUS_IN_PROGRESS 0x00 #define ASPI_STATUS_NO_ERROR 0x01 #define ASPI_STATUS_ABORTED 0x02 #define ASPI_STATUS_ERROR 0x04 #define ASPI_STATUS_INVALID_COMMAND 0x80 #define ASPI_STATUS_INVALID_ADAPTER 0x81 #define ASPI_STATUS_INVALID_TARGET 0x82 //-------------------------------------------------------// // ASPI Flags in ASPI_SRB_HEADER->ASPIReqFlags // //-------------------------------------------------------// #define ASPI_REQFLAG_POST_ENABLE 0x01 #define ASPI_REQFLAG_LINKED_SRB 0x02 #define ASPI_REQFLAG_RESIDUAL 0x04 #define ASPI_REQFLAG_DIRECTION_BITS 0x18 #define ASPI_REQFLAG_DIR_TO_HOST 0x08 #define ASPI_REQFLAG_DIR_TO_TARGET 0x10 #define ASPI_REQFLAG_DIR_NO_DATA_XFER 0x18 #define ASPI_REQFLAG_SG_ENABLE 0x20 //*********************************************************************// // ASPI ADAPTER INQUIRY SRB (for ASPI_CMD_ADAPTER_INQUIRY) // //*********************************************************************// typedef struct _ASPI_SRB_ADAPTER_INQUIRY { /* ASAI */ ASPI_SRB_HEADER SRBHdr; UCHAR Reserved_1[4]; UCHAR AdapterCount; UCHAR AdapterTargetID; UCHAR ManagerName[16]; UCHAR AdapterName[16]; UCHAR AdapterParms[16]; } ASPI_SRB_INQUIRY, *NPASPI_SRB_INQUIRY, FAR *PASPI_SRB_INQUIRY; //**********************************************************************// // ASPI GET DEVICE TYPE SRB (for ASPI_CMD_DEVICE_TYPE) // //**********************************************************************// typedef struct _ASPI_SRB_DEVICE_TYPE { /* ASDT */ ASPI_SRB_HEADER SRBHdr; UCHAR Reserved_1[4]; UCHAR DeviceTargetID; UCHAR DeviceTargetLUN; UCHAR DeviceType; } ASPI_SRB_DEVICE_TYPE, *NPASPI_SRB_DEVICE_TYPE, FAR *PASPI_SRB_DEVICE_TYPE; //**********************************************************************// // ASPI EXECUTE IO SRB (for ASPI_CMD_EXECUTE_IO) // //**********************************************************************// typedef struct _ASPI_SRB_EXECUTE_IO { /* ASEI */ ASPI_SRB_HEADER SRBHdr; USHORT SGListLen; UCHAR Reserved_1[2]; UCHAR DeviceTargetID; UCHAR DeviceTargetLUN; ULONG DataXferLen; UCHAR SenseDataLen; ULONG ppDataBuffer; ULONG ppNxtSRB; UCHAR SCSICDBLen; UCHAR HostStatus; UCHAR TargetStatus; VOID (FAR *RM_PostAddress)(USHORT DataSeg,PASPI_SRB_HEADER pSRBH); USHORT RM_DataSeg; VOID (FAR *PM_PostAddress)(USHORT DataSeg,PASPI_SRB_HEADER pSRBH); USHORT PM_DataSeg; ULONG ppSRB; UCHAR ASPIWorkSpace[22]; UCHAR SCSICDBStart[1]; } ASPI_SRB_EXECUTE_IO, *NPASPI_SRB_EXECUTE_IO, FAR *PASPI_SRB_EXECUTE_IO; //-----------------------------------------------------// // Status returned in ASPI_SRB_EXECUTE_IO->HostStatus // //-----------------------------------------------------// #define ASPI_HSTATUS_NO_ERROR 0x00 #define ASPI_HSTATUS_SELECTION_TIMEOUT 0x11 #define ASPI_HSTATUS_DATA_OVERRUN 0x12 #define ASPI_HSTATUS_BUS_FREE 0x13 #define ASPI_HSTATUS_BUS_PHASE_ERROR 0x14 #define ASPI_HSTATUS_BAD_SGLIST 0x1A //@53040 //-------------------------------------------------------// // Status returned in ASPI_SRB_EXECUTE_IO->TargetStatus // //-------------------------------------------------------// #define ASPI_TSTATUS_NO_ERROR 0x00 #define ASPI_TSTATUS_CHECK_CONDITION 0x02 #define ASPI_TSTATUS_BUSY 0x08 #define ASPI_TSTATUS_RESERV_CONFLICT 0x18 //***********************************************************************// // ASPI ABORT IO SRB (for ASPI_CMD_ABORT_IO) // //***********************************************************************// typedef struct _ASPI_SRB_ABORT_IO { /* ASAI */ ASPI_SRB_HEADER SRBHdr; UCHAR Reserved_1[4]; ULONG ppSRB; } ASPI_SRB_ABORT_IO, *NPASPI_SRB_ABORT_IO, FAR *PASPI_SRB_ABORT_IO; //**********************************************************************// // ASPI RESET DEVICE SRB (for ASPI_RESET_DEVICE) // //**********************************************************************// typedef struct _ASPI_SRB_RESET_DEVICE { /* ASRD */ ASPI_SRB_HEADER SRBHdr; UCHAR Reserved_1[4]; UCHAR DeviceTargetID; UCHAR DeviceTargetLUN; UCHAR Reserved_2[14]; UCHAR HostStatus; UCHAR TargetStatus; VOID (FAR *RM_PostAddress) (USHORT DataSeg,PASPI_SRB_HEADER pS RBH); USHORT RM_DataSeg; VOID (FAR *PM_PostAddress)(USHORT DataSeg,PASPI_SRB_HEADER pS RBH); USHORT PM_DataSeg; UCHAR ASPIWorkSpace[22]; } ASPI_SRB_RESET_DEVICE, *NPASPI_SRB_RESET_DEVICE, FAR *PASPI_SRB_RESET_DEVICE; //**********************************************************************// // ASPI SET HOST ADAPTER PARAMETERS (for ASPI_CMD_SET_ADAPTER_PARMS) // //**********************************************************************// typedef struct _ASPI_SRB_ADAPTER_PARMS { /* ASAP */ ASPI_SRB_HEADER SRBHdr; UCHAR Reserved_1[4]; UCHAR AdapterParms[16]; } ASPI_SRB_ADAPTER_PARMS, *NPASPI_SRB_ADAPTER_PARMS, FAR *PASPI_SRB_ADAPTER_PARMS; ASPISEGS.ASM include devhdr.inc ;Explicit segment ordering required for device drivers PUBLIC __acrtused PUBLIC DriverHeader EXTRN _ASPIDriverEntry:NEAR DeviceHeader segment dword public 'DATA' DriverHeader dd -1 dw DEV_CHAR_DEV+DEVLEV_1+DEV_GIOCTL+DEV_30 dw OFFSET _STRATEGY dw 0 db "ASPIDRV$" dw 0 dw 0 dw 0 dw 0 dd 0 dw 0 DeviceHeader ends LIBDATA segment dword public 'DATA' LIBDATA ends _DATA segment dword public 'DATA' _DATA ends CONST segment dword public 'CONST' CONST ends _BSS segment dword public 'BSS' _BSS ends _TEXT segment dword public 'CODE' .286p _STRATEGY proc far assume cs:_TEXT __acrtused: start: push es push bx call _ASPIDriverEntry pop bx pop es mov word ptr es:[bx+3], ax ret _STRATEGY endp _TEXT ends Code segment dword public 'CODE' Code ends LIBCODE segment dword public 'CODE' LIBCODE ends SwapCode segment dword public 'CODE' SwapCode ends DGROUP group CONST, _BSS, DeviceHeader, LIBDATA, _DATA StaticGroup group _TEXT, LIBCODE, Code SwapGroup group SwapCode end ASPIDRV.C //****************************************************************************** // // Copyright 1993 Adaptec, Inc., All Rights Reserved. // // This software contains the valuable trade secrets of Adaptec. The // software is protected under copyright laws as an unpublished work of // Adaptec. Notice is for informational purposes only and does not imply // publication. The user of this software may make copies of the software // for use with parts manufactured by Adaptec or under license from Adaptec // and for no other use. // //**********************************************************************//**********************************************************************// // Driver Name: ASPIDRV.SYS // // Version: 1.0 // // Source Code: ASPIDRV.C ASPIDRV.H MAKEFILE // // Base Code #: // // Description: This driver, ASPIDRV.SYS is a sample device driver that // works in conjunction with an OS/2 application to provide SRBs to an // OS/2 ASPI manager (i.e OS2ASPI.DMD). // // - You should have an understanding of writing OS/2 device // drivers to fully understand this driver. // // - There are NO command line switches. The driver will // automatically attach itself to OS2ASPI.DMD (if present) // and display a status message on the screen. // // - Only single-thread requests are supported. // // - Scatter/gather lists are NOT supported. A virtual pointer to the // data buffer is passed in the IOCtl data buffer pointer and the // driver places a physical pointer in the SRB. // // - Initialization code and data are thrown away after INIT // to minimize resident memory requirements. // // History: // // 07/15/93 - JHL - v1.0 submitted. // //**********************************************************************#define INCL_NOBASEAPI #define INCL_NOPMAPI #include #include #include #define INCL_INITRP_ONLY #include #include #include #include #include #include #include “aspidrv.h” extern APIRET APIENTRY DosPutMessage(USHORT hf, USHORT cbMsg, PCHAR pchMsg); extern void STRATEGY(); //name of strategy routine in DDSTART */ extern char *ASPIDriverInstalled; extern char *ASPIDriverAborted; static strlen(PSZ s); void FAR_loadds ASPI_Post(USHORT DataSeg, PASPI_SRB_HEADER pSRBH); BOOL CreatePhysicalDataPointer(PASPI_SRB_EXECUTE_IO pSRB, PUCHAR dataBufferPtr); int Init(PRPINITIN pRPI); int ASPIDriverEntry(PRPH rp); PFN Device_Help = 0; // Pointer to Dev_Help ATTACHAREA ASPIData; // OS2ASPI entry information ULONG dataHandle; // Handle for locked data buffer ULONG parameterHandle; // Handle for locked memory //**********************************************************************// // Function Name : ASPIDriverEntry // // Function Description : This function receives all // request packets from the application and routes // them based on the command and function values. // // An ASPI request must be a generic IOCTL with // function type ASPI_REQ. Once these requests are // identified the SRB is updated to include any new // information that is required and then the request // is forwarded to OS2ASPI.DMD // // Function Input : // rp : A pointer to the driver’s request packet // // Function Output : This function returns STDON if // the command is successfully handled and an error // code if a problem is detected. // //**********************************************************************int ASPIDriverEntry(PRPH rp) { ULONG parameterPtr; // Temporary variable for physical ptr PRP_GENIOCTL rpIOCTL; USHORT result = STDON; switch (rp->Cmd) { case RPINIT: //Initialize the driver return (Init((PRPINITIN) rp)); case RPOPEN: //Open the driver return(STDON); case RPCLOSE: //Close the driver return(STDON); case RPIOCTL: rpIOCTL = (PRP_GENIOCTL) rp; if (rpIOCTL->Category == ASPI_REQ) // Is it an ASPI call? { if (DevHelp_Lock(SELECTOROF(rpIOCTL->ParmPacket), 1, // long term lock 0, // block until available (PULONG) ¶meterHandle)) return(STDON | STERR | ERROR_GEN_FAILURE); switch (rpIOCTL->Function) // Which ASPI call? { case ASPI_CMD_ADAPTER_INQUIRY: case ASPI_CMD_GET_DEVICE_TYPE: // Verify access to the SRB if (DevHelp_VerifyAccess(SELECTOROF(rpIOCTL->ParmPacket) OFFSETOF(rpIOCTL->ParmPacket), sizeof(ASPI_SRB_HEADER), VERIFY_READWRITE)) { DevHelp_UnLock(parameterHandle); result = STDON | STERR | ERROR_GEN_FAILURE; } else // Send the ASPI request to OS2ASPI.DMD { (*ASPIData.protectedEntryPoint)(ASPIData.protectedDS, (PASPI_SRB_HEADER) rpIOCTL->ParmPacket); // Unlock the parameter packet DevHelp_UnLock(parameterHandle); } break; case ASPI_CMD_EXECUTE_IO: // Verify access to the SRB if (DevHelp_VerifyAccess(SELECTOROF(rpIOCTL->ParmPacket), OFFSETOF(rpIOCTL->ParmPacket), sizeof(ASPI_SRB_EXECUTE_IO), VERIFY_READWRITE)) { DevHelp_UnLock(parameterHandle); result = STDON | STERR | ERROR_GEN_FAILURE; } else // Create a physical pointer to the SRB if (DevHelp_VirtToPhys(rpIOCTL->ParmPacket, ¶meterPtr)) result = (STDON | STERR | ERROR_GEN_FAILURE); else { // Copy the physical SRB pointer into the SRB ((PASPI_SRB_EXECUTE_IO)(rpIOCTL->ParmPacket))-> ppSRB = parameterPtr; // Copy the post routine address into the SRB ((PASPI_SRB_EXECUTE_IO)(rpIOCTL->ParmPacket))-> PM_PostAddress = ASPI_Post; // Copy the post routine data selector to the SRB ((PASPI_SRB_EXECUTE_IO)(rpIOCTL->ParmPacket))-> PM_DataSeg = ASPIData.protectedDS; // Create a physical pointer to the data buffer if ((CreatePhysicalDataPointer((PASPI_SRB_EXECUTE_IO) (rpIOCTL->ParmPacket, rpIOCTL ->DataPacket)) == FALSE) result = (STDON | STERR | ERROR_GEN_FAILURE); else { // Send the ASPI request to OS2ASPI.DMD (*ASPIData.protectedEntryPoint)(ASPIData.protectedDS, (PASPI_SRB_HEADER) rpIOCTL->ParmPacket); DISABLE // Make sure the command has completed if (((PASPI_SRB_EXECUTE_IO)(rpIOCTL->ParmPacket))-> SRBHdr.ASPIReqFlags & ASPI_REQFLAG_POST_ENABLE) { while (((PASPI_SRB_EXECUTE_IO)(rpIOCTL->- -ParmPacket))->SRBHdr.ASPIStatus == ASPI_STATUS_IN_PROGRESS) { DevHelp_ProcBlock(parameterPtr, (ULONG) -1, WAIT_IS_INTERRUPTABLE); DISABLE } } ENABLE // Unlock the data buffer DevHelp_UnLock(dataHandle); // Unlock the parameter packet. DevHelp_UnLock(parameterHandle); } } break; case ASPI_CMD_ABORT_IO: // Verify access to the SRB if (DevHelp_VerifyAccess(SELECTOROF(rpIOCTL->ParmPacket), OFFSETOF(rpIOCTL->ParmPacket), sizeof(ASPI_SRB_ABORT_IO), VERIFY_READWRITE)) { DevHelp_UnLock(parameterHandle); result = STDON | STERR | ERROR_GEN_FAILURE; } else { // Create a physical pointer to the SRB if (DevHelp_VirtToPhys(rpIOCTL->ParmPacket, ¶meterPtr)) { DevHelp_UnLock(parameterHandle); result = STDON | STERR | ERROR_GEN_FAILURE; } else { // Copy the physical SRB pointer into the SRB ((PASPI_SRB_ABORT_IO)(rpIOCTL->ParmPacket))->ppSRB = parameterPtr; // Send the ASPI request to OS2ASPI.DMD (*ASPIData.protectedEntryPoint)(ASPIData.protectedDS, (PASPI_SRB_HEADER) rpIOCTL->ParmPacket); // Unlock the parameter packet. DevHelp_UnLock(parameterHandle); } } break; case ASPI_CMD_RESET_DEVICE: // Verify access to the SRB if (DevHelp_VerifyAccess(SELECTOROF(rpIOCTL->ParmPacket), OFFSETOF(rpIOCTL->ParmPacket), sizeof(ASPI_SRB_RESET_DEVICE), VERIFY_READWRITE)) { DevHelp_UnLock(parameterHandle); result = STDON | STERR | ERROR_GEN_FAILURE; } else { // Copy the post routine address into the SRB ((PASPI_SRB_RESET_DEVICE)(rpIOCTL->ParmPacket))-> PM_PostAddress = ASPI_Post; // Copy the post routine data selector to the SRB ((PASPI_SRB_RESET_DEVICE)(rpIOCTL->ParmPacket))-> PM_DataSeg = ASPIData.protectedDS; // Send the ASPI request to OS2ASPI.DMD (*ASPIData.protectedEntryPoint)(ASPIData.protectedDS, (PASPI_SRB_HEADER) rpIOCTL->ParmPacket); DISABLE // Make sure the command has completed if (((PASPI_SRB_RESET_DEVICE)(rpIOCTL->ParmPacket))-> SRBHdr.ASPIReqFlags & ASPI_REQFLAG_POST_ENABLE) { while (((PASPI_SRB_RESET_DEVICEPG23)(rpIOCTL-> -ParmPacket))->SRBHdr.ASPIStatus == ASPI_STATUS_IN_PROGRESS) { DevHelp_ProcBlock(parameterPtr, (ULONG) -1, WAIT_IS_INTERRUPTABLE); DISABLE } } ENABLE // Unlock the parameter packet. DevHelp_UnLock(parameterHandle); } } break; case ASPI_CMD_SET_ADAPTER_PARMS: default: // No other functions are supported result = STDON | STERR | ERROR_BAD_COMMAND; } return(result); } else // No other categories are supported return (STDON | STERR | ERROR_BAD_COMMAND); default: // An unknown command was issued to the driver return(STDON | STERR | ERROR_BAD_COMMAND); } } //****************************************************** // // Function Name : CreatePhysicalDataPointer // // Function Description : This function converts the // virtual data pointer into a physical pointer and // copies it into the appropriate SRB field. // // Function Input : // pSRB - A pointer to the SRB being processed. // // Function Output : This function returns TRUE if a // valid pointer is created and FALSE if there is // an error detected. // //****************************************************** BOOL CreatePhysicalDataPointer(PASPI_SRB_EXECUTE_IO pSRB) PUCHAR dataBufferPtr) { // If the command does not transfer data, no pointer is required if (pSRB->DataXferLen == 0) { pSRB->ppDataBuffer = 0; return(TRUE); } if (!(DevHelp_Lock(SELECTOROF(dataBufferPtr), 1, // long term lock 0, // block until available (PULONG) &dtaHandle))) if (!(DevHelp_VerifyAccess(SELECTOROF (dataBufferPtr), OFFSETOF (dataBufferPtr), pSRB->DataXferLen, VERIFY_READWRITE))) if (!(DevHelp_VirtToPhys(dataBufferPtr, &(pSRB->ppDataBuffer)))) return(TRUE); else { DevHelp_Unlock(dataHandle); return(FALSE); } else { DevHelp_Unlock(dataHandle); return(FALSE); } else { return(FALSE); } } //****************************************************** // // Function Name : ASPI_Post // // Function Description : This function is called // whenever an ASPI request is completed by the ASPI // device manager. // // Currently all that it does is wake up the thread // which sent the SRB. It is the thread’s // responsibility to check the status of the SRB and // perform any actions based on that status. // // Function Input : // DataSeg - The data selector of this driver // pSRBH - A pointer to the completed SRB // // Function Output : // //******************************************************/ void FAR_loadds ASPI_Post(USHORT DataSeg,PASPI_SRB_HEADER pSRBH) { USHORT awakeCount; // The following code assumes that requests are single threaded. // If you are going to allow multiple requests to be active // simultaneously then you need to create data structures that will // record the handle and virtual data pointer for each request. // Wake up the thread which made the request. DevHelp_ProcRun((ULONG) pSRBH, &awakeCount); // Return control to OS2ASPI.DMD } //****************************************************** // // Function Name : Init // // Function Description : This function formally // sets up the device driver so that it can be // loaded into memory and accessed by subsequent // calls from application programs. // // Function Input : // rp : A pointer to the driver’s request packet // // Function Output : This function returns RPDONE if // it successfully completes all its tasks and a // result code indicating the problem that occurred // if it cannot be loaded. // //******************************************************* int Init(PRPINITIN pRPI) { char *SCSIManager = “SCSIMGR$ “; PRPINITOUT pRPO = (PRPINITOUT) pRPI; // Initialize DevHelp entry point Device_Help = pRPI->DevHlpEP; // Attach to OS2ASPI.DMD if (DevHelp_AttachDD(SCSIManager, (NPBYTE) &ASPIData)) { // The driver failed to install DosPutMessage(1, // Handle is STDOUT strlen(ASPIDriverAborted), // Message length ASPIDriverAborted); // Message ptr pRPO->CodeEnd = 0; pRPO->DataEnd = 0; return(RPDONE | RPERR | ERROR_BAD_COMMAND); } else { // The driver was succesfully installed DosPutMessage(1, // Handle is STDOUT strlen(ASPIDriverInstalled), // Message length ASPIDriverInstalled); // Message ptr pRPO->CodeEnd = (USHORT) &Init; pRPO->DataEnd = (USHORT) ¶meterHandle + sizeof(PULONG); return(RPDONE); } } // Functions that replace C library functions unavailable to a device driver //****************************************************** // Function Name : strlen // // Function Description : This function calculates the // length of a string. // // Function Input : // s : A pointer to the string // // Function Output : This function returns the length // of the string. // //******************************************************* static strlen(PSZ s) { int i = 0; while (*s++) i++; return (i); } ASPIDRV.DEF LIBRARY ASPIDRV DESCRIPTION "@#ADAPTEC:6.426#@ OS/2 ASPI Device Driver" PROTMODE SEGMENTS DeviceHeader CLASS 'DATA' CONST CLASS 'CONST' _BSS CLASS 'BSS' LIBDATA CLASS 'DATA' _DATA CLASS 'DATA' 'CODE' CLASS 'CODE' IOPL _TEXT CLASS 'CODE' IOPL LIBCODE CLASS 'CODE' IOPL ASPIDRV.H //**********************************************************************// // Copyright 1993 Adaptec, Inc., All Rights Reserved. // // This software contains the valuable trade secrets of Adaptec. The // software is protected under copyright laws as an unpublished work of // Adaptec. Notice is for informational purposes only and does not imply // publication. The user of this software may make copies of the software // for use with parts manufactured by Adaptec or under license from Adaptec // and for no other use. // //**********************************************************************// ASPIDrv.h // // typedef USHORT OFFSET; typedef USHORT SEG; #define DAW_CHR 0x8000 // Character device driver #define DAW_IDC 0x4000 // IDC available #define DAW_IBM 0x2000 // Non-IBM block device driver #define DAW_SHR 0x1000 // Support device sharing #define DAW_OPN 0x0800 // Device supports open/close #define DAW_LEVEL1 0x0080 // Level 1 OS/2 #define DAW_LEVEL2 0x0100 // Level 2 DevIOCtl2 #define DAW_LEVEL3 0x0180 // Level 3 Bit Strip #define DAW_GIO 0x0040 // Support generic IOCtl #define DAW_CLK 0x0008 // Clock device #define DAW_NUL 0x0004 // NULL device #define DAW_SCR 0x0002 // STDOUT (screen) #define DAW_KBD 0x0001 // STDIN (keyboard) // IOCtl Category #define ASPI_REQ 0x80 // Request packet commands #define RPINIT 0x00 #define RPOPEN 0x0D #define RPCLOSE 0x0E #define RPIOCTL 0x10 #define RPDEINSTALL 0x14 // RPstatus bit values #define RPERR 0x8000 #define RPDEV 0x4000 #define RPBUSY 0x0200 #define RPDONE 0x0100 // Error codes returned in RPstatus #define ERROR_WRITE_PROTECT 0x0000 #define ERROR_BAD_UNIT 0x0001 #define ERROR_NOT_READY 0x0002 #define ERROR_BAD_COMMAND 0x0003 #define ERROR_CRC 0x0004 #define ERROR_BAD_LENGTH 0x0005 #define ERROR_SEEK 0x0006 #define ERROR_NOT_DOS_DISK 0x0007 #define ERROR_SECTOR_NOT_FOUND 0x0008 #define ERROR_OUT_OF_PAPER 0x0009 #define ERROR_WRITE_FAULT 0x000A #define ERROR_READ_FAULT 0x000B #define ERROR_GEN_FAILURE 0x000C #define ERROR_DISK_CHANGE 0x000D #define ERROR_WRONG_DISK 0x000F #define ERROR_UNCERTAIN_MEDIA 0x0010 #define ERROR_CHAR_CALL_INTERRUPTED 0x0011 #define ERROR_NO_MONITOR_SUPPORT 0x0012 #define ERROR_INVALID_PARAMETER 0x0013 #define ERROR_DEVICE_IN_USE 0x0014 #define DISABLE _asm {cli} #define ENABLE _asm {sti} typedef struct AttachArea { VOID (FAR *realEntryPoint)(SEG realDS, PASPI_SRB_HEADER pSRB); SEG realDS; VOID (FAR *protectedEntryPoint)(SEL protectedDS, PASPI_SRB_HEADER pSRB); SEL protectedDS; } ATTACHAREA; typedef ATTACHAREA near *PATTACHAREA; ASPIDRV.SYS makefile #***********************************************************************# ASPIDRV.SYS makefile # # This makefile assumes that the source code is located in the OS/2 2.0 # device driver development kit build tree. The code should be placed in # a subdirectory within \DDK\SRC\DEV\DASD. Be sure and include all # appropriate tool directories (i.e. \DDK\TOOLS and \C600) in your PATH! # #***********************************************************************# # Compiler Location w/ includes, libs and tools # INC = ..\..\..\..\inc H = ..\..\..\..\h LIB = ..\..\..\..\lib TOOLSPATH = ..\..\..\..\tools DISKH = ..\diskh DISKINC = ..\diskinc DHLIB = ..\devhelp ADDLIB = ..\addcalls HFLAGS= -d -f -w -s # # Compiler/tools Macros # AS=masm CC=cl LINK=link MAPSYM=mapsym # # Compiler and Linker Options # AFLAGS = -MX -T -Z $(ENV) AINC = -I. -I$(INC) CINC = -I. -I$(H) -I$(DISKH) CFLAGS = /c /Zp /Oe /Og /Oc /Ol /Ot /Gs /Oa /Oz /G2s /Answ /W3 /FR $(ENV) DFLAGS = /c /Zp /G2s /Answ /W3 $(ENV) -DDEBUG LFLAGS = /map /nod /exepack /packd /a:16 /far RFLAGS = -r LIBS = $(DHLIB)\dhcalls.lib $(ADDLIB)\addcalls.lib $(LIB)\os2286.lib #***********************************************************************# Set up Macros that will contain all the different dependencies for the # executables and dlls etc. that are generated. #***********************************************************************# # OBJ files # OBJ1 = ASPISEGS.OBJ ASPIDRV.OBJ ASPIMSG.OBJ # # List files # LST1= ASPISEGS.LST ASPIDRV.LST ASPIINIT.LST LIST= $(LST1) OBJS = $(OBJ1) #***********************************************************************# Setup the inference rules for compiling and assembling source code to # object code. #*********************************************************************** .asm.obj: $(AS) $(AFLAGS) $(AINC) $*.asm; .asm.lst: $(AS) -l -n $(AFLAGS) $(AINC) $*.asm; .c.obj: $(CC) $(CFLAGS) $(CINC) $*.c .c.lst: $(CC) $(CFLAGS) /Fc $(CINC) $*.c copy $*.cod $*.lst del $*.cod .h.inc: H2INC $(HFLAGS) $*.h -o $*.inc # # Should be the default tag for all general processing # all: ASPIDRV.SYS inc: list: $(LIST) clean: if exist *.lnk del *.lnk if exist *.obj del *.obj if exist *.mbj del *.mbj if exist *.map del *.map if exist *.old del *.old if exist *.lst del *.lst if exist *.lsd del *.lsd if exist *.sym del *.sym if exist *.sys del *.sys if exist *.tff del *.tff if exist *.cod del *.cod if exist *.add del *.add #***********************************************************************# OBJ dependant rules for compiling and assembling source code #*********************************************************************** #***********************************************************************# Specific Description Block Information #***********************************************************************# This section would only be for specific direction as to how to create # unique elements that are necessary to the build process. This could # be compiling or assembling, creation of DEF files and other unique # files. # If all compiler and assembly rules are the same, use an inference rule to # perform the compilation. # ASPIDRV.SYS: $(OBJS) $(LIBS) makefile $(LINK) $(LFLAGS) @<<$(@B).lnk $(OBJ1) $*.sys $*.map $(LIBS) $*.def <