home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / aspir101.zip / aspirout.doc < prev    next >
Text File  |  1997-06-08  |  20KB  |  608 lines

  1.  
  2.  
  3.  
  4.  
  5.  ASPI  Router  for  OS/2
  6.  
  7.  Daniel Dorau (woodst@cs.tu-berlin.de)
  8.  
  9.  Version 1.01  June 1997
  10.  
  11.  
  12.  
  13.  
  14. Licence and Warranty
  15.  
  16.  
  17. ASPI Router and the accompaning library are provided to you iAS ISj, without
  18. warranty of any kind. You may use ASPI Router and the accompaning library
  19. for free. The use of ASPI Router and/or the accompaning library implies that
  20. you use it at your own risk and that you agree that the author (Daniel Dorau)
  21. has no warranty obligations and shall not be liable for any damages arising out
  22. of your use of this code, even if they have been advised of the possibility of
  23. such damages. You are allowed to use/modify the library code and use it in your
  24. own code together with the ASPI Router device driver.
  25.    Furthermore you may freely distribute ASPI Router and the library as long
  26. as you distribute it in the original non-modioed state together with this docu-
  27. mentation and without taking any charge other than for making it available to
  28. others.
  29.  
  30.  
  31.  
  32.                                  2
  33.  
  34.  
  35.  
  36.  
  37. Contents
  38.  
  39.  
  40. 1  Overview                                                                3
  41.  
  42.    1.1  Why ASPI Router?   . . . . . . . . . . . . . . . . . . . . . . .   3
  43.  
  44.    1.2  Why ASPI?  . . . . . . . . . . . . . . . . . . . . . . . . . . .   4
  45.  
  46.    1.3  What does ASPI Router?   . . . . . . . . . . . . . . . . . . . .   4
  47.  
  48.    1.4  The ASPILIB library  . . . . . . . . . . . . . . . . . . . . . .   4
  49.  
  50.    1.5  Current limitations   . . . . . . . . . . . . . . . . . . . . . .  4
  51.  
  52.  
  53. 2  Interface to ASPI Router                                                4
  54.  
  55.    2.1  Opening the driver . . . . . . . . . . . . . . . . . . . . . . .   4
  56.  
  57.    2.2  Semaphore initialization   . . . . . . . . . . . . . . . . . . .   5
  58.  
  59.    2.3  Buffer initialization    . . . . . . . . . . . . . . . . . . . .   5
  60.  
  61.    2.4  Host adapter inquiry   . . . . . . . . . . . . . . . . . . . . .   6
  62.  
  63.    2.5  Get Device Type  . . . . . . . . . . . . . . . . . . . . . . . .   7
  64.  
  65.    2.6  Abort SRB  . . . . . . . . . . . . . . . . . . . . . . . . . . .   7
  66.  
  67.    2.7  Reset SCSI device  . . . . . . . . . . . . . . . . . . . . . . .   8
  68.  
  69.    2.8  Issuing SCSI commands  . . . . . . . . . . . . . . . . . . . . .   8
  70.  
  71.    2.9  Closing the driver   . . . . . . . . . . . . . . . . . . . . . .   9
  72.  
  73.    2.10 Summary of ASPI Rounter function codes   . . . . . . . . . . . .  10
  74.  
  75.  
  76. 3  The ASPILIB library                                                    10
  77.  
  78.    3.1  Initializing the library   . . . . . . . . . . . . . . . . . . .  10
  79.  
  80.    3.2  Using library funtions   . . . . . . . . . . . . . . . . . . . .  10
  81.  
  82.    3.3  Closing the library  . . . . . . . . . . . . . . . . . . . . . .  10
  83.  
  84.  
  85. 4  Other Information                                                      11
  86.  
  87.    4.1  People I want to thank   . . . . . . . . . . . . . . . . . . . .  11
  88.  
  89.    4.2  Contact, Reporting bugs  . . . . . . . . . . . . . . . . . . . .  11
  90.  
  91.  
  92.  
  93. 1    Overview
  94.  
  95.  
  96.  
  97. 1.1   Why ASPI Router?
  98.  
  99.  
  100. In OS/2 it is not possible for Ring-3 applications to call OS2SCSI.DMD or OS2-
  101. ASPI.DMD directly, therefore any application which wants to access the SCSI
  102. bus has to provide its own driver to access the SCSI bus via OS2SCSI.DMD or
  103. OS2ASPI.DMD. Since many users want to write their own SCSI applications but
  104. shy away from writing their own driver, I decided to write a simple driver which
  105. provides access to OS2ASPI.DMD for Ring-3 applications.  Since it only routes
  106. SRBs (SCSI request blocks) to OS2ASPI.DMD I named it iASPI Routerj.
  107.  
  108.  
  109.  
  110.                                  3
  111.  
  112.  
  113.  
  114.  
  115. 1.2   Why ASPI?
  116.  
  117.  
  118. Besides ASPI, in OS/2 there also exists the possibility to issue SCSI commands
  119. through OS2SCSI.DMD. So why did I decide to use OS2ASPI.DMD?
  120.  
  121. I decided to use ASPI because a) it seemed to be easier to use for the
  122. application developer as well as for the device driver developer (me) and b)
  123. I hope that libraries for other platforms using ASPI can be ported more
  124. easily.
  125.  
  126.  
  127.  
  128. 1.3   What does ASPI Router?
  129.  
  130.  
  131. The interface of ASPI Router merely is an extension of the interface of OS2-
  132. ASPI.DMD which expects a SRB and a callback function to call when the SRB
  133. was processed.  ASPI Router simply takes this SRB from your application via
  134. DosDevIOCtl and calls OS2ASPI.DMD with this SRB after conversion of virtual
  135. to physical addresses.  Additionaly, ASPI Router provides a callback function
  136. for OS2ASPI.DMD. If this function gets called by OS2ASPI.DMD, ASPI Router
  137. posts an event semaphore opened by your application before.  So before ASPI
  138. Router can process the orst SRB, the application has to pass the handle of this
  139. semaphore to the driver. ASPI Router closes its own handle of the semaphore
  140. automatically when the application closes the driver.
  141.  
  142.  
  143.  
  144. 1.4   The ASPILIB library
  145.  
  146.  
  147. The accompaning library consisting of the oles aspilib.cpp, aspilib.h and
  148. srb.h is intended as an example of how to use the ASPI Router device driver.
  149. You may use this library or parts of it in your own programs or modify parts of
  150. it so that it meets your requirements.
  151.  
  152.  
  153.  
  154. 1.5   Current limitations
  155.  
  156.  
  157. ASPI Router does not support scatter/gather or SRB linking.  The maximum
  158. size of data transferred per SRB is 64K (=65536 bytes).  Only one applica-
  159. tion can use this driver at a time.  Therefore you need to open it with the
  160. OPEN_SHARE_DENYREADWRITE AEag to prevent other applications from opening
  161. the driver while already in use.
  162.  
  163.  
  164.  
  165. 2    Interface to ASPI Router
  166.  
  167.  
  168. All functions of ASPI Router can be accessed with DosDevIOCtl after opening
  169. the driver with DosOpen. The name of the driver handle is ASPIROU$.
  170.  
  171.  
  172.  
  173. 2.1   Opening the driver
  174.  
  175.  
  176. The driver can be opened with the following call:
  177.  
  178.  
  179.  
  180.                                  4
  181.  
  182.  
  183.  
  184.  
  185.   ULONG rc;                                      // return value
  186.   ULONG ActionTaken;                             // return value
  187.  
  188.  
  189.   rc = DosOpen((PSZ) "aspirou$",                // open driver
  190.                 &driver_handle,
  191.                 &ActionTaken,
  192.                 0,
  193.                 0,
  194.                 FILE_OPEN,
  195.                 OPEN_SHARE_DENYREADWRITE |
  196.                 OPEN_ACCESS_READWRITE,
  197.                 NULL);
  198.  
  199.  
  200.  
  201. 2.2   Semaphore initialization
  202.  
  203.  
  204. Before any SRBs can be processed, ASPI Router needs a handle of an event
  205. semaphore. ASPI Router will post this semaphore for every SRB which has been
  206. processed. To create this semaphore and to send its handle to ASPI Router, the
  207. following code can be used:
  208.  
  209.  
  210.   ULONG  rc;                                   // return value
  211.   USHORT openSemaReturn;                      // return value
  212.   HEV    postSema;                             // event
  213.                                                 // semaphore
  214.   unsigned long cbreturn;
  215.   unsigned long cbParam;
  216.  
  217.  
  218.   rc = DosCreateEventSem(NULL, &postSema,    // create event
  219.                            DC_SEM_SHARED, 0);  // semaphore
  220.  
  221.  
  222.   rc = DosDevIOCtl(driver_handle, 0x92,       // pass
  223.                     0x03,                      // semaphore
  224.                     (void*) &postSema,         // handle to
  225.                     sizeof(HEV), &cbParam,    // driver
  226.                     (void*) &openSemaReturn,
  227.                     sizeof(USHORT), &cbreturn);
  228.  
  229.  
  230. If ASPI Router could open the semaphore, openSemaReturn will be set to zero.
  231. Otherwise an error occured.
  232.  
  233.  
  234.  
  235. 2.3   Buoeer initialization
  236.  
  237.  
  238. After passing the semaphore handle to the driver you still need to do one step
  239. before you can issue SCSI commands. You have to initialize the buoeer. You have
  240. to allocate a buoeer in your application where the driver can access the data to
  241.  
  242.  
  243.  
  244.                                  5
  245.  
  246.  
  247.  
  248.  
  249. be transferred. The driver has not only to convert virtual to physical
  250. addresses,
  251. it also has to ensure that the virtual address is in physical memory (e.g.  not
  252. swapped out) and that it does not change its position in physical memory. To
  253. achieve this, it calls a helper function which locks the buoeer down in memory.
  254. Another important point is that the buoeer must not cross a 64K-boundary in
  255. physical memory. Your task is to allocate this buoeer and pass its address to
  256. the driver. You can do this as follows:
  257.  
  258.  
  259.   PVOID  buffer                                // our buffer
  260.   ULONG  rc;                                   // return value
  261.   USHORT lockSegmentReturn;                   // return value
  262.   unsigned long cbreturn;
  263.   unsigned long cbParam;
  264.  
  265.  
  266.   rc = DosAllocMem(&buffer, bufsize,          // allocate the
  267.                     OBJ_TILE | PAG_READ        // buffer at a
  268.                     | PAG_WRITE                // 64K boundary
  269.                     | PAG_COMMIT);
  270.   rc = DosDevIOCtl(driver_handle, 0x92,       // pass buffer
  271.                     0x04, (void*) buffer,      // pointer
  272.                     sizeof(PVOID),             // to driver
  273.                     &cbParam,
  274.                     (void*) &lockSegmentReturn,
  275.                     sizeof(USHORT), &cbreturn);
  276.  
  277.  
  278. If DosDevIOCtl returns with a non-zero value of lockSegmentReturn some-
  279. thing went wrong with locking the buoeer.
  280.  
  281.  
  282.  
  283. 2.4   Host adapter inquiry
  284.  
  285.  
  286. Do determine the number of host adapters available and to retrieve information
  287. about them you can issue the iHost adapter Inquiryj command.  Refer to the
  288. iStorage Device Driver Referencej [1] to get more information about it. Here is
  289. an example:
  290.  
  291.  
  292.   ULONG rc;                              // return value
  293.   unsigned long cbreturn;
  294.   unsigned long cbParam;
  295.  
  296.  
  297.   SRBlock.cmd=SRB_Inquiry;              // host adapter inquiry
  298.   SRBlock.ha_num=ha;                    // host adapter number
  299.   SRBlock.flags=0;                      // no flags set
  300.  
  301.  
  302.   rc = DosDevIOCtl(driver_handle, 0x92, 0x02,
  303.                     (void*) &SRBlock, sizeof(SRB), &cbParam,
  304.  
  305.  
  306.  
  307.                                  6
  308.  
  309.  
  310.  
  311.  
  312.                     (void*) &SRBlock, sizeof(SRB), &cbreturn);
  313.  
  314.  
  315.  
  316. 2.5   Get Device Type
  317.  
  318.  
  319. To get the device type there is the iGet Device Typej command. Refer to the
  320. iStorage Device Driver Referencej [1] to get more information about it. Here is
  321. an example:
  322.  
  323.  
  324.  
  325.   ULONG rc;                               // return value
  326.   unsigned long cbreturn;
  327.   unsigned long cbParam;
  328.  
  329.  
  330.   SRBlock.cmd=SRB_Device;                // get device type
  331.   SRBlock.ha_num=0;                      // host adapter number
  332.   SRBlock.flags=0;                       // no flags set
  333.   SRBlock.u.dev.target=id;               // target id
  334.   SRBlock.u.dev.lun=lun;                 // target LUN
  335.  
  336.  
  337.   rc = DosDevIOCtl(driver_handle, 0x92, 0x02,
  338.                     (void*) &SRBlock, sizeof(SRB), &cbParam,
  339.                     (void*) &SRBlock, sizeof(SRB), &cbreturn);
  340.  
  341.  
  342.  
  343. 2.6   Abort SRB
  344.  
  345.  
  346. With this command you tell OS2ASPI.DMD to abort the previous SRB. You have
  347. to specify a second SRB with which you pass the address of the SRB to be
  348. aborted to the driver. Aborting a SRB does not have to be successful. Watch
  349. the status values and sense code of the SRB you aborted. For further information
  350. about this command refer to the iStorage Device Driver Referencej [1]. Here is
  351. an example:
  352.  
  353.  
  354.  
  355.   ULONG rc;                               // return value
  356.   unsigned long cbreturn;
  357.   unsigned long cbParam;
  358.  
  359.  
  360.   AbortSRB.cmd=SRB_Abort;                // abort SRB
  361.   AbortSRB.ha_num=0;                     // host adapter number
  362.   AbortSRB.flags=0;                      // no flags set
  363.   AbortSRB.u.abt.srb=&SRBlock;           // SRB to abort
  364.  
  365.  
  366.   rc = DosDevIOCtl(driver_handle, 0x92, 0x02,
  367.                     (void*) &AbortSRB, sizeof(SRB), &cbParam,
  368.                     (void*) &AbortSRB, sizeof(SRB), &cbreturn);
  369.  
  370.  
  371.  
  372.                                  7
  373.  
  374.  
  375.  
  376.  
  377. 2.7   Reset SCSI device
  378.  
  379.  
  380. A SCSI device can be reset with the iReset SCSI devicej command as described
  381. in the iStorage Device Driver Referencej [1]. Here is an example:
  382.  
  383.  
  384.   ULONG rc;                               // return value
  385.   unsigned long cbreturn;
  386.   unsigned long cbParam;
  387.  
  388.  
  389.   SRBlock.cmd=SRB_Reset;                 // reset device
  390.   SRBlock.ha_num=0;                      // host adapter number
  391.   SRBlock.flags=SRB_Post;                // posting enabled
  392.   SRBlock.u.res.target=id;               // target id
  393.   SRBlock.u.res.lun=lun;                 // target LUN
  394.  
  395.  
  396.   rc = DosDevIOCtl(driver_handle, 0x92, 0x02,
  397.                     (void*) &SRBlock, sizeof(SRB), &cbParam,
  398.                     (void*) &SRBlock, sizeof(SRB), &cbreturn);
  399.  
  400.  
  401.  
  402. 2.8   Issuing SCSI commands
  403.  
  404.  
  405. SCSI commands can be issued by sending ASPI SRBs (SCSI Request Blocks)
  406. to the ASPI Router. The data structure deonition of the SRB and it's constant
  407. deonitions can be found in srb.h. The cdb_st oeld has to be olled with a valid
  408. SCSI command. Refer to the SCSI command reference [2] for a description of
  409. the dioeerent SCSI devices and their commands. An example of sending a SRB
  410. to ASPI Router follows below:
  411.  
  412.  
  413.   ULONG rc;                                   // return value
  414.   SRB   SRBlock;
  415.  
  416.  
  417.   unsigned long cbreturn;
  418.   unsigned long cbParam;
  419.  
  420.  
  421.   SRBlock.cmd=SRB_Command;                   // execute SCSI
  422.                                                // command
  423.   SRBlock.ha_num=0;                           // host adapter
  424.                                                // number
  425.   SRBlock.flags=SRB_Read _ SRB_Post;         // data transfer,
  426.                                                // posting enabled
  427.   SRBlock.u.cmd.target=6;                    // Target SCSI ID
  428.   SRBlock.u.cmd.lun=0;                       // Target SCSI LUN
  429.   SRBlock.u.cmd.data_len=512*transfer;       // # of bytes
  430.                                                // transferred
  431.   SRBlock.u.cmd.sense_len=32;                // length of
  432.  
  433.  
  434.  
  435.                                  8
  436.  
  437.  
  438.  
  439.  
  440.                                                // sense buffer
  441.   SRBlock.u.cmd.data_ptr=NULL;               // pointer to
  442.                                                // data buffer
  443.   SRBlock.u.cmd.link_ptr=NULL;               // pointer to
  444.                                                // next SRB
  445.   SRBlock.u.cmd.cdb_len=6;                   // SCSI command
  446.                                                // length
  447.   SRBlock.u.cmd.cdb_st[0]=0x08;              // read command
  448.   SRBlock.u.cmd.cdb_st[1]=1;                 // fixed length
  449.   SRBlock.u.cmd.cdb_st[2]=(transfer >> 16)  // transfer
  450.                             & 0xFF;            // length MSB
  451.   SRBlock.u.cmd.cdb_st[3]=(transfer >> 8)   // transfer
  452.                             & 0xFF;            // length
  453.   SRBlock.u.cmd.cdb_st[4]=transfer & 0xFF;  // transfer
  454.                                                // length LSB
  455.   SRBlock.u.cmd.cdb_st[5]=0;
  456.  
  457.  
  458.   rc = DosDevIOCtl(driver_handle, 0x92, 0x02,
  459.                    (void*) &SRBlock, sizeof(SRB), &cbParam,
  460.                    (void*) &SRBlock, sizeof(SRB), &cbreturn);
  461.  
  462.  
  463. After the SRB is being processed you may read the status oelds out of the SRB
  464. and decide whether the SRB was processed successfully or not.  Notice that
  465. the oeld data_ptr is always set to NULL. Since you initialize the data buoeer
  466. before any SRBs can be processed the driver knows the correct physical address
  467. and inserts it automatically.  Note that the valid bit in sense data does not
  468. always represent its current state. Refer to the target status oeld of the SRB
  469. to determine whether the sense data is valid or not.
  470.  
  471.  
  472.  
  473. 2.9   Closing the driver
  474.  
  475.  
  476. After you're done you have to close the driver. The driver will close its
  477. semaphore
  478. handle and unlock the buoeer (otherwise you won't be able to free the memory).
  479. Then don't forget to close the semaphore in your app and free the buoeer memory.
  480. This shows how it can be done:
  481.  
  482.  
  483.  
  484.   ULONG  rc;                            // return value
  485.  
  486.  
  487.   rc = DosCloseEventSem(postSema);    // close event semaphore
  488.   rc = DosClose(driver_handle);        // close driver
  489.   rc = DosFreeMem(buffer);             // free our buffer
  490.  
  491.  
  492. Be careful to close the driver before you free the memory. Attempting to free
  493. locked memory does not work.
  494.  
  495.  
  496.  
  497.                                  9
  498.  
  499.  
  500.  
  501.  
  502. 2.10   Summary of ASPI Rounter function codes
  503.  
  504.  
  505. ASPI Router provides the following functions:
  506.  
  507.  
  508.    _______________________________________________________________
  509.    |_Category__Function__Description______________________________|
  510.  
  511.    | 92h       02h       Route SRB to ASPI driver                 |
  512.    |                     The driver expects the address of a SRB. The|
  513.    |                     'Data Buoeer Pointer' oeld needs not to be|olled.
  514.    |                                                              |
  515.    | 92h       03h       Pass semaphore handle                    |
  516.    |                     The driver expects the pointer to an event|
  517.    |                                                              |
  518.    |                     semaphore handle to notify the application|that
  519.    |                     a SRB has be processed.                  |
  520.    |                                                              |
  521.    | 92h       04h       Pass Data Buoeer Pointer                 |
  522.    |                     The driver expects the pointer to a data buoeer.|
  523.    |                     The buoeer must not cross a 64K-boundary.|
  524.    |______________________________________________________________|
  525.  
  526.  
  527.  
  528. 3    The ASPILIB library
  529.  
  530.  
  531.  
  532. The ASPILIB library is written as a C++ object to be used with (hopefully) any
  533. C++ compiler. I developed it as an example library that shows how to use the
  534. driver. Since I need it for my tape drive, only functions I need for this
  535. application
  536. are implemented. If you need additional functions, add them.
  537.  
  538.  
  539.  
  540. 3.1   Initializing the library
  541.  
  542.  
  543. First, create a variable of the object type scsiObj. Then you have to call the
  544. init(ULONG bufsize) function to which you have to pass the size of the data
  545. buoeer you wish to use.  Note that the maximum size supported by the driver
  546. is 64K (=65536 bytes).  If the call returns with TRUE, all went ok, otherwise
  547. something went wrong.
  548.  
  549.  
  550.  
  551. 3.2   Using library funtions
  552.  
  553.  
  554. After initializing the library you can use any public member functions of your
  555. SCSI object.  Be careful to check if your calls return successful and check the
  556. error codes or sense data if necessary.
  557.  
  558.  
  559.  
  560. 3.3   Closing the library
  561.  
  562.  
  563. Before you quit your application you have to close the library. This is done by
  564. calling the close() function.
  565.  
  566.  
  567.  
  568.                                  10
  569.  
  570.  
  571.  
  572.  
  573. 4    Other Information
  574.  
  575.  
  576. 4.1   People I want to thank
  577.  
  578.  
  579. Big thanks go to Alger Pike (acp107@psu.edu) who wrote the Hello World Device
  580. Driver. Without this I wouldn't have known where to start.
  581.  
  582.  
  583.  
  584. 4.2   Contact, Reporting bugs
  585.  
  586.  
  587. If you use my driver and/or the library, please tell me what you think about it.
  588. Furthermore you're welcome to report any bugs to me you encounter. My email
  589. address is woodst@cs.tu-berlin.de.
  590. If you want to use PGP for your email, you can retrieve my public key by sending
  591. me a mail with send pgp key in the subject line.
  592.  
  593.  
  594.  
  595. References
  596.  
  597.  
  598. [1] Storage Device Driver Reference, part of IBM's Device Driver Kit (DDK),
  599.     freely available at http://service.boulder.ibm.com/ddk
  600.  
  601.  
  602. [2] SCSI command reference, for those who have Internet access: I found one
  603.     in the WWW at http://abekas.com:8080/SCSI2/
  604.  
  605.  
  606.  
  607.                                  11
  608.