Nandflash 驱动移植 (四)
接着上一篇,这一篇介绍cpp部分
fmd.cpp,这里将逐个函数进行分析讲解:
NFCONF[0]必须写0,NFCONF[2]必须写1,所以最后修改为:接下来直接看到
BOOL FMD_OEMIoControl(DWORD dwIoControlCode, PBYTE pInBuf, DWORD nInBufSize, PBYTE pOutBuf, DWORD nOutBufSize, PDWORD pBytesReturned) { switch(dwIoControlCode) { case IOCTL_FMD_GET_INTERFACE: { RETAILMSG(1, (TEXT("[FMD] FMD_OEMIoControl() : IOCTL_FMD_GET_INTERFACE\n"))); if (!pOutBuf || nOutBufSize < sizeof(FMDInterface)) { DEBUGMSG(1, (TEXT("FMD_OEMIoControl: IOCTL_FMD_GET_INTERFACE bad parameter(s).\n"))); return(FALSE); } PFMDInterface pInterface = (PFMDInterface)pOutBuf; pInterface->cbSize = sizeof(FMDInterface); pInterface->pInit = FMD_Init; pInterface->pDeInit = FMD_Deinit; pInterface->pGetInfo = FMD_GetInfo; pInterface->pGetInfoEx = NULL; //FMD_GetInfoEx; pInterface->pGetBlockStatus = FMD_GetBlockStatus; pInterface->pSetBlockStatus = FMD_SetBlockStatus; pInterface->pReadSector = FMD_ReadSector; pInterface->pWriteSector = FMD_WriteSector; pInterface->pEraseBlock = FMD_EraseBlock; pInterface->pPowerUp = FMD_PowerUp; pInterface->pPowerDown = FMD_PowerDown; pInterface->pGetPhysSectorAddr = NULL; break; } case IOCTL_FMD_LOCK_BLOCKS: RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_LOCK_BLOCKS Not Supported\n"))); return FALSE; case IOCTL_FMD_UNLOCK_BLOCKS: RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_UNLOCK_BLOCKS Not Supported\n"))); return FALSE; case IOCTL_FMD_READ_RESERVED: RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_READ_RESERVED\n"))); return FALSE; case IOCTL_FMD_WRITE_RESERVED: RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_WRITE_RESERVED\n"))); return FALSE; case IOCTL_FMD_GET_RESERVED_TABLE: RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_GET_RESERVED_TABLE\n"))); return FALSE; case IOCTL_FMD_SET_REGION_TABLE: RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_SET_REGION_TABLE\n"))); return FALSE; case IOCTL_FMD_SET_SECTORSIZE: RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_SET_SECTORSIZE\n"))); return FALSE; case IOCTL_FMD_RAW_WRITE_BLOCKS: RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_RAW_WRITE_BLOCKS\n"))); return FALSE; case IOCTL_FMD_GET_RAW_BLOCK_SIZE: RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_GET_RAW_BLOCK_SIZE\n"))); return FALSE; case IOCTL_FMD_GET_INFO: RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_GET_INFO\n"))); return FALSE; case IOCTL_FMD_SET_XIPMODE : RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_SET_XIPMODE\n"))); return FALSE; case IOCTL_FMD_GET_XIPMODE: RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_GET_XIPMODE\n"))); return FALSE; case IOCTL_DISK_FLUSH_CACHE: //RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_DISK_FLUSH_CACHE\n"))); return TRUE; default: RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : Unknown IOCTL (0x%08x)\n"), dwIoControlCode)); return FALSE; } return TRUE; } BOOL FMD_Deinit(PVOID hFMD) { #if (NAND_DEBUG) RETAILMSG(1, (TEXT("[FMD] FMD_Deinit() \n"))); #endif return(TRUE); } /* @func BOOL | FMD_GetInfo | Provides information on the NAND flash. @rdesc TRUE = Success, FALSE = Failure. @comm @xref */ BOOL FMD_GetInfo(PFlashInfo pFlashInfo) { // Add by AlexLee RunNo[5] UINT32 nCnt; UINT32 nNandID; UINT8 nMID, nDID; if (pFlashInfo == NULL) { RETAILMSG(1, (TEXT("[FMD:ERR] FMD_GetInfo() : Invalid Parameter\n"))); return(FALSE); } pFlashInfo->flashType = NAND; #ifdef SYNC_OP EnterCriticalSection(&g_csNandFlash); #endif nNandID = ReadFlashID(); #ifdef SYNC_OP LeaveCriticalSection(&g_csNandFlash); #endif nMID = nNandID >> 8; nDID = nNandID & 0xff; for (nCnt = 0; astNandSpec[nCnt].nMID != 0; nCnt++) { if (nDID == astNandSpec[nCnt].nDID) { break; } } // OK, instead of reading it from the chip, we use the hardcoded // numbers here. pFlashInfo->dwNumBlocks = NUM_OF_BLOCKS; pFlashInfo->wSectorsPerBlock = PAGES_PER_BLOCK; pFlashInfo->wDataBytesPerSector = NAND_SECTOR_SIZE; pFlashInfo->dwBytesPerBlock = (PAGES_PER_BLOCK * NAND_SECTOR_SIZE); //RETAILMSG(1, (TEXT("[FMD] FMD_GetInfo() : NUMBLOCKS = %d(0x%x), SECTORSPERBLOCK = %d(0x%x), BYTESPERSECTOR = %d(0x%x) \n"), pFlashInfo->dwNumBlocks, pFlashInfo->dwNumBlocks, pFlashInfo->wSectorsPerBlock, pFlashInfo->wSectorsPerBlock, pFlashInfo->wDataBytesPerSector, pFlashInfo->wDataBytesPerSector)); // del by alexlee return TRUE; } /* @func DWORD | FMD_GetBlockStatus | Returns the status of the specified block. @rdesc Block status (see fmd.h). @comm @xref */ DWORD FMD_GetBlockStatus(BLOCK_ID blockID) { DWORD dwResult = 0; #if (NAND_DEBUG) RETAILMSG(1, (TEXT("[FMD] ++FMD_GetBlockStatus(0x%08x) \n"), blockID)); #endif #ifdef SYNC_OP EnterCriticalSection(&g_csNandFlash); #endif if ( IS_LB ) { dwResult = FMD_LB_GetBlockStatus(blockID); } else { dwResult = FMD_SB_GetBlockStatus(blockID); } #ifdef SYNC_OP LeaveCriticalSection(&g_csNandFlash); #endif #if (NAND_DEBUG) RETAILMSG(1, (TEXT("[FMD] --FMD_GetBlockStatus()\n"))); #endif return dwResult; } /* @func BOOL | FMD_SetBlockStatus | Marks the block with the specified block status. @rdesc TRUE = Success, FALSE = Failure. @comm @xref */ BOOL FMD_SetBlockStatus(BLOCK_ID blockID, DWORD dwStatus) { BOOL bRet = TRUE; #if (NAND_DEBUG) RETAILMSG(1, (TEXT("[FMD] ++FMD_SetBlockStatus(0x%08x, 0x%08x) \n"), blockID, dwStatus)); #endif #ifdef SYNC_OP EnterCriticalSection(&g_csNandFlash); #endif if ( IS_LB ) { bRet = FMD_LB_SetBlockStatus(blockID, dwStatus); } else { bRet = FMD_SB_SetBlockStatus(blockID, dwStatus); } #ifdef SYNC_OP LeaveCriticalSection(&g_csNandFlash); #endif #if (NAND_DEBUG) RETAILMSG(1, (TEXT("[FMD] --FMD_SetBlockStatus()\n"))); #endif return bRet; }文章有点长,先到这里了,关键点将在下一篇介绍