📄 scsi2.c
字号:
memset(&pDevice->DiskInfo, 0, sizeof(DISK_INFO) );
break;
case ASC_RESET :
DEBUGMSG(ZONE_WARN,(TEXT("SENSE_UNIT_ATTENTION : ASC_RESET\n")));
break;
case ASC_COMMANDS_CLEARED :
default:
DEBUGMSG(ZONE_WARN,(TEXT("SENSE_UNIT_ATTENTION : Unhandled ASC:0x%x\n"),
ASC));
break;
}
dwErr = DISK_REMOVED_ERROR;
break;
case SENSE_DATA_PROTECT :
dwErr = ERROR_WRITE_PROTECT;
break;
default:
dwErr = ERROR_FLOPPY_UNKNOWN_ERROR;
break;
}
LeaveCriticalSection(&pDevice->Lock);
} else {
DEBUGMSG(ZONE_ERR,(TEXT("ScsiGetSenseData error:%d\n"), dwErr));
}
ReleaseRemoveLock(&pDevice->RemoveLock, NULL);
DEBUGMSG(ZONE_TRACE,(TEXT("USBDISK6<ScsiGetSenseData:%d\n"), dwErr));
return dwErr;
}
// returns Win32 error
DWORD
ScsiInquiry(
PSCSI_DEVICE pDevice,
UCHAR Lun
)
{
TRANSPORT_COMMAND tCommand;
UCHAR bCDB[MAX_CDB];
TRANSPORT_DATA tData = {0};
UCHAR bDataBlock[36]; // Standard Inquiry Data
#ifdef DEBUG
DWORD dwStatus;
ANSI_STRING asString;
UNICODE_STRING usString = {0, 0, 0};
WCHAR wcBuff[128]; // excessively large for the unexcected
#endif
DWORD dwErr = ERROR_SUCCESS;;
DEBUGMSG(ZONE_SCSI,(TEXT("USBDISK6>ScsiInquiry:Lun:%d\n"), Lun));
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;
tCommand.dwLun=Lun;
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;
tCommand.dwLun=Lun;
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;
tCommand.dwLun=Lun;
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -