📄 scsi2.h
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Module Name:
scsi2.h
Abstract:
USB Disk Class for
bInterfaceSubClass = 0x06 : SCSI Passthrough
bInterfaceSubClass = 0x04 : USB Floppy Interface (UFI), which is a SCSI2 subset
bInterfaceSubClass = 0x02 : SFF8020i CD-ROM Data Only; Digital Audio requires CD-DA work
Functions:
Notes:
--*/
#if !defined( _SCSI2_ )
#define _SCSI2_
//*****************************************************************************
// I N C L U D E S
//*****************************************************************************
#include <windows.h>
#include <winioctl.h>
#include <diskio.h>
#include "warning.h"
#include "remlock.h"
#include "utils.h"
#include "cdioctl.h"
//*****************************************************************************
// D E F I N E S
//*****************************************************************************
#define DRIVER_NAME_SZ TEXT("USBDISK6.DLL")
#define USBSCSI_SIG 'SCSI'
//
// Default Timeout/repeat values in msec
//
#define MEDIA_POLL_SZ TEXT("MediaPollInterval")
#define SCSI_MEDIA_POLL_INTERVAL 1250
// timeout in msec per sector
#define READ_SECTOR_SZ TEXT("ReadSectorTimeout")
#define SCSI_READ_SECTOR_TIMEOUT 10000
// timeout in msec per sector
#define WRITE_SECTOR_SZ TEXT("WriteSectorTimeout")
#define SCSI_WRITE_SECTOR_TIMEOUT 10000
#define SCSI_COMMAND_SZ TEXT("ScsiCommandTimeout")
#define SCSI_COMMAND_TIMEOUT 5000
#define UNIT_ATTENTION_SZ TEXT("UnitAttnRepeat")
#define UNIT_ATTENTION_REPEAT 10
//
// Size in bytes
//
#define FAT_SECTOR_SIZE 512
#define CDSECTOR_SIZE 2048
#define MAX_SECTOR_SIZE CDSECTOR_SIZE
#define SG_BUFF_SIZE max((MAX_SG_BUF*FAT_SECTOR_SIZE),(3*CDSECTOR_SIZE))
//
// Is the context pointer valid
//
#define VALID_CONTEXT( p ) \
( p != NULL && USBSCSI_SIG == p->Sig )
//
// Can the device accept I/O requests
//
#define ACCEPT_IO( p ) \
( VALID_CONTEXT( p ) && \
p->Flags.Open && \
!p->Flags.DeviceRemoved && \
!p->Flags.PoweredDown )
//
// SCSI-2 DEVICE TYPES
//
#define SCSI_DEVICE_DIRECT_ACCESS 0x00 // e.g. disk
#define SCSI_DEVICE_SEQUENTIAL_ACCESS 0x01
#define SCSI_DEVICE_PRINTER 0x02
#define SCSI_DEVICE_PROCESSOR 0x03
#define SCSI_DEVICE_WRITE_ONCE 0x04
#define SCSI_DEVICE_CDROM 0x05
#define SCSI_DEVICE_SCANNER 0x06
#define SCSI_DEVICE_OPTICAL 0x07
#define SCSI_DEVICE_MEDIUM_CHANGER 0x08
#define SCSI_DEVICE_COMM 0x09
#define SCSI_DEVICE_UNKNOWN 0x1F
//
// SCSI-2 MEDIUM TYPES
//
#define SCSI_MEDIUM_UNKNOWN 0xFF
//
// CD-ROM MEDIUM TYPES
//
#define MEDIUM_CD_ROM_UNKNOWN 0x00
#define MEDIUM_CD_ROM_120 0x01
#define MEDIUM_CD_DA_120 0x02
#define MEDIUM_CD_MIXED_120 0x03
#define MEDIUM_CD_HYBRID_120 0x04
#define MEDIUM_CD_ROM_80 0x05
#define MEDIUM_CD_DA_80 0x06
#define MEDIUM_CD_MIXED_80 0x07
#define MEDIUM_CD_HYBRID_80 0x08
#define MEDIUM_CDR_ROM_UNKNOWN 0x10
#define MEDIUM_CDR_ROM_120 0x11
#define MEDIUM_CDR_DA_120 0x12
#define MEDIUM_CDR_MIXED_120 0x13
#define MEDIUM_CDR_HYBRID_120 0x14
#define MEDIUM_CDR_ROM_80 0x15
#define MEDIUM_CDR_DA_80 0x16
#define MEDIUM_CDR_MIXED_80 0x17
//
// MANDATORY SCSI-2 COMMANDS
//
#define SCSI_TEST_UNIT_READY 0x00
#define SCSI_REQUEST_SENSE 0x03
#define SCSI_INQUIRY 0x12
#define SCSI_SEND_DIAGNOSTIC 0x1D
//
// MANDATORY DEVICE SPECIFIC COMMANDS
//
#define SCSI_READ10 0x28
#define SCSI_READ_CAPACITY 0x25
//
// OPTIONAL DEVICE SPECIFIC COMMANDS
//
#define SCSI_MODE_SELECT6 0x15
#define SCSI_MODE_SENSE6 0x1A
#define SCSI_START_STOP 0x1B
#define SCSI_WRITE10 0x2A
#define SCSI_MODE_SELECT10 0x55
#define SCSI_MODE_SENSE10 0x5A
//
// (ATAPI) CD-ROM Commamds
//
#define SCSI_CD_READ_TOC 0x43
#define SCSI_CD_PLAY10 0x45
#define SCSI_CD_PLAY_MSF 0x47
#define SCSI_CD_PAUSE_RESUME 0x4B
#define SCSI_CD_STOP 0x4E
//
// Mode Pages
//
#define MODE_PAGE_FLEXIBLE_DISK 0x05
#define MODE_PAGE_CDROM 0x0D
#define MODE_PAGE_CDROM_AUDIO 0x0E
#define MODE_PAGE_CDROM_CAPS 0x2A
//
// SCSI-2 SENSE KEYS
//
#define SENSE_NONE 0x00
#define SENSE_RECOVERED_ERROR 0x01
#define SENSE_NOT_READY 0x02
#define SENSE_MEDIUM_ERROR 0x03
#define SENSE_HARDWARE_ERROR 0x04
#define SENSE_ILLEGAL_REQUEST 0x05
#define SENSE_UNIT_ATTENTION 0x06
#define SENSE_DATA_PROTECT 0x07
#define SENSE_BLANK_CHECK 0x08
//...
//
// SCSI-2 ASC (of interest)
//
#define ASC_LUN 0x04
#define ASC_INVALID_COMMAND_FIELD 0x24
#define ASC_MEDIA_CHANGED 0x28
#define ASC_RESET 0x29
#define ASC_COMMANDS_CLEARED 0x2F
#define ASC_MEDIUM_NOT_PRESENT 0x3A
//
// Max LUN index
//
#define MAX_LUN 0x7
#define SCSI_CDB_6 6
#define SCSI_CDB_10 10
#define UFI_CDB 12
#define ATAPI_CDB 12
#define MAX_CDB UFI_CDB
#define START TRUE
#define STOP FALSE
#define FAILURE (-1)
//
// SCSI Passthrough IOCTLs
//
#define IOCTL_SCSI_BASE FILE_DEVICE_MASS_STORAGE
#define IOCTL_SCSI_PASSTHROUGH \
CTL_CODE(IOCTL_SCSI_BASE, 0x700, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_CDROM_PLAY_AUDIO \
CTL_CODE(IOCTL_SCSI_BASE, 0x701, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_CDROM_PLAY_AUDIO_TRACK_INDEX \
CTL_CODE(IOCTL_SCSI_BASE, 0x702, METHOD_BUFFERED, FILE_ANY_ACCESS)
//*****************************************************************************
// T Y P E D E F S
//*****************************************************************************
//
// Reg configurable Timeout/repeat values
//
typedef struct _TIMEOUTS {
ULONG MediaPollInterval;
ULONG ReadSector;
ULONG WriteSector;
ULONG ScsiCommandTimeout;
ULONG UnitAttnRepeat;
} TIMEOUTS, *PTIMEOUTS;
//
// Device Flags
//
typedef struct _DEVICE_FLAGS {
//
// Removal Media Bit (RMB)
//
ULONG RMB : 1;
//
// MediumPresent
//
ULONG MediumPresent : 1;
//
// Is the FSD Mounted?
//
ULONG FSDMounted : 1;
//
// WriteProtect
//
ULONG WriteProtect : 1;
//
// Is the device currently open/closed
// Set via DSK_Xxx
//
ULONG Open : 1;
//
// The device has been flagged for removed.
// This flag should only be set by the
// UsbDiskAttach, or UsbDiskDetach routines
//
ULONG DeviceRemoved : 1;
// The device has been flagged for Power Down.
// This flag should only be set by DSK_PowerDown
//
ULONG PoweredDown : 1;
//
// Currently used to signal CD-ROM is busy
//
ULONG Busy : 1;
//
// MediumChanged
//
ULONG MediumChanged:1;
//
// preMediumStatus;
//
ULONG prevMediumStatus:1;
// Reserved
// ...
} DEVICE_FLAGS, *PDEVICE_FLAGS;
typedef struct _SCSI_DEVICE {
//
// device context Signature
//
ULONG Sig;
//
// bInterfaceSubClass as reported in the device descriptor;
// received in UsbDiskAttach.
//
UCHAR DiskSubClass;
//
// HKEY as enumerated by USB Mass Storage Class; received in UsbDiskAttach.
// Used as Active registry path.
//
LPWSTR ActivePath;
//
// Handle to the USB Mass Storage Class Transport;
// received in UsbDiskAttach
//
HANDLE hUsbTransport;
//
// global sync object for this instance
//
CRITICAL_SECTION Lock;
//
// Handle to Media Polling Thread
//
HANDLE hMediaPollThread;
//
// Handle to Media Changed Event
//
HANDLE hMediaChangedEvent;
//
// Handle to Stream interface.
//
HANDLE hStreamDevice;
//
// Our process handle
//
HANDLE hProc;
//
// Device Type
//
UCHAR DeviceType;
//
// Logical Unit Number
//
UCHAR Lun;
UCHAR MaxLun;
//
// Medium Type
//
UCHAR MediumType;
//
// FLAGS
//
DEVICE_FLAGS Flags;
//
// DSK_Open reference count
//
LONG OpenCount;
//
// Timeout values
//
TIMEOUTS Timeouts;
//
// Disk Information
//
DISK_INFO DiskInfo;
//
// Device Remove Lock
//
REMOVE_LOCK RemoveLock;
//
// To support odd Scatter Gather buffer combinations (DDTK)
// we need to use double buffering. We R/W to/from our own S/G buffer then
// copy to/from the callers buffer. Our S/G Buffer needs to accommodate at
// least 8 full FAT sectors, or 3 UDFS sectors.
// TODO: alloc buffer based on disk type.
// A double buffering scheme is required, else don't support all the odd
// sized combinations. However, you will still need at least 1 full sector
// buffer handy for transfers < sector because the disks only take full sector
// sized transfers. Sector aligned transfers do not use double buffering.
//
UCHAR SgBuff[SG_BUFF_SIZE];
} SCSI_DEVICE, *PSCSI_DEVICE;
//*****************************************************************************
// P R O T O S
//*****************************************************************************
//
// scsi2.c
//
DWORD
ScsiGetSenseData(
PSCSI_DEVICE pDevice,
UCHAR Lun
);
DWORD
ScsiInquiry(
PSCSI_DEVICE pDevice,
UCHAR Lun
);
DWORD
ScsiModeSense10(
PSCSI_DEVICE pDevice,
UCHAR Lun
);
DWORD
ScsiPassthrough(
PSCSI_DEVICE pDevice,
PTRANSPORT_COMMAND Command,
PTRANSPORT_DATA Data
);
DWORD
ScsiReadCapacity(
PSCSI_DEVICE pDevice,
PDISK_INFO pDiskInfo,
UCHAR Lun
);
DWORD
ScsiReadWrite(
IN PSCSI_DEVICE pDevice,
IN DWORD dwStartSector,
IN DWORD dwNumSectors,
IN OUT PVOID pvBuffer, // pointer to transfer buffer
IN OUT PDWORD pdwTransferSize, // IN: sizeof input buffer, OUT: number of bytes transferred
IN UCHAR Lun,
IN BOOL bRead
);
DWORD
ScsiRWSG(
PSCSI_DEVICE pDevice,
PSG_REQ pSgReq,
UCHAR Lun,
BOOL bRead
);
DWORD
ScsiRequestSense(
PSCSI_DEVICE pDevice,
PTRANSPORT_DATA pTData,
UCHAR Lun
);
DWORD
ScsiSendDiagnostic(
PSCSI_DEVICE pDevice,
UCHAR Lun
);
DWORD
ScsiStartStopUnit(
PSCSI_DEVICE pDevice,
BOOL Start,
BOOL LoEj,
UCHAR Lun
);
DWORD
ScsiTestUnitReady(
PSCSI_DEVICE pDevice,
UCHAR Lun
);
DWORD
ScsiUnitAttention(
PSCSI_DEVICE pDevice,
UCHAR Lun
);
//
// cd.c
//
DWORD
ScsiCDRead(
PSCSI_DEVICE pDevice,
PCDROM_READ pSgReq,
PULONG pdwBytesTransferred
);
DWORD
ScsiCDAudio(
PSCSI_DEVICE pDevice,
DWORD Ioctl,
PUCHAR pInBuf,
DWORD InBufLen,
PUCHAR pOutBuf,
DWORD OutBufLen,
PDWORD pdwBytesTransferred
);
//*****************************************************************************
// D E B U G
//*****************************************************************************
#if DEBUG
#define ZONE_ERR DEBUGZONE(0)
#define ZONE_WARN DEBUGZONE(1)
#define ZONE_INIT DEBUGZONE(2)
#define ZONE_TRACE DEBUGZONE(3)
#define ZONE_SCSI DEBUGZONE(4)
#define ZONE_CDROM DEBUGZONE(5)
#define ZONE_CDDA DEBUGZONE(6)
#define ZONE_DSK_IOCTL DEBUGZONE(7)
#define ZONE_READ DEBUGZONE(8)
#define ZONE_WRITE DEBUGZONE(9)
#define ZONE_THREAD DEBUGZONE(10)
#define ZONE_EVENTS DEBUGZONE(11)
//...
//
// these should be removed in the code if you can 'g' past these successfully
//
#define TEST_TRAP() { \
NKDbgPrintfW( TEXT("%s: Code Coverage Trap in: %s, Line: %d\n"), DRIVER_NAME_SZ, TEXT(__FILE__), __LINE__); \
DebugBreak(); \
}
#define DUMP_DISK_INFO( pDI ) { \
if (pDI) { \
DEBUGMSG( ZONE_DSK_IOCTL, (TEXT("DISK_INFO:\n"))); \
DEBUGMSG( ZONE_DSK_IOCTL, (TEXT("---------------------\n"))); \
DEBUGMSG( ZONE_DSK_IOCTL, (TEXT("di_total_sectors: %u\n"), pDI->di_total_sectors )); \
DEBUGMSG( ZONE_DSK_IOCTL, (TEXT("di_bytes_per_sect: %u\n"), pDI->di_bytes_per_sect )); \
DEBUGMSG( ZONE_DSK_IOCTL, (TEXT("di_cylinders: %u\n"), pDI->di_cylinders )); \
DEBUGMSG( ZONE_DSK_IOCTL, (TEXT("di_heads: %u\n"), pDI->di_heads )); \
DEBUGMSG( ZONE_DSK_IOCTL, (TEXT("di_sectors: %u\n"), pDI->di_sectors )); \
DEBUGMSG( ZONE_DSK_IOCTL, (TEXT("di_flags: 0x%x\n"), pDI->di_flags )); \
DEBUGMSG( ZONE_DSK_IOCTL, (TEXT("\n"))); \
} \
}
#else
#define TEST_TRAP()
#define DUMP_DISK_INFO( pDI )
#endif // DEBUG
#endif // _SCSI2_
// EOF
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -