NT SCSI Pass Through Interface (SPTI) behavior
SPTI is a perfect technology for direct communication with SCSI-compatible devices for
Windows NT family. SPTI unifies communication interface for the following device classes
(the list can appear much more wide):
- SCSI devices, connected via SCSI-controller
- devices using SCSI command set, connected via non-SCSI-controllers
- all currently available IDE/ATAPI CD/DVD-drives and most of very old ones.
- LPT, USB and FireWire HDD and CD/DVD-drives.
- devices with driver-side SCSI-interface emulation - IDE/ATA HDD
You can pass any SCSI command with any paramenters through SPTI. You can also obtain complete
error condition information (SenseInfo) from device. Look at the brief list of advantages:
- Works under all NT-family OS'es.
- Doesn't require any additional drivers installed. (Such as multiple implementaions of ASPI
with their multiple bugs).
- Is available in Win32 via DeviceIoControl() with handle to physical device (see. MSDN,
CreateFileEx(), \\.\<DriveLetter>:, etc.)
SPTI is pretty, but there are some undocumented troubles, those I have meet.
The further story is about them.
You can read much more about SCSI commands for CD/DVD drives in MMC specs.
Transfer length limitations
Problem: IOCTL_SCSI_PASS_THROUGH_DIRECT fails when I attempt to transfer 64k
from Win32 using DeviceIoControl(). Port driver returns STATUS_INVALID_PARAMETER.
MS DDK Help states, that such error occures if data buffer has improper size.
Knowledge base (PSS ID Number: Q126369) states, that we must use
IOCTL_SCSI_GET_CAPABILITIES to obtain MaximumTransferLength and MaximumPhysicalPages.
According to docs user buffer is copied to temporary system-allocated buffer (METHOD_BUFFERED)
and after operation completion data from temporary buffer is copied back to user buffer.
I checked it. MaximumTransferLength is 64k, no problem should be. MaximumPhysicalPages
is 16, also no problem. So why it doesn't work ?
Answer: user buffer is passed down as is. Port driver compares its size with
MaximumTransferLength. That is ok. Then it calculates how much pages spans user buffer.
Because Win32 allocates 8-byte aligned memory blocks, 64k buffer will usually span
17 pages. That was the reason for my problem.
Solution: trivial. Buffer must be PAGE_SIZE-aligned. In kernel mode memory blocks
greater than PAGE_SIZE are aligned to PAGE_SIZE by memory manager. In user mode
you should either allocate larger buffer and use PAGE_SIZE-aligned part of it or
implement own heap manager specially for large blocks.
Auto-sense (device error reporting) issues
Small trouble: when SenseInfoOffset is used you should not set SenseInfoLength
greater than sizeof(SENSE_DATA) - 24 bytes. If you specify extra length, no Sense Info will be returned.
This happens because when error occures Port-driver sends REQUEST_SENSE commend to device.
It uses user-specified SenseInfoLength for this request. The device cannot return more than 24 bytes,
and an error is generated.
Trouble: Imagine physical ATAPI CD-Recorder which is mapped to IDE bus of virtual machine.
Neither CD-recording software using SPTI can operate properly. I discovered, that VMWare blocks
MODE_SELECT command with MODE_PAGE_WRITE_PARAMS - 0x05 and WRITE commands. Further investigations
shown that the trouble affected all ways of sending write requests.
Solution: tune VMWare in order to expose physical ATAPI CD-recorder as SCSI device inside