NT SCSI Pass Through Interface (SPTI) behavior
SPTI - замечательная технология для непосредственного обращения к SCSI-совместимым устройствам
для NT-подобный систем. SPTI обеспечивает единообразный интерфейс для работы со следующими
типами устройств (в действительности список может оказаться более широким)
- SCSI устройства, подключенные через SCSI-контроллер
- устройства, использующие SCSI'шный набор команд, подключенные не-SCSI-контроллеры
- все современные IDE/ATAPI CD/DVD-приводы и большинство старых.
- LPT, USB и FireWire HDD и CD/DVD-приводы.
- устройства, для которых эмулируется SCSI-интерфейс на уровне драйверов - IDE/ATA HDD
Через SPTI можно передать любую SCSI команду с любыми параметрами и получить полную
информацию об ошибке (SenseInfo) от устройства. Вот краткий список преимуществ:
- Работает во всей линейке NT-подобных систем.
- Не требует никаких дополнительных драйверов (таких как многочисленные реализации ASPI с их не менее
многочисленными глюками).
- Доступно в Win32 через DeviceIoControl() с handle'ом физического устройства (см. MSDN,
CreateFileEx(), \\.\<DriveLetter>: и т.п.)
Всем хорош SPTI, но есть ряд недокументированых граблей, на которые я имел честь наступить.
Именно о них дальнейший рассказ.
Подробно о SCSI командах для CD/DVD приводов можно найти в спецификациях MMC.
Transfer length limitations
Проблема: IOCTL_SCSI_PASS_THROUGH_DIRECT возвращает ошибку при попытке
передать 64k данных устройству из
Win32 через DeviceIoControl(). Вскрытие показало, что Port driver возвращает STATUS_INVALID_PARAMETER.
MS DDK Help говорит, что такая ошибка возникает при неправильном размере буфера.
В Knowledge base (PSS ID Number: Q126369) сказано, что нужно использовать
IOCTL_SCSI_GET_CAPABILITIES для того, чтобы узнать MaximumTransferLength и MaximumPhysicalPages.
Согласно докам пользовательский буфер копируется во временный system-allocated буфер (METHOD_BUFFERED)
а после завершения операции данные копируются обратно из временного буфера в пользовательский.
Я проверил.. MaximumTransferLength = 64k, так что никаких проблем быть не должно. MaximumPhysicalPages
= 16, типа тоже no problem. Так где же, спрашивается, грабли ?
Ответ: пользовательский буфер передался вниз как был. Port driver сравнил его размер с
MaximumTransferLength. Пока все хорошо. Подсчитал, сколько страниц (полных и неполных) перекрывает
пользовательский буфер. Т.к. Win32 выделяет память блоками, выровнеными на 8 байт, 64k буфер как правило
будет перекрывать 17 страниц (1ю и последнюю - частично). Вот и грабельки.
Solution: Выровнять буфер на размер страницы (PAGE_SIZE). В kernel-mode это делает
memory maneger. А в Win32 придется делать самостоятельно.
Либо выделять бОльший буфер и использовать из него выровненый блок, либо
делать собственный heap manager специально для таких случаев.
Auto-sense (device error reporting) issues
Мелкие грабли: при использовании SenseInfoOffset нельзя устанавливать SenseInfoLength
больше чем sizeof(SENSE_DATA) - 24 байта. Иначе SenseInfo не будет возвращено. Это связано с тем,
что при возникновении ошибки Port-driver самостоятельно посылает устройству команду REQUEST_SENSE
и передает ей как раз SenseInfoLength. Поскольку устройство не может отдать в ответ больше 24 байт,
возникает ошибка.
VMWare compatibility
Проблемка: при отображении физического ATAPI CD-recorder'а на IDE шину виртуальной машины
не работает CD-пишущий софт, работающий через SPTI. Оказалось, что VMWare блокирует команды установки
режима записи (MODE_SELECT, MODE_PAGE_WRITE_PARAMS - 0x05), а также сами команды записи.
Дальнейшее исследование показало, что проблема касается не только SPTI, и писать на устройство
нельзя вообще.
Solution: настроить VMWare так, чтобы физический ATAPI CD-recorder отображался в виртуальную
машину как SCSI устройство.
|