📄 disk.c
字号:
SgCount = pUnsafeCDROMRead->sgcount;
if (SgCount > MAX_SG_BUF) {
dwErr = ERROR_INVALID_PARAMETER;
pDevice->Flags.Busy = FALSE;
break;
}
// Convert CDROM_READ to SG_REQ
pPseudoUnsafeIoRequest->sr_start = pUnsafeCDROMRead->StartAddr.Address.lba;
pPseudoUnsafeIoRequest->sr_num_sec = pUnsafeCDROMRead->TransferLength;
pPseudoUnsafeIoRequest->sr_num_sg = SgCount;
for (i = 0; i < SgCount; i++) {
pPseudoUnsafeIoRequest->sr_sglist[i].sb_buf = pUnsafeCDROMRead->sglist[i].sb_buf;
pPseudoUnsafeIoRequest->sr_sglist[i].sb_len = pUnsafeCDROMRead->sglist[i].sb_len;
}
// Sterilize the caller's SG_REQ.
if (!SterilizeIoRequest(
pDevice->pSterileIoRequest,
pPseudoUnsafeIoRequest,
sizeof(SG_REQ) + ((pPseudoUnsafeIoRequest->sr_num_sg - 1) * sizeof(SG_BUF)))
) {
dwErr = ERROR_INVALID_PARAMETER;
pDevice->Flags.Busy = FALSE;
break;
}
// Initiate I/O. Note that to determine if ScsiRWSG succeeded,
// we are required to inspect the sr_status. It's safe to do so,
// because pSterileIoRequest is our safe copy of the caller's
// SG_REQ. The following is a workaround for UDFS not refreshing
// disk info.
if (
0 == pDevice->DiskInfo.di_bytes_per_sect ||
0 == pDevice->DiskInfo.di_total_sectors
) {
DISK_INFO di = {0};
dwErr = ScsiReadCapacity(pDevice, &di, pDevice->Lun);
if (ERROR_SUCCESS != dwErr) {
pDevice->Flags.Busy = FALSE;
break;
}
}
dwErr = ScsiCDRead(
pDevice,
pDevice->pSterileIoRequest,
&SafeBytesReturned
);
if (pdwBytesTransferred) {
if (0 == CeSafeCopyMemory((LPVOID)pdwBytesTransferred, (LPVOID)&SafeBytesReturned, sizeof(DWORD))) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
}
pDevice->Flags.Busy = FALSE;
break;
}
case IOCTL_CDROM_TEST_UNIT_READY:
{
PCDROM_TESTUNITREADY pCDROMTestUnitReady = (PCDROM_TESTUNITREADY)pOutBuf;
ULONG ulMediumPresentSnapshot = 0;
ULONG ulMediumChanged = 0;
DEBUGMSG(ZONE_DSK_IOCTL, (TEXT("USBDISK6>DSK_IOControl>IOCTL_CDROM_TEST_UNIT_READY\r\n")));
if (NULL == pOutBuf || OutBufLen < sizeof(CDROM_TESTUNITREADY)) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
if (pDevice->Flags.Busy) {
dwErr = ERROR_BUSY;
break;
}
// Note that UDFS uses this IOCTL to poll the device to test for
// the presence of media. If the device's medium has changed, then
// update the medium info.
pDevice->Flags.Busy = TRUE;
// Take a snapshot of whether a medium is present.
ulMediumPresentSnapshot = pDevice->Flags.MediumPresent;
dwErr = ScsiUnitAttention(pDevice, pDevice->Lun);
if (ERROR_SUCCESS == dwErr) {
ulMediumChanged = ulMediumPresentSnapshot ^ pDevice->Flags.MediumPresent;
// The device's medium has changed, update the medium info.
if (ulMediumChanged && pDevice->Flags.MediumPresent) {
DISK_INFO di = {0};
dwErr = ScsiReadCapacity(pDevice, &di, pDevice->Lun);
}
dwErr = ERROR_SUCCESS;
}
pDevice->Flags.Busy = FALSE;
__try {
pCDROMTestUnitReady->bUnitReady = (ERROR_SUCCESS == dwErr);
}
__except(EXCEPTION_EXECUTE_HANDLER) {
dwErr = ERROR_INVALID_PARAMETER;
}
break;
}
case IOCTL_CDROM_DISC_INFO:
DEBUGMSG(ZONE_DSK_IOCTL, (TEXT("USBDISK6>DSK_IOControl>IOCTL_CDROM_DISC_INFO\r\n")));
// This IOCTL is not implemented.
break;
case IOCTL_CDROM_LOAD_MEDIA:
DEBUGMSG(ZONE_DSK_IOCTL, (TEXT("USBDISK6>DSK_IOControl>IOCTL_CDROM_LOAD_MEDIA\r\n")));
dwErr = ScsiStartStopUnit(pDevice, START, TRUE, pDevice->Lun);
break;
case IOCTL_CDROM_EJECT_MEDIA:
DEBUGMSG(ZONE_DSK_IOCTL, (TEXT("USBDISK6>DSK_IOControl>IOCTL_CDROM_EJECT_MEDIA\r\n")));
dwErr = ScsiStartStopUnit(pDevice, STOP, TRUE, pDevice->Lun);
break;
case IOCTL_CDROM_GET_SENSE_DATA:
{
TRANSPORT_DATA SafeTransportData = {0};
CD_SENSE_DATA SafeCDSenseData = {0};
SafeBytesReturned = 0;
DEBUGMSG(ZONE_DSK_IOCTL, (TEXT("USBDISK6>DSK_IOControl>IOCTL_CDROM_GET_SENSE_DATA\r\n")));
if (!pOutBuf || OutBufLen < sizeof(CD_SENSE_DATA)) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
// Note that this drive performs auto-sense. The sense data
// returned may not be as expected.
SafeTransportData.TransferLength = 0;
SafeTransportData.RequestLength = sizeof(CD_SENSE_DATA);
SafeTransportData.DataBlock = &SafeCDSenseData;
// Fetch sense data.
dwErr = ScsiRequestSense(pDevice, &SafeTransportData, pDevice->Lun);
SafeBytesReturned = SafeTransportData.TransferLength;
if (0 == CeSafeCopyMemory((LPVOID)pOutBuf, (LPVOID)&SafeCDSenseData, SafeBytesReturned)) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
if (pdwBytesTransferred) {
if (0 == CeSafeCopyMemory((LPVOID)pdwBytesTransferred, (LPVOID)&SafeBytesReturned, sizeof(DWORD))) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
}
break;
}
// CD-DA IOCTLs
case IOCTL_CDROM_READ_TOC:
case IOCTL_CDROM_GET_CONTROL:
case IOCTL_CDROM_PLAY_AUDIO:
case IOCTL_CDROM_PLAY_AUDIO_MSF:
case IOCTL_CDROM_SEEK_AUDIO_MSF:
case IOCTL_CDROM_STOP_AUDIO:
case IOCTL_CDROM_PAUSE_AUDIO:
case IOCTL_CDROM_RESUME_AUDIO:
case IOCTL_CDROM_GET_VOLUME:
case IOCTL_CDROM_SET_VOLUME:
case IOCTL_CDROM_READ_Q_CHANNEL:
case IOCTL_CDROM_GET_LAST_SESSION:
case IOCTL_CDROM_RAW_READ:
case IOCTL_CDROM_DISK_TYPE:
case IOCTL_CDROM_SCAN_AUDIO:
{
dwErr = ScsiCDAudio(
pDevice,
Ioctl,
pInBuf,
InBufLen,
pOutBuf,
OutBufLen,
pdwBytesTransferred
);
break;
}
default:
DEBUGMSG(ZONE_DSK_IOCTL, (TEXT("USBDISK6>DSK_IOControl>Unsupported IOCTL %d\r\n"), Ioctl));
dwErr = ERROR_NOT_SUPPORTED;
break;
}
LeaveCriticalSection(&pDevice->Lock);
if (ERROR_SUCCESS != dwErr) {
SetLastError(dwErr);
}
else {
bRc = TRUE;
}
DEBUGMSG(ZONE_DSK_IOCTL,(TEXT("USBDISK6<DSK_IOControl(dwErr:%d, bRc:%d)\r\n"), 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(100);
}
} 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -