home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / driver / scsi / aspiscsi / aspi.c next >
C/C++ Source or Header  |  1993-11-11  |  16KB  |  519 lines

  1. // ----------------------------------------------------------------------
  2. // Module ASPI.C
  3. // ASPI manager interface routines.
  4. //
  5. // Copyright (C) 1993, Brian Sawert.
  6. // All rights reserved.
  7. //
  8. // Notes:
  9. //    Compile with MEDIUM or SMALL model for DOS, MEDIUM for DLL.
  10. //    Compiling as DLL defines __DLL__ and defines _FAR as far.
  11. //
  12. // ----------------------------------------------------------------------
  13.  
  14. #if defined(__DLL__)                    // DLL options
  15. #include <windows.h>
  16. #else
  17. #include <stdlib.h>
  18. #endif
  19.  
  20. #include <fcntl.h>
  21. #include <mem.h>
  22. #include <dos.h>
  23. #include <io.h>
  24. #include <string.h>
  25.  
  26. #if defined(__DLL__)                    // DLL options
  27. #include "aspidll.h"                    // ASPI DLL routines and variables
  28. #endif
  29. #include "aspi.h"                        // ASPI definitions and constants
  30. #include "scsi.h"                        // SCSI definitions and constants
  31.  
  32.  
  33. // -------------------- defines and macros -------------------
  34.  
  35. #define BUSY_WAIT    0x1000;                // repeat count for busy check
  36. #define IOCTL_READ    2                    // IOCTL read function
  37. #define ASPI_NAME    "SCSIMGR$"            // SCSI manager driver name
  38.  
  39.  
  40. // -------------------- global variables -------------------
  41.  
  42. void (far *ASPIRoutine) (aspi_req_t far *);    // far address of ASPI routine
  43. BYTE f_installed;                        // flag for ASPI existence
  44. BYTE aspi_stat;                            // ASPI status byte
  45. BYTE host_stat;                            // host status byte
  46. BYTE targ_stat;                            // target status byte
  47. BYTE host_count;                        // number of host adapters
  48. BYTE host_num;                            // host adapter number (0 default)
  49. BYTE host_id = -1;                        // host SCSI ID
  50.  
  51. aspi_req_t _FAR *srb;                    // SCSI Request Block pointers
  52. abort_req_t _FAR *abortsrb;                // SCSI abort request structure
  53. sense_block_t _FAR *srb_sense;            // pointer to SRB sense data
  54.  
  55.  
  56. // -------------------- external variables -------------------
  57.  
  58. // -------------------- local functions -------------------
  59.  
  60. int aspi_func(aspi_req_t _FAR *ar);        // ASPI entry point function
  61.  
  62.  
  63. // -------------------- external functions -------------------
  64.  
  65. // -------------------- function definitions -------------------
  66.  
  67.  
  68. // ----------------------------------------------------------------------
  69. // Routine to check for and initialize ASPI driver.
  70. //
  71. // Usage:    int FUNC aspi_open(void);
  72. //
  73. // Returns nonzero on success, 0 if ASPI driver not found or init failed.
  74. // ----------------------------------------------------------------------
  75.  
  76. int FUNC aspi_open(void)
  77.     {
  78.     int dh;                                // ASPI driver handle
  79.  
  80.     if (!f_installed)
  81.         {                                // not initialized
  82.         if ((dh = open(ASPI_NAME, O_RDONLY | O_BINARY)) != -1)
  83.             {                            // open device driver
  84.             if (ioctl(dh, IOCTL_READ, (void _FAR *) &ASPIRoutine,
  85.                 sizeof(ASPIRoutine)) == sizeof(ASPIRoutine))
  86.                 {                        // got ASPI entry point
  87. #if defined(__DLL__)                    // DLL options
  88.                 dwPtr[0] = AllocRealBuff((DWORD) sizeof(aspi_req_t));
  89.                 dwPtr[1] = AllocRealBuff(sizeof(abort_req_t));
  90.  
  91.                 if (dwPtr[0] != NULL && dwPtr[1] != NULL)
  92.                     {                    // allocated SRB buffers
  93.                     srb = (aspi_req_t far *) MAKELP(LOWORD(dwPtr[0]), 0);
  94.                     abortsrb = (abort_req_t far *) MAKELP(LOWORD(dwPtr[1]), 0);
  95.                     f_installed++;        // set installed flag
  96.                     }
  97. #else
  98.                 srb = (aspi_req_t *) malloc(sizeof(aspi_req_t));
  99.                 abortsrb = (abort_req_t *) malloc(sizeof(abort_req_t));
  100.                 if (srb != NULL && abortsrb != NULL)
  101.                     {                    // allocated SRB buffers
  102.                     f_installed++;        // set installed flag
  103.                     }
  104. #endif
  105.                 }
  106.             close(dh);                    // close device driver
  107.             }
  108.         }
  109.  
  110.     return(f_installed);
  111.     }
  112.  
  113.  
  114. // ----------------------------------------------------------------------
  115. // Routine to close and clean up.
  116. //
  117. // Usage:    void FUNC aspi_close(void);
  118. //
  119. // Called with nothing.
  120. // Returns nothing.
  121. // ----------------------------------------------------------------------
  122.  
  123. void FUNC aspi_close(void)
  124.     {
  125.  
  126.     if (f_installed)
  127.         {                                // already initialized
  128. #if defined(__DLL__)                    // DLL options
  129.         dwPtr[0] = FreeRealBuff(dwPtr[0]);    // deallocate buffers
  130.         dwPtr[1] = FreeRealBuff(dwPtr[1]);
  131. #else
  132.         free(srb);                        // deallocate buffers
  133.         free(abortsrb);
  134. #endif
  135.         srb = abortsrb = NULL;            // clear pointers
  136.         f_installed = 0;                // clear installed flag
  137.         }
  138.  
  139.     return;
  140.     }
  141.  
  142.  
  143. // ----------------------------------------------------------------------
  144. // Routine to call ASPI driver.
  145. //
  146. // Usage:    int aspi_func(aspi_req_t _FAR *ar);
  147. //    
  148. // Called with pointer to SCSI Request Block (SRB).
  149. // Returns nonzero on success, 0 on error.
  150. // ----------------------------------------------------------------------
  151.  
  152. int aspi_func(aspi_req_t _FAR *ar)
  153.     {
  154.     int retval = 0;
  155.  
  156.     if (f_installed)
  157.         {                                // ASPI manager initialized
  158. #if defined(__DLL__)                    // DLL options
  159.         aspi_req_t far *arptr;            // real mode pointer
  160.  
  161.         if ((arptr = (aspi_req_t far *) MaptoReal(ar)) != NULL)
  162.             {                            // got a valid real mode pointer
  163.             retval = AspiCall(ASPIRoutine, arptr); // call ASPI through DPMI
  164.             }
  165. #else
  166.         ASPIRoutine((aspi_req_t far *) ar);    // call ASPI manager
  167.         retval++;
  168. #endif
  169.         }
  170.  
  171.     return(retval);
  172.     }
  173.  
  174.  
  175. // ----------------------------------------------------------------------
  176. // Inquire the status of the host adapter.
  177. //
  178. // Usage:    int FUNC aspi_host_inq(char _FAR *idstr, BYTE _FAR *hprm);
  179. //
  180. // Called with pointers to buffer for manager ID string and host adapter
  181. //    parameters.
  182. // Returns number of host adapters on success, -1 on error.
  183. //
  184. // Note:
  185. //    Host parameter support depends on vendor and hardware.
  186. // ----------------------------------------------------------------------
  187.  
  188. int FUNC aspi_host_inq(char _FAR *idstr, BYTE _FAR *hprm)
  189.     {
  190.     int retval = -1;
  191.  
  192.     memset(srb, 0, sizeof(aspi_req_t));    // clear SRB
  193.     srb->command = HOST_INQ;            // set command byte
  194.  
  195.     if (aspi_func(srb))
  196.         {                                // ASPI call succeeded
  197.         if ((aspi_stat = srb->status) == REQ_NOERR)
  198.             {                            // request completed without error
  199.             host_id = srb->su.s0.targid;    // save host SCSI ID
  200.             if (idstr != NULL)
  201.                 {                        // copy manager ID string
  202.                 strncpy(idstr, srb->su.s0.manageid, MAX_IDSTR);
  203.                 }
  204.             if (hprm != NULL)
  205.                 {                        // copy host adapter parameters
  206.                 memcpy(hprm, srb->su.s0.hostparams, MAX_IDSTR);
  207.                 }
  208.  
  209.             retval = srb->su.s0.numadapt;    // return host adapter count
  210.             }
  211.         }
  212.  
  213.     return(retval);
  214.     }
  215.  
  216.  
  217. // ----------------------------------------------------------------------
  218. // Inquire device type for specified SCSI ID.
  219. //
  220. // Usage:    int FUNC aspi_devtype(BYTE id);
  221. //
  222. // Called with target ID.
  223. // Returns device type on success, -1 on error.
  224. // ----------------------------------------------------------------------
  225.  
  226. int FUNC aspi_devtype(BYTE id)
  227.     {
  228.     int retval = -1;
  229.  
  230.     memset(srb, 0, sizeof(aspi_req_t));    // clear SRB
  231.     srb->command = GET_DEV;                // set command byte
  232.  
  233.     srb->hostnum = host_num;            // set host adapter number
  234.     srb->su.s1.targid = id;                // set target SCSI ID
  235.  
  236.     if (aspi_func(srb))
  237.         {                                // ASPI call succeeded
  238.         if ((aspi_stat = srb->status) == REQ_NOERR)
  239.             {                            // request completed without error
  240.             retval = srb->su.s1.devtype;    // return device type code
  241.             }
  242.         }
  243.  
  244.     return(retval);
  245.     }
  246.  
  247.  
  248. // ----------------------------------------------------------------------
  249. // Execute SCSI I/O through ASPI interface.
  250. //
  251. // Usage:    int FUNC aspi_io(BYTE _FAR *cdb, BYTE far *dbuff,
  252. //            WORD dbytes, BYTE flags, BYTE id, WORD _FAR *stat);
  253. //
  254. // Called with pointer to data buffer, data buffer size, pointer to CDB,
  255. //    request flags, and target ID.
  256. // Returns ASPI status on success, -1 on error.  Fills stat variable
  257. //    with host status in high byte, target status in low byte.
  258. // ----------------------------------------------------------------------
  259.  
  260. int FUNC aspi_io(BYTE _FAR *cdb, BYTE far *dbuff, WORD dbytes,
  261.     BYTE flags, BYTE id, WORD _FAR *stat)
  262.     {
  263. #if defined(__DLL__)                    // DLL options
  264.     void far *pptr, far *rptr;            // real and protected mode pointers
  265. #endif
  266.     int cdbsize;
  267.     int timeout;                        // timeout counter for polling
  268.     int retval = -1;
  269.  
  270.     memset(srb, 0, sizeof(aspi_req_t));    // clear SRB
  271.     srb->command = SCSI_IO;                // set command byte
  272.  
  273.     srb->hostnum = host_num;            // set host adapter number
  274.     srb->su.s2.targid = id;                // set target SCSI ID
  275.     srb->reqflags = flags;                // set request flags
  276.     srb->su.s2.databufptr = dbuff;        // set pointer to data buffer
  277.     srb->su.s2.datalength = dbytes;        // set data buffer length
  278.     srb->su.s2.senselength = sizeof(sense_block_t);
  279.                                         // set sense data buffer length
  280.     cdbsize = sizeof(group_0_t);        // assume 6 byte CDB
  281.     if (*((BYTE _FAR *) cdb) >= MIN_GRP_1 && *((BYTE _FAR *) cdb) < MIN_GRP_6)
  282.         {                                // CDB size is 10 bytes
  283.         cdbsize = sizeof(group_1_t);
  284.         }
  285.  
  286.     srb->su.s2.cdblength = cdbsize;        // set CDB length
  287.     srb->su.s2.senselength = MAX_SENSE;    // sense sense data length
  288.  
  289.     memcpy(srb->su.s2.scsicdb, cdb, cdbsize);    // copy CDB to SRB
  290.     srb_sense = srb->su.s2.scsicdb + cdbsize;    // point to sense data buffer
  291.  
  292. #if defined(__DLL__)                    // DLL options
  293.     if ((dwPtr[2] = AllocRealBuff((DWORD) dbytes)) != NULL)
  294.         {                                // allocated real mode buffer
  295.         pptr = MAKELP(LOWORD(dwPtr[2]), 0);    // create protected pointer
  296.         rptr = MAKELP(HIWORD(dwPtr[2]), 0);    // create real pointer
  297.  
  298.         memcpy(pptr, dbuff, dbytes);    // copy data to real buffer
  299.         srb->su.s2.databufptr = rptr;    // set pointer to real mode buffer
  300. #endif
  301.  
  302.     if (aspi_func(srb))
  303.         {                                // ASPI call succeeded
  304.         timeout = BUSY_WAIT;            // set timeout counter
  305.         
  306.         while (srb->status == REQ_INPROG && timeout > 0)
  307.             {                            // request in progress - keep polling
  308.             timeout--;                    // decrement timeout counter
  309.             }
  310.  
  311.         retval = aspi_stat = srb->status;    // save ASPI status
  312.  
  313.         if (aspi_stat != REQ_INPROG)
  314.             {                            // request completed
  315.             host_stat = srb->su.s2.hoststat;    // save host status
  316.             targ_stat = srb->su.s2.targstat;    // save target status
  317.             *stat = ((WORD) host_stat << 8) | targ_stat;
  318.                                         // return combined SCSI status
  319.             }
  320.         }
  321.  
  322. #if defined(__DLL__)                    // DLL options
  323.         memcpy(dbuff, pptr, dbytes);    // copy data back to protected buffer
  324.         dwPtr[2] = FreeRealBuff(dwPtr[2]);    // free real mode buffer
  325.         }
  326.     else
  327.         {                                // memory allocate failed
  328.         retval = -1;                    // return error
  329.         }
  330. #endif
  331.  
  332.     return(retval);
  333.     }
  334.  
  335.  
  336. // ----------------------------------------------------------------------
  337. // Abort pending SCSI I/O request.
  338. //
  339. // Usage:    int FUNC aspi_abort_io(void);
  340. //
  341. // Called with nothing.
  342. // Returns ASPI status of aborted SRB on success, -1 on error.
  343. // ----------------------------------------------------------------------
  344.  
  345. int FUNC aspi_abort_io(void)
  346.     {
  347.     int timeout;                        // timeout counter for polling
  348.     int retval = -1;
  349.  
  350.     memset(abortsrb, 0, sizeof(abort_req_t));    // clear abort SRB
  351.     abortsrb->command = ABORT_IO;        // set command byte
  352.  
  353.     abortsrb->hostnum = host_num;        // set host adapter number
  354.     abortsrb->s3.srbptr = (void far *) srb;    // point to current SRB
  355.  
  356.     if (aspi_func((aspi_req_t _FAR *) abortsrb))
  357.         {                                // ASPI call succeeded
  358.         timeout = BUSY_WAIT;            // set timeout counter
  359.         
  360.         while (srb->status == REQ_INPROG && timeout > 0)
  361.             {                            // request in progress - keep polling
  362.             timeout--;                    // decrement timeout counter
  363.             }
  364.  
  365.         retval = aspi_stat = srb->status;    // save ASPI status
  366.         }
  367.  
  368.     return(retval);
  369.     }
  370.  
  371.  
  372. // ----------------------------------------------------------------------
  373. // Reset SCSI device through ASPI driver.                           
  374. //
  375. // Usage:    int FUNC aspi_reset_dev(BYTE id);
  376. //
  377. //
  378. // Called with target ID.
  379. // Returns ASPI status on success, -1 on error.
  380. // ----------------------------------------------------------------------
  381.  
  382. int FUNC aspi_reset_dev(BYTE id)
  383.     {
  384.     int timeout;                        // timeout counter for polling
  385.     int retval = -1;
  386.  
  387.     memset(srb, 0, sizeof(aspi_req_t));    // clear SRB
  388.     srb->command = SCSI_RESET;            // set command byte
  389.  
  390.     srb->hostnum = host_num;            // set host adapter number
  391.     srb->su.s4.targid = id;                // set target SCSI ID
  392.  
  393.     if (aspi_func(srb))
  394.         {                                // ASPI call succeeded
  395.         timeout = BUSY_WAIT;            // set timeout counter
  396.         
  397.         while (srb->status == REQ_INPROG && timeout > 0)
  398.             {                            // request in progress - keep polling
  399.             timeout--;                    // decrement timeout counter
  400.             }
  401.  
  402.         retval = aspi_stat = srb->status;    // save ASPI status
  403.  
  404.         if (aspi_stat != REQ_INPROG)
  405.             {                            // request completed
  406.             host_stat = srb->su.s4.hoststat;    // save host status
  407.             targ_stat = srb->su.s4.targstat;    // save target status
  408.             }
  409.         }
  410.  
  411.     return(retval);
  412.     }
  413.  
  414.  
  415. // ----------------------------------------------------------------------
  416. // Set host adapter parameters.
  417. //
  418. // Usage:    int FUNC aspi_set_hostprm(BYTE _FAR *hprm, int hbytes);
  419. //
  420. // Called with pointer to vendor specific host parameters buffer.
  421. // Returns ASPI status on success, -1 on error.
  422. //
  423. // Note:
  424. //    Host parameter support depends on vendor and hardware.
  425. // ----------------------------------------------------------------------
  426.  
  427. int FUNC aspi_set_hostprm(BYTE _FAR *hprm, int hbytes)
  428.     {
  429.     int nbytes;
  430.     int retval = -1;
  431.  
  432.     memset(srb, 0, sizeof(aspi_req_t));    // clear SRB
  433.     srb->command = HOST_SET;            // set command byte
  434.  
  435.     srb->hostnum = host_num;            // set host adapter number
  436.     nbytes = (hbytes < MAX_IDSTR) ? hbytes : MAX_IDSTR;    // set transfer length
  437.     memcpy(srb->su.s5.hostparams, hprm, nbytes);    // copy host parameters
  438.  
  439.     if (aspi_func(srb))
  440.         {                                // ASPI call succeeded
  441.         retval = aspi_stat = srb->status;    // save ASPI status
  442.         }
  443.  
  444.     return(retval);
  445.     }
  446.  
  447.  
  448. // ----------------------------------------------------------------------
  449. // Get disk drive parameters.
  450. //
  451. // Usage:    int FUNC aspi_get_driveprm(BYTE id, BYTE _FAR *flags,
  452. //     BYTE _FAR *drvnum, int _FAR *heads, int _FAR *sectsize);
  453. //
  454. // Called with SCSI ID and pointers to flags byte, INT 13 drive number,
  455. //    number of heads, bytes per sector.
  456. // Returns ASPI status on success, -1 on error.
  457. //
  458. // Note:
  459. //    This function is not supported by all manufacturers.
  460. // ----------------------------------------------------------------------
  461.  
  462. int FUNC aspi_get_driveprm(BYTE id, BYTE _FAR *flags, BYTE _FAR *drvnum,
  463.     int _FAR *heads, int _FAR *sectsize)
  464.     {
  465.     int retval = -1;
  466.  
  467.     memset(srb, 0, sizeof(aspi_req_t));    // clear SRB
  468.     srb->command = DISK_INFO;            // set command byte
  469.  
  470.     srb->hostnum = host_num;            // set host adapter number
  471.     srb->su.s6.targid = id;                // set target ID
  472.  
  473.     if (aspi_func(srb))
  474.         {                                // ASPI call succeeded
  475.         if ((aspi_stat = srb->status) == REQ_NOERR)
  476.             {                            // request completed without error
  477.             *flags = srb->su.s6.driveflags;    // return disk drive flags
  478.             *drvnum = srb->su.s6.drivenum;    // return INT 13 drive number
  479.             *heads = srb->su.s6.headtrans;    // return number of heads
  480.             *sectsize = srb->su.s6.secttrans;    // return bytes per sector
  481.             }
  482.  
  483.         retval = aspi_stat;                // return ASPI status
  484.         }
  485.  
  486.     return(retval);
  487.     }
  488.  
  489.  
  490. // ----------------------------------------------------------------------
  491. // Retrieve sense data from last ASPI I/O call.
  492. //
  493. // Usage:    int FUNC aspi_sense(BYTE _FAR *sb, int sbytes);
  494. //
  495. // Called with pointer to sense data buffer and data buffer length.
  496. // Returns number of bytes transferred on success, -1 on error.
  497. //
  498. // Note:
  499. //    Reads static data from last call where targ_stat was T_CHKSTAT.
  500. // ----------------------------------------------------------------------
  501.  
  502. int FUNC aspi_sense(BYTE _FAR *sb, int sbytes)
  503.     {
  504.     int nbytes;
  505.     int retval = -1;
  506.  
  507.     if (targ_stat == T_CHKSTAT)
  508.         {                                // check for valid sense data
  509.         nbytes = (sbytes < srb->su.s2.senselength) ?
  510.             sbytes : srb->su.s2.senselength;    // set transfer length
  511.         memcpy(sb, srb_sense, nbytes);
  512.                                         // copy sense data
  513.         retval = nbytes;                // return byte count
  514.         }
  515.  
  516.     return(retval);
  517.     }
  518.  
  519.