📄 disk.c
字号:
LeaveCriticalSection(&pDevice->Lock);
} else {
dwErr = ERROR_ACCESS_DENIED;
DEBUGMSG(ZONE_ERR,(TEXT("DSK_IOControl: ERROR_ACCESS_DENIED\n")));
}
if (ERROR_SUCCESS != dwErr) {
DEBUGMSG( ZONE_ERR,(TEXT("DSK_IOControl error: %d\n"), dwErr));
SetLastError(dwErr);
}
DEBUGMSG(ZONE_DSK_IOCTL,(TEXT("USBDISK6<DSK_IOControl(BytesTransferred:%d, dwErr:%d, bRc:%d)\n"), pdwBytesTransferred?*pdwBytesTransferred:0, dwErr, bRc));
return bRc;
}
// returns # of Luns supported
UCHAR
DiscoverLuns(
IN PSCSI_DEVICE pDevice
)
{
DWORD dwErr, dwRepeat;
UCHAR Lun = 0;
DEBUGMSG(ZONE_INIT,(TEXT("USBDISK6>DiscoverLuns\n")));
// need to wait a bit for some units to init, spin up, etc.
//
dwRepeat = 10;
do {
dwErr = ScsiUnitAttention(pDevice, 0);
if (ERROR_ACCESS_DENIED == dwErr || ERROR_INVALID_HANDLE == dwErr)
break;
else if ( ERROR_SUCCESS != dwErr )
{
Sleep(5);
}
} while (ERROR_NOT_READY == dwErr && --dwRepeat != 0 );
if (ERROR_SUCCESS != dwErr) {
return 0;
}
// Discover Max Luns
//
for (Lun = 0; Lun <= MAX_LUN; Lun++)
{
dwErr = ScsiInquiry(pDevice, Lun);
if (ERROR_SUCCESS != dwErr) {
break;
}
}
DEBUGMSG(ZONE_INIT,(TEXT("USBDISK6<DiscoverLuns:%d\n"), Lun));
return Lun;
}
BOOL
WaitForUnitReady(
IN PSCSI_DEVICE pDevice
)
{
DWORD dwErr, dwRepeat;
DEBUGMSG(ZONE_INIT,(TEXT("USBDISK6>WaitForDeviceReady\n")));
// need to wait a bit for some units to init, spin up, etc.
//
dwRepeat = 10;
do {
dwErr = ScsiUnitAttention(pDevice, pDevice->Lun);
if (ERROR_ACCESS_DENIED == dwErr || ERROR_INVALID_HANDLE == dwErr)
break;
else if ( ERROR_SUCCESS != dwErr )
{
Sleep(5);
}
} while (ERROR_NOT_READY == dwErr && --dwRepeat != 0 );
if (ERROR_SUCCESS != dwErr) {
return 0;
}
DEBUGMSG(ZONE_INIT,(TEXT("USBDISK6<WaitForDeviceReady:dwErr =%d\n"),dwErr));
return (dwErr == ERROR_SUCCESS);
}
DWORD
GetMediumInfo(
IN PSCSI_DEVICE pDevice,
IN UCHAR Lun
)
{
DWORD dwErr = ERROR_SUCCESS;
DEBUGMSG(ZONE_TRACE,(TEXT("Usbdisk6!GetMediumInfo++\r\n")));
EnterCriticalSection(&pDevice->Lock);
do {
if (SCSI_DEVICE_UNKNOWN == pDevice->DeviceType || SCSI_MEDIUM_UNKNOWN == pDevice->MediumType ) {
dwErr = ScsiUnitAttention(pDevice, Lun);
if (ERROR_SUCCESS != dwErr)
break;
}
// determine device type
if (SCSI_DEVICE_UNKNOWN == pDevice->DeviceType) {
dwErr = ScsiInquiry(pDevice, Lun);
if (ERROR_SUCCESS != dwErr)
break;
}
// determine medium type
if (SCSI_DEVICE_UNKNOWN != pDevice->DeviceType && SCSI_MEDIUM_UNKNOWN == pDevice->MediumType ) {
dwErr = ScsiModeSense10(pDevice, Lun);
if (ERROR_SUCCESS != dwErr) {
TRANSPORT_DATA tData;
UCHAR senseData[18];
tData.TransferLength = 0;
tData.RequestLength = sizeof(senseData);
tData.DataBlock = senseData;
memset(senseData,0,sizeof(senseData));
dwErr = ScsiRequestSense(pDevice, &tData, Lun);
if (ERROR_SUCCESS != dwErr) {
break;
}
}
}
// determine disk information
if (!pDevice->Flags.MediumPresent) {
DISK_INFO di = {0};
dwErr = ScsiReadCapacity(pDevice, &di, Lun);
if (ERROR_SUCCESS != dwErr)
break;
}
} while (0);
dwErr = ERROR_SUCCESS;
LeaveCriticalSection(&pDevice->Lock);
DEBUGMSG(ZONE_TRACE,(TEXT("Usbdisk6!GetMediumInfo-- Error(%d)\r\n"), dwErr));
return dwErr;
}
// returns number of bytes written in the pDiskInfo
DWORD
GetDiskInfo(
IN PSCSI_DEVICE pDevice,
IN OUT PDISK_INFO pDiskInfo,
IN UCHAR Lun
)
{
DWORD dwErr;
DWORD dwSize = sizeof(DISK_INFO);
DWORD dwRepeat = 1;
DEBUGMSG(ZONE_TRACE,(TEXT("USBDISK6>GetDiskInfo\n")));
dwErr = ScsiUnitAttention(pDevice, Lun);
if (dwErr == ERROR_GEN_FAILURE) {
return 0;
}
if ( ERROR_SUCCESS == dwErr ) {
dwRepeat = pDevice->Timeouts.UnitAttnRepeat;
do {
dwErr = ScsiReadCapacity(pDevice, pDiskInfo, Lun);
dwRepeat--;
} while (ERROR_SUCCESS != dwErr && dwRepeat != 0 );
}
if ( ERROR_SUCCESS != dwErr ||
0 == pDiskInfo->di_total_sectors ||
0 == pDiskInfo->di_bytes_per_sect )
{
dwSize = 0;
}
DEBUGMSG(ZONE_TRACE,(TEXT("USBDISK6<GetDiskInfo:%d\n"), dwSize));
return dwSize;
}
//*****************************************************************************
// U S B D I S K I N T E R F A C E
//*****************************************************************************
//
// The USB Mass Storage Class driver found a SCSI-2 disk that we support.
// Setup our device context and kick-start our Media Polling Thread.
//
PVOID
UsbDiskAttach(
HANDLE UsbTransport,
LPCWSTR pHardwareKey,
DWORD dwLun,
UCHAR bInterfaceSubClass
)
{
BOOL bRc = TRUE;
DWORD dwErr = ERROR_SUCCESS;
PSCSI_DEVICE pDevice = NULL;
REG_VALUE_DESCR rdTimeouts[] = {
MEDIA_POLL_SZ, REG_DWORD, sizeof(DWORD), (PUCHAR)(NULL),
READ_SECTOR_SZ, REG_DWORD, sizeof(DWORD), (PUCHAR)(NULL),
WRITE_SECTOR_SZ, REG_DWORD, sizeof(DWORD), (PUCHAR)(NULL),
SCSI_COMMAND_SZ, REG_DWORD, sizeof(DWORD), (PUCHAR)(NULL),
UNIT_ATTENTION_SZ, REG_DWORD, sizeof(DWORD), (PUCHAR)(NULL),
NULL, 0, 0, NULL
};
DEBUGMSG(ZONE_INIT, (TEXT("USBDISK6>DiskAttach\n")));
if (!UsbTransport || !pHardwareKey) {
SetLastError(ERROR_INVALID_PARAMETER);
DEBUGMSG( ZONE_ERR, (TEXT("Invalid Parameter\n")));
return NULL;
}
// try to accept all disks, probe the device, then unload if we can't controll it.
if ( !((bInterfaceSubClass >= USBMSC_SUBCLASS_RBC) && (bInterfaceSubClass <= USBMSC_SUBCLASS_SCSI)) ) {
DEBUGMSG( ZONE_ERR, (TEXT("Unsupported Disk bInterfaceSubClass:0x%x\n"), bInterfaceSubClass));
return NULL;
}
do {
//
// alloc at least 1 disk device context
//
pDevice = (PSCSI_DEVICE)LocalAlloc( LPTR, sizeof(SCSI_DEVICE) );
if ( !pDevice ) {
DEBUGMSG( ZONE_ERR, (TEXT("LocalAlloc error:%d\n"), GetLastError() ));
bRc = FALSE;
break;
}
pDevice->Sig = USBSCSI_SIG;
pDevice->hUsbTransport = UsbTransport;
pDevice->ActivePath = LocalAlloc(LPTR, wcslen(pHardwareKey)*sizeof(WCHAR)+sizeof(WCHAR));
if (!pDevice->ActivePath) {
DEBUGMSG( ZONE_ERR, (TEXT("LocalAlloc ERROR:%d\n"), GetLastError()));
bRc = FALSE;
break;
}
wcscpy(pDevice->ActivePath, pHardwareKey);
DEBUGMSG(ZONE_INIT, (TEXT("ActivePath:%s\n"), pDevice->ActivePath));
pDevice->DiskSubClass = bInterfaceSubClass;
InitializeCriticalSection( &pDevice->Lock );
if ( !InitializeRemoveLock( &pDevice->RemoveLock) ) {
DEBUGMSG( ZONE_ERR, (TEXT("InitializeRemoveLock failed\n")));
bRc = FALSE;
break;
}
//
// Grab the RemoveLock, which balances
// the ReleaseRemoveLockAndWait on UsbDiskDetach
//
AcquireRemoveLock(&pDevice->RemoveLock,NULL);
//
// set state flags
//
pDevice->MediumType = SCSI_MEDIUM_UNKNOWN;
pDevice->DeviceType = SCSI_DEVICE_UNKNOWN;
pDevice->Flags.MediumPresent = FALSE;
pDevice->Flags.MediumChanged = TRUE;
pDevice->Flags.DeviceRemoved = FALSE;
pDevice->Flags.PoweredDown = FALSE;
pDevice->Lun = (UCHAR)dwLun;
//
// Check registry for timeout values
//
rdTimeouts[0].Data = (PUCHAR)(&pDevice->Timeouts.MediaPollInterval);
rdTimeouts[1].Data = (PUCHAR)(&pDevice->Timeouts.ReadSector);
rdTimeouts[2].Data = (PUCHAR)(&pDevice->Timeouts.WriteSector);
rdTimeouts[3].Data = (PUCHAR)(&pDevice->Timeouts.ScsiCommandTimeout);
rdTimeouts[4].Data = (PUCHAR)(&pDevice->Timeouts.UnitAttnRepeat);
if ( !GetSetKeyValues(pHardwareKey,
&rdTimeouts[0],
GET,
FALSE) ) {
//
// use defaults
//
pDevice->Timeouts.MediaPollInterval = SCSI_MEDIA_POLL_INTERVAL;
pDevice->Timeouts.ReadSector = SCSI_READ_SECTOR_TIMEOUT;
pDevice->Timeouts.WriteSector = SCSI_WRITE_SECTOR_TIMEOUT;
pDevice->Timeouts.ScsiCommandTimeout = SCSI_COMMAND_TIMEOUT;
pDevice->Timeouts.UnitAttnRepeat = UNIT_ATTENTION_REPEAT;
// stuff defaults back in reg for tuning
if ( !GetSetKeyValues(pHardwareKey,
&rdTimeouts[0],
SET,
TRUE) ) {
DEBUGMSG(ZONE_ERR, (TEXT("GetSetKeyValues ERROR:%d\n"), GetLastError() ));
}
}
// let the user try a zero value, but complain in the debugger
ASSERT(pDevice->Timeouts.MediaPollInterval);
ASSERT(pDevice->Timeouts.ReadSector);
ASSERT(pDevice->Timeouts.WriteSector);
ASSERT(pDevice->Timeouts.ScsiCommandTimeout);
ASSERT(pDevice->Timeouts.UnitAttnRepeat);
// TODO: alloc additional disk instances and activate their interface...
//
// Activate the Streams Interface.
// This call invokes our DSK_Init.
//
pDevice->hStreamDevice = ActivateDevice(pDevice->ActivePath,
(DWORD)pDevice );
if ( !pDevice->hStreamDevice ) {
bRc = FALSE;
DEBUGMSG(ZONE_ERR, (TEXT("ActivateDevice ERROR:%d\n"), GetLastError() ));
TEST_TRAP();
break;
}
//
// Finally, if we discovered the device type and it has the removable media bit set
// (via the SCSI_INQUIRY command) then setup the media polling thread.
// Special case: CD-ROM must load UDFS, which has it's owm polling mechanism.
//
//
// We call need to ScsiInquiry() explicit because if a unit is not ready we do
// not know the DeviceType.
//
ScsiInquiry(pDevice, pDevice->Lun);
Sleep(500);
if ( SCSI_DEVICE_UNKNOWN != pDevice->DeviceType && pDevice->Flags.RMB &&
SCSI_DEVICE_CDROM != pDevice->DeviceType )
{
pDevice->hMediaChangedEvent = CreateEvent( NULL, AUTO_RESET_EVENT, FALSE, NULL);
if ( !pDevice->hMediaChangedEvent ) {
DEBUGMSG( ZONE_ERR, (TEXT("CreateEvent error:%d\n"), GetLastError() ));
bRc = FALSE;
break;
}
__try {
pDevice->hMediaPollThread = CreateThread( NULL, 0,
MediaChangeThread,
pDevice,
0, NULL );
if ( !pDevice->hMediaPollThread ) {
DEBUGMSG( ZONE_ERR, (TEXT("CreateThread error:%d\n"), GetLastError() ));
bRc = FALSE;
break;
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
dwErr = GetExceptionCode();
DEBUGMSG(ZONE_ERR,(TEXT("USBDISK6::UsbDiskAttach:EXCEPTION:0x%x\n"), dwErr));
TEST_TRAP();
}
}
} while (0);
if (!bRc) {
//
// If error then clean up
//
TEST_TRAP();
if (pDevice) {
ReleaseRemoveLock(&pDevice->RemoveLock,NULL);
RemoveDeviceContext( pDevice );
}
}
DEBUGMSG(ZONE_INIT, (TEXT("USBDISK6<DiskAttach:%d\n"), bRc));
return (bRc ? pDevice : NULL);
}
//
// The USB Mass Storage Class driver is removing this disk instance.
// Delete our context & streams interface.
//
BOOL
UsbDiskDetach(
PSCSI_DEVICE pDevice // Context
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -