home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / scsipg.zip / WORKINGS < prev   
Text File  |  1993-05-14  |  52KB  |  1,078 lines

  1. Contents
  2.  
  3. 1.0  Introduction
  4.  
  5. This section talks about the SCSIPGMG package in general - what its intended
  6. use is, how it came to be, and who the author is.
  7.  
  8. 1.1. What is this package is
  9.  
  10. This package is a program, device driver and documentation that demonstrates
  11. and explains how to interface to SCSI devices in OS/2 V2.0 and above.
  12. Source is included for all software that I wrote and information is provided
  13. for obtaining source and documentation for many of the OS/2 supplied parts.
  14.  
  15. 1.2. What this package tries to do
  16.  
  17. This package tries to teach the reader how to interface to SCSI devices in the
  18. OS/2 environment.  It describes how SCSI works, how SCSI drivers fit into the
  19. OS/2 architecture, what the interfaces to these drivers are and how to use
  20. them.  It examines in detail a working device driver that interfaces to the
  21. provided SCSI drivers and a program that drives SCSI devices.  It goes into
  22. some detail explaining how SCSI works so the reader will have a better
  23. understanding of the technical specifications of SCSI devices and adapters.
  24.  
  25. 1.3. What this package doesn't try to do
  26.  
  27. This package does not attempt to teach the reader how to write OS/2 device
  28. drivers or programs.  Those topics are covered in much greater detail in
  29. other sources and by much better teachers.
  30.  
  31. 1.4. Who am I
  32.  
  33. My name is Dennis Rowe.  I am a Advisory Engineer working for IBM in Boulder,
  34. Colorado, currently in the IBM Software Manufacturing Company.  I've been
  35. programming since 1978 and doing OS/2 device drivers since 1988.  Most of my
  36. work has been for technology investigations or for internal use projects, but
  37. I have been part of 2 products released for sale :
  38.  
  39. 1. IBM S/370 and S/390 Optical Media Attach/2 - this is a piece of software
  40.    and hardware for Microchannel machines that makes a PC look like a 3422
  41.    tape drive to a mainframe.  It gives the mainframe access to any PC storage
  42.    available to an OS/2 application via the OS/2 filesystems.  I wrote the
  43.    microcode running in the adapter, the OS/2 device driver and the Control
  44.    Unit emulation code in the application layer.
  45.  
  46. 2. IBM Portable CDROM - This is a CDROM drive that attaches to a PC via the
  47.    parallel port, available from IBM to OEMs.  I wrote the 2 OS/2 device
  48.    drivers and the DOS/Windows device driver.
  49.  
  50. I can be reached via EMAIL at the following addresses:
  51. Internet - rowe@vnet.ibm.com
  52. Compuserve - 75140,3710
  53. Prodigy - CPMG10A
  54. Internal IBM - ROWE at BOULDER
  55.                ROWE at BLDVMA
  56. Internal IBM IPNET - user@rowe.swm.boulder.ibm.com
  57.  
  58. 1.5. Why did I do this?
  59.  
  60. There are really two questions here: why did I do these programs and why did
  61. I put this package together.
  62.  
  63. I wrote these programs for my own uses.  One of my current projects (late 1992
  64. to early 1993) involves driving SCSI devices from a mainframe in support of the
  65. IBM Software Manufacturing Company's manufacturing processes.  In order to gain
  66. an understanding of how to interface to the OS/2 SCSI driver system, I wrote
  67. the GENSCSI driver.  As this driver provides a good generic SCSI interface for
  68. application programs, I plan to build my application on it.  In order to gain
  69. an understanding of the specific devices I needed to drive, I wrote the
  70. SCSITEST program.  It has been invaluable in experimenting with the devices
  71. themselves.
  72.  
  73. I put this package together because I saw many questions on Compuserve, BIX
  74. and on IBM's internal bulletin boards asking how to write OS/2 software to
  75. drive SCSI attached tape drives and printers and such.  Since I feel that for
  76. OS/2 to be a big success, there must be lots of information about to program
  77. it, especially examples, I decided to put this software I had written together
  78. with a good explanation out in the general public.
  79.  
  80. This package was done on my own time with no assistance from IBM.  IBM has no
  81. responsibility for it.  If you have a problem with it, talk to me, not IBM.
  82.  
  83. 1.6. Where you can get more information
  84.  
  85. More information on OS2 device drivers and SCSI can be found in the following:
  86.  
  87. OS/2 Device Drivers:
  88. Writing OS/2 2.0 Device Drivers in C - Steve Mastrianni
  89.    ISBN - 0-442-01141-5
  90.  
  91. The IBM OS/2 Device Driver Development Kit (DDK) :
  92.    Send a fax that includes your your company's name and address and phone
  93.    numbers (including a FAX number) to 407-982-4218. You will then receive
  94.    a form from them to the address you have given them.  The DDK is a CDROM
  95.    with source for many of the device drivers shipped with OS/2, including
  96.    the OS2SCSI.DMD discussed in this paper, several CDROM device drivers,
  97.    a hard disk driver and an ASPI driver that interface to SCSI.
  98.  
  99. In addition, the OS/2 Technical Library (aka the Toolkit) contains the
  100. Physical Device Driver Reference - the last word in OS/2 device drivers.
  101.  
  102. SCSI:
  103.    SCSI - Architecture and Implementation  IBM Redbooks GG24-3507
  104.    The SCSI Bus - A 2-part series on the history and operation of SCSI
  105.                   appeared in the February, 1990 and March, 1990 issues of
  106.                   Byte Magazine.
  107.  
  108.  
  109. Finally, at the end of the OEMBASE document included in this package is
  110. another list of useful references.
  111.  
  112. 2. Architecture
  113. 2.1. Where the pieces fit in OS/2
  114.  
  115.                +--------------+ +----------------+ +--------------+
  116.                | CDROM Music  | |  SCSITEST Demo | | Other SCSI   |  ....
  117.                | Player App   | |    Program     | | Application  |
  118.                +--------------+ +----------------+ +--------------+
  119.                       |                  |                 |
  120.                       |                  |                 |
  121.                +-----------------------------------------------------------+
  122.                |                                                           |
  123.                |                                                           |
  124.                |                       OS/2 KERNEL                         |
  125.                |                                                           |
  126.                |                                                           |
  127.                +-----------------------------------------------------------+
  128.                       |                  |                 |
  129.                       |                  |                 |
  130.                +--------------+ +----------------+ +----------------+
  131.                | CDROM CLASS  | |  OPTICAL CLASS | | GENSCSI Device |  ....
  132.                |   DRIVER     | |     DRIVER     | |    DRIVER      |
  133.                +--------------+ +----------------+ +----------------+
  134.                       |                  |                 |
  135.                       |                  |                 |
  136.                +-----------------------------------------------------------+
  137.                |                                                           |
  138.                |             OS2SCSI.DMD SCSI DEVICE MANAGER               |
  139.                |                                                           |
  140.                +-----------------------------------------------------------+
  141.                                              |
  142.                                              |
  143.                +-----------------------------------------------------------+
  144.                |                         SCSI ADD                          |
  145.                +-----------------------------------------------------------+
  146.                                              |
  147.                                              |
  148.                +-----------------------------------------------------------+
  149.                |                        SCSI ADAPTER                       |
  150.                +-----------------------------------------------------------+
  151.                       |                 |                  |
  152.                       |                 |                  |
  153.                +--------------+ +----------------+ +--------------+
  154.                | CDROM SCSI   | |  OPTICAL SCSI  | | OTHER SCSI   |  ....
  155.                |    DEVICE    | |     DEVICE     | |    DEVICE    |
  156.                +--------------+ +----------------+ +--------------+
  157.  
  158. With V2, OS/2 has adopted a layered approach to driving SCSI devices.  There
  159. are 3 layers of drivers - the Adapter Device Driver (.ADD), the Device Manager
  160. Driver (.DMD), and the Class Driver (.SYS).  Each has its specific task.
  161. In this case, we are discussing a specific Device manager - OS2SCSI.DMD.
  162.  
  163. The .ADD's main job is to direct given SCSI commands to a device at a given
  164. device.  It doesn't concern itself with what the commands mean or whether the
  165. device will accept the command or what state the device is in, or even what
  166. the device is.  It just tries to send the command and reports the results.
  167. Its other main job is to tell anybody who asks what types of devices it has
  168. attached to each of its supported adapters and what the capabilities of each
  169. adapter is.  This lets the caller (.DMD) know how to send commands.  It is up
  170. to the manufacturer of an adapter to provide an .ADD for their adapter.
  171.  
  172. The OS2SCSI.DMD's job is to provide a single interface to all the SCSI devices
  173. in the system that are not reserved by another .DMD. It provides facilities
  174. for reserving devices, dealing with adapter caches, reading and setting device
  175. capabilities and issuing commands to the device through a single interface.
  176. That interface is described in detail in the portion of the OEMBASE.TXT file
  177. included in this package.  This document will describe how to use the interface
  178. and give examples.
  179.  
  180. The Class driver's job is to provide a single interface to all the SCSI devices
  181. in the system of a particular type (CDROM, tape, etc).  It maintains device
  182. state information, translates high level commands (READ, SEEK, WRITE) into the
  183. command specific to the particular device.  This is the layer that knows
  184. what command each device understands and how to interpret each device's
  185. particular error codes.
  186.  
  187. This architecture is not, however, rigid.  OS/2 2.1 puts it's CDROM class
  188. drivers at the same level as the device managers.  In this case, it is one of
  189. those other .DMD's mentioned above.
  190.  
  191. 2.2. OS2SCSI.DMD
  192.  
  193. IBM supplies several DMDs with OS/2.  We are interested in one of them -
  194. OS2SCSI.DMD.  This is a generic device manager.  Other device managers
  195. will request that a particular device be allocated to them and will translate
  196. the READ/WRITE/SEEK/etc. commands into specific SCSI commands designed for
  197. the particular device and pass the command to OS2SCSI.DMD for execution.
  198. When OS2SCSI.DMD returns, the driver will examine the results and translate
  199. them into the proper response for OS/2.
  200.  
  201. The advantage of this system is that the class drivers do not have to know
  202. how to get a SCSI command executed or what SCSI ID their device is set to.
  203. The also don't have to deal with details like supporting multiple SCSI adapters
  204. or different SCSI adapters.  They just reserve the device, issue commands and
  205. free the device when done.
  206.  
  207. 2.3. GENSCSI.SYS
  208.  
  209. The problem, from an application point of view, with OS2SCSI.DMD is that it
  210. was designed to be called by another device driver.  It expects physical
  211. addresses in some of the control blocks.  It also expects some virtual
  212. addresses to be valid at interrupt time.  This requires that the address be a
  213. GDT based address.  Applications cannot supply physical addresses or GDT
  214. based virtual addresses, only a device driver can do that.
  215.  
  216. To solve these problems I wrote GENSCSI.SYS.  Its job is to accept the same
  217. commands that OS2SCSI.DMD accepts, but it knows that they are coming from an
  218. application.  It builds a new request packet, converting virtual addresses to
  219. physical addresses where needed and converting LDT based pointers to GDT
  220. based pointers in other cases.  It then passes this new command to OS2SCSI.DMD
  221. and waits for a response.  When the response returns, it transfers the results
  222. to the original request packet and returns to the caller.  In this way, it
  223. provides an interface to OS2SCSI.DMD for applications.
  224.  
  225.  
  226. 2.4. SCSITEST.EXE
  227.  
  228. SCSITEST.EXE is a program that lets you manually issue commands to OS2SCSI.DMD
  229. and to SCSI devices via GENSCSI.SYS.  With this in mind, it provides 2
  230. functions:  it allows you to explore how a SCSI device works and it provides
  231. sample code for interfacing to GENSCSI.SYS, OS2SCSI.DMD and SCSI devices.
  232.  
  233.  
  234. 3.       SCSI
  235.  
  236. SCSI stands for Small Computer Systems Interface.  It is a standardized
  237. interface through which computers may communicate with a large variety of
  238. peripherals such as disk drives, tape drives, printers and plotters.
  239.  
  240. 3.1.     How SCSI works
  241.  
  242. SCSI is composed of an 8-bit parallel bus and a number of control signals.
  243. Its operation is basically a command oriented operation.  One device on the
  244. bus sends a command to another device and there may be a transfer of data
  245. involved.  It is a peer-to-peer connection.  Any device may send a command
  246. to any other device, in theory.  In practice, though, it tends to be a
  247. master-slave arrangement with the CPU doing all the commands and the
  248. peripherals only responding to commands.
  249.  
  250. SCSI originally evolved out of the S/360 Channel - introduced in 1964.  You
  251. can see many similarities - selection/reselection, command phase, data
  252. transfer, and status phase.  There have been several major changes, though.
  253. The peer-to-peer arrangement is different; the channel is strictly master-
  254. slave.  The command has been expanded from 1 byte to up to 12 bytes.  There
  255. is provision for disconnection before any data is transferred, where in the
  256. channel that was only allowed in byte multiplexor mode - the slowest mode.
  257.  
  258. 3.1.1.   The Basic Sequence
  259.  
  260. There are 7 basic phases to the SCSI bus:
  261.    1. Bus Free phase - In this phase there is no operation occurring on the
  262.                       bus.  Any device is available for any device to use.
  263.  
  264.    2. Arbitration phase - In this phase one or more devices is attempting
  265.                       to gain control of the bus.
  266.  
  267.    3. Selection/Reselection phase - In this phase, the initiator is attempting
  268.                       to start communication with the target.
  269.  
  270.    4. Command Phase - This is where the command is sent from the initiator to
  271.                       the target.
  272.  
  273.    5. Data In/Out Phase - This is when data transfer takes place.
  274.  
  275.    6. Status Phase - In this phase the target sends a status byte to the
  276.                       initiator indication the completion status of the
  277.                       command.
  278.  
  279.    7. Message Phase - Here, the target and initiator MAY pass messages to each
  280.                       other describing the SCSI bus and how they will
  281.                       communicate.
  282.  
  283. 3.2.   How the IBM Microchannel SCSI cards work
  284.  
  285. The IBM Microchannel SCSI cards are really small processors that have access
  286. to the CPU's memory.  You essentially point them at a block of memory that
  287. holds their commands and say 'Go!'  When they are done, they interrupt you
  288. and you examine the results.
  289.  
  290. 3.2.1. Bus Masters
  291.  
  292. A bus master has the ability to read and write memory or I/O on its own,
  293. acting like another CPU in the system.  The IBM SCSI adapters are such
  294. adapters.  All it takes to set one off working on one or more SCSI commands
  295. is to point it at the physical address of its chain of control blocks (SCBs)
  296. and tell it to go.  It will examine the memory, initiate the SCSI operations,
  297. store the data and status in the requested memory and interrupt the CPU when
  298. done.  OS2SCSI's job is to pass these requests on to the adapter device driver
  299. who sends it out the card to the device.
  300.  
  301. 3.2.2. SCBs
  302.  
  303. For a full description of the SCBs, see the IBM Technical Reference for your
  304. particular IBM SCSI adapter.  Or, if your adapter supports the IBM SCB
  305. interface, it will be described in the programming documentation for that
  306. adapter.
  307.  
  308. Generally, an SCB contains the SCSI command to be executed, pointers to the
  309. data buffer into or out of which the data travels, a pointer to the sense
  310. data (if any) that is read from the device in case of an error, and some
  311. control information.  The control information includes things like how big is
  312. the data buffer, where the Termination Status Block is and a whole bunch of
  313. bits describing things like:
  314.    - Is the command a READ or a WRITE : which way is the buffer data going?
  315.    - Should the TSB be set always or only on error
  316.    - Should the adapter retry on error?
  317.    - Is the system buffer address a pointer to a scatter/gather list?
  318.    - Is there another SCB chained after this one?
  319.    - Should we stop chaining on error?
  320.  
  321. Finally, the IBM SCSI adapters are smart enough to know how to do some standard
  322. SCSI commands without the explicit SCSI command being given to it.  Some of
  323. these commands are Sense, Read, Write, Inquiry, Read Capacity, Mode Select,
  324. and Mode Sense.  These commands are built into the first word of the SCB.
  325.  
  326. 3.2.3. CDBs
  327.  
  328. Command Descriptor Blocks (CDBs) are the actual blocks of bytes that make
  329. up a command.  For instance, the sense command (which is the IBM SCSI cards
  330. have a special SCB to perform) can also be done with the 'Send Other SCSI
  331. Command SCB' - see the next section for details on this SCB.  The sense CDB
  332. is 6 bytes long composed of the following:
  333.  
  334.    Byte 0 - 0x03
  335.    Byte 1 - 0x00
  336.    Byte 2 - 0x00
  337.    Byte 3 - 0x00
  338.    Byte 4 - Number of bytes to transfer - max = 98
  339.    Byte 5 - 0x00
  340.  
  341. After this command is complete, if it succeeded, the data buffer will hold
  342. the sense data from the device.
  343.  
  344. Another example is the Inquiry command.  This command is also 6 bytes long
  345. composed of the following:
  346.  
  347.    Byte 0 - 0x12
  348.    Byte 1 - 0x00
  349.    Byte 2 - 0x00
  350.    Byte 3 - 0x00
  351.    Byte 4 - Number of bytes to transfer - max = 255
  352.    Byte 5 - 0x00
  353.  
  354. After this command is complete, if it succeeded, the data buffer will hold
  355. the Inquiry data from the device.  This data holds information as the device
  356. type (CDROM, hard disk, printer, tape, etc), if the media is removable, what
  357. the manufacturer's name and model is, and what standards the device conforms
  358. to.
  359.  
  360. You can find the details of the CDBs for your device from the manufacturer
  361. or in the technical reference for the particular device.
  362.  
  363. 3.2.4. What if you don't have an IBM Microchannel SCSI card.
  364.  
  365. If you don't have a Microchannel machine with an IBM SCSI card, don't worry,
  366. OS/2 is set up to handle you, if you have an Adapter Device Driver (ADD) for
  367. your card.  OS2SCSI will query the ADD and convert the commands GENSCSI sends
  368. it to the proper form for the card.  To make sure, you could only use the
  369. Send Other command for all SCSI commands to be sent to the device.  The SCB
  370. to use is:
  371.  
  372. Word  0 - 0x245F
  373. Word  1 - 0x6600 (write) or 0xD600 (read)
  374. Word  2 - High byte = 0, Low byte = SCSI command length
  375. Word  3 - 0x0000 (reserved)
  376. Word  4 - System Buffer Address Low Word
  377. Word  5 - System Buffer Address High Word
  378. Word  6 - System Buffer Byte Count Low Word
  379. Word  7 - System Buffer Byte Count High Word
  380. Word  8 - Termination Status Block Address Low Word
  381. Word  9 - Termination Status Block Address High Word
  382. Word 10 - 0x0000 Optional SCB Chain Address Low Word
  383. Word 11 - 0x0000 Optional SCB Chain Address High Word
  384. Word 12 - SCSI Command bytes 0,1     --+
  385. Word 13 - SCSI Command bytes 2,3       |
  386. Word 14 - SCSI Command bytes 4,5       |__ This is where the CDB goes
  387. Word 15 - SCSI Command bytes 6,7       |   (see discussion on CDBs above)
  388. Word 16 - SCSI Command bytes 8,9       |
  389. Word 17 - SCSI Command bytes 10,11   --+
  390.  
  391. The system buffer address is the 16:16 address of the data buffer.  The
  392. System Buffer byte count is just that : how big is the data buffer.  The
  393. TSB address is the 16:16 address of the TSB.  Set word 1 to 0x6600 if the
  394. transfer of data is from the device to the CPU (read).  If it is from the
  395. CPU to the SCSI device, set word 1 to 0xD600 (write).
  396.  
  397. This block does not chain SCBs.  To do that, you would turn on the low
  398. order bit of word 1 and fill the SCB chain address with the 16:16 address.
  399. Beware that GENSCSI.SYS does not support this.  It will not convert the
  400. SCB chain address to a GDT based pointer and it will not chase down the
  401. SCB chain to convert virtual addresses to physical.  If you want to chain
  402. SCSI commands, you need to write your own device driver to interface to
  403. OS2SCSI.
  404.  
  405. SCSITEST is a good vehicle to determine what features your adapter support.
  406.  
  407. 4.     SCSI.SYS, OS2SCSI.DMD, etc.
  408.  
  409. The idea of the layered device driver architecture in OS/2 V2 is that higher
  410. level drivers, especially those dealing with specific devices on standard
  411. busses (SCSI, IDE, ESDI, etc) do not have to concern themselves with the
  412. details of driving the adapter.  It also provides for the management of the
  413. adapter at a single point.  These drivers are called Adapter Device Drivers
  414. (.ADDs).  Their job is to provide a standard interface to each device
  415. attached to each of their supported adapters.
  416.  
  417. In the case of SCSI, however, there is another layer of abstraction available.
  418. The problem is that some SCSI cards are true bus masters, with the intelligence
  419. to do scatter/gather (able to work with physically scattered pages of memory),
  420. command chaining (able to execute more than one SCSI command in sequence), and
  421. error handling (automatic request of Sense data from the device), while other
  422. SCSI adapters are really simple.  All these simple adapters can do is execute
  423. the command, and only with massive software assist for the phase
  424. interpretation.  To smooth out these massive differences between ADDs, the
  425. OS2SCSI device manager is provided by OS/2.  This driver determines the best
  426. way to call the ADD.  It may split a chain of commands into individual commands
  427. and hand them to the ADD one at a time.  It may do the sense command if the
  428. adapter doesn't.  In short, it provides much of the intelligence of a smart
  429. adapter to a dumb adapter.  It makes all adapters look smart.
  430.  
  431. Source code for the OS2SCSI.DMD driver can be found in the DDK.
  432.  
  433. 4.1.   Interface Big Picture
  434.  
  435. The interface to OS2SCSI.DMD is through IOCtl request packets handed to it via
  436. an Inter-device Driver Call.  This section will discuss this interface in more
  437. detail.
  438.  
  439. 4.1.1. What major functions it performs
  440.  
  441. The major functions provided by OS2SCSI.DMD are:
  442.    o Device Allocate/Deallocate
  443.    o Adapter Cache Control
  444.    o Set/Read some device parameters
  445.    o Reset/Initialization Operations
  446.    o SCSI Command Processing/Aborting
  447.  
  448. 4.1.2. How you talk to it in general terms
  449.  
  450. The way you communicate with OS2SCSI.DMD is through an IDC interface.  Your
  451. device driver builds an IOCtl request packet and passes it to OS2SCSI by
  452. calling the IDC entry point.  After the command is complete, OS2SCSI sets the
  453. status field of the request packet and returns control to your device driver.
  454. It is up to you to examine the status field and possibly the Sense and TSB
  455. buffers to determine how the command went, what errors occurred and what
  456. recovery, if any, needs to be done.
  457.  
  458. 4.1.3. Basic listing of commands and what they do
  459.  
  460. OS2SCSI provides 12 commands.  These are, with a short explanation of their
  461. function:
  462.   1. Read Device Parameters       - Returns information about a particular
  463.                                     adapter and LUN (Logical Unit).
  464.  
  465.   2. Reset/Initialization         - This function sends a reset message to a
  466.                                     particular device.
  467.  
  468.   3. Enable Adapter Cache         - This function turns on the adapter cache
  469.                                     for all subsequent commands to a given
  470.                                     device.
  471.  
  472.   4. Disable Adapter Cache        - This function turns off the adapter cache
  473.                                     for commands to this device.
  474.  
  475.   5. Return Adapter Cache Status  - This function tells if commands to this
  476.                                     device are cached.
  477.  
  478.   6. Set Device Timeout           - Sets the timeout value for this device.
  479.  
  480.   7. Read Device Timeout          - Returns the current timeout value for this
  481.                                     device.
  482.  
  483.   8. Transfer SCB                 - Causes a chain of 1 or more SCBs to be sent
  484.                                     to the adapter.
  485.  
  486.   9. Deallocate Device            - Reserves a device for this caller's use.
  487.  
  488.  10. Allocate Device              - Returns an allocated device to the pool
  489.                                     of free devices.
  490.  
  491.  11. Return Peripheral Type Count - Returns how many devices of a particular
  492.                                     type have been detected.
  493.  
  494.  12. Abort                        - Stops a command in progress.
  495.  
  496. The details of each command are given in the OEMBASE.TXT file supplied in this
  497. package.
  498.  
  499. 4.3.   Getting in contact
  500.  
  501. During initialization, your device driver needs to do two things:
  502.    1. It needs to get the Interdevice Driver Call address of OS2SCSI.
  503.    2. It needs to get a file handle for future calls to OS2SCSI.
  504.  
  505. 4.3.1. Calling OS2SCSI
  506.  
  507. To call OS2SCSI, your device driver will use the IDC entry point.  It gets
  508. the address of this entry point via the AttachDD Device Helper function in
  509. OS/2.  What comes back is a CS:IP that will be used as the target of an
  510. indirect call and the value to be set in DS before making that call.  This
  511. value is the data segment of OS2SCSI.  Also, before calling, your DD will
  512. set ES:BX to point at the request packet you are passing to OS2SCSI.
  513.  
  514. If this looks familiar, it is.  Essentially, you are doing the function of
  515. OS/2 when it calls OS2SCSI with an IOCtl request.  The IDC entry point in
  516. OS2SCSI winds up calling the Strategy entry point.  The only difference is
  517. that some functions are allowed from OS/2 that are not allowed from another
  518. device driver via IDC, and some operations are handled a little differently.
  519.  
  520. To get the IDC address of OS2SCSI, your device driver should do a AttachDD
  521. command at INIT time with the name of "SCSI-02$".
  522.  
  523. 4.3.2. You need a handle
  524.  
  525. When your device driver passes commands to OS2SCSI, it needs a number to fill
  526. in the System File Number field of the IOCtl request packet.  It gets this
  527. handle by doing a DosOpen on the name "SCSI=02$" at INIT time.  Some of the
  528. flags that need to be set are:
  529.    o Open Mode = 0x0012 - Read/Write access
  530.    o Open Flag = 0x0001 - Open the device if it exists, fail if it doesn't
  531.    o Attribute = 0x0000 - Normal File
  532.  
  533. This operation needs to be done at INIT time as the DosOpen function is not
  534. available at any other time.
  535.  
  536. 4.4.   Sending commands
  537.  
  538. Getting your device driver to use OS2SCSI is fairly easy.  At INIT time, you
  539. call the AttachDD device helper to get the IDC entry point.  Then, you do a
  540. DosOpen to get a handle.  You are now ready to send commands and work with
  541. your devices.
  542.  
  543. 4.4.1  Are there any of my devices?
  544.  
  545. The next step is to find out if there are any of your devices there.  This is
  546. done via the Return Peripheral Type Count command.  If you put, for example, a
  547. 5 in the Peripheral type field of the buffer pointed to by the Parameter
  548. pointer field of the request packet and set the removable flag in the device
  549. flags field, you will get a count of the CD-ROM drives with removable media
  550. capability that were detected at boot time.  Using this command, you can
  551. determine if any of your supported devices exist.
  552.  
  553. 4.4.2  Reserving the device
  554.  
  555. After determining that there are some of your devices out there, you must then
  556. get a device handle for each device that you want to use.  This handle will be
  557. used to indicate which device you want to issue a command to later.  You do
  558. this with the Allocate Device command.
  559.  
  560. 4.4.3  Sending commands to the device
  561.  
  562. The Transfer SCB command is the heart of OS2SCSI.  It is the IOCtl that you
  563. use to send SCSI commands to devices.  Buried in the Subsystem Control Block
  564. (SCB) is the actual 6 to 12 byte SCSI command that is sent to the device,
  565. along with a pointer to the buffer where data is to be transferred to or from.
  566.  
  567. Commands such as Read, Write, Seek, Rewind (for a tape drive), Play Audio (for
  568. a CDROM reader), etc. are sent to the device with this command.  Included
  569. in the command is a sense buffer that will may be filled in if an error
  570. occurs.  The return code from this IOCtl will indicate if there is valid sense
  571. data in the buffer.
  572.  
  573. 4.4.4  Finishing with the device
  574.  
  575. After you have finished with a device, you return it to the pool of available
  576. devices with the Deallocate Device command.  Some drivers, such as CDROM device
  577. drivers will never free the device, while others, like printer or tape drivers
  578. probably will.
  579.  
  580. 4.4.5  Miscellaneous stuff
  581.  
  582. Finally, there are commands for determining if there is a cache in the adapter
  583. and for determining and chaining the caching controls.  There are commands to
  584. send reset commands and abort commands to a particular device as well as to
  585. read and set the timeout values for any device.
  586.  
  587. 4.5.   Errors
  588.  
  589. Whenever an error happens, it will be reflected in the status field of the
  590. request packet.  An examination of the bits will tell if there is sense data
  591. available (for Transfer SCB commands).
  592.  
  593. 4.6.   Things to watch out for
  594.  
  595. The biggest thing that you have to watch out for is that most of the virtual
  596. addresses passed to OS2SCSI must be GDT based addresses, especially those used
  597. in the Transfer SCB command.  The reason for this is that OS2SCSI must be able
  598. to access the buffers pointed to by these addresses at Interrupt time.  The
  599. only addresses you can depend on at this time are GDT based addresses.
  600.  
  601. The second thing to watch out for is that you lock any buffers whose address
  602. is passed by physical address.
  603.  
  604. 5.       GENSCSI.SYS
  605.  
  606. This section discusses the device driver GENSCSI.SYS.  It talks about what
  607. function the device driver performs, how to interface to it, and how it works.
  608. It includes a discussion of the source code for GENSCSI.SYS which is a part
  609. of this package.
  610.  
  611. 5.1.     Interface Big Picture
  612.  
  613. The basic function of GENSCSI.SYS is to provide applications with an interface
  614. to OS2SCSI.DMD.  It only answers 4 commands: Open, Close, IOCtl, and Init.
  615. All others cause an Invalid Command error.
  616.  
  617. 5.1.1.   What it does
  618.  
  619. GENSCSI accepts IOCtl commands in the same format that OS2SCSI does, except
  620. GENSCSI expects all addresses to be ring 3 addresses while OS2SCSI expects
  621. them to be ring 0 addresses, physical addresses or scatter/gather lists.
  622. GENSCSI will convert the ring 3 addresses to the proper form and pass the
  623. command on to OS2SCSI.  When OS2SCSI is done with the command, it returns
  624. the results back to GENSCSI who passes it back to the application.
  625.  
  626. 5.1.2.   How you talk to it in general terms
  627.  
  628. The basic steps are:
  629.  
  630. 1. DosOpen on $GENSCSI.  This will get you a handle to talk to GENSCSI.
  631.  
  632. 2. DosDevIOtls following the OEMBASE.TXT file included in this package to
  633.    query, allocate, command and deallocate SCSI devices.  This is where your
  634.    work is done.
  635.  
  636. 3. DosClose with the handle received in step 1.
  637.  
  638. 5.2.     A sample sequence
  639.  
  640. A simple sequence: locate a CDROM drive, see if it has a disk loaded and read
  641. the first DATA sector to determine if the CD is ISO9660 or something else would
  642. look like this:
  643.  
  644.    Get access to the device driver via DosOpen
  645.  
  646.    See if there are any CDROM drives via Return Peripheral Type Count
  647.  
  648.    If there aren't any CDROM drives, quit here
  649.  
  650.    Get a device handle for the next available CDROM drive via Allocate Device
  651.  
  652.    Ask the CDROM for its capacity by doing a Read Device Capacity SCSI command
  653.        that is sent using the Transfer SCB IOCtl.
  654.    If the Read Device Capacity command failed, you would have to determine
  655.        why.  By examining the sense data returned, you could learn if it was
  656.        because media had been changed or because the device has been reset
  657.        since the last operation, or for some other reason.  If it was one of
  658.        the first two, retrying the command is in order.  If it is some other
  659.        reason, you would quit here.
  660.  
  661.    If the Read Device Capacity succeeded, you would next do a Read Sector
  662.        command, once again via Transfer SCB, with the read starting at sector
  663.        16 and going for 1 2048 byte sector.
  664.    If the read fails, it can be for several reasons, all of which lead to the
  665.        conclusion that the disk is not ISO9660.
  666.  
  667.    If the read was successful, examination of the data returned will allow
  668.       you to tell if the disk is ISO9660 or not.  See the ISO9660 spec for
  669.       more detail.
  670.  
  671.    After the determination, release the drive via the Deallocate IOCtl.
  672.  
  673.    We are all finished, do a DosClose on the file handle returned from DosOpen.
  674.  
  675.  
  676. 5.3.     Construction - a look at the source
  677. 5.3.1.   STRATEGY.C
  678.  
  679. There is one function in STRATEGY.C: strategy_c().  It does 2 functions: call
  680. the proper command handler and set the status in the request packet.  If the
  681. command is not one of the supported 4, it sets the request packet status to
  682. Invalid Command.
  683.  
  684. Note that the device helper function DevDone is not called if the command is
  685. INIT.  This is because DevDone is only valid at kernel and interrupt times,
  686. not init time.
  687.  
  688. 5.3.2.   INIT.C
  689.  
  690. INIT.C performs the initialize command (surprise!).  The steps are fairly
  691. straightforward:
  692.  
  693. 1. Save the devhelper address away
  694.  
  695. 2. Set the values in the request packet for a failure.  This way, we can
  696.    just return if we really do get a failure at any time along the line.  If
  697.    we end up succeeding, we'll set the proper values.
  698.  
  699. 3. Construct the name of the message file from the line in CONFIG.SYS.
  700.  
  701. 4. Display the commercial describing what we are.
  702.  
  703. 5. Initialize the open array.
  704.  
  705. 6. Do the SCSI initialization - make contact with OS2SCSI.DMD get a file
  706.    handle.
  707.  
  708. 7. Set the values in the request packet for a successful completion.
  709.  
  710. 8. Return SUCCESS to the caller.
  711.  
  712. 5.3.3.   IOCTL.C
  713.  
  714. Once again, this function is very simple.  We filter off 1 IOCtl command:
  715. Category 0x81, function 0x40.  This command is our internal breakpoint command.
  716. It allows us to execute an INT 3 machine instruction on command.  The INT 3
  717. instruction is a breakpoint to most debuggers, including the kernel debugger.
  718. This way, we can, on command, cause the debugger to be invoked in the
  719. context of our device driver so we can set other breakpoints.
  720.  
  721. All other IOCtl commands are passed on to the SCSI device driver caller.
  722.  
  723. 5.3.4.   SCSI.C
  724.  
  725. This is the heart of the GENSCSI device driver.  It converts the addresses in
  726. the IOCtl packets to the proper form for OS2SCSI, passes the command along
  727. and stores the results in the original request packet.
  728.  
  729. There are 4 functions in this file:
  730.    1. scsi_init()    - Makes the connection with OS2SCSI.
  731.    2. call_scsi()    - Handles all commands to OS2SCSI except the Transfer SCB
  732.                        command.
  733.    3. transfer_scb() - Handles the Transfer SCB IOCtl command.
  734.    4. free_dhand()   - Issues a Deallocate Device for a given device handle.
  735.  
  736. 5.3.4.1  scsi_init()
  737.  
  738. There are three steps done in scsi_init().
  739.   1. Allocate the GDT selectors that the device driver will need during normal
  740.      operation.  There are 4 needed.
  741.  
  742.   2. Acquire the IDC values for OS2SCSI.  This is done through the AttachDD
  743.      device helper function.
  744.  
  745.   3. Acquire a file handle to OS2SCSI.  This is done through the DosOpen system
  746.      call.  Note that this must be done at INIT time by a device driver.  It
  747.      cannot be done at kernel time and it cannot be done by an ADD or DMD as
  748.      this service has not been loaded yet.
  749.  
  750. If any of these steps fail, we return General Failure to the caller.
  751. Otherwise, we return OK.
  752.  
  753. 5.3.4.2  call_scsi()
  754.  
  755. The steps (along with their line numbers in scsi.c) follow:
  756.  
  757. 1.  Filter off the obvious unsupported IOCtl commands.  If the category isn't
  758.     0x80, return an Invalid Command error.  (line 233)
  759.  
  760. 2.  Handle the Transfer SCB command separately.  It has several more addresses
  761.     to convert from LDT based to GDT based, as well as some physical addresses
  762.     and a scatter/gather list indicator to set.  (line 241)
  763.  
  764. 3.  If this is an Allocate Device request, we need to make sure that there is
  765.     enough room in the open array to store the device handle.  We need to keep
  766.     the handle around so that if the application ends without deallocating the
  767.     handle, we can do it.  (line 246)
  768.  
  769. 4.  Create a new request packet to be passed to OS2SCSI.DMD and copy all the
  770.     values from the original request packet except the file handle and the parm
  771.     and data buffer pointers into this new packet.  The new request packet is
  772.     created with the AllocReqPacket Device Helper.  (line 258)
  773.  
  774. 5.  Convert the parm buffer pointer from an LDT based pointer to a GDT based
  775.     pointer.  This is done because OS2SCSI may have to access the buffer at
  776.     interrupt time - when the current LDT is not valid.  The only virtual
  777.     addresses that are valid are GDT based ones.  This conversion has 3 steps:
  778.     Lock the buffer, determine the physical address of the buffer and create
  779.     a GDT pointer to the physical address.  (line 279)
  780.  
  781. 6.  Do the same operation with the data buffer pointer, for the same reason.
  782.     (line 285)
  783.  
  784. 7.  Set the file handle to OS2SCSI we got during scsi_init() into the system
  785.     file handle field of the new request packet.  (line 291)
  786.  
  787. 8.  Call OS2SCSI through the IDC entry point, pointing ES:BX at the newly
  788.     created request packet before calling.  (line 294)
  789.  
  790. 9.  On return from OS2SCSI, the new request packet's status field has the
  791.     completion status of the operation.  It needs to be copied to the original
  792.     request packet, along with the parm buffer and data buffer lengths.
  793.     (line 297)
  794.  
  795. 10. The allocated request packet is freed.  (line 302)
  796.  
  797. 11. If the request was an Allocate or Deallocate Device and it was successful,
  798.     the open array needs to be updated with the device handle either added to
  799.     or removed from the array.  (line 305)
  800.  
  801. 12. Finally, we unlock the parm and data buffers and return the completion
  802.     status to the caller.  (line 325)
  803.  
  804. 5.3.4.3  transfer_scb()
  805.  
  806. 1.  This function does the same thing as call_scsi(), except, since it is
  807.     working on a transfer SCB request packet, it has a few more addresses to
  808.     deal with.  They are:
  809.  
  810.     1. The SCB header pointer in the transfer SCB control block.  This pointer
  811.        is converted from an LDT based virtual address to a GDT based address,
  812.        just like the parm and data pointers.  in addition, we save the original
  813.        LDT based address for replacement after the operation is done.
  814.        (line 397)
  815.  
  816.     2. We store the physical address of the SCB in the Transfer SCB control
  817.        block (line 409)
  818.  
  819.     3. The TSB pointer in the SCB itself is handled just like the SCB Header
  820.        pointer in (1). line (413).
  821.  
  822.     4. Next, we convert the System Buffer address in the SCB from a virtual
  823.        address to a physical one, saving the original virtual address away.
  824.        (line 419)
  825.  
  826.     5. Finally, we deal with the idea that the system buffer may need to be
  827.        represented as a page list (or scatter/gather list) rather than a
  828.        single physical address.  If the buffer is big enough, it may be
  829.        scattered over several non-contiguous pages of physical memory.  If
  830.        that is the case, we need to tell OS2SCSI (who, in turn, will tell
  831.        the SCSI adapter ADD) that the buffer is a page list.  This
  832.        determination is done by converting the virtual address to a page list
  833.        and seeing if there is more than 1 block of pages.  If there is, we
  834.        have a scatter/gather list; if not, we have a single block of contiguous
  835.        pages and can use the physical address.  (line 424)
  836.  
  837. 2. For the next 3 steps, the operation is the same as call_scsi() - call
  838.    OS2SCSI, transfer the results to the original request packet and free the
  839.    allocated request packet.  (line 465)
  840.  
  841. 3. Next, we replace the virtual addresses that we changed to physical or GDT
  842.    based pointers.  (line 476)
  843.  
  844. 4. As in call_scsi(), we now unlock all the locked buffers and return the
  845.    request packet status to the caller.
  846.  
  847. 5.3.5.   OPENCLOS
  848.  
  849. The functions in OPENCLOS.C manage the open array.  The open array is an array
  850. of records describing all the applications that have issued a DosOpen call to
  851. the device driver and the devices that they have allocated.  There is one
  852. readon for keeping this information: if an application fails or for any reason
  853. ends without deallocating any devices it has allocated, those devices will not
  854. be available for any other application to use until the system has been
  855. restarted.  To prevent this, GENSCSI will issue a Deallocate command to OS2SCSI
  856. for any devices owned by an ending application.
  857.  
  858. The open array consists of an array of 50 records, one for each possible open
  859. call.  Each handle can have a maximum of 8 devices allocated.  These numbers
  860. are arbitrary and can be changed with no ill effect (until the total size of
  861. the array begins to approach 64K bytes).
  862.  
  863. There are functions in OPENCLOS.C to initialize the array, determine how many
  864. free device handle slots are available to a given file handle, to set a device
  865. handle into the array and to remove a device handle from the array.
  866.  
  867. Every time a new file handle is received, it is recorded in the array.  Each
  868. device allocate and deallocate associated with that file handle that is
  869. successful is also recorded in the array.  If a close on a file handle is
  870. received and it still has outstanding device allocates, the devices will
  871. be freed by GENSCSI before the close is completed.
  872.  
  873. 5.3.6.   Others
  874.  
  875. The rest of the source consists of utility functions to help the device driver
  876. do its work.  There are routines to call various devhelper functions, functions
  877. to handle a message file and display messages at INIT time.  There area
  878. functions to parse the parameters in CONFIG.SYS and assembler functions to
  879. arrange the segments to build a proper OS/2 device driver.
  880.  
  881. 5.4.     Putting the pieces together - Following a request through the driver
  882.  
  883. This section will show how a request is processed in GENSCSI.SYS.
  884.  
  885. 5.4.1.   Strategy
  886.  
  887. A request is received by the strategy function.  What happens, from the
  888. device driver's point of view is that it is entered at the address pointed
  889. to by the strategy pointer in the device header with ES:BX pointing to the
  890. request packet.  The Strategy code immediately pushes the pointer onto the
  891. stack and calls the C code which will do all the work.
  892.  
  893. The C function strategy_c() found in the file STRATEGY.C is this function.
  894. It examines the command in the request packet and calls the proper command
  895. handler - either INIT, OPEN, CLOSE, or IOCTL.  If it isn't one of these 4,
  896. we set Invalid Command in the request packet status and return the request
  897. to OS/2.
  898.  
  899. 5.4.2.   IOCTL
  900.  
  901. Assuming that the request was an IOCTL, the IOCtl command processor, ioctl()
  902. in IOCTL.C, looks to see if it is our internal test function (category 0x81,
  903. function 0x40).  If it isn't, it passes the command to the SCSI command
  904. handler who will convert the addresses and pass it on to OS2SCSI.
  905.  
  906. 5.4.3.   SCSI
  907.  
  908. The SCSI command handler (call_scsi() in SCSI.C) handles all but the Transfer
  909. SCB command.  The first step is to filter off the obviously incorrect
  910. commands: those whose category is not 0x80.  These are returned with a status
  911. of invalid command.  We then filter off the Transfer SCB commands and pass
  912. them to transfer_scb(), also located in SCSI.C.  This is because the Transfer
  913. SCB processing is different enough to warrant its own function.
  914.  
  915. The next step is to check if we are going to allow the command.  If it is an
  916. Allocate Device command, we need to have enough space to hold the device
  917. handle if the allocate is successful.  If we do have the space, the command
  918. proceeds.  It not, it is returned now with an appropriate error code.
  919.  
  920. Now that we are going to handle the command, the first thing to do is to
  921. construct a new request packet.  We allocate one and copy all the fields
  922. from the original packet except the file handle and the parm and data buffer
  923. pointers.  Next we need to convert the Ring 3 parm and datat buffer
  924. virtual addresses to Ring 0 virtual addresses.  Each buffer is locked down,
  925. its physical address extracted and a GDT based pointer set to point at the
  926. same physical address.  These pointers are stored in the new request packet
  927. along with the file handle received from the DosOpen we did at INIT time.
  928.  
  929. The handling of the Transfer SCB command is similar except there are several
  930. more addresses to be converted from Ring 3 to Ring 0 along with a couple of
  931. Ring 3 virtual address to physical address conversions.
  932.  
  933. Next, we hand the newly built request packet to OS2SCSI.DMD through the IDC
  934. call.
  935.  
  936. ON return from OS2SCSI, we transfer the request packet status from the newly
  937. created one to the original received from OS/2, we unlock the buffers and
  938. free the allocated request packet.
  939.  
  940. 5.4.4.   Back to OS/2
  941.  
  942. On return from call_scsi(), the device driver tells OS/2 that the request is
  943. finished and returns to OS/2.  The request is finished.
  944.  
  945. 5.5.     What it doesn't do - Watch out!
  946.  
  947. There are several things to watch out for with this device driver.  They are
  948. generally related to the fact that this driver was written for my own use on
  949. IBM Microchannel machines, so I know what to avoid.
  950.  
  951. The first thing to watch out for is that GENSCSI doesn't handle chained
  952. requests.  OS2SCSI and the IBM SCSI cards will handle a list of SCSI commands
  953. automatically.  The problem is that GENSCSI will only convert the addresses
  954. in one SCB.  This means that your application cannot pass chained commands to
  955. GENSCSI for execution.  You have to do them one at a time.
  956.  
  957. The second thing to watch out for is that GENSCSI doesn't verify that the
  958. pointers you gave it are valid.  If the pointer you give is invalid, you run
  959. the risk of stepping on system memory or getting a protection exception in
  960. the kernel - either of which will crash the system in such a way as to force
  961. a power off to recover.  Since I wrote this driver to be used for poking around
  962. the system, I didn't worry too much about crashing it.  If you are going to
  963. use it in more of a production environment, I would recommend putting the
  964. verify operations in.
  965.  
  966. The last thing to note is that it expects all virtual addresses to be 16:16
  967. rather than 0:32.  It wouldn't be too hard to create another set of IOCTLs
  968. that handle 0:32 addresses as well.  But, since it does want 16:16 addresses,
  969. all pointers in the application space must be declared as _Sys16 if you use
  970. C-Set/2 as your compiler.
  971.  
  972. 6.       SCSITEST
  973. 6.1.     The Big Picture
  974.  
  975. SCSITEST is a program that lets the user issue commands through GENSCSI.SYS
  976. to OS2SCSI.DMD or to a particular SCSI device.
  977.  
  978. 6.1.1.   What does it do
  979.  
  980. SCSITEST lets the user issue a set of standard commands to OS2SCSI or to
  981. build almost any SCSI command and send it to a pre-defined SCSI device.  It
  982. operates by accepting commands from the user and then asking for more data.
  983. Afer it has gathered all the data it needs, it eitehr does the operation or
  984. it builds the command packets and sends them to OS2SCSI through GENSCSI.
  985.  
  986. Some of the operations SCSITEST will do are:
  987.  
  988.    Allocate/Deallocate a device
  989.    Read or Write a block up to 64K from/to a device
  990.    Query a device for its capacity or device type/manufacturer
  991.    Reset a device
  992.    Display the latest sense data in hex or interpreted form
  993.    Display the latest Termination Status Block in hex or interpreted form
  994.    Write the data buffer to file in binary or printable hex form
  995.    Issue any SCSI command at a device
  996.    Reset a SCSI device
  997.  
  998. 6.1.2.   How do you use it
  999.  
  1000. If the program successfully gets access to the GENSCSI device driver, it
  1001. displays all the possible commands.  Type in one of the commands and the
  1002. program will prompt you for the rest fo the information needed to perform the
  1003. requested operation.
  1004.  
  1005. Generally, the first step is to either request a count of the devices of
  1006. interest (count command) or, if you know that one is available, to allocate
  1007. the device (alloc).
  1008.  
  1009. Next, you issue the commands of interest (read, write, inq, capac, etc) until
  1010. you are finished with this particular device.  If you wish to use other
  1011. devices, you first free the currently allocated device (free) and allocate
  1012. the next one.
  1013.  
  1014. When you exit the program (quit), any allocated devices are automatically
  1015. freed - if not by the program then by GENSCSI iteslf.
  1016.  
  1017. 6.2.     A quick look at the source
  1018.  
  1019. The source for SCSITEST is fairly straightforward.  The main routine is a
  1020. simple loop, waiting for input from STDIN.  When it gets it, it determines
  1021. what command is requested and, if it is a valid command, calls the proper
  1022. function to execute the command.  If the command is not valid, it displays
  1023. the list of valid commands.  On return from the function that executes the
  1024. command, it goes back to waiting for another command.
  1025.  
  1026. The commands are broken into 2 basic classes:  those that interface through
  1027. GENSCSI to OS2SCSI and those which display or manipulate the data received
  1028. or to be sent to OS2SCSI.
  1029.  
  1030. The commands to GENSCSI/OS2SCSI are all very simple - ask the user for
  1031. any information that we don't already have or that isn't canned in, build the
  1032. IOCtl parm and data buffers and issue the IOCtl.  When the IOCtl returns,
  1033. tell how it went and display the information requested; if there was any.
  1034.  
  1035. The data manipulation commands generally fall into 2 groups - those that
  1036. display the data and those which write it to disk.  The displayers can
  1037. display it in raw form (ususally just the hex bytes) or interpreted form.
  1038. The data writers will write the data either in a printable hex format or
  1039. straight binary which is just a raw dump of the buffer to the file.
  1040.  
  1041. 6.3.     Limitations
  1042.  
  1043. The biggest limitation of SCSITEST is that it isn't very defensively
  1044. programmed.  If you give it a read command that will result in a buffer bigger
  1045. than 64K, it will fail.  If you say to display the current data buffer via
  1046. the p_data command and there is no buffer, it will crash with a protection
  1047. exception.
  1048.  
  1049. The next limitation is that its user interface is fairly crude and limited.
  1050. It doesn't allow you to specify the name of the file when you write the buffer
  1051. to disk.  Its biggest user interface limitation is that it doesn't easily let
  1052. you build a data buffer to send with a command other than WRITE.
  1053.  
  1054. Not to make excuses, but the original intent of this program was to explore
  1055. how to drive SCSI devices and OS2SCSI.DMD, not to produce a bulletproof, easy
  1056. to use program.  In addition, its simplicity makes it easier to understand,
  1057. making it a useful demonstration - there isn't much user interface getting
  1058. in the way of seeing the really functional parts of the program.
  1059.  
  1060. 7.   Tools
  1061. 7.1. GENSCSI.SYS
  1062.  
  1063. GENSCSI.SYS will compile with MSC V6.00 and MS MASM V5.1 through 6.0.  You can
  1064. also use the assembler that came with the original OS/2 SDK or the MASM386 that
  1065. is included in the DDK.  Other assemblers may work as well, but I have no
  1066. experience with them.
  1067.  
  1068. 7.2. SCSITEST
  1069.  
  1070. SCSITEST is built with C-Set/2.  I am currently using the 3th beta (2/2/93)
  1071. of the C-Set/C++ compiler.
  1072.  
  1073. The options on the compile in the MAKE file are set to use the Multithreaded
  1074. libraries.  This is because the machine I am building this on is fairly
  1075. small so I only installed those libraries.  If you want to change them, go
  1076. ahead.
  1077.  
  1078.