<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-html40"> <head> <meta http-equiv=Content-Type content="text/html; charset=unicode"> <meta name=ProgId content=Word.Document> <meta name=Generator content="Microsoft Word 9"> <meta name=Originator content="Microsoft Word 9"> <link rel=File-List href="./spti_files/filelist.xml"> <!--[if gte mso 9]><xml> <w:WordDocument> <w:ActiveWritingStyle Lang="EN-US" VendorID="64" DLLVersion="131077" NLCheck="1">1</w:ActiveWritingStyle> </w:WordDocument> </xml><![endif]--> <style> <!-- /* Font Definitions */ @font-face {font-family:"MS Sans Serif"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:3 0 0 0 1 0;} @font-face {font-family:Wingdings; panose-1:5 0 0 0 0 0 0 0 0 0; mso-font-charset:2; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:0 268435456 0 0 -2147483648 0;} @font-face {font-family:"MS Mincho"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-alt:"MS 明朝"; mso-font-charset:128; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:fixed; mso-font-signature:1 134676480 16 0 131072 0;} @font-face {font-family:Verdana; panose-1:2 11 6 4 3 5 4 4 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:536871559 0 0 0 415 0;} @font-face {font-family:"\@MS Mincho"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:128; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:fixed; mso-font-signature:1 134676480 16 0 131072 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0in; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman"; color:black;} h2 {margin-right:0in; mso-margin-top-alt:auto; mso-margin-bottom-alt:auto; margin-left:0in; mso-pagination:widow-orphan; mso-outline-level:2; font-size:18.0pt; font-family:"Times New Roman"; color:black; font-weight:bold;} h3 {margin-right:0in; mso-margin-top-alt:auto; mso-margin-bottom-alt:auto; margin-left:0in; mso-pagination:widow-orphan; mso-outline-level:3; font-size:13.5pt; font-family:"Times New Roman"; color:black; font-weight:bold;} h4 {margin-right:0in; mso-margin-top-alt:auto; mso-margin-bottom-alt:auto; margin-left:0in; mso-pagination:widow-orphan; mso-outline-level:4; font-size:12.0pt; font-family:"Times New Roman"; color:black; font-weight:bold;} a:link, span.MsoHyperlink {color:blue; text-decoration:underline; text-underline:single;} a:visited, span.MsoHyperlinkFollowed {color:purple; text-decoration:underline; text-underline:single;} p.MsoPlainText, li.MsoPlainText, div.MsoPlainText {margin:0in; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Courier New"; mso-fareast-font-family:"Times New Roman"; mso-bidi-font-family:"Times New Roman"; color:windowtext;} p {margin-right:0in; mso-margin-top-alt:auto; mso-margin-bottom-alt:auto; margin-left:0in; mso-pagination:widow-orphan; font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman"; color:black;} pre {margin:0in; margin-bottom:.0001pt; mso-pagination:widow-orphan; tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt; font-size:10.0pt; font-family:"Courier New"; mso-fareast-font-family:"Courier New"; mso-bidi-font-family:"Times New Roman"; color:black;} @page Section1 {size:8.5in 11.0in; margin:1.0in 1.25in 1.0in 1.25in; mso-header-margin:.5in; mso-footer-margin:.5in; mso-paper-source:0;} div.Section1 {page:Section1;} /* List Definitions */ @list l0 {mso-list-id:1019158786; mso-list-type:hybrid; mso-list-template-ids:-386474800 67698689 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;} @list l0:level1 {mso-level-number-format:bullet; mso-level-text:; mso-level-tab-stop:.5in; mso-level-number-position:left; text-indent:-.25in; font-family:Symbol;} ol {margin-bottom:0in;} ul {margin-bottom:0in;} --> </style> <!--[if gte mso 9]><xml> <o:shapedefaults v:ext="edit" spidmax="1027"/> </xml><![endif]--><!--[if gte mso 9]><xml> <o:shapelayout v:ext="edit"> <o:idmap v:ext="edit" data="1"/> </o:shapelayout></xml><![endif]--> <meta content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot" name=Template> </head> <body bgcolor=white lang=EN-US link=blue vlink=purple style='tab-interval:.5in' leftmargin=8> <div class=Section1> <h2><a name="_Communicating_with_SCSI"></a><span style='font-family:Verdana'>Communicating with SCSI devices via Win32 application <o:p></o:p></span></h2> <p class=MsoNormal><span style='font-family:Verdana;color:red'>[This is preliminary documentation and subject to change.]</span><span style='font-family: Verdana'> <o:p></o:p></span></p> <h3><span style='font-family:Verdana'>SUMMARY<o:p></o:p></span></h3> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>Win32 applications can communicate directly with SCSI devices using the Win32 API DeviceIoControl and specifying the appropriate I/O control code (IOCTL).<span style="mso-spacerun: yes"> </span>Before DeviceIoControl can be used, a valid handle to the device must be obtained.<span style="mso-spacerun: yes"> </span>The handle is obtained using the Win32 API CreateFile.<o:p></o:p></span></p> <p><b><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>New for Windows 2000:<span style="mso-spacerun: yes"> </span></span></b><span style='font-size:10.0pt; mso-bidi-font-size:12.0pt;font-family:Verdana;mso-fareast-font-family:"MS Mincho"'>When using the SCSI pass through IOCTLs (described below), you must specify an access mode of <span style="mso-spacerun: yes"> </span>(GENERIC_READ | GENERIC_WRITE) in CreateFile or the DeviceIoControl call will fail with ERROR_ACCESS_DENIED (5L).<span style="mso-spacerun: yes"> </span>The access mode is specified in the second parameter to CreateFile, dwDesiredAccess.<span style="mso-spacerun: yes"> </span>Refer to the MSDN documentation for specific information about the Win32 APIs CreateFile and DeviceIoControl.<o:p></o:p></span></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>There are several IOCTLs that the SCSI port driver supports.<span style="mso-spacerun: yes"> </span>Refer to the DDK file NTDDSCSI.H for the most current information regarding the supported IOCTLs.<span style="mso-spacerun: yes"> </span>This sample will demonstrate the following IOCTLs: <a href="#_IOCTL_SCSI_GET_INQUIRY_DATA">IOCTL_SCSI_GET_INQUIRY_DATA</a>, <a href="#_IOCTL_SCSI_GET_CAPABILITIES">IOCTL_SCSI_GET_CAPABILITIES</a>, <a href="#_IOCTL_SCSI_PASS_THROUGH_and_IOCTL_SCSI_">IOCTL_SCSI_PASS_THROUGH</a>, and <a href="#_IOCTL_SCSI_PASS_THROUGH_and_IOCTL_SCSI_">IOCTL_SCSI_PASS_THROUGH_DIRECT</a>.<o:p></o:p></span></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>To issue these IOCTLs, the user must be either the administrator or a member of the Administrator's group.<span style="mso-spacerun: yes"> </span>If the user does not have the correct privilege level, the CreateFile call will fail with ERROR_ACCESS_DENIED (5L).<span style="mso-spacerun: yes"> </span><o:p></o:p></span></p> <p style='margin-left:.5in;text-indent:-.25in;mso-list:l0 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; mso-bidi-font-size:12.0pt;font-family:Symbol;mso-fareast-font-family:"MS Mincho"'>·<span style='font:7.0pt "Times New Roman"'> </span></span><![endif]><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt; font-family:Verdana;mso-fareast-font-family:"MS Mincho"'>If CreateFile fails with ERROR_ACCESS_DENIED, the user doesn't have the correct privilege level.<span style="mso-spacerun: yes"> </span><o:p></o:p></span></p> <p style='margin-left:.5in;text-indent:-.25in;mso-list:l0 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; mso-bidi-font-size:12.0pt;font-family:Symbol;mso-fareast-font-family:"MS Mincho"'>·<span style='font:7.0pt "Times New Roman"'> </span></span><![endif]><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt; font-family:Verdana;mso-fareast-font-family:"MS Mincho"'>If DeviceIoControl fails with ERROR_ACCESS_DENIED, the access mode (GENERIC_READ | GENERIC_WRITE) was not specified in the CreateFile call.<o:p></o:p></span></p> <h4><a name="_IOCTL_SCSI_GET_INQUIRY_DATA"></a><span style='font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>IOCTL_SCSI_GET_INQUIRY_DATA<o:p></o:p></span></h4> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>IOCTL_SCSI_GET_INQUIRY_DATA returns a SCSI_ADAPTER_BUS_INFO structure for all devices that are on the SCSI bus.<span style="mso-spacerun: yes"> </span>The structure member, BusData, is a structure of type SCSI_BUS_DATA.<span style="mso-spacerun: yes"> </span>It contains an offset to the SCSI Inquiry data, which is also stored as a structure, SCSI_INQUIRY_DATA.<span style="mso-spacerun: yes"> </span>See NTDDSCSI.H for more details about these structures.<span style="mso-spacerun: yes"> </span><o:p></o:p></span></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>Within the SCSI_INQUIRY_DATA structure is a member named DeviceClaimed.<span style="mso-spacerun: yes"> </span>DeviceClaimed indicates whether or not a class driver has claimed this particular SCSI device.<span style="mso-spacerun: yes"> </span>If a device is claimed, all SCSI pass through requests must be sent first through the class driver, which will typically pass the request unmodified to the SCSI port driver.<span style="mso-spacerun: yes"> </span>The class driver is allowed to fail the SCSI pass through request if it desires.<span style="mso-spacerun: yes"> </span>However, the drivers currently shipped by Microsoft simply pass the SCSI pass through requests on to the SCSI port driver.<span style="mso-spacerun: yes"> </span>If the device is unclaimed, the SCSI pass through requests are sent directly to the SCSI port driver.<span style="mso-spacerun: yes"> </span>See <a href="#_Obtaining_a_handle">Obtaining a handle to a device</a> for more details.<o:p></o:p></span></p> <h4><a name="_IOCTL_SCSI_GET_CAPABILITIES"></a><span style='font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>IOCTL_SCSI_GET_CAPABILITIES<o:p></o:p></span></h4> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>IOCTL_SCSI_GET_CAPABILITIES returns an IO_SCSI_CAPABILITIES structure (also found in NTDDSCSI.H).<span style="mso-spacerun: yes"> </span>This structure contains valuable information about the capabilities of the SCSI adapter.<span style="mso-spacerun: yes"> </span>Two items of note are the MaximumTransferLength, which is a byte value indicating the largest data block that can be transferred in a single SRB, and the MaximumPhysicalPages, which is the maximum number of physical pages that a data buffer can span.<span style="mso-spacerun: yes"> </span>The MaximumPhysicalPages indicates how many Scatter/Gather entries the SCSI miniport driver and adapter can support.<o:p></o:p></span></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>To determine the largest transfer that an adapter can handle, you have to first convert the MaximumPhysicalPages into a byte value that we’ll refer to here as MaximumPhysicalPages_in_bytes.<span style="mso-spacerun: yes"> </span>Subtract one from MaximumPhysicalPages and then multiply this value by the system PAGE_SIZE (defined in NTDDK.H) to get the MaximumPhysicalPages_in_bytes.<span style="mso-spacerun: yes"> </span>Then the largest transfer that can be issued on an adapter is the smaller of MaximumTransferLength and MaximumPhysicalPages_in_bytes.<o:p></o:p></span></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>For example, assume a system has PAGE_SIZE = 4KB, and the SCSI capabilities indicate MaximumTransferLength = 16MB and MaximumPhysicalPages = 17.<span style="mso-spacerun: yes"> </span>Then, the largest transfer on this adapter would be 64KB based on the following calculations:<o:p></o:p></span></p> <p style='margin-left:.5in'><span style='font-size:10.0pt;mso-bidi-font-size: 12.0pt;font-family:Verdana;mso-fareast-font-family:"MS Mincho"'>MaximumPhysicalPages – 1 = 17 – 1 = 16 * PAGE_SIZE = 16 * 4096 = 64KB<o:p></o:p></span></p> <p style='margin-left:.5in'><span style='font-size:10.0pt;mso-bidi-font-size: 12.0pt;font-family:Verdana;mso-fareast-font-family:"MS Mincho"'>largest transfer = min(MaximumTransferLength, MaximumPhysicalPages_in_bytes) = min(16MB, 64KB) = 64KB<o:p></o:p></span></p> <h4><a name="_IOCTL_SCSI_PASS_THROUGH_and_IOCTL_SCSI_"></a><span style='font-family:Verdana;mso-fareast-font-family:"MS Mincho"'>IOCTL_SCSI_PASS_THROUGH and IOCTL_SCSI_PASS_THROUGH_DIRECT<o:p></o:p></span></h4> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>The two IOCTLs IOCTL_SCSI_PASS_THROUGH and IOCTL_SCSI_PASS_THROUGH_DIRECT allow SCSI CDBs (Command Descriptor Blocks) to be sent from a Win32 application to a SCSI device.<span style="mso-spacerun: yes"> </span>Depending on which IOCTL is sent, a corresponding pass through structure is filled out by the Win32 application.<span style="mso-spacerun: yes"> </span>IOCTL_SCSI_PASS_THROUGH uses the structure SCSI_PASS_THROUGH.<span style="mso-spacerun: yes"> </span>IOCTL_SCSI_PASS_THROUGH_DIRECT uses the structure SCSI_PASS_THROUGH_DIRECT.<span style="mso-spacerun: yes"> </span>See NTDDSCSI.H for more details about these structures.<o:p></o:p></span></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>The structures SCSI_PASS_THROUGH and SCSI_PASS_THROUGH_DIRECT are virtually identical.<span style="mso-spacerun: yes"> </span>The only difference is that the data buffer for the SCSI_PASS_THROUGH structure must be contiguous with the structure.<span style="mso-spacerun: yes"> </span>This structure member is called DataBufferOffset and is of type ULONG.<span style="mso-spacerun: yes"> </span>The data buffer for the SCSI_PASS_THROUGH_DIRECT structure does not have to be contiguous with the structure.<span style="mso-spacerun: yes"> </span>This structure member is called DataBuffer and is of type PVOID.<span style="mso-spacerun: yes"> </span>This is the only difference between the two structures.<o:p></o:p></span></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>IOCTL_SCSI_PASS_THROUGH and IOCTL_SCSI_PASS_THROUGH_DIRECT are not substitutes for a SCSI class driver and should only be used for infrequent I/O processing.<span style="mso-spacerun: yes"> </span>For situations in which frequent SCSI commands need to be sent to a device, with strict error processing and high performance requirements, the best solution is to write a SCSI class driver that will send these CDBs to the respective devices.<span style="mso-spacerun: yes"> </span>SCSI pass through requests are handled synchronously by the SCSI port driver, even if the Win32 application has the proper code to handle the requests as overlapped I/O.<o:p></o:p></span></p> <h4><a name="_Obtaining_a_handle"></a><u><span style='font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>Obtaining a handle to a device</span></u><u><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'><o:p></o:p></span></u></h4> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>Before any IOCTLs can be sent to a SCSI device, a handle for the device must be obtained.<span style="mso-spacerun: yes"> </span>The Win32 API CreateFile is used to obtain this handle and to define the sharing mode and the access mode.<span style="mso-spacerun: yes"> </span>The access mode must be specified as (GENERIC_READ | GENERIC_WRITE).<span style="mso-spacerun: yes"> </span>The key to obtaining a valid handle is to supply the proper filename for the device that is to be opened.<span style="mso-spacerun: yes"> </span>It is possible to obtain a handle to the device via either the SCSI port driver or the appropriate SCSI class driver, depending on whether the device was claimed (see the DeviceClaimed information returned from <a href="#_IOCTL_SCSI_GET_INQUIRY_DATA">IOCTL_SCSI_GET_INQUIRY_DATA</a>).<span style="mso-spacerun: yes"> </span><o:p></o:p></span></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>If the device is claimed by a class driver, then you have to specify a filename that will route requests through the class driver.<span style="mso-spacerun: yes"> </span>In the case of fixed disks and optical storage devices, the filename is typically the corresponding drive letter.<span style="mso-spacerun: yes"> </span>"\\.\I:" can be used to obtain a handle to a CD-ROM drive that has been mapped to driver "I:".<span style="mso-spacerun: yes"> </span>In the case of SCSI printers, the filename is "LPTn", where n = 1, 2, etc.<span style="mso-spacerun: yes"> </span>For all remaining SCSI devices, the SCSI class driver defines the appropriate name.<span style="mso-spacerun: yes"> </span>Typically the name is related to the device (e.g. - "\\.\Scanner0", "\\.\Tape1").<span style="mso-spacerun: yes"> </span>Except for COMn and LPTn, all device filenames must be prepended with a \\.\ to inform the I/O Manager that this is a device and not a standard file name. <o:p></o:p></span></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>If the device is unclaimed by a SCSI class driver, then a handle to the SCSI port driver is required.<span style="mso-spacerun: yes"> </span>The filename in this case is "\\.\ScsiN:", where N = 0, 1, 2, etc.<span style="mso-spacerun: yes"> </span>The number N corresponds to the SCSI host adapter card number that controls the desired SCSI device.<span style="mso-spacerun: yes"> </span>When the SCSI port name is used, the Win32 application must set the proper PathId, TargetId, and Lun in the SCSI pass through structure.<span style="mso-spacerun: yes"> </span>Failure to set this SCSI address information will cause the SCSI request to fail (if directed to a target device claimed by a class driver) or possibly cause data corruption (if the unexpected target device processed the I/O request).<o:p></o:p></span></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>If the device is claimed by a class driver but a handle to the SCSI port driver is used, the DeviceIoControl call will fail the IOCTL_SCSI_PASS_THROUGH and IOCTL_SCSI_PASS_THROUGH_DIRECT with ERROR_INVALID_PARAMETER (87L).<span style="mso-spacerun: yes"> </span>The Win32 API QueryDosDevice can be used to display the symbolic links between the Win32 device names and their corresponding kernel mode names.<span style="mso-spacerun: yes"> </span>If you are unsure of which device name to specify for CreateFile, one should be able to examine the output from QueryDosDevice to determine the correct name.<o:p></o:p></span></p> <p><b><u><span style='font-family:Verdana;mso-fareast-font-family:"MS Mincho"'>Initializing the structures</span></u></b><span style='font-size:10.0pt;mso-bidi-font-size: 12.0pt;font-family:Verdana;mso-fareast-font-family:"MS Mincho"'><o:p></o:p></span></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>Once a valid handle is obtained to a SCSI device, then appropriate input and output buffers for the requested IOCTL must be allocated and, in some cases, filled in correctly.<span style="mso-spacerun: yes"> </span>This section describes general guidelines for setting up the parameters for the DeviceIoControl call.<span style="mso-spacerun: yes"> </span><o:p></o:p></span></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>For IOCTL_SCSI_GET_INQUIRY_DATA, no data is sent to the device - data is only read from the device.<span style="mso-spacerun: yes"> </span>Set lpInBuffer to NULL and nInBufferSize to zero.<span style="mso-spacerun: yes"> </span>The output buffer might be quite large, as each SCSI device on the bus will provide data that will fill three structures for each device:<span style="mso-spacerun: yes"> </span>SCSI_ADAPTER_BUS_INFO, SCSI_BUS_DATA, and SCSI_INQUIRY_DATA.<span style="mso-spacerun: yes"> </span>Allocate a buffer that will hold the information for all the devices on that particular SCSI adapter.<span style="mso-spacerun: yes"> </span>Set lpOutBuffer to point to this allocated buffer and nOutBufferSize to the size of the allocated buffer.<o:p></o:p></span></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>For IOCTL_SCSI_GET_CAPABILITIES, no data is sent to the device - data is only read from the device.<span style="mso-spacerun: yes"> </span>Set lpInBuffer to NULL and nInBufferSize to zero.<span style="mso-spacerun: yes"> </span>Set lpOutBuffer to a pointer to hold the IO_SCSI_CAPABILITIES structure, and nOutBufferSize to sizeof(IO_SCSI_CAPABILITIES).<span style="mso-spacerun: yes"> </span>A larger output buffer can be used, but the output buffer length must be set as described here.<o:p></o:p></span></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>For the two SCSI pass through IOCTLs, IOCTL_SCSI_PASS_THROUGH and IOCTL_SCSI_PASS_THROUGH_DIRECT, both lpInBuffer and lpOutBuffer can vary in size depending on the Request Sense buffer size and the data buffer size.<span style="mso-spacerun: yes"> </span>In all cases, nInBufferSize and nOutBufferSize must be at least the size of the SCSI_PASS_THROUGH (or SCSI_PASS_THROUGH_DIRECT) structure.<span style="mso-spacerun: yes"> </span>If the SCSI port driver detects that one of the two buffers is too small, then the DeviceIoControl API will fail with ERROR_INVALID_PARAMETER.<span style="mso-spacerun: yes"> </span><o:p></o:p></span></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>Once the appropriate input and output buffers have been allocated, then the appropriate structure must be initialized.<span style="mso-spacerun: yes"> </span>The SCSI_PASS_THROUGH structure is defined in NTDDSCSI.H as follows:<o:p></o:p></span></p> <p style='margin-top:0in;margin-right:0in;margin-bottom:0in;margin-left:.5in; margin-bottom:.0001pt'><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt; font-family:Verdana;mso-fareast-font-family:"MS Mincho"'>typedef struct _SCSI_PASS_THROUGH {<o:p></o:p></span></p> <p style='margin-top:0in;margin-right:0in;margin-bottom:0in;margin-left:.5in; margin-bottom:.0001pt'><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt; font-family:Verdana;mso-fareast-font-family:"MS Mincho"'><span style="mso-spacerun: yes"> </span><span style="mso-spacerun: yes"> </span>USHORT Length;<o:p></o:p></span></p> <p style='margin-top:0in;margin-right:0in;margin-bottom:0in;margin-left:.5in; margin-bottom:.0001pt'><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt; font-family:Verdana;mso-fareast-font-family:"MS Mincho"'><span style="mso-spacerun: yes"> </span>UCHAR ScsiStatus;<o:p></o:p></span></p> <p style='margin-top:0in;margin-right:0in;margin-bottom:0in;margin-left:.5in; margin-bottom:.0001pt'><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt; font-family:Verdana;mso-fareast-font-family:"MS Mincho"'><span style="mso-spacerun: yes"> </span>UCHAR PathId;<o:p></o:p></span></p> <p style='margin-top:0in;margin-right:0in;margin-bottom:0in;margin-left:.5in; margin-bottom:.0001pt'><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt; font-family:Verdana;mso-fareast-font-family:"MS Mincho"'><span style="mso-spacerun: yes"> </span>UCHAR TargetId;<o:p></o:p></span></p> <p style='margin-top:0in;margin-right:0in;margin-bottom:0in;margin-left:.5in; margin-bottom:.0001pt'><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt; font-family:Verdana;mso-fareast-font-family:"MS Mincho"'><span style="mso-spacerun: yes"> </span>UCHAR Lun;<o:p></o:p></span></p> <p style='margin-top:0in;margin-right:0in;margin-bottom:0in;margin-left:.5in; margin-bottom:.0001pt'><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt; font-family:Verdana;mso-fareast-font-family:"MS Mincho"'><span style="mso-spacerun: yes"> </span>UCHAR CdbLength;<o:p></o:p></span></p> <p style='margin-top:0in;margin-right:0in;margin-bottom:0in;margin-left:.5in; margin-bottom:.0001pt'><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt; font-family:Verdana;mso-fareast-font-family:"MS Mincho"'><span style="mso-spacerun: yes"> </span>UCHAR SenseInfoLength;<o:p></o:p></span></p> <p style='margin-top:0in;margin-right:0in;margin-bottom:0in;margin-left:.5in; margin-bottom:.0001pt'><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt; font-family:Verdana;mso-fareast-font-family:"MS Mincho"'><span style="mso-spacerun: yes"> </span>UCHAR DataIn;<o:p></o:p></span></p> <p style='margin-top:0in;margin-right:0in;margin-bottom:0in;margin-left:.5in; margin-bottom:.0001pt'><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt; font-family:Verdana;mso-fareast-font-family:"MS Mincho"'><span style="mso-spacerun: yes"> </span>ULONG DataTransferLength;<o:p></o:p></span></p> <p style='margin-top:0in;margin-right:0in;margin-bottom:0in;margin-left:.5in; margin-bottom:.0001pt'><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt; font-family:Verdana;mso-fareast-font-family:"MS Mincho"'><span style="mso-spacerun: yes"> </span>ULONG TimeOutValue;<o:p></o:p></span></p> <p style='margin-top:0in;margin-right:0in;margin-bottom:0in;margin-left:.5in; margin-bottom:.0001pt'><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt; font-family:Verdana;mso-fareast-font-family:"MS Mincho"'><span style="mso-spacerun: yes"> </span>ULONG DataBufferOffset;<o:p></o:p></span></p> <p style='margin-top:0in;margin-right:0in;margin-bottom:0in;margin-left:.5in; margin-bottom:.0001pt'><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt; font-family:Verdana;mso-fareast-font-family:"MS Mincho"'><span style="mso-spacerun: yes"> </span>ULONG SenseInfoOffset;<o:p></o:p></span></p> <p style='margin-top:0in;margin-right:0in;margin-bottom:0in;margin-left:.5in; margin-bottom:.0001pt'><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt; font-family:Verdana;mso-fareast-font-family:"MS Mincho"'><span style="mso-spacerun: yes"> </span>UCHAR Cdb[16];<o:p></o:p></span></p> <p style='margin-top:0in;margin-right:0in;margin-bottom:0in;margin-left:.5in; margin-bottom:.0001pt'><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt; font-family:Verdana;mso-fareast-font-family:"MS Mincho"'>}SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH;<o:p></o:p></span></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>The Length is the size of the SCSI_PASS_THROUGH structure.<span style="mso-spacerun: yes"> </span>The ScsiStatus should be initialized to 0.<span style="mso-spacerun: yes"> </span>The SCSI status of the requested SCSI operation is returned in this structure member.<span style="mso-spacerun: yes"> </span>The possible SCSI statuses are defined in SCSI.H and are of the form SCSISTAT_xxx. The PathId is the bus number for the SCSI host adapter that controls the SCSI device in question.<span style="mso-spacerun: yes"> </span>Typically, this value will be 0, but there are SCSI host adapters that have more than one SCSI bus on the adapter.<span style="mso-spacerun: yes"> </span>The TargetId and Lun are the SCSI ID number and logical unit number for the device.<span style="mso-spacerun: yes"> </span>If the handle was obtained for a claimed device, then the PathId, TargetId and Lun as defined in this structure will be ignored and the appropriate class driver will provide this SCSI address information.<span style="mso-spacerun: yes"> </span>If the handle was obtained for the SCSI port driver, then the PathId, TargetId and Lun must be correct for the device intended.<span style="mso-spacerun: yes"> </span><o:p></o:p></span></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>The CdbLength is the length of the CDB. Typical values are 6, 10, and 12 up to the maximum of 16.<span style="mso-spacerun: yes"> </span>The SenseInfoLength is the length of the SenseInfo buffer.<span style="mso-spacerun: yes"> </span>DataIn has three possible values which are defined in NTDDSCSI.H;<span style="mso-spacerun: yes"> </span>SCSI_IOCTL_DATA_OUT, SCSI_IOCTL_DATA_IN and SCSI_IOCTL_DATA_UNSPECIFIED. <span style="mso-spacerun: yes"> </span>SCSI_IOCTL_DATA_UNSPECIFIED should be used only if the appropriate SCSI miniport driver supports its usage.<span style="mso-spacerun: yes"> </span>The DataTransferLength is the byte size of the data buffer.<span style="mso-spacerun: yes"> </span>The TimeOutValue is the length of time, in seconds, until a time-out error should occur.<span style="mso-spacerun: yes"> </span>This can range from 0 to a maximum of 30 minutes (108000 seconds).<span style="mso-spacerun: yes"> </span><o:p></o:p></span></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>The DataBufferOffset is the offset of the data buffer from the beginning of the pass through structure.<span style="mso-spacerun: yes"> </span>For the SCSI_PASS_THROUGH_DIRECT structure, this value is not an offset, but rather is a pointer to a data buffer.<span style="mso-spacerun: yes"> </span>The SenseInfoOffset is similarly an offset to the SenseInfo buffer from the beginning of the pass through structure. Finally, the sixteen remaining bytes are for the CDB data.<span style="mso-spacerun: yes"> </span>The format of this data must conform to the SCSI-2 standard as defined by ANSI.<o:p></o:p></span></p> <p><b><u><span style='font-family:Verdana;mso-fareast-font-family:"MS Mincho"'>Buffer Alignment</span></u></b><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt; font-family:Verdana;mso-fareast-font-family:"MS Mincho"'><o:p></o:p></span></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>The AlignmentMask member returned in the structure via the IOCTL_SCSI_GET_CAPABILITIES indicates the buffer alignment requirements of the SCSI adapter.<span style="mso-spacerun: yes"> </span>Buffer alignment is handled using two methods for assuring that buffers are aligned on the appropriate boundaries.<span style="mso-spacerun: yes"> </span><o:p></o:p></span></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>The first method uses the compiler to align the buffer on the correct boundary.<span style="mso-spacerun: yes"> </span>The structure SCSI_PASS_THROUGH_WITH_BUFFERS contains a member, Filler that is of type ULONG.<span style="mso-spacerun: yes"> </span>The compiler aligns Filler on a ULONG (double word) boundary.<span style="mso-spacerun: yes"> </span>The structure member that follows Filler, ucSenseBuf, is also aligned on a double word boundary.<span style="mso-spacerun: yes"> </span>The ucSenseBuf array is of a size that is a multiple of a double word, and so this makes the last structure member, ucDataBuf, also begin on a double word boundary. <o:p></o:p></span></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>A second method to ensure buffer alignment is demonstrated in the AllocateAlignedBuffer procedure.<span style="mso-spacerun: yes"> </span>This procedure depends on the fact that a buffer aligned on a certain boundary will have 0's in its least significant bits indicating the buffer alignment.<span style="mso-spacerun: yes"> </span>A buffer allocation request is made using the C runtime call (malloc) that is the size of the requested buffer plus the AlignmentMask value as returned by IOCTL_SCSI_GET_CAPABILITIES.<span style="mso-spacerun: yes"> </span>A pointer is manipulated so that it is pointing to the first possible address in the buffer that meets the alignment requirements.<o:p></o:p></span></p> <p><b><u><span style='font-family:Verdana;mso-fareast-font-family:"MS Mincho"'>Direct versus Buffered<o:p></o:p></span></u></b></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>Here's the big difference between IOCTL_SCSI_PASS_THROUGH versus IOCTL_SCSI_PASS_THROUGH_DIRECT: the SCSI data is transferred directly into the specified ucDataBuf for IOCTL_SCSI_PASS_THROUGH_DIRECT while the data will be buffered in an intermediate I/O manager allocated buffer for IOCTL_SCSI_PASS_THROUGH.<o:p></o:p></span></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>The various IOCTLs that are demonstrated in this sample are defined by the SCSI port driver (see NTDDSCSI.H for details).<span style="mso-spacerun: yes"> </span>The memory buffering for these IOCTLs is METHOD_BUFFERED.<span style="mso-spacerun: yes"> </span>What this means is that the I/O manager examines the length lpInBuffer and the length of lpOutBuffer as defined by the DeviceIoControl parameters and allocates a contiguous buffer that is the size of the larger of the two buffers.<span style="mso-spacerun: yes"> </span>On entry to the I/O manager (i.e. the call to DeviceIoControl), the contents of the Win32 application's lpInBuffer is copied to the buffer that was allocated by the I/O manager.<span style="mso-spacerun: yes"> </span>The nInBufferSize controls the amount of data copied.<span style="mso-spacerun: yes"> </span>The I/O manager then calls the appropriate SCSI class driver's (or port driver's) DeviceIoControl routine passing it the new buffer.<span style="mso-spacerun: yes"> </span>On exit, the reverse process occurs and the data in the new buffer is copied back into the Win32 application's lpOutBuffer.<span style="mso-spacerun: yes"> </span>This behavior is not user configurable.<o:p></o:p></span></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>When using IOCTL_SCSI_PASS_THROUGH, the SCSI data buffer (ucDataBuf) is part of lpInBuffer.<span style="mso-spacerun: yes"> </span>Therefore, the data in ucDataBuf is copied into the new buffer (allocated by the I/O manager) and presented to the SCSI port driver and the SCSI miniport driver.<span style="mso-spacerun: yes"> </span>On completion, the new buffer is copied back to the ucDataBuf.<o:p></o:p></span></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>When using IOCTL_SCSI_PASS_THROUGH_DIRECT, the SCSI data buffer (ucDataBuf) is not part of lpInBuffer.<span style="mso-spacerun: yes"> </span>Recall that the SCSI_PASS_THROUGH_DIRECT has a PVOID DataBuffer member.<span style="mso-spacerun: yes"> </span>That is, DataBuffer is a pointer to the data buffer, and the data buffer does not have to be contiguous with the SCSI_PASS_THROUGH_DIRECT structure.<span style="mso-spacerun: yes"> </span>When the Win32 application calls DeviceIoControl, the lpInBuffer is copied into an I/O manager allocated buffer, and this new buffer is passed to the SCSI port driver.<span style="mso-spacerun: yes"> </span>In the SCSI port driver, the SCSI_PASS_THROUGH_DIRECT structure is examined, the pointer to the DataBuffer is retrieved from the structure, and the user's buffer is probed and locked for direct access.<span style="mso-spacerun: yes"> </span><o:p></o:p></span></p> <p><b><u><span style='font-family:Verdana;mso-fareast-font-family:"MS Mincho"'>Running the SPTI.EXE sample</span></u></b><span style='font-size:10.0pt;mso-bidi-font-size: 12.0pt;font-family:Verdana;mso-fareast-font-family:"MS Mincho"'><o:p></o:p></span></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>Two command line parameters can be used with SPTI.EXE.<o:p></o:p></span></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>The first parameter is mandatory.<span style="mso-spacerun: yes"> </span>It is the name of the device to be opened.<span style="mso-spacerun: yes"> </span>Typical values for this are drive letters such as "C:", or device names as defined by a class driver such as Scanner0, or the SCSI port driver name, ScsiN:, where N = 0, 1, 2, etc.<span style="mso-spacerun: yes"> </span>See <a href="#_Obtaining_a_handle">Obtaining a handle for a device</a> for details on this first parameter.<o:p></o:p></span></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>The second parameter is optional and is used to set the share mode (note that access mode and share mode are different things) and sector size.<span style="mso-spacerun: yes"> </span>The default share mode is (FILE_SHARE_READ | FILE_SHARE_WRITE) and the default sector size is 512.<span style="mso-spacerun: yes"> </span>A parameter of "r" changes the share mode to only FILE_SHARE_READ.<span style="mso-spacerun: yes"> </span>A parameter of "w" changes the share mode to only FILE_SHARE_WRITE.<span style="mso-spacerun: yes"> </span>A parameter of "c" changes the share mode to only FILE_SHARE_READ and also changes the sector size to 2048.<span style="mso-spacerun: yes"> </span>Typically, a CD-ROM device would use the "c" parameter.<span style="mso-spacerun: yes"> </span><o:p></o:p></span></p> <p><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana; mso-fareast-font-family:"MS Mincho"'>The examples below assume that there is a system with a disk drive "c:", CD-ROM "d:", and an unclaimed SCSI device on the second SCSI adapter (scsi1:).<o:p></o:p></span></p> <p style='margin:0in;margin-bottom:.0001pt'><b><span style='font-size:10.0pt; mso-bidi-font-size:12.0pt;font-family:Verdana;mso-fareast-font-family:"MS Mincho"'>spti c:</span></b><span style='font-size:10.0pt;mso-bidi-font-size:12.0pt; font-family:Verdana;mso-fareast-font-family:"MS Mincho"'><o:p></o:p></span></p> <p style='margin:0in;margin-bottom:.0001pt'><span style='font-size:10.0pt; mso-bidi-font-size:12.0pt;font-family:Verdana;mso-fareast-font-family:"MS Mincho"'>To send SCSI commands to the disk drive. <o:p></o:p></span></p> <p style='margin-bottom:0in;margin-bottom:.0001pt'><b><span style='font-size: 10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana;mso-fareast-font-family: "MS Mincho"'>spti d: c</span></b><span style='font-size:10.0pt;mso-bidi-font-size: 12.0pt;font-family:Verdana;mso-fareast-font-family:"MS Mincho"'><o:p></o:p></span></p> <p style='margin:0in;margin-bottom:.0001pt'><span style='font-size:10.0pt; mso-bidi-font-size:12.0pt;font-family:Verdana;mso-fareast-font-family:"MS Mincho"'>To send SCSI commands to the CD-ROM device.<span style="mso-spacerun: yes"> </span>Remember that CD-ROM devices typically use 2048 sector size, so the "c" parameter should be used. <o:p></o:p></span></p> <p style='margin-bottom:0in;margin-bottom:.0001pt'><b><span style='font-size: 10.0pt;mso-bidi-font-size:12.0pt;font-family:Verdana;mso-fareast-font-family: "MS Mincho"'>spti scsi1:</span></b><span style='font-size:10.0pt;mso-bidi-font-size: 12.0pt;font-family:Verdana;mso-fareast-font-family:"MS Mincho"'> <o:p></o:p></span></p> <p style='margin-top:0in'><span style='font-size:10.0pt;mso-bidi-font-size: 12.0pt;font-family:Verdana;mso-fareast-font-family:"MS Mincho"'>To send SCSI commands to the unclaimed SCSI device.<span style="mso-spacerun: yes"> </span>Make sure that the SCSI pass through structure has the correct PathId, TargetId and Lun, filled in.<span style="mso-spacerun: yes"> </span>If the SCSI address information is incorrectly set, the request might fail or be directed towards the wrong device.<span style="mso-spacerun: yes"> </span><o:p></o:p></span></p> <p><b><u>BUILDING THE SAMPLE<o:p></o:p></u></b></p> <p><span style='font-size:10.0pt;font-family:Verdana'>Click the Free Build Environment or Checked Build Environment icon under your <b>Development Kits </b>program group to set basic environment variables needed by the build utility. <o:p></o:p></span></p> <p><span style='font-size:10.0pt;font-family:Verdana'>Change to the directory containing the device source code.<o:p></o:p></span></p> <p><span style='font-size:10.0pt;font-family:Verdana'>To build the sample, run <b>build -ceZ</b>, or use the macro <b>BLD</b>.<span style="mso-spacerun: yes"> </span>The "e" option produces a log file (buildXXX.log), a warning file (buildXXX.wrn), and an error file (buildXXX.err) where XXX means either <b>fre</b> or <b>chk, </b>depending on the environment chosen.<span style="mso-spacerun: yes"> </span>If there are no warnings, then the warning file will not be built and if there are no errors, there will be no error file built.<span style="mso-spacerun: yes"> </span>If the build succeeds, the Win32 application spti.exe will be placed in a subdirectory of either the objfre (for free build) or objchk (for checked build) directories. <o:p></o:p></span></p> No INF file is needed to install this application. <P> <h3><span style='font-family:Verdana'>CODE TOUR<o:p></o:p></span></h3> <h4><span style='font-family:Verdana'>File Manifest<o:p></o:p></span></h4> <pre><u><span style='mso-bidi-font-family:"Courier New"'>File<span style='mso-tab-count:2'> </span>Description<o:p></o:p></span></u></pre><pre><span style='mso-bidi-font-family:"Courier New"'><![if !supportEmptyParas]> <![endif]><o:p></o:p></span></pre><pre><span style='mso-bidi-font-family:"Courier New"'><![if !supportEmptyParas]> <![endif]><o:p></o:p></span></pre><pre><span style='mso-bidi-font-family:"Courier New"'>spti.htm<span style='mso-tab-count: 1'> </span>The documentation for these samples (this file)<o:p></o:p></span></pre><pre><span style='mso-bidi-font-family:"Courier New"'>spti.c<span style="mso-spacerun: yes"> </span>Implements the Win32 application to communicate with the SCSI devices.<o:p></o:p></span></pre><pre><span style='mso-bidi-font-family:"Courier New"'>spti.h<span style="mso-spacerun: yes"> </span>Header file for spti.c<o:p></o:p></span></pre><pre><span style='mso-bidi-font-family:"Courier New"'>Sources<span style="mso-spacerun: yes"> </span>DDK build instructions<o:p></o:p></span></pre> <p style='margin:0in;margin-bottom:.0001pt;tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt'><span style='font-size:10.0pt;font-family:"Courier New";mso-fareast-font-family:"Courier New"'><![if !supportEmptyParas]> <![endif]><o:p></o:p></span></p> <p style='margin:0in;margin-bottom:.0001pt;tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt'><span style='font-size:10.0pt;font-family:"Courier New";mso-fareast-font-family:"Courier New"'><![if !supportEmptyParas]> <![endif]><o:p></o:p></span></p> <p align=center style='margin:0in;margin-bottom:.0001pt;text-align:center; tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt'><span style='font-size:10.0pt;font-family:Verdana;mso-fareast-font-family:"Courier New"; mso-bidi-font-family:"Courier New"'><a href="#_Communicating_with_SCSI">Top of page </a></span><span class=MsoHyperlink><span style='font-size:10.0pt; font-family:Verdana;mso-fareast-font-family:"Courier New";mso-bidi-font-family: "Courier New"'><o:p></o:p></span></span></p> <pre><span style='mso-bidi-font-family:"Courier New"'><![if !supportEmptyParas]> <![endif]><o:p></o:p></span></pre> <table border=0 cellspacing=0 cellpadding=0 width=624 style='width:6.5in; mso-cellspacing:0in;mso-padding-alt:0in 0in 0in 0in'> <tr style='height:1.5pt'> <td style='background:aqua;padding:.75pt .75pt .75pt .75pt;height:1.5pt'> <p class=MsoNormal> </p> </td> </tr> </table> <pre><span style='mso-bidi-font-family:"Courier New"'><![if !supportEmptyParas]> <![endif]><o:p></o:p></span></pre><pre><span style='mso-bidi-font-family:"Courier New"'><![if !supportEmptyParas]> <![endif]><o:p></o:p></span></pre> <p style='margin:0in;margin-bottom:.0001pt;tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt'><span style='font-size:7.5pt;font-family:"MS Sans Serif";mso-fareast-font-family: "Courier New";mso-bidi-font-family:"Courier New"'>© 1999 Microsoft Corporation</span><span style='font-size:10.0pt;font-family:Verdana;mso-fareast-font-family:"Courier New"; mso-bidi-font-family:"Courier New"'> <o:p></o:p></span></p> </div> </body> </html>