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

📄 disk.c

📁 Windows CE 5.0下的U盘驱动源代码。
💻 C
📖 第 1 页 / 共 4 页
字号:
        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 + -