现在的位置: 首页 > 综合 > 正文

WinCE下面直接对Nand进行一些操作

2013年05月13日 ⁄ 综合 ⁄ 共 9356字 ⁄ 字号 评论关闭

有些时候我们需要在WinCE下面直接对Nand进行一些操作,比如erase,mask bad block,unmask bad block,或者一些基于block的数据操作。
如果我们直接用Nand驱动去访问会造成一个问题,就是无法与系统的Nand驱动互斥访问,这样子很有可能会出现问题
所以我们可以实现FMD_OEMIoControl这个函数来给我们直接提供一个接口
由于通过DeviceIoControl去访问系统的Nand驱动,如DSK1,所以不存在访问冲突问题
为了确认调用DSK的DeviceIoControl会调用FMD_OEMIoControl,特意看了下CE6下FAL的代码(感谢鹏虾提供),在Falmain.cpp中有DSK_IOControl的源代码

BOOL
DSK_IOControl(
    DWORD Handle,
    DWORD dwIoControlCode,
    PBYTE pInBuf,
    DWORD nInBufSize,
    PBYTE pOutBuf,
    DWORD nOutBufSize,
    PDWORD pBytesReturned)
{
    BOOL fRet = FALSE;
    EnterCriticalSection(&g_csMain);
    EnterCriticalSection(&g_csFlashDevice);
    __try
    {
    //----- 1. Check the function parameters to make sure we can handle the request... -----
    switch (dwIoControlCode)
    {
        case DISK_IOCTL_INITIALIZED:
            if(pInBuf == NULL)
            {
                goto PARAMETER_ERROR;
            }
            break;
        case DISK_IOCTL_READ:case IOCTL_DISK_READ:
        case DISK_IOCTL_WRITE:case IOCTL_DISK_WRITE:
            if(pInBuf == NULL || nInBufSize < sizeof(SG_REQ))
            {
                goto PARAMETER_ERROR;
            }
            break;
        case IOCTL_DISK_GETINFO:
            if(pOutBuf == NULL || nOutBufSize != sizeof(DISK_INFO))
            {
                goto PARAMETER_ERROR;
            }
            break;
        case DISK_IOCTL_GETINFO:
        case DISK_IOCTL_SETINFO:case IOCTL_DISK_SETINFO:
            if(pInBuf == NULL || nInBufSize != sizeof(DISK_INFO))
            {
                goto PARAMETER_ERROR;
            }
            break;
        case DISK_IOCTL_GETNAME:case IOCTL_DISK_GETNAME:
            if(pOutBuf == NULL || nOutBufSize == 0)
            {
                goto PARAMETER_ERROR;
            }
            break;
           
        case DISK_IOCTL_FORMAT_MEDIA: case IOCTL_DISK_FORMAT_MEDIA:
            break;
           
        case IOCTL_DISK_DELETE_SECTORS:
        case IOCTL_DISK_SET_SECURE_WIPE_FLAG:
            if(pInBuf == NULL || nInBufSize != sizeof(DELETE_SECTOR_INFO))
            {
                goto PARAMETER_ERROR;
            }
            break;
        case IOCTL_DISK_SECURE_WIPE:
            if(pInBuf == NULL || nInBufSize != sizeof(DELETE_SECTOR_INFO))
            {
                goto PARAMETER_ERROR;
            }
            break;
        case IOCTL_DISK_DEVICE_INFO:
            if(pInBuf == NULL || nInBufSize != sizeof(STORAGEDEVICEINFO))
            {
                goto PARAMETER_ERROR;
            }
            break;
        case IOCTL_DISK_GET_SECTOR_ADDR:
            if(pInBuf == NULL || pOutBuf == NULL || nInBufSize != nOutBufSize)
            {
                goto PARAMETER_ERROR;
            }
            break;       
        case IOCTL_POWER_CAPABILITIES:
            if(pOutBuf == NULL || nOutBufSize < sizeof(POWER_CAPABILITIES) || pBytesReturned == NULL)
            {
                goto PARAMETER_ERROR;
            }
            break;
           
        case IOCTL_POWER_SET:
            if(pOutBuf == NULL || nOutBufSize < sizeof(CEDEVICE_POWER_STATE) || pBytesReturned == NULL)
            {
                goto PARAMETER_ERROR;
            }
            break;
           
        case IOCTL_POWER_GET:
            if(pOutBuf == NULL || nOutBufSize < sizeof(CEDEVICE_POWER_STATE) || pBytesReturned == NULL)
            {
                goto PARAMETER_ERROR;
            }
            break;
           
        default:
            // Pass any other IOCTL through to the FMD.
            fRet = FMD.pOEMIoControl(dwIoControlCode, pInBuf, nInBufSize, pOutBuf, nOutBufSize, pBytesReturned);
            goto IO_EXIT;
        }

        //----- 2. Now handle the IOCTL request... -----   
        switch (dwIoControlCode)
        {
        case DISK_IOCTL_INITIALIZED:
            break;

        case DISK_IOCTL_READ:case IOCTL_DISK_READ:
            DEBUGMSG(ZONE_FUNCTION,(TEXT("FLASHDRV.DLL:DSK_IOControl(DISK_IOCTL_READ)/r/n")));     
            //----- Service this scatter/gather READ request -----
            if(!(fRet = ReadFromMedia((PSG_REQ)pInBuf)))
            {
                ReportError((TEXT("FLASHDRV.DLL:ReadFromMedia() failed./r/n")));       
            }  
            break;

        case DISK_IOCTL_WRITE:case IOCTL_DISK_WRITE:
            DEBUGMSG(ZONE_FUNCTION,(TEXT("FLASHDRV.DLL:DSK_IOControl(DISK_IOCTL_WRITE)/r/n")));    
           
            //----- Service this scatter/gather WRITE request -----
            if(!(fRet = WriteToMedia((PSG_REQ)pInBuf)))
            {
                ReportError((TEXT("FLASHDRV.DLL:WriteToMedia() failed./r/n")));    
            }
            break;

        case DISK_IOCTL_GETINFO:case  IOCTL_DISK_GETINFO:
            DEBUGMSG(ZONE_FUNCTION,(TEXT("FLASHDRV.DLL:DSK_IOControl(DISK_IOCTL_GETINFO)/r/n")));      
            //----- Retrieve the storage information for this FLASH device -----
            if(!(fRet = GetDiskInfo((PDISK_INFO)(dwIoControlCode!=IOCTL_DISK_GETINFO?pInBuf:pOutBuf))))
            {
                ReportError((TEXT("FLASHDRV.DLL:ERROR - Unable to get disk information from FMD!/r/n")));
                goto IO_EXIT;
            }
            break;

        case DISK_IOCTL_SETINFO: case IOCTL_DISK_SETINFO:
            DEBUGMSG(ZONE_FUNCTION,(TEXT("FLASHDRV.DLL:DSK_IOControl(DISK_IOCTL_SETINFO)/r/n")));      
            //----- The FLASH media is a fixed size; hence, nothing needs to be done -----
            break;

        case DISK_IOCTL_GETNAME:case IOCTL_DISK_GETNAME:
            SetLastError(ERROR_NOT_SUPPORTED);
            break;

        case DISK_IOCTL_FORMAT_MEDIA:case IOCTL_DISK_FORMAT_MEDIA:
            DEBUGMSG(ZONE_FUNCTION,(TEXT("FLASHDRV.DLL:DSK_IOControl(DISK_IOCTL_FORMAT_MEDIA)/r/n")));     
            //----- Format the media on the FLASH device -----
            if(!(fRet = FormatMedia()))
            {
                ReportError((TEXT("FLASHDRV.DLL:ERROR - Unable to format FLASH media!/r/n")));
                goto IO_EXIT;
            }
            break;
        case IOCTL_DISK_DEVICE_INFO:
        {
            fRet = GetDeviceInfo((PSTORAGEDEVICEINFO)pInBuf);
            if (pBytesReturned)
                *pBytesReturned = sizeof(STORAGEDEVICEINFO);
            break;   
        }   
        case IOCTL_DISK_DELETE_SECTORS:
            DEBUGMSG(ZONE_FUNCTION, (TEXT("FLASHDRV.DLL:DSK_IOControl(IOCTL_DISK_DELETE_SECTORS)/r/n")));
            //----- Delete the requested sectors -----
            if(!(fRet = DeleteSectors((PDELETE_SECTOR_INFO)pInBuf)))
            {
                ReportError((TEXT("FLASHDRV.DLL:ERROR - DeleteSectors() failed./r/n")));
                goto IO_EXIT;
            }
            break;
        case IOCTL_DISK_SECURE_WIPE:
            DEBUGMSG(ZONE_FUNCTION, (TEXT("FLASHDRV.DLL:DSK_IOControl(IOCTL_DISK_SECURE_WIPE)/r/n")));
            //----- Secure wipe the flash region  -----
            if(!(fRet = SecureWipe((PDELETE_SECTOR_INFO)pInBuf)))
            {
                ReportError((TEXT("FLASHDRV.DLL:ERROR - SecureWipe() failed./r/n")));
                goto IO_EXIT;
            }
            break;
        case IOCTL_DISK_SET_SECURE_WIPE_FLAG:
            DEBUGMSG(ZONE_FUNCTION, (TEXT("FLASHDRV.DLL:DSK_IOControl(IOCTL_DISK_SET_SECURE_WIPE_FLAG)/r/n")));
            //----- Set the secure wipe flag for the flash region  -----
            if(!(fRet = SetSecureWipeFlag((PDELETE_SECTOR_INFO)pInBuf)))
            {
                ReportError((TEXT("FLASHDRV.DLL:ERROR - SetSecureWipeFlag() failed./r/n")));
                goto IO_EXIT;
            }
            break;
           
        case IOCTL_DISK_GET_SECTOR_ADDR:
        {
            DEBUGMSG(ZONE_FUNCTION,(TEXT("FLASHDRV.DLL:DSK_IOControl(IOCTL_DISK_GET_SECTOR_ADDR)/r/n")));     
            //----- Service this scatter/gather READ request -----
            if(!(fRet = GetPhysSectorAddr((PSECTOR_ADDR)pInBuf, (PSECTOR_ADDR)pOutBuf, nInBufSize / sizeof(SECTOR_ADDR))))
            {
                ReportError((TEXT("FLASHDRV.DLL:ReadFromMedia() failed./r/n")));       
            }  
            break; 
        }
        case IOCTL_POWER_CAPABILITIES:
            DEBUGMSG(ZONE_FUNCTION, (TEXT("FLASHDRV.DLL:DSK_IOControl(IOCTL_POWER_CAPABILITIES)/r/n")));
            if(!(fRet = GetPowerCapabilities((PPOWER_CAPABILITIES)pOutBuf)))
            {
                ReportError((TEXT("FLASHDRV.DLL:ERROR - GetPowerCapabilities() failed./r/n")));
                goto IO_EXIT;
            }
            *pBytesReturned = sizeof(POWER_CAPABILITIES);
            break;
           
        case IOCTL_POWER_SET:
            DEBUGMSG(ZONE_FUNCTION, (TEXT("FLASHDRV.DLL:DSK_IOControl(IOCTL_POWER_SET)/r/n")));
            if(!(fRet = SetPowerState((PCEDEVICE_POWER_STATE)pOutBuf)))
            {
                ReportError((TEXT("FLASHDRV.DLL:ERROR - SetPowerState() failed./r/n")));
                goto IO_EXIT;
            }
            *pBytesReturned = sizeof(CEDEVICE_POWER_STATE);
            break;
           
        case IOCTL_POWER_GET:
            DEBUGMSG(ZONE_FUNCTION, (TEXT("FLASHDRV.DLL:DSK_IOControl(IOCTL_POWER_GET)/r/n")));
            if(!(fRet = GetPowerState((PCEDEVICE_POWER_STATE)pOutBuf)))
            {
                ReportError((TEXT("FLASHDRV.DLL:ERROR - GetPowerState() failed./r/n")));
                goto IO_EXIT;
            }
            *pBytesReturned = sizeof(CEDEVICE_POWER_STATE);
            break;
       
    }
    }       
    __except (EXCEPTION_EXECUTE_HANDLER) 
    {     
        SetLastError(ERROR_INVALID_PARAMETER);
    }
          
IO_EXIT:      
    LeaveCriticalSection(&g_csFlashDevice);
    LeaveCriticalSection(&g_csMain);
    return fRet;
PARAMETER_ERROR:
    SetLastError(ERROR_INVALID_PARAMETER);
    LeaveCriticalSection(&g_csFlashDevice);
    LeaveCriticalSection(&g_csMain);
    return FALSE;
   
}          

这里我们看到,进入函数就EnterCriticalSection,这样保证了驱动访问Nand不会产生冲突,然后如果不是系统的IOCTL代码,就会调用FMD.pOEMIoControl来处理,这里的FMD.pOEMIoControl就是通过FMDInterface结构体传递过来的FMD_OEMIoControl。
所以只要我们自定义了一个IOCTL,就会交由FMD_OEMIoControl来处理,这里可以做任何你想做的事情,不必考虑Nand访问冲突的问题。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/gooogleman/archive/2009/09/03/4513622.aspx

抱歉!评论已关闭.