⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 disk.c

📁 WIN CE 下storage 存储外设的驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:

            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 + -