📄 scsi2.c
字号:
tCommand.CommandBlock = bCDB;
memset( bCDB, 0, sizeof(bCDB));
bCDB[0] = SCSI_INQUIRY;
ASSERT(Lun <= 0x7);
bCDB[1] = ((Lun & 0x7) << 5);
// EVPB is tbd
// PageCode = 0
bCDB[4] = sizeof(bDataBlock); // Allocation Length
memset( bDataBlock, 0, sizeof(bDataBlock));
tData.TransferLength = 0;
tData.RequestLength = sizeof(bDataBlock);
tData.DataBlock = bDataBlock;
dwErr = UsbsDataTransfer(pDevice->hUsbTransport,
&tCommand,
&tData );
if (dwErr != ERROR_SUCCESS || (tData.TransferLength != tData.RequestLength))
{
dwErr = ScsiGetSenseData( pDevice, Lun );
DEBUGMSG(ZONE_ERR,(TEXT("ScsiInquiry ERROR:%d\n"), dwErr));
SetLastError(dwErr);
} else {
CHAR asBuff[17] = {0};
UCHAR perq; // peripherial qualifier
#define PERQ_LUN_CONNECTED 0x0
#define PERQ_LUN_DISCONNECTED 0x1
#define PERQ_LUN_INVALID 0x3
DEBUGMSG(ZONE_SCSI,(TEXT("InquiryData@Lun:%d = 0x%x\n"),
Lun, bDataBlock[0]));
if (bDataBlock[0] == 0x7F) {
dwErr = ERROR_INVALID_PARAMETER;
TEST_TRAP();
} else {
EnterCriticalSection(&pDevice->Lock);
pDevice->DeviceType = bDataBlock[0] & SCSI_DEVICE_UNKNOWN;
perq = (bDataBlock[0] & 0xE0) >> 5;
ASSERT(PERQ_LUN_INVALID != perq);
// currently developing Direct Access & CD-ROM devices only
ASSERT(SCSI_DEVICE_DIRECT_ACCESS == pDevice->DeviceType ||
SCSI_DEVICE_CDROM == pDevice->DeviceType);
pDevice->Flags.RMB = (bDataBlock[1] & 0x80) >> 7;
// ASSERT(bDataBlock[3] & 0x01); // Response Data Format
#ifdef DEBUG
usString.Buffer = wcBuff;
usString.MaximumLength = sizeof(wcBuff);
//
// VID
//
memcpy(asBuff, &bDataBlock[8], 8); asBuff[8] = 0;
RtlInitAnsiString( &asString, asBuff);
dwStatus = RtlAnsiStringToUnicodeString(&usString, &asString, FALSE);
if (STATUS_SUCCESS != dwStatus) { // NT status code
DEBUGMSG(ZONE_ERR, (TEXT("RtlAnsiStringToUnicodeString error:0x%x\n"),
dwStatus));
TEST_TRAP();
} else {
DEBUGMSG(ZONE_SCSI, (TEXT("VID: %s\n"), usString.Buffer ));
}
//
// PID
//
memcpy(asBuff, &bDataBlock[16], 16); asBuff[16] = 0;
RtlInitAnsiString( &asString, asBuff );
dwStatus = RtlAnsiStringToUnicodeString( &usString, &asString, FALSE );
if (STATUS_SUCCESS != dwStatus) { // NT status code
DEBUGMSG(ZONE_ERR, (TEXT("RtlAnsiStringToUnicodeString error:0x%x\n"),
dwStatus));
TEST_TRAP();
} else {
DEBUGMSG(ZONE_SCSI, (TEXT("PID: %s\n"), usString.Buffer ));
}
//
// PRL
//
memcpy(asBuff, &bDataBlock[32], 4); asBuff[4] = 0;
RtlInitAnsiString( &asString, asBuff );
dwStatus = RtlAnsiStringToUnicodeString(&usString, &asString, FALSE);
if (STATUS_SUCCESS != dwStatus) { // NT status code
DEBUGMSG(ZONE_ERR, (TEXT("RtlAnsiStringToUnicodeString error:0x%x\n"),
dwStatus));
TEST_TRAP();
} else {
DEBUGMSG(ZONE_SCSI, (TEXT("PRL: %s\n"), usString.Buffer ));
}
#endif DEBUG
LeaveCriticalSection(&pDevice->Lock);
}
}
ReleaseRemoveLock(&pDevice->RemoveLock, NULL);
DEBUGMSG(ZONE_SCSI,(TEXT("USBDISK6<ScsiInquiry:%d\n"), dwErr));
return dwErr;
}
DWORD
ScsiSendDiagnostic(
PSCSI_DEVICE pDevice,
UCHAR Lun
)
{
TRANSPORT_COMMAND tCommand;
UCHAR bCDB[MAX_CDB];
DWORD dwErr;
DEBUGMSG(ZONE_SCSI,(TEXT("USBDISK6>ScsiSendDiagnostic\n")));
dwErr = AcquireRemoveLock(&pDevice->RemoveLock, NULL) ;
if ( ERROR_SUCCESS != dwErr) {
return dwErr;
}
tCommand.Flags = DATA_IN;
tCommand.Timeout = pDevice->Timeouts.ScsiCommandTimeout;
tCommand.Length = USBMSC_SUBCLASS_SCSI == pDevice->DiskSubClass ?
SCSI_CDB_6 : UFI_CDB;
tCommand.CommandBlock = bCDB;
memset( bCDB, 0, sizeof(bCDB));
bCDB[0] = SCSI_SEND_DIAGNOSTIC;
ASSERT(Lun <= 0x7);
bCDB[1] = ((Lun & 0x7) << 5);
bCDB[1] |= 0x4; // SelfTest
dwErr = UsbsDataTransfer(pDevice->hUsbTransport,
&tCommand,
NULL );
if ( dwErr != ERROR_SUCCESS ) {
dwErr = ScsiGetSenseData( pDevice, Lun );
DEBUGMSG(ZONE_ERR,(TEXT("ScsiSendDiagnostic ERROR:%d\n"), dwErr));
SetLastError(dwErr);
}
ReleaseRemoveLock(&pDevice->RemoveLock, NULL);
DEBUGMSG(ZONE_SCSI,(TEXT("USBDISK6<ScsiSendDiagnostic:%d\n"), dwErr));
return dwErr;
}
// returns Win32 error
DWORD
ScsiReadCapacity(
PSCSI_DEVICE pDevice,
PDISK_INFO pDiskInfo,
UCHAR Lun
)
{
TRANSPORT_COMMAND tCommand;
UCHAR bCDB[MAX_CDB];
TRANSPORT_DATA tData;
UCHAR bDataBlock[8];
DWORD dwSizeDB = sizeof(bDataBlock);
DWORD dwSizeDI = sizeof(DISK_INFO);
DWORD dwErr = ERROR_SUCCESS;
DEBUGMSG(ZONE_SCSI,(TEXT("USBDISK6>ScsiReadCapacity\n")));
dwErr = AcquireRemoveLock(&pDevice->RemoveLock, NULL) ;
if ( ERROR_SUCCESS != dwErr) {
return dwErr;
}
memset(pDiskInfo, 0, dwSizeDI);
tCommand.Flags = DATA_IN;
tCommand.Timeout = pDevice->Timeouts.ScsiCommandTimeout;
tCommand.Length = USBMSC_SUBCLASS_SCSI == pDevice->DiskSubClass ?
SCSI_CDB_10 : UFI_CDB;
tCommand.CommandBlock = bCDB;
memset( bCDB, 0, sizeof(bCDB));
bCDB[0] = SCSI_READ_CAPACITY;
ASSERT(Lun <= 0x7);
bCDB[1] = ((Lun & 0x7) << 5);
// PMI & LBA support is TBD
// It's useful in determining where longer access times occur
memset( bDataBlock, 0, dwSizeDB);
tData.TransferLength = 0;
tData.RequestLength = dwSizeDB;
tData.DataBlock = bDataBlock;
dwErr = UsbsDataTransfer(pDevice->hUsbTransport,
&tCommand,
&tData );
if ( dwErr != ERROR_SUCCESS ||
(tData.TransferLength != tData.RequestLength) ) {
dwErr = ScsiGetSenseData( pDevice, Lun );
DEBUGMSG(ZONE_ERR,(TEXT("ScsiReadCapacity ERROR:%d\n"), dwErr));
SetLastError(dwErr);
} else {
EnterCriticalSection(&pDevice->Lock);
// Get total sectors from Last Logical Block Address
pDiskInfo->di_total_sectors = GetDWORD(&bDataBlock[0])+1;
// Block Length in bytes
pDiskInfo->di_bytes_per_sect = GetDWORD(&bDataBlock[4]);
pDiskInfo->di_flags |= DISK_INFO_FLAG_PAGEABLE | DISK_INFO_FLAG_CHS_UNCERTAIN;
if ( pDiskInfo->di_bytes_per_sect && pDiskInfo->di_total_sectors) {
//
// update our media info & flags
//
pDevice->Flags.MediumPresent = TRUE;
if ( 0 != memcmp(&pDevice->DiskInfo, pDiskInfo, dwSizeDI) ) {
memcpy(&pDevice->DiskInfo, pDiskInfo, dwSizeDI);
}
}
LeaveCriticalSection(&pDevice->Lock);
DUMP_DISK_INFO(pDiskInfo);
}
ReleaseRemoveLock(&pDevice->RemoveLock, NULL);
DEBUGMSG(ZONE_SCSI,(TEXT("USBDISK6<ScsiReadCapacity:%d\n"), dwErr));
return dwErr;
}
//
// Mode sense is dependant on Device Type.
// returns Win32 error.
//
DWORD
ScsiModeSense10(
PSCSI_DEVICE pDevice,
UCHAR Lun
)
{
TRANSPORT_DATA tData;
TRANSPORT_COMMAND tCommand;
UCHAR bCDB[MAX_CDB];
#define MAX_LIST_LENGTH 512
UCHAR bDataBlock[MAX_LIST_LENGTH] = {0}; // Standard Header + mode pages
USHORT usPageLength = 8; // Standard Header size
DWORD dwErr = ERROR_SUCCESS;
DEBUGMSG(ZONE_SCSI,(TEXT("USBDISK6>ScsiModeSense\n")));
dwErr = AcquireRemoveLock(&pDevice->RemoveLock, NULL) ;
if ( ERROR_SUCCESS != dwErr) {
return dwErr;
}
ASSERT( SCSI_DEVICE_DIRECT_ACCESS == pDevice->DeviceType ||
SCSI_DEVICE_CDROM == pDevice->DeviceType );
memset( bCDB, 0, sizeof(bCDB));
tCommand.Flags = DATA_IN;
tCommand.Timeout = pDevice->Timeouts.ScsiCommandTimeout;
tCommand.Length = USBMSC_SUBCLASS_SCSI == pDevice->DiskSubClass ?
SCSI_CDB_10 : UFI_CDB;
tCommand.CommandBlock = bCDB;
bCDB[0] = SCSI_MODE_SENSE10;
ASSERT(Lun <= 0x7);
bCDB[1] = ((Lun & 0x7) << 5);
bCDB[1] |= 0x8; // DBD
// PC = current
// Page Code
bCDB[2] = 0;
switch (pDevice->DeviceType)
{
case SCSI_DEVICE_DIRECT_ACCESS:
if (pDevice->DiskSubClass == USBMSC_SUBCLASS_UFI) {
bCDB[2] = MODE_PAGE_FLEXIBLE_DISK;
usPageLength += 32;
} else {
usPageLength = sizeof(bDataBlock);
}
break;
case SCSI_DEVICE_CDROM:
bCDB[2] = MODE_PAGE_CDROM;
usPageLength += 8;
break;
default:
DEBUGMSG(ZONE_ERR,(TEXT("ScsiModeSense10: Unknown DeviceType:0x%x\n"),
pDevice->DeviceType));
TEST_TRAP();
usPageLength = sizeof(bDataBlock);
break;
}
bCDB[7] = (sizeof(bDataBlock) & 0xFF00) >> 8; // MSB
bCDB[8] = sizeof(bDataBlock) & 0x00FF; // LSB
memset( bDataBlock, 0, sizeof(bDataBlock));
ASSERT( usPageLength <= sizeof(bDataBlock));
tData.TransferLength = 0;
// Note: some devices fail with only 8 byte header request length,
// but all should recover with extra buffer space.
tData.RequestLength = usPageLength;
tData.DataBlock = bDataBlock;
dwErr = UsbsDataTransfer( pDevice->hUsbTransport,
&tCommand,
&tData );
if ( dwErr != ERROR_SUCCESS || tData.TransferLength < 8 ) { // want at least the header
dwErr = ScsiGetSenseData( pDevice, Lun );
SetLastError(dwErr);
DEBUGMSG(ZONE_ERR,(TEXT("ScsiModeSense ERROR:%d\n"), dwErr));
} else {
EnterCriticalSection(&pDevice->Lock);
// look at the Header
DEBUGMSG(ZONE_SCSI,(TEXT("Medium Type:0x%x\n"), bDataBlock[2]));
pDevice->MediumType = bDataBlock[2];
// bit7 is WP bit
DEBUGMSG(ZONE_SCSI,(TEXT("Device Specific:0x%x\n"), bDataBlock[3] ));
pDevice->Flags.WriteProtect = bDataBlock[3] & 0x80;
LeaveCriticalSection(&pDevice->Lock);
//
// TBD: look at the the requested page ...
//
}
ReleaseRemoveLock(&pDevice->RemoveLock, NULL);
DEBUGMSG(ZONE_SCSI,(TEXT("USBDISK6<ScsiModeSense:%d\n"), dwErr));
return dwErr;
}
DWORD
ScsiStartStopUnit(
PSCSI_DEVICE pDevice,
BOOL Start, // TRUE = START, else STOP
BOOL LoEj,
UCHAR Lun
)
{
TRANSPORT_COMMAND tCommand;
UCHAR bCDB[MAX_CDB];
DWORD dwErr;
DEBUGMSG(ZONE_SCSI,(TEXT("USBDISK6>ScsiStartStopUnit\n")));
dwErr = AcquireRemoveLock(&pDevice->RemoveLock, NULL);
if ( ERROR_SUCCESS != dwErr) {
return dwErr;
}
tCommand.Flags = DATA_OUT;
tCommand.Timeout = pDevice->Timeouts.ScsiCommandTimeout;
tCommand.Length = USBMSC_SUBCLASS_SCSI == pDevice->DiskSubClass ?
SCSI_CDB_6 : UFI_CDB;
tCommand.CommandBlock = bCDB;
memset( bCDB, 0, sizeof(bCDB));
bCDB[0] = SCSI_START_STOP;
ASSERT(Lun <= 0x7);
bCDB[1] = ((Lun & 0x7) << 5);
bCDB[4] = (LoEj & 0x1) << 1;
bCDB[4] |= Start & 0x1;
dwErr = UsbsDataTransfer(pDevice->hUsbTransport,
&tCommand,
NULL );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -