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

📄 fmd.cpp

📁 三星2440原版bsp
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    //  Read the bad block mark
    pInfo->bBadBlock = (BYTE) ((rddata>>8) & 0xff);

    //  Second reserved field (WORD)
    pInfo->wReserved2 = (WORD) ((rddata>>16) & 0xffff);

    SetChipSelect(mode,HIGH);

    SetKMode(bLastMode);
}

/*
 *  NAND_LB_WriteSectorInfo
 *
 *  Write SectorInfo out to the spare area. The current implementation only handles
 *  one sector at a time.
 */
BOOL NAND_LB_WriteSectorInfo(SECTOR_ADDR sectorAddr, PSectorInfo pInfo, int mode)
{
	volatile DWORD	wrdata;
    BOOL    bRet = TRUE;
	int NewSpareAddr = 2048 + 16*(sectorAddr%4);
	int NewSectorAddr = sectorAddr/4;

    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_WRITE);

    //  Write the address
    NF_ADDR((NewSpareAddr)&0xff);
    NF_ADDR((NewSpareAddr>>8)&0xff);
    NF_ADDR(NewSectorAddr & 0xff);
    NF_ADDR((NewSectorAddr >> 8) & 0xff);

    if (LB_NEED_EXT_ADDR) {
        NF_ADDR((NewSectorAddr >> 16) & 0xff);
    }

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

	wrdata = (DWORD)(pInfo->bOEMReserved) | (((DWORD)(pInfo->bBadBlock) << 8)&0x0000ff00) | (((DWORD)(pInfo->wReserved2) << 16)&0xffff0000);

    NF_DATA_W4( wrdata );

    //  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_LB_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_LB_WriteSectorInfo() ######## Error Programming page %d!\n"), sectorAddr));
			bRet = FALSE;
		}
	}

    SetChipSelect(mode,HIGH);

    SetKMode(bLastMode);
    return bRet;
}

//  FMD_LB_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
//

BOOL FMD_LB_ReadSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff,
                        PSectorInfo pSectorInfoBuff, DWORD dwNumSectors, int mode)
{
    DWORD       i;
    BYTE        eccBuf[8];
	volatile DWORD		rddata;
	int NewSpareAddr = 2048 + 16*(startSectorAddr%4);
	int NewDataAddr = 512*(startSectorAddr%4);
	int NewSectorAddr = startSectorAddr/4;
//	DWORD	Mecc0, Mecc1;

//	RETAILMSG(1, (TEXT("FMD::FMD_LB_ReadSector 0x%x \r\n"), startSectorAddr));
//	RETAILMSG(1, (TEXT("startSectorAddr = 0x%x \r\n"), startSectorAddr));
//	RETAILMSG(1, (TEXT("NewSpareAddr = 0x%x \r\n"), NewSpareAddr));
//	RETAILMSG(1, (TEXT("NewDataAddr = 0x%x \r\n"), NewDataAddr));
//	RETAILMSG(1, (TEXT("NewSectorAddr = 0x%x \r\n"), NewSectorAddr));

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

    if(!pSectorBuff) {
        //  We are reading spare only
//		RETAILMSG(1, (TEXT("FMD::FMD_LB_ReadSector **** Read Spare Only **** \r\n")));
        NAND_LB_ReadSectorInfo(startSectorAddr, pSectorInfoBuff, mode);

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

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

	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((NewDataAddr)&0xff);
    NF_ADDR(((NewDataAddr)>>8)&0xff);
	NF_ADDR((NewSectorAddr) & 0xff);
	NF_ADDR((NewSectorAddr >> 8) & 0xff);

	if (LB_NEED_EXT_ADDR) {
		NF_ADDR((NewSectorAddr >> 16) & 0xff);
	}

	NF_CMD(CMD_READ3);	// 2nd command

	NF_DETECT_RB();	 // Wait tR(max 12us)

	//  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/sizeof(DWORD); i++) {
			rddata = (DWORD) NF_DATA_R4();
			pSectorBuff[i*4+0] = (BYTE)(rddata & 0xff);
			pSectorBuff[i*4+1] = (BYTE)(rddata>>8 & 0xff);
			pSectorBuff[i*4+2] = (BYTE)(rddata>>16 & 0xff);
			pSectorBuff[i*4+3] = (BYTE)(rddata>>24 & 0xff);
		}
	}
	else {
		ReadPage512(pSectorBuff, pNFDATA);
    }
    //  Do the ECC thing here
    //  We read the ECC value from the ECC register pFNECC
	NF_MECC_Lock();

//	Mecc0 = READ_REGISTER_ULONG(pNFMECC0);
//	Mecc1 = READ_REGISTER_ULONG(pNFMECC1);

	NF_CMD(CMD_RDO);
	//  Set up address
    NF_ADDR((NewSpareAddr)&0xff);
    NF_ADDR(((NewSpareAddr)>>8)&0xff);
	NF_CMD(CMD_RDO2);

    //  Read the SectorInfo data
    if(pSectorInfoBuff) {
        //  Read the SectorInfo data (we only need to read first 8 bytes)
        pSectorInfoBuff->dwReserved1  = NF_DATA_R4();
		rddata = NF_DATA_R4();
		//  OEM byte
		pSectorInfoBuff->bOEMReserved = (BYTE) (rddata & 0xff);

		//  Read the bad block mark
		pSectorInfoBuff->bBadBlock = (BYTE) ((rddata>>8) & 0xff);

		//  Second reserved field (WORD)
		pSectorInfoBuff->wReserved2 = (WORD) ((rddata>>16) & 0xffff);
    }
    else {
        //  Advance the read pointer
        for(i=0; i<sizeof(SectorInfo)/sizeof(DWORD); i++) {
            rddata = (DWORD) NF_DATA_R4();		// read and trash the data
        }
    }

//	RETAILMSG(1, (TEXT("3 \r\n")));
    //  Verify the ECC values
    //
    //  Read the ECC buffer 8bytes
	for(i=0; i<2; i++) {
		rddata = (DWORD) NF_DATA_R4();
//		RETAILMSG(1, (TEXT("rddata 0x%x \r\n"), rddata));
		eccBuf[i*4+0] = (BYTE)(rddata & 0xff);
		eccBuf[i*4+1] = (BYTE)(rddata>>8 & 0xff);
		eccBuf[i*4+2] = (BYTE)(rddata>>16 & 0xff);
		eccBuf[i*4+3] = (BYTE)(rddata>>24 & 0xff);
    }

//	Mecc0 = READ_REGISTER_ULONG(pNFMECC0);

    //  Copmare with the ECC generated from the HW
	WRITE_REGISTER_ULONG(pNFMECCD0, (DWORD)((DWORD)(eccBuf[1]<<16) | (DWORD)(eccBuf[0]&0xff)));
	WRITE_REGISTER_ULONG(pNFMECCD1, (DWORD)((DWORD)(eccBuf[3]<<16) | (DWORD)(eccBuf[2]&0xff)));
//	WRITE_REGISTER_ULONG(pNFMECCD0, (DWORD)((eccBuf[5])<<24) | (DWORD)((eccBuf[1])<<16) | (DWORD)((eccBuf[4])<<8) | (DWORD)((eccBuf[0]&0xff)));
//	WRITE_REGISTER_ULONG(pNFMECCD1, (DWORD)((eccBuf[7])<<24) | (DWORD)((eccBuf[3])<<16) | (DWORD)((eccBuf[6])<<8) | (DWORD)((eccBuf[2]&0xff)));

	SetChipSelect(mode,HIGH);

//	RETAILMSG(1, (TEXT("4 \r\n")));
	if ((READ_REGISTER_ULONG(pNFESTAT0)&0x3) == 0x0){
	}
	else {
		RETAILMSG(1, (TEXT("FMD(FMD_LB_ReadSector): ECC ERROR - Page #: 0x%x \r\n"), startSectorAddr));
		return FALSE;
	}

	SetKMode(bLastMode);

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

	return TRUE;
}

//
//  LB_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 LB_IsBlockBad(BLOCK_ID blockID, int mode)
{
    DWORD   dwPageID = blockID << LB_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_READ);

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

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

	NF_CMD(CMD_READ3);

    //  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) {
		RETAILMSG(1, (TEXT("FMD: IsBlockBad - Page #: 0x%x \r\n"), dwPageID));
        bRet = TRUE;
    }

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

    SetKMode(bLastMode);
    return bRet;
}

//
//  FMD_LB_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_LB_GetBlockStatus(BLOCK_ID blockID, int mode)
{
    SECTOR_ADDR sectorAddr = blockID << LB_NAND_LOG_2_PAGES_PER_BLOCK;
    SectorInfo SI;
    DWORD dwResult = 0;

//	RETAILMSG(1, (TEXT("FMD_LB_GetBlockStatus (0x%x)0x%x \r\n"), blockID, sectorAddr));

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

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

    if(SI.bBadBlock != 0xFF)
	{
        dwResult |= BLOCK_STATUS_BAD;
	}

    return dwResult;
}




//  FMD_LB_EraseBlock
//
//  Erase the given block
//
BOOL FMD_LB_EraseBlock(BLOCK_ID blockID, int mode)
{
    BOOL    bRet = TRUE;
    DWORD   dwPageID = blockID << LB_NAND_LOG_2_PAGES_PER_BLOCK;

//	RETAILMSG(1, (TEXT("FMD_LB_EraseBlock 0x%x \r\n"), blockID));

    BOOL bLastMode = SetKMode(TRUE);

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

    //  Issue command
    NF_CMD(CMD_ERASE);

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

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

    //  Complete erase operation
    NF_CMD(CMD_ERASE2);

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

	if ( READ_REGISTER_USHORT(pNFSTAT) & STATUS_ILLACC )
	{
        RETAILMSG(1, (TEXT("LB######## Error Erasing block (Illigar Access) %d!\n"), blockID));
		WRITE_REGISTER_USHORT(pNFSTAT, STATUS_ILLACC);	// Write 1 to clear.
        bRet = FALSE;
	}
	else
	{
		//  Check the status
		NF_CMD(CMD_STATUS);

		if(NF_DATA_R() & STATUS_ERROR) {
			RETAILMSG(1, (TEXT("LB######## Error Erasing block %d!\n"), blockID));
			bRet = FALSE;
		}
	}

    SetChipSelect(mode,HIGH);

    SetKMode(bLastMode);

    return bRet;
}



//  FMD_LB_WriteSector
//
//  Write dwNumPages pages to the startSectorAddr
//
BOOL FMD_LB_WriteSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors, int mode)
{
    DWORD   i;
    BOOL    bRet = TRUE;
	volatile DWORD	wrdata;
	DWORD	Mecc0;
	int NewSpareAddr = 2048 + 16*(startSectorAddr%4);
	int NewDataAddr = 512*(startSectorAddr%4);
	int NewSectorAddr = startSectorAddr/4;

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

    //  Sanity check
    //  BUGBUGBUG: I need to come back to support dwNumSectors > 1
    //
    if((!pSectorBuff && !pSectorInfoBuff) || dwNumSectors != 1) {
        RETAILMSG(1, (TEXT("Invalid parameters!\n")));
        return FALSE;
    }

    if(!pSectorBuff) {
        //  If we are asked just to write the SectorInfo, we will do that separately
        bRet = NAND_LB_WriteSectorInfo(startSectorAddr, pSectorInfoBuff, mode);
		return bRet;			// Do not write the actual sector information...
    }

    BOOL bLastMode = SetKMode(TRUE);

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

    //  Enable Chip
    SetChipSelect(mode,LOW);

    //  Issue command
    NF_CMD(CMD_WRITE);

    //  Setup address
    NF_ADDR((NewDataAddr)&0xff);
    NF_ADDR(((NewDataAddr)>>8)&0xff);
    NF_ADDR((NewSectorAddr) & 0xff);
    NF_ADDR((NewSectorAddr >> 8) & 0xff);

    if (LB_NEED_EXT_ADDR) {
        NF_ADDR((NewSectorAddr >> 16) & 0xff);
    }

    //  Special case to handle un-aligned buffer pointer.
    //
    if( ((DWORD) pSectorBuff) & 0x3) {
        //  Write the data
        for(i=0; i<SECTOR_SIZE/sizeof(DWORD); i++) {
			wrdata = pSectorBuff[i*4+0];
			wrdata |= pSectorBuff[i*4+1]<<8;
			wrdata |= pSectorBuff[i*4+2]<<16;
			wrdata |= pSectorBuff[i*4+3]<<24;
            NF_DATA_W4(wrdata);
        }
    }
    else {
#ifndef USENANDDMA
        WritePage512(pSectorBuff, pNFDATA);
#else	// USENANDDMA
#ifdef USESETKMODE
		SetKMode(TRUE);
		v_pINTregs->rSRCPND=BIT_DMA3;	// Init DMA src pending.
#endif // USESETKMODE
		memcpy(pDMABuffer, pSectorBuff, 512);
		// Nand to memory dma setting
	    v_pDMAregs->rDISRC3  = (int)SDI_DMA_BUFFER_PHYS; 	// Nand flash data register
	    v_pDMAregs->rDISRCC3 = (0

⌨️ 快捷键说明

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