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

📄 fmd.cpp

📁 三星2440原版bsp
💻 CPP
📖 第 1 页 / 共 5 页
字号:
			}
			pBSPArgs->nfsblk = pLockInfo->StartBlock + pLockInfo->NumBlocks;

			break;
		case IOCTL_FMD_UNLOCK_BLOCKS:
			RETAILMSG(1, (TEXT("IOCTL_FMD_UNLOCK_BLOCKS!!!!(0x%x,0x%x) \r\n"), pLockInfo->StartBlock, pLockInfo->NumBlocks));
			RETAILMSG(1, (TEXT("S3C2440 Does not support IOCTL_FMD_UNLOCK_BLOCKS !!!! \r\n")));
	        return(FALSE);
			/*
			pLockInfo = (BlockLockInfo *)pInBuf;
			RETAILMSG(1, (TEXT("IOCTL_FMD_UNLOCK_BLOCKS!!!!(0x%x,0x%x) \r\n"), pLockInfo->StartBlock, pLockInfo->NumBlocks));

			if ( astNandSpec[dwPrimaryNandDevice].nSctsPerPg == 4 )		// Large Block
			{
				if ( READ_REGISTER_BYTE(pNFSBLK) >> 5 > (ULONG)(pLockInfo->StartBlock - 1) )
					WRITE_REGISTER_USHORT(pNFSBLK, (pLockInfo->StartBlock - 1)<<5 );
			}
			else	// Small Block
			{
				if ( READ_REGISTER_BYTE(pNFSBLK) >> 5 > (ULONG)(pLockInfo->StartBlock - 1)*8 )
					WRITE_REGISTER_USHORT(pNFSBLK, ((ULONG)(pLockInfo->StartBlock - 1)*8)<<5 );
			}
			pBSPArgs->nfsblk = pLockInfo->StartBlock - 1;
			*/

			break;
			/*
		case IOCTL_FMD_READ_RESERVED:
			RETAILMSG(1,(TEXT("IOCTL_FMD_READ_RESERVED\r\n")));
			return(FALSE);	
			break;
		case IOCTL_FMD_WRITE_RESERVED:
			RETAILMSG(1,(TEXT("IOCTL_FMD_WRITE_RESERVED\r\n")));
			return(FALSE);	
			break;
		case IOCTL_FMD_GET_RESERVED_TABLE:
			RETAILMSG(1,(TEXT("IOCTL_FMD_GET_RESERVED_TABLE\r\n")));
			return(FALSE);	
			break;
		case IOCTL_FMD_SET_REGION_TABLE:
			RETAILMSG(1,(TEXT("IOCTL_FMD_SET_REGION_TABLE\r\n")));
			return(FALSE);	
			break;
		case IOCTL_FMD_SET_SECTORSIZE:
			RETAILMSG(1,(TEXT("IOCTL_FMD_SET_SECTORSIZE\r\n")));
			return(FALSE);	
			break;			
		case IOCTL_FMD_RAW_WRITE_BLOCKS:
			RETAILMSG(1,(TEXT("IOCTL_FMD_RAW_WRITE_BLOCKS\r\n")));
			return(FALSE);	
			break;	
		case IOCTL_FMD_GET_RAW_BLOCK_SIZE:
			RETAILMSG(1,(TEXT("IOCTL_FMD_GET_RAW_BLOCK_SIZE\r\n")));
			return(FALSE);	
			break;	
		case IOCTL_FMD_GET_INFO:
			RETAILMSG(1,(TEXT("IOCTL_FMD_GET_INFO\r\n")));
			return(FALSE);	
			break;	
			*/																		
	    default:
	        RETAILMSG(1, (TEXT("FMD_OEMIoControl: unrecognized IOCTL (0x%x).\r\n"), dwIoControlCode));
	        return(FALSE);
    }

    return TRUE; 
}

#endif // NOSYSCALL

//------------------------------- Private Interface (NOT used by the FAL) --------------------------

//  FMD_GetOEMReservedByte
//
//  Retrieves the OEM reserved byte (for metadata) for the specified physical sector.
//
//
BOOL FMD_GetOEMReservedByte(SECTOR_ADDR physicalSectorAddr, PBYTE pOEMReserved)
{
	if ( physicalSectorAddr < (unsigned)wPRIMARY_NAND_BLOCKS*PAGES_PER_BLOCK )		// First NAND Flash
	{
		if ( astNandSpec[dwPrimaryNandDevice].nSctsPerPg == 4 )
			FMD_LB_GetOEMReservedByte( physicalSectorAddr,  pOEMReserved, USE_NFCE);
		else
			FMD_SB_GetOEMReservedByte( physicalSectorAddr,  pOEMReserved, USE_NFCE);
	}
	else
	{
		if ( astNandSpec[dwSecondaryNandDevice].nSctsPerPg == 4 )
			FMD_LB_GetOEMReservedByte( physicalSectorAddr-wPRIMARY_NAND_BLOCKS*PAGES_PER_BLOCK,  pOEMReserved, USE_GPIO);
		else
			FMD_SB_GetOEMReservedByte( physicalSectorAddr-wPRIMARY_NAND_BLOCKS*PAGES_PER_BLOCK,  pOEMReserved, USE_GPIO);
	}
	return TRUE;
}

//  FMD_SetOEMReservedByte
//
//  Sets the OEM reserved byte (for metadata) for the specified physical sector.
//
BOOL FMD_SetOEMReservedByte(SECTOR_ADDR physicalSectorAddr, BYTE bOEMReserved)
{
    BOOL    bRet = TRUE;
	if ( physicalSectorAddr < (unsigned)wPRIMARY_NAND_BLOCKS*PAGES_PER_BLOCK )		// First NAND Flash
	{
		if ( astNandSpec[dwPrimaryNandDevice].nSctsPerPg == 4 )
			bRet = FMD_LB_SetOEMReservedByte(physicalSectorAddr, bOEMReserved, USE_NFCE);
		else
			bRet = FMD_SB_SetOEMReservedByte(physicalSectorAddr, bOEMReserved, USE_NFCE);
	}
	else
	{
		if ( astNandSpec[dwSecondaryNandDevice].nSctsPerPg == 4 )
			bRet = FMD_LB_SetOEMReservedByte(physicalSectorAddr-wPRIMARY_NAND_BLOCKS*PAGES_PER_BLOCK, bOEMReserved, USE_GPIO);
		else
			bRet = FMD_SB_SetOEMReservedByte(physicalSectorAddr-wPRIMARY_NAND_BLOCKS*PAGES_PER_BLOCK, bOEMReserved, USE_GPIO);
	}
    return bRet;
}

//---------------------------------------- Helper Functions ----------------------------------------

//  Interface function for testing purpose.
//
BOOL FMD_ReadSpare(DWORD dwStartPage, LPBYTE pBuff, DWORD dwNumPages)
{
	RETAILMSG(1, (TEXT("FMD_ReadSpare Not Support !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\r\n")));
    return FALSE;
}

//  Reset the chip
//
void SB_NF_Reset(int mode)
{
	int i;
    SetChipSelect(mode,LOW);
	NF_CLEAR_RB();
    NF_CMD(CMD_RESET);
	for(i=0;i<10;i++);  //tWB = 100ns. //??????
    SetChipSelect(mode,HIGH);
}

/*
 *  NAND_SB_ReadSectorInfo
 *
 *  Read SectorInfo out of the spare area. The current implementation only handles
 *  one sector at a time.
 */
void NAND_SB_ReadSectorInfo(SECTOR_ADDR sectorAddr, PSectorInfo pInfo, int mode)
{
    BOOL bLastMode = SetKMode(TRUE);
    
    //  Chip enable
    SetChipSelect(mode,LOW);
	NF_CLEAR_RB();

    //  Write the command
    NF_CMD(CMD_READ2);

    //  Write the address
    NF_ADDR(0x00);
    NF_ADDR(sectorAddr & 0xff);
    NF_ADDR((sectorAddr >> 8) & 0xff);

    if (SB_NEED_EXT_ADDR) {
        NF_ADDR((sectorAddr >> 16) & 0xff);
    }

    //  Wait for the Ready bit
	NF_DETECT_RB();	 // Wait tR(max 12us)

    //  Read the SectorInfo data (we only need to read first 8 bytes)
    pInfo->dwReserved1  = NF_DATA_R4();

    //  OEM byte
    pInfo->bOEMReserved = (BYTE) NF_DATA_R();

    //  Read the bad block mark
    pInfo->bBadBlock = (BYTE) NF_DATA_R();

    //  Second reserved field (WORD)
    pInfo->wReserved2 = ((BYTE) NF_DATA_R() << 8);
    pInfo->wReserved2 |= ((BYTE) NF_DATA_R());

    SetChipSelect(mode,HIGH);

    SetKMode(bLastMode);
}

/*
 *  NAND_SB_WriteSectorInfo
 *
 *  Write SectorInfo out to the spare area. The current implementation only handles
 *  one sector at a time.
 */
BOOL NAND_SB_WriteSectorInfo(SECTOR_ADDR sectorAddr, PSectorInfo pInfo, int mode)
{
    BOOL    bRet = TRUE;

    BOOL bLastMode = SetKMode(TRUE);

    //  Chip enable
    SetChipSelect(mode,LOW);
	NF_CLEAR_RB();

    //  Write the command
    //  First, let's point to the spare area
    NF_CMD(CMD_READ2);
    NF_CMD(CMD_WRITE);

    //  Write the address
    NF_ADDR(0x00);
    NF_ADDR(sectorAddr & 0xff);
    NF_ADDR((sectorAddr >> 8) & 0xff);

    if (SB_NEED_EXT_ADDR) {
        NF_ADDR((sectorAddr >> 16) & 0xff);
    }

    //  Now let's write the SectorInfo data
    //
    //  Write the first reserved field (DWORD)
    NF_DATA_W4( pInfo->dwReserved1 );

    //  Write OEM reserved flag
    NF_DATA_W( (pInfo->bOEMReserved) );

    //  Write the bad block flag
    NF_DATA_W( (pInfo->bBadBlock) );

    //  Write the second reserved field
    NF_DATA_W( (pInfo->wReserved2 >> 8) & 0xff );
    NF_DATA_W( (pInfo->wReserved2) );

    //  Issue the write complete command
    NF_CMD(CMD_WRITE2);

    //  Check ready bit
	NF_DETECT_RB();	 // Wait tR(max 12us)

	if ( READ_REGISTER_USHORT(pNFSTAT) & STATUS_ILLACC )
	{
		RETAILMSG(1, (TEXT("NAND_WriteSectorInfo() ######## Error Programming page (Illigar Access) %d!\n"), sectorAddr));
		WRITE_REGISTER_USHORT(pNFSTAT, STATUS_ILLACC);	// Write 1 to clear.
        bRet = FALSE;
	}
	else
	{
		//  Check the status of program
		NF_CMD(CMD_STATUS);

		if(NF_DATA_R() & STATUS_ERROR) {
			RETAILMSG(1, (TEXT("NAND_WriteSectorInfo() ######## Error Programming page %d!\n"), sectorAddr));
			bRet = FALSE;
		}
	}

    SetChipSelect(mode,HIGH);

    SetKMode(bLastMode);
    return bRet;
}

//  FMD_SB_ReadSector
//
//  Read the content of the sector.
//
//  startSectorAddr: Starting page address
//  pSectorBuff  : Buffer for the data portion
//  pSectorInfoBuff: Buffer for Sector Info structure
//  dwNumSectors : Number of sectors
//
typedef union _ECCRegVal
{
    DWORD   dwECCVal;
    BYTE    bECCBuf[4];
} ECCRegVal;

BOOL FMD_SB_ReadSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff,
                        PSectorInfo pSectorInfoBuff, DWORD dwNumSectors, int mode)
{
    DWORD       i;
    BYTE        eccBuf[8];
    ECCRegVal   eccRegVal;

//	RETAILMSG(1, (TEXT("FMD::FMD_SB_ReadSector 0x%x \r\n"), startSectorAddr));
//	RETAILMSG(1, (TEXT("startSectorAddr = 0x%x \r\n"), startSectorAddr));

	//  Sanity check
    if (!pSectorBuff && !pSectorInfoBuff || dwNumSectors > 1) {
        RETAILMSG(1, (TEXT("Invalid parameters!\n")));
        return FALSE;
    }

    if(!pSectorBuff) {
        //  We are reading spare only
        NAND_SB_ReadSectorInfo(startSectorAddr, pSectorInfoBuff, mode);

        //  There is no ECC for the sector info, so the read always succeed.
        return TRUE;
    }

	BOOL bLastMode = SetKMode(TRUE);

	//  Initialize ECC register
	NF_RSTECC();
	NF_MECC_UnLock();

	//  Enable the chip
	SetChipSelect(mode,LOW);
	NF_CLEAR_RB();

	//  Issue command
	NF_CMD(CMD_READ);

	//  Set up address
	NF_ADDR(0x00);
	NF_ADDR((startSectorAddr) & 0xff);
	NF_ADDR((startSectorAddr >> 8) & 0xff);

	if (SB_NEED_EXT_ADDR) {
		NF_ADDR((startSectorAddr >> 16) & 0xff);
	}

//	RETAILMSG(1, (TEXT("1 \r\n")));
	NF_DETECT_RB();	 // Wait tR(max 12us)
//	RETAILMSG(1, (TEXT("2 \r\n")));

	//  BUGBUG, because Media Player for Pocket PC sometimes pass us un-aligned buffer
	//  we have to waste cycle here to work around this problem
	if( ((DWORD) pSectorBuff) & 0x3) {
		for(i=0; i<SECTOR_SIZE; i++) {
			pSectorBuff[i] = (BYTE) NF_DATA_R();
		}
	}
	else {
		//  The right way.
		ReadPage512(pSectorBuff, pNFDATA);
    }

    //  Do the ECC thing here
    //  We read the ECC value from the ECC register pFNECC
	NF_MECC_Lock();
    eccRegVal.dwECCVal = NF_ECC();

    //  Read the SectorInfo data
    if(pSectorInfoBuff) {
        //  Read the SectorInfo data (we only need to read first 8 bytes)
        pSectorInfoBuff->dwReserved1  = NF_DATA_R4();

        //  OEM byte
        pSectorInfoBuff->bOEMReserved = (BYTE) NF_DATA_R();

        //  Read the bad block mark
        pSectorInfoBuff->bBadBlock = (BYTE) NF_DATA_R();

        //  Second reserved field (WORD)
        pSectorInfoBuff->wReserved2 = ((BYTE) NF_DATA_R() << 8);
        pSectorInfoBuff->wReserved2 |= ((BYTE) NF_DATA_R());
    }
    else {
        //  Advance the read pointer
        for(i=0; i<sizeof(SectorInfo); i++) {
            eccBuf[i] = (BYTE) NF_DATA_R();
        }
    }

    //  Verify the ECC values
    //
    //  Read the ECC buffer
    for(i=0; i<3; i++) {
        eccBuf[i] = (BYTE) NF_DATA_R();
    }

    SetChipSelect(mode,HIGH);

    //  Copmare with the ECC generated from the HW

    if(eccBuf[0] != eccRegVal.bECCBuf[0] ||
       eccBuf[1] != eccRegVal.bECCBuf[1]  ||
       eccBuf[2] != eccRegVal.bECCBuf[2] ) {
        RETAILMSG(1, (TEXT("FMD(FMD_SB_ReadSector): ECC ERROR - Page #: %d\r\n"), startSectorAddr));
        //  Now try to correct them
        if(!ECC_CorrectData(pSectorBuff, eccBuf, eccRegVal.bECCBuf)) {
            RETAILMSG(1, (TEXT("FMD: Unable to correct the ECC error - Page #: %d\r\n"),
                          startSectorAddr));
            SetKMode(bLastMode);
			return FALSE;
        }
    }

//	RETAILMSG(1, (TEXT("FMD::FMD_SB_ReadSector -- \r\n")));

    SetKMode(bLastMode);
    return TRUE;
}

//
//  SB_IsBlockBad
//
//  Check to see if the given block is bad. A block is bad if the 517th byte on
//  the first or second page is not 0xff.
//
//  blockID:    The block address. We need to convert this to page address
//
//
BOOL SB_IsBlockBad(BLOCK_ID blockID, int mode)
{
    DWORD   dwPageID = blockID << SB_NAND_LOG_2_PAGES_PER_BLOCK;
    BOOL    bRet = FALSE;
    BYTE    wFlag;

    BOOL bLastMode = SetKMode(TRUE);

    //  Enable the chip
    SetChipSelect(mode,LOW);
	NF_CLEAR_RB();

    //  Issue the command
    NF_CMD(CMD_READ2);

    //  Set up address
    NF_ADDR(VALIDADDR);
    NF_ADDR((dwPageID) & 0xff);
    NF_ADDR((dwPageID >> 8) & 0xff);

    if (SB_NEED_EXT_ADDR) {
        NF_ADDR((dwPageID >> 16) & 0xff);
    }

    //  Wait for Ready bit
	NF_DETECT_RB();	 // Wait tR(max 12us)

    //  Now get the byte we want
    wFlag = (BYTE) NF_DATA_R();

    if(wFlag != 0xff) {
        bRet = TRUE;
    }

    //  Disable the chip
    SetChipSelect(mode,HIGH);

    SetKMode(bLastMode);
    return bRet;
}

//
//  FMD_SB_GetBlockStatus
//
//  Returns the status of a block.  The status information is stored in the spare area of the first sector for
//  the respective block.
//
//  A block is BAD if the bBadBlock byte on the first page is not equal to 0xff.
//
DWORD FMD_SB_GetBlockStatus(BLOCK_ID blockID, int mode)
{
    SECTOR_ADDR sectorAddr = blockID << SB_NAND_LOG_2_PAGES_PER_BLOCK;
    SectorInfo SI;
    DWORD dwResult = 0;

	if(!FMD_SB_ReadSector(sectorAddr, NULL, &SI, 1, mode))
	{
        return BLOCK_STATUS_UNKNOWN;
	}

    if(!(SI.bOEMReserved & OEM_BLOCK_READONLY))
	{
        dwResult |= BLOCK_STATUS_READONLY;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -