home *** CD-ROM | disk | FTP | other *** search
/ Media Share 13 / mediashare_13.zip / mediashare_13 / ZIPPED / PROGRAM / DDJ9403A.ZIP / ASPI.ASC next >
Text File  |  1994-01-30  |  13KB  |  290 lines

  1. _THE ADVANCED SCSI PROGRAMMING INTERFACE_
  2. by Brian Sawert
  3.  
  4.  
  5. Listing One
  6.  
  7. // ------ Initializing the ASPI driver. -------
  8. #include "aspi.h"                       // ASPI definitions and constants
  9. #include "scsi.h"                       // SCSI definitions and constants
  10. // -------------------- defines and macros --------------------
  11. #define IOCTL_READ  2                   // IOCTL read function
  12. #define ASPI_NAME   "SCSIMGR$"          // SCSI manager driver name
  13. // -------------------- global variables --------------------
  14. void (far *ASPIRoutine) (aspi_req_t far *); // far address of ASPI routine
  15. BYTE f_installed;                       // flag for ASPI existence
  16.  
  17. aspi_req_t *srb;                        // SCSI Request Block pointers
  18. // ----------------------------------------------------------------------
  19. // Routine to check for and initialize ASPI driver.
  20. // Usage:   int aspi_open(void);
  21. // Returns nonzero on success, 0 if ASPI driver not found or init failed.
  22. int aspi_open(void)
  23.     {
  24.     int dh;                             // ASPI driver handle
  25.     if (!f_installed)
  26.         {                               // not initialized
  27.         if ((dh = open(ASPI_NAME, O_RDONLY | O_BINARY)) != -1)
  28.             {                           // open device driver
  29.             if (ioctl(dh, IOCTL_READ, (void *) &ASPIRoutine,
  30.                 sizeof(ASPIRoutine)) == sizeof(ASPIRoutine))
  31.                 {                       // got ASPI entry point
  32.                 srb = (aspi_req_t *) malloc(sizeof(aspi_req_t));
  33.                 if (srb != NULL)
  34.                     {                   // allocated SRB buffers
  35.                     f_installed++;      // set installed flag
  36.                     }
  37.                 }
  38.             close(dh);                  // close device driver
  39.             }
  40.         }
  41.     return(f_installed);
  42.     }
  43. // ----------------------------------------------------------------------
  44. // Routine to close and clean up.
  45. // Usage:   void aspi_close(void);
  46. // Called with nothing. Returns nothing.
  47. void aspi_close(void)
  48.     {
  49.     if (f_installed)
  50.         {                               // already initialized
  51.         free(srb);                      // deallocate buffers
  52.         f_installed = 0;                // clear installed flag
  53.         }
  54.     return;
  55.     }
  56.  
  57.  
  58. Listing Two
  59.  
  60. // ------ Calling the ASPI entry point and ASPI I/O. -------
  61. #include "aspi.h"                       // ASPI definitions and constants
  62. #include "scsi.h"                       // SCSI definitions and constants
  63.  
  64. // -------------------- defines and macros --------------------
  65. #define BUSY_WAIT   0x1000              // repeat count for busy check
  66. #define MIN_GRP_1   0x20                // minimum SCSI group 1 command
  67. // -------------------- global variables --------------------
  68. void (far *ASPIRoutine) (aspi_req_t far *); // far address of ASPI routine
  69. BYTE f_installed;                       // flag for ASPI existence
  70. BYTE aspi_stat;                         // ASPI status byte
  71. BYTE host_stat;                         // host status byte
  72. BYTE targ_stat;                         // target status byte
  73. BYTE host_num;                          // host adapter number (0 default)
  74.  
  75. aspi_req_t *srb;                        // SCSI Request Block pointers
  76. sense_block_t *srb_sense;               // pointer to SRB sense data
  77. // ----------------------------------------------------------------------
  78. // Routine to call ASPI driver.
  79. // Usage:   int aspi_func(aspi_req_t *ar);
  80. // Called with pointer to SCSI Request Block (SRB).
  81. // Returns nonzero on success, 0 on error.
  82. int aspi_func(aspi_req_t *ar)
  83.     {
  84.     int retval = 0;
  85.  
  86.     if (f_installed)
  87.         {                               // ASPI manager initialized
  88.         ASPIRoutine((aspi_req_t far *) ar); // call ASPI manager
  89.         retval++;
  90.         }
  91.     return(retval);
  92.     }
  93. // ----------------------------------------------------------------------
  94. // Execute SCSI I/O through ASPI interface.
  95. // Usage:   int aspi_io(BYTE *cdb, BYTE far *dbuff, WORD dbytes,
  96. //              BYTE flags, BYTE id, WORD *stat);
  97. // Called with pointer to data buffer, data buffer size, pointer to CDB,
  98. //  request flags, and target ID. Returns ASPI status on success, -1 on error. 
  99. //  Fills stat variable with host status in high byte, target in low byte.
  100. int aspi_io(BYTE *cdb, BYTE far *dbuff, WORD dbytes, BYTE flags,
  101.     BYTE id, WORD *stat)
  102.     {
  103.     int cdbsize;
  104.     int timeout;                        // timeout counter for polling
  105.     int retval = -1;
  106.  
  107.     memset(srb, 0, sizeof(aspi_req_t)); // clear SRB
  108.     srb->command = SCSI_IO;             // set command byte
  109.     srb->hostnum = host_num;            // set host adapter number
  110.     srb->su.s2.targid = id;             // set target SCSI ID
  111.     srb->reqflags = flags;              // set request flags
  112.     srb->su.s2.databufptr = dbuff;      // set pointer to data buffer
  113.     srb->su.s2.datalength = dbytes;     // set data buffer length
  114.     srb->su.s2.senselength = sizeof(sense_block_t);
  115.                                         // set sense data buffer length
  116.     cdbsize = sizeof(group_0_t);        // assume 6 byte CDB
  117.     if (*((BYTE *) cdb) >= MIN_GRP_1 && *((BYTE *) cdb) < MIN_GRP_6)
  118.         {                               // CDB size is 10 bytes
  119.         cdbsize = sizeof(group_1_t);
  120.         }
  121.     srb->su.s2.cdblength = cdbsize;     // set CDB length
  122.     srb->su.s2.senselength = MAX_SENSE; // sense sense data length
  123.     memcpy(srb->su.s2.scsicdb, cdb, cdbsize);   // copy CDB to SRB
  124.     srb_sense = srb->su.s2.scsicdb + cdbsize;   // point to sense data buffer
  125.     if (aspi_func(srb))
  126.         {                               // ASPI call succeeded
  127.         timeout = BUSY_WAIT;            // set timeout counter
  128.         
  129.         while (srb->status == REQ_INPROG && timeout > 0)
  130.             {                           // request in progress - keep polling
  131.             timeout--;                  // decrement timeout counter
  132.             }
  133.         retval = aspi_stat = srb->status;   // save ASPI status
  134.         if (aspi_stat != REQ_INPROG)
  135.             {                           // request completed
  136.             host_stat = srb->su.s2.hoststat;    // save host status
  137.             targ_stat = srb->su.s2.targstat;    // save target status
  138.             *stat = ((WORD) host_stat << 8) | targ_stat;
  139.                                         // return combined SCSI status
  140.             }
  141.         }
  142.     return(retval);
  143.     }
  144.  
  145.  
  146. Listing Three
  147.  
  148. // ------  Initializing and using ASPI in a DLL. ------ 
  149. #include "aspi.h"                       // ASPI definitions and constants
  150. #include "scsi.h"                       // SCSI definitions and constants
  151. // -------------------- defines and macros -------------------
  152. #define IOCTL_READ  2                   // IOCTL read function
  153. #define ASPI_NAME   "SCSIMGR$"          // SCSI manager driver name
  154. #define DPMI_INT    0x31                // DPMI interrupt number
  155. #define REAL_CALL   0x301               // real mode call function
  156.  
  157. typedef struct RealCall
  158.     {                                   // struct for real mode call
  159.     DWORD edi, esi, ebp, reserved, ebx, edx, ecx, eax;
  160.     WORD flags, es, ds, fs, gs, ip, cs, sp, ss;
  161.     } RealCall_t ;
  162. // -------------------- global variables -------------------
  163. void (far *ASPIRoutine) (aspi_req_t far *); // far address of ASPI routine
  164. BYTE f_installed;                       // flag for ASPI existence
  165. aspi_req_t _FAR *srb;                   // SCSI Request Block pointers
  166. DWORD dwPtr;                            // return from GlobalDOSAlloc
  167. // -------------------- local functions -------------------
  168. void far *MaptoReal(void far *pptr);    // map to real mode address
  169. int AspiCall(void far *aspiproc, aspi_req_t far *ar);   // DPMI function
  170. // ----------------------------------------------------------------------
  171. // Routine to check for and initialize ASPI driver.
  172. // Usage:   int FUNC aspi_open(void);
  173. // Returns nonzero on success, 0 if ASPI driver not found or init failed.
  174. int FUNC aspi_open(void)
  175.     {
  176.     int dh;                             // ASPI driver handle
  177.     UINT wSRB;                          // selector for buffer memory
  178.     if (!f_installed)
  179.         {                               // not initialized
  180.         if ((dh = open(ASPI_NAME, O_RDONLY | O_BINARY)) != -1)
  181.             {                           // open device driver
  182.             if (ioctl(dh, IOCTL_READ, (void far *) &ASPIRoutine,
  183.                 sizeof(ASPIRoutine)) == sizeof(ASPIRoutine))
  184.                 {                       // got ASPI entry point
  185.                 dwPtr = GlobalDosAlloc(sizeof(aspi_req_t));
  186.  
  187.                 if (dwPtr[0] != NULL)
  188.                     {                   // allocated SRB buffer
  189.                     wSRB = LOWORD(dwPtr[0]);    // extract selector
  190.                     GlobalPageLock(wSRB);   // lock memory
  191.                     srb = (aspi_req_t _FAR *) MAKELP(wSRB, 0);
  192.                     f_installed++;      // set installed flag
  193.                     }
  194.                 }
  195.             close(dh);                  // close device driver
  196.             }
  197.         }
  198.     return(f_installed);
  199.     }
  200. // ----------------------------------------------------------------------
  201. // Routine to close and clean up.
  202. // Usage:   void FUNC aspi_close(void);
  203. // Called with nothing. Returns nothing.
  204. void FUNC aspi_close(void)
  205.     {
  206.     UINT wSRB;                          // selector for buffer memory
  207.     if (f_installed)
  208.         {                               // already initialized
  209.         wSRB = FP_SEG(srb);             // extract selector from pointer
  210.         GlobalPageUnlock(wSRB);         // unlock buffer
  211.         GlobalDosFree(wSRB);            // deallocate buffer
  212.         dwPtr = NULL;
  213.         srb = NULL;
  214.         f_installed = 0;                // clear installed flag
  215.         }
  216.     return;
  217.     }
  218. // ----------------------------------------------------------------------
  219. // Routine to call ASPI driver.
  220. // Usage:   int aspi_func(aspi_req_t _FAR *ar);
  221. // Called with pointer to SCSI Request Block (SRB).
  222. // Returns nonzero on success, 0 on error.
  223. int aspi_func(aspi_req_t _FAR *ar)
  224.     {
  225.     aspi_req_t far *arptr;              // real mode pointer
  226.     int retval = 0;
  227.     if (f_installed)
  228.         {                               // ASPI manager initialized
  229.         if ((arptr = (aspi_req_t far *) MaptoReal(ar)) != NULL)
  230.             {                           // got a valid real mode pointer
  231.             retval = AspiCall(ASPIRoutine, arptr); // call ASPI through DPMI
  232.             }
  233.         }
  234.     return(retval);
  235.     }
  236. // ----------------------------------------------------------------------
  237. // Routine to map protected mode pointer to real mode.
  238. // Usage:   void far *MaptoReal(void far *pptr);
  239. // Returns real mode pointer on success, NULL on error.
  240. void far *MaptoReal(void far *pptr)
  241.     {
  242.     WORD sel;                           // protected mode selector
  243.     void far *ptr = NULL;               // real mode pointer
  244.     sel = FP_SEG(pptr);                 // get selector value
  245.     if (sel == LOWORD(dwPtr))
  246.         {                               // found matching selector
  247.         ptr = MAKELP(HIWORD(dwPtr), FP_OFF(pptr));
  248.                                         // build real mode pointer
  249.         }
  250.     return(ptr);
  251.     }
  252. // ----------------------------------------------------------------------
  253. // Call ASPI manager through DPMI server.
  254. // Usage:   int AspiCall(void far *aspiproc, aspi_req_t far *ar);
  255. // Returns 1 on success, 0 otherwise.
  256. int AspiCall(void far *aspiproc, aspi_req_t far *ar)
  257.     {
  258.     RealCall_t rcs;                     // real mode call struct
  259.     int retval = 0;
  260.     int npush;
  261.     void far *sptr;
  262.     memset(&rcs, 0, sizeof(RealCall_t));    // clear call structure
  263.     rcs.cs = HIWORD(aspiproc);          // point to real mode proc
  264.     rcs.ip = LOWORD(aspiproc);
  265.     npush = sizeof(aspi_req_t far *) / sizeof(WORD); // words to pass on stack
  266.     sptr = (void far *) &rcs;           // far pointer to call structure
  267.     asm {
  268.         push di                         // save registers
  269.         push es
  270.         sub bx, bx                      // don't reset A20 line
  271.         mov cx, npush;                  // number of words to copy to stack
  272.         les di, sptr                    // point ES:DI to call structure
  273.         mov ax, REAL_CALL               // load function number
  274.         push WORD PTR [ar + 2]          // push SRB address
  275.         push WORD PTR [ar]
  276.         int DPMI_INT                    // call DPMI server
  277.         pop ax                          // restore stack count
  278.         pop ax
  279.         pop es                          // restore registers
  280.         pop di
  281.         jc asm_exit                     // DPMI error
  282.         mov retval, 1                   // return 1 for success
  283.         }
  284.     asm_exit:
  285.     return(retval);
  286.     }
  287.  
  288.  
  289.  
  290.