📄 scsi2.c
字号:
UCHAR bCDB[MAX_CDB] = {0};
#define MAX_LIST_LENGTH 512
UCHAR bDataBlock[MAX_LIST_LENGTH] = {0};
USHORT usPageLength = 0;
DWORD dwErr = ERROR_SUCCESS;
DEBUGMSG(ZONE_SCSI,(TEXT("USBDISK6!ScsiModeSense10: Enter\r\n")));
dwErr = AcquireRemoveLock(&pDevice->RemoveLock, NULL);
if (ERROR_SUCCESS != dwErr) {
return dwErr;
}
ASSERT(SCSI_DEVICE_DIRECT_ACCESS == pDevice->DeviceType || SCSI_DEVICE_CDROM == pDevice->DeviceType);
ASSERT(Lun <= 0x7);
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;
bCDB[0] = SCSI_MODE_SENSE10;
bCDB[1] = ((Lun & 0x7) << 5);
// Set disable block descriptors (DBD) bit to 1.
//bCDB[1] |= 0x8;
// Set page control (PC) and page code to 0; i.e., return current, vendor-
// specific values.
bCDB[2] = 0;
bCDB[7] = 0;
bCDB[8] = 8;
usPageLength = 8;
/*
switch (pDevice->DeviceType) {
case SCSI_DEVICE_DIRECT_ACCESS:
if (pDevice->DiskSubClass == USBMSC_SUBCLASS_UFI || pDevice->DiskSubClass == USBMSC_SUBCLASS_SFF8070i) {
bCDB[2] = MODE_PAGE_FLEXIBLE_DISK;
}
break;
case SCSI_DEVICE_CDROM:
bCDB[2] = MODE_PAGE_CDROM;
break;
default:
DEBUGMSG(ZONE_ERR, (TEXT("USBDISK6!ScsiModeSense10: Unknown device type (0x%x)\r\n"), pDevice->DeviceType));
break;
}
*/
memset(bDataBlock, 0, sizeof(bDataBlock));
ASSERT(usPageLength <= sizeof(bDataBlock));
tData.TransferLength = 0;
tData.RequestLength = usPageLength;
tData.DataBlock = bDataBlock;
dwErr = UsbsDataTransfer(pDevice->hUsbTransport, &tCommand, &tData);
if ((ERROR_SUCCESS != dwErr) || (tData.TransferLength < 4)) {
dwErr = ScsiGetSenseData(pDevice, Lun);
SetLastError(dwErr);
DEBUGMSG(ZONE_ERR,(TEXT("USBDISK6!ScsiModeSense10: Failed to issue MODE SENSE (10) (%d) \r\n"), dwErr));
}
else {
EnterCriticalSection(&pDevice->Lock);
DEBUGMSG(ZONE_SCSI, (TEXT("USBDISK6!ScsiModeSense10: Device reported medium type of 0x%x\r\n"), bDataBlock[2]));
pDevice->MediumType = bDataBlock[2];
DEBUGMSG(ZONE_SCSI, (TEXT("USBDISK6!ScsiModeSense10: %s \r\n"), (bDataBlock[3] & 0x80) ? TEXT("Write-protected") : TEXT("Not write-protected")));
pDevice->Flags.WriteProtect = bDataBlock[3] & 0x80;
LeaveCriticalSection(&pDevice->Lock);
}
ReleaseRemoveLock(&pDevice->RemoveLock, NULL);
DEBUGMSG(ZONE_SCSI,(TEXT("USBDISK6!ScsiModeSense10: Exit (%d)\r\n"), dwErr));
return dwErr;
}
DWORD
ScsiModeSense6(
PSCSI_DEVICE pDevice,
UCHAR Lun
)
{
TRANSPORT_DATA tData;
TRANSPORT_COMMAND tCommand;
UCHAR bCDB[SCSI_CDB_6];
UCHAR bDataBlock[MAX_LIST_LENGTH] = {0};
USHORT usPageLength = 0;
DWORD dwErr = ERROR_SUCCESS;
DEBUGMSG(ZONE_SCSI,(TEXT("USBDISK6!ScsiModeSense6: Enter\r\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_6 : UFI_CDB;
tCommand.CommandBlock = bCDB;
tCommand.dwLun = Lun;
DEBUGCHK(Lun <= 0x7);
bCDB[0] = SCSI_MODE_SENSE6;
bCDB[1] = ((Lun & 0x7) << 5);
bCDB[2] = 0;
usPageLength = 4;
/*
switch (pDevice->DeviceType) {
case SCSI_DEVICE_DIRECT_ACCESS:
if (pDevice->DiskSubClass == USBMSC_SUBCLASS_UFI || pDevice->DiskSubClass == USBMSC_SUBCLASS_SFF8070i) {
bCDB[2] = MODE_PAGE_FLEXIBLE_DISK;
}
break;
case SCSI_DEVICE_CDROM:
bCDB[2] = MODE_PAGE_CDROM;
break;
}
*/
DEBUGCHK(usPageLength <= sizeof(bDataBlock));
memset(bDataBlock, 0, sizeof(bDataBlock));
tData.TransferLength = 0;
tData.RequestLength = usPageLength;
tData.DataBlock = bDataBlock;
dwErr = UsbsDataTransfer(pDevice->hUsbTransport, &tCommand, &tData);
if ((ERROR_SUCCESS != dwErr) || (tData.TransferLength < 4)) {
dwErr = ScsiGetSenseData(pDevice, Lun);
SetLastError(dwErr);
DEBUGMSG(ZONE_ERR,(TEXT("USBDISK6!ScsiModeSense6: Failed to issue MODE SENSE (6) (%d) \r\n"), dwErr));
}
else {
EnterCriticalSection(&pDevice->Lock);
DEBUGMSG(ZONE_SCSI, (TEXT("USBDISK6!ScsiModeSense6: Device reported medium type of 0x%x\r\n"), bDataBlock[2]));
pDevice->MediumType = bDataBlock[2];
DEBUGMSG(ZONE_SCSI, (TEXT("USBDISK6!ScsiModeSense6: %s \r\n"), (bDataBlock[3] & 0x80) ? TEXT("Write-protected") : TEXT("Not write-protected")));
pDevice->Flags.WriteProtect = bDataBlock[3] & 0x80;
LeaveCriticalSection(&pDevice->Lock);
}
ReleaseRemoveLock(&pDevice->RemoveLock, NULL);
DEBUGMSG(ZONE_SCSI,(TEXT("USBDISK6!ScsiModeSense6: Exit (%d)\r\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;
tCommand.dwLun=Lun;
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 );
if ( dwErr != ERROR_SUCCESS ) {
dwErr = ScsiGetSenseData( pDevice, Lun );
DEBUGMSG(ZONE_ERR,(TEXT("ScsiStartStopUnit ERROR:%d\n"), dwErr));
SetLastError(dwErr);
}
ReleaseRemoveLock(&pDevice->RemoveLock, NULL);
DEBUGMSG(ZONE_SCSI,(TEXT("USBDISK6<ScsiStartStopUnit:%d\n"), dwErr));
return dwErr;
}
//
// Checks the users SG to see if we can use it.
// Since we basically do a prescan then return flag saying
// if we need to use double buffering.
//
DWORD
CheckSegments(
IN PSCSI_DEVICE pDevice,
IN PSG_REQ pSgReq,
IN OUT PDWORD pTransferLength,
IN OUT PDWORD pFlags
)
{
DWORD dwErr = ERROR_SUCCESS;
DWORD sg;
DEBUGMSG(ZONE_TRACE,(TEXT("USBMSC>CheckSegments\n")));
if ( !pDevice || 0 == pDevice->DiskInfo.di_bytes_per_sect ||
0 == pDevice->DiskInfo.di_total_sectors )
{
dwErr = ERROR_FLOPPY_UNKNOWN_ERROR;
DEBUGMSG(ZONE_ERR,(TEXT("CheckSegments ERROR:1: di_bytes_per_sect:%d di_total_sectors:%d\n"),
pDevice?pDevice->DiskInfo.di_bytes_per_sect:-1, pDevice?pDevice->DiskInfo.di_total_sectors:-1));
TEST_TRAP();
} else if ( !pSgReq || !pTransferLength || !pFlags) {
dwErr=ERROR_INVALID_PARAMETER;
DEBUGMSG(ZONE_ERR,(TEXT("CheckSegments ERROR:2: %d\n"), dwErr ));
} else if (pSgReq->sr_num_sg > MAX_SG_BUF ||
pSgReq->sr_start + pSgReq->sr_num_sec > pDevice->DiskInfo.di_total_sectors)
{
dwErr=ERROR_INVALID_PARAMETER;
DEBUGMSG(ZONE_ERR,(TEXT("CheckSegments ERROR:3: sg:%d sr_start:%d, sr_num_sec:%d, di_total_sectors:%d di_bytes_per_sect:%d\n"),
pSgReq->sr_num_sg, pSgReq->sr_start, pSgReq->sr_num_sec, pDevice->DiskInfo.di_total_sectors, pDevice->DiskInfo.di_bytes_per_sect));
} else {
//
// ensure all the buffers in the SG list are OK
//
ASSERT(pFlags);
ASSERT(pTransferLength);
EnterCriticalSection(&pDevice->Lock);
for (sg = 0, *pTransferLength = 0, *pFlags = 0; sg < pSgReq->sr_num_sg; sg++)
{
if ( !pSgReq->sr_sglist[sg].sb_buf )
{
dwErr = ERROR_INVALID_PARAMETER;
DEBUGMSG(ZONE_ERR,(TEXT("CheckSegments ERROR:4:%d\n"), dwErr));
break;
}
// do we need double buffering?
if ((pSgReq->sr_sglist[sg].sb_len % pDevice->DiskInfo.di_bytes_per_sect) != 0)
{
*pFlags |= 0x1;
DEBUGMSG(ZONE_READ,(TEXT("CheckSegments: Double Buffered\n")));
}
// sum all the buffer lengths to make sure they match
// the requested number of sectors
*pTransferLength += pSgReq->sr_sglist[sg].sb_len;
}
if (dwErr == ERROR_SUCCESS &&
*pTransferLength > (pSgReq->sr_num_sec * pDevice->DiskInfo.di_bytes_per_sect))
{
dwErr = ERROR_INVALID_PARAMETER;
DEBUGMSG(ZONE_ERR,(TEXT("CheckSegments ERROR:5: invalid user SG buffers (%u > %u)\n"),
*pTransferLength, (pSgReq->sr_num_sg * pDevice->DiskInfo.di_bytes_per_sect)));
}
LeaveCriticalSection(&pDevice->Lock);
}
DEBUGMSG(ZONE_TRACE,(TEXT("USBMSC<CheckSegments:%d\n"), dwErr));
return dwErr;
}
/*++
Validate a Scatter/Gather request object.
Returns: If fail, Win32 error.
If pass, ERROR_SUCCESS.
--*/
static DWORD
InspectSgReq(
PSG_REQ pSgReq,
UINT uiBytesPerSector
)
{
UINT uiSgIndex; // Index into Scatter/Gather buffer array.
UINT uiBytesToTransfer; // Running count of the number of bytes requested to transfer.
DEBUGMSG(ZONE_SCSI, (TEXT("USBMSC>InspectSgReq\n")));
if (pSgReq == NULL) {
DEBUGMSG(ZONE_ERR, (TEXT("USBMSC>InspectSgReq: Error: pSqReq: NULL\n")));
return ERROR_BAD_ARGUMENTS;
}
if (pSgReq->sr_num_sec == 0) {
DEBUGMSG(ZONE_ERR, (TEXT("USBMSC>InspectSgReq: Error: ->sr_num_sec: 0\n")));
return ERROR_BAD_ARGUMENTS;
}
if (pSgReq->sr_num_sg == 0) {
DEBUGMSG(ZONE_ERR, (TEXT("USBMSC>InspectSgReq: Error: ->sr_num_sg: 0\n")));
return ERROR_BAD_ARGUMENTS;
}
DEBUGMSG(ZONE_SCSI, (TEXT("USBMSC>InspectSgReq: ->sr_num_sec: %d, ->sr_num_sg: %d, bytes/sec: %d\n"), pSgReq->sr_num_sec, pSgReq->sr_num_sg, uiBytesPerSector));
for (uiSgIndex = 0, uiBytesToTransfer = 0; uiSgIndex < pSgReq->sr_num_sg; uiSgIndex += 1) {
if (pSgReq->sr_sglist[uiSgIndex].sb_buf == NULL) {
DEBUGMSG(ZONE_ERR, (TEXT("USBMSC>InspectSgReq: Error: ->sr_sglist[%d].sb_buf: NULL\n"), uiSgIndex));
return ERROR_BAD_ARGUMENTS;
}
if (pSgReq->sr_sglist[uiSgIndex].sb_len == 0) {
DEBUGMSG(ZONE_ERR, (TEXT("USBMSC>InspectSgReq: Error: ->sr_sglist[%d].sb_len: 0\n"), uiSgIndex));
return ERROR_BAD_ARGUMENTS;
}
DEBUGMSG(ZONE_SCSI, (TEXT("USBMSC>InspectSgReq: ->sr_sglist[%d].sb_len: %d\n"), uiSgIndex, pSgReq->sr_sglist[uiSgIndex].sb_len));
uiBytesToTransfer += pSgReq->sr_sglist[uiSgIndex].sb_len;
}
if (uiBytesPerSector==0 || ((uiBytesToTransfer / uiBytesPerSector) != pSgReq->sr_num_sec)) {
DEBUGMSG(ZONE_ERR, (TEXT("USBMSC>InspectSgReq: Error: [(tot bytes = %d)*(bytes/sec = %d)] != (->sr_num_sec = %d)\n"), uiBytesToTransfer, uiBytesPerSector, pSgReq->sr_num_sec));
return ERROR_BAD_ARGUMENTS;
}
DEBUGMSG(ZONE_SCSI,(TEXT("USBMSC<InspectSgReq\n")));
return ERROR_SUCCESS;
}
/*++
Complete a Scatter/Gather request on a SCSI device.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -