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

📄 fmd.cpp

📁 老外的一个开源项目
💻 CPP
📖 第 1 页 / 共 3 页
字号:
VOID FMD_GetPhysSectorAddr (DWORD dwSector, PSECTOR_ADDR pStartSectorAddr)
{
    GetPhysicalSectorAddress (dwSector, pStartSectorAddr, NULL);
}


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       FMD_ReadSector()

Description:    Reads the requested sector data and/or sector metadata from the
                Flash media.

Notes:          Notice that although each byte of a NOR Flash block is individually
                addressable, the media is still logically broken up into sectors.  
                Thus, for each sector request, we must determine where this data
                resides in the respective Flash block (see note above).

                By default, the NOR Flash is configured in READ ARRAY MODE so there
                is no need to set any control lines to access the media.  The data
                can just be read directly from the media (like RAM).
                
Returns:        Boolean indicating success.
------------------------------------------------------------------------------*/
BOOL  FMD_ReadSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors)
{
    volatile SECTOR_ADDR  physicalSectorAddr = 0;
    volatile SECTOR_ADDR  physicalSectorInfoAddr = 0;
    BLOCK_ID blockID = 0;
    DWORD i = 0;
    DWORD j = 0;
	
    //----- 1. Check the input parameters -----
    //         NOTE: The FAL insures that the starting sector address is in the allowable range.
    if((dwNumSectors == 0) || ((pSectorBuff == NULL) && (pSectorInfoBuff == NULL)))
    {
        return(FALSE);
    }

    //----- 2. Process the read request(s)... -----
    
    for(i = startSectorAddr ; i < (startSectorAddr + dwNumSectors) ; i++)
    {
        //----- Compute the physical address for the requested -----
        GetPhysicalSectorAddress(i, (PSECTOR_ADDR)&physicalSectorAddr, (PSECTOR_ADDR)&physicalSectorInfoAddr);
        DEBUGMSG(1, (TEXT("FMD_ReadSector: physical address 0x%x\r\n"),physicalSectorAddr));

        //----- Read the necessary sector data -----
        if(pSectorBuff)
        {
//			if (!g_bPairedFlash)
//			{
//				for (j=0;j<g_FMDInfo.SectorSize;j++,physicalSectorAddr+=2)
//				{
// dv                    READ_FLASH(physicalSectorAddr);
//				}
//			}
//			else
//			{
//				memcpy(pSectorBuff, (UCHAR*)physicalSectorAddr, g_FMDInfo.SectorSize);
//			}
			memcpy(pSectorBuff, (UCHAR*)physicalSectorAddr, g_FMDInfo.SectorSize);
			pSectorBuff += g_FMDInfo.SectorSize;
        }

        //----- Read the necessary SectorInfo data (metadata) -----
        if(pSectorInfoBuff)
        {
            if (g_bXIPEntire)
            {
                // For XIP, fill the SectorInfo with 1:1 log/phys mapping and read-only status
                memset (pSectorInfoBuff, 0xff, sizeof(SectorInfo));
                pSectorInfoBuff->dwReserved1 = startSectorAddr;
            }
            else 
            {
                // For non-XIP, The metadata bytes are read directly into the SectorInfo structure...
                memcpy(pSectorInfoBuff, (CONST PVOID)physicalSectorInfoAddr, sizeof(SectorInfo));
            }
            pSectorInfoBuff++;
        }
    }

    return(TRUE);
}


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       FMD_WriteSector()

Description:    Writes the requested sector data and/or sector metadata to the
                Flash media.

Notes:          Notice that although each byte of a NOR Flash block is individually
                addressable, the media is still logically broken up into sectors.
                Thus, for each sector request, we must determine where to put the
                data in each respective Flash block (see note above).

                By default, the NOR Flash is configured in READ ARRAY MODE we need
                to set some control lines to prepare for the WRITE operation.

Returns:        Boolean indicating success.
------------------------------------------------------------------------------*/
BOOL  FMD_WriteSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors)
{
    volatile SECTOR_ADDR physicalSectorAddr = 0;
    volatile SECTOR_ADDR physicalSectorInfoAddr = 0;
    BLOCK_ID blockID = 0;
    DWORD i = 0;
    DWORD j = 0;
    DWORD k = 0;
    volatile ULONG ulBlockAddress = 0;
    DWORD dwBusWidth = g_bPairedFlash ? sizeof(ULONG) : sizeof(USHORT);
    LPBYTE pBuffer = pSectorBuff;
    BOOL fRet = FALSE;
    LPBYTE pTempBuffer = NULL;

    //----- 1. Check the input parameters -----
    //         NOTE: The FAL insures that the starting sector address is in the allowable range.
    if((dwNumSectors == 0) || ((pSectorBuff == NULL) && (pSectorInfoBuff == NULL)))
    {
        return(FALSE);
    }

    //----- 2. Process the write request(s)... -----


    for(i = startSectorAddr; i < (startSectorAddr + dwNumSectors); i++)
    {
        //----- Compute the physical address for the requested -----
        GetPhysicalSectorAddress(i, (PSECTOR_ADDR)&physicalSectorAddr, (PSECTOR_ADDR)&physicalSectorInfoAddr);
        DEBUGMSG(1, (TEXT("FMD_WriteSector: physical address 0x%x\r\n"),physicalSectorAddr));

        // Compute the block address for this sector write.
        //
        ulBlockAddress = (ULONG)(physicalSectorAddr - (physicalSectorAddr % g_FMDInfo.BlockSize));
        
        //----- Write the necessary sector data -----       
        if(pSectorBuff)
        {
            
#ifdef READ_FROM_REGISTRY                
            // Check for unaligned pointer.  Only need to do this if the FMD is being used as 
            // a block driver (and therefore READ_FROM_REGISTRY is set)
            if ((DWORD)pSectorBuff & (dwBusWidth - 1))
            {
                if (!pTempBuffer) {
                    if (!(pTempBuffer = (LPBYTE)LocalAlloc (LMEM_FIXED, g_FMDInfo.SectorSize))) {
                        RETAILMSG(1, (TEXT("FMD_WriteSector: Memory allocation failed.\r\n")));
                        goto exit;
                    }
                }
                RETAILMSG(1, (TEXT("FMD_WriteSector: Unaligned pointer - using internal buffer\r\n")));
                memcpy(pTempBuffer, pSectorBuff, g_FMDInfo.SectorSize);
                pBuffer = pTempBuffer;
            }
            else
#endif
            {
                pBuffer = pSectorBuff;
            }

            // from Intel: if the sector is not aligned modulo write buffer size - 
            // performance can be enhanced my doing a partial write to align the buffer 
            // for the rest of the writes to complete the sector.  If you are doing 
            // partial writes to align the buffer address, and a single word 
            // (or DWORD of x32) is being written, it is faster to use the flash's WORD  
            // write command instead of the buffered write.

            for (j = 0, k = 0 ; (j < g_FMDInfo.SectorSize) ; j += k)
            {
                // Since we're using the StrataFlash write buffer to accelerate the write operation, we need to determine how many words should be written
                // to the part(s).  The value will be the minimum of either the sector bytes remaining or the write buffer size itself (including the number
                // of flash parts/banks in the design).  Since we write the data in longword form, we assume 2 banks in our design.
                //
                USHORT NumWriteBytes = (USHORT)MIN((g_FMDInfo.SectorSize - j), g_dwWriteBufferSize);
                k = DoBufferedWrite(ulBlockAddress, physicalSectorAddr + j, pBuffer + j, NumWriteBytes);
                if (!k)
                    goto exit;
            }
            pSectorBuff += g_FMDInfo.SectorSize;
        }


        //----- Write the necessary sector info data (metadata) -----
        if (!g_bXIPEntire && pSectorInfoBuff)
        {
            if (!DoBufferedWrite(ulBlockAddress, physicalSectorInfoAddr, (PUCHAR)pSectorInfoBuff, sizeof(SectorInfo)))
                goto exit;
            pSectorInfoBuff++;            
        }
    }

    fRet = TRUE;

exit:

#ifdef READ_FROM_REGISTRY                
    if (pTempBuffer)
        LocalFree (pTempBuffer);
#endif

    //----- 3. Put the Flash back into READ ARRAY mode -----
    WRITE_COMMAND(ulBlockAddress, READ_ARRAY_CMD);

    return fRet;
}


DWORD DoBufferedWrite(volatile ULONG ulBlockAddress,
                      volatile SECTOR_ADDR physicalSectorAddr,
                      PUCHAR pBuffer,
                      USHORT NumWriteBytes)
{
    DWORD k = 0;
    DWORD dwBusWidth = g_bPairedFlash ? sizeof(ULONG) : sizeof(USHORT);

    // Let the flash know the size of the buffer we plan to send (note that this is a 0-based word count and we simulatenously
    // write it to both flash parts (upper and lower).
    DWORD dwWordCount = (NumWriteBytes / dwBusWidth) - 1;

	
	WRITE_COMMAND(ulBlockAddress, BUFFER_WRITE_CMD);
	
	if (!CheckStatus(ulBlockAddress, FALSE))
		return 0;

	if (g_bPairedFlash)
	{
		PULONG pLongBuffer = (PULONG)pBuffer;
		WRITE_ULONG (ulBlockAddress, (dwWordCount << 16) | dwWordCount);
	    
		for(k = 0 ; k < NumWriteBytes ; k += dwBusWidth)
		{
			WRITE_ULONG (physicalSectorAddr + k, *pLongBuffer++);
		}
	}
	else 
	{
		PUSHORT pShortBuffer = (PUSHORT)pBuffer;
		WRITE_USHORT (ulBlockAddress, (USHORT)dwWordCount);
	    
		for(k = 0 ; k < NumWriteBytes ; k += dwBusWidth)
		{
			WRITE_USHORT (physicalSectorAddr + k, *pShortBuffer++);        
		}
	}        

	// Now program the buffer into flash...
	//
	WRITE_COMMAND(ulBlockAddress, BLOCK_PROCEED_CMD);

	if (!CheckStatus(ulBlockAddress, FALSE))
		return 0;

    return NumWriteBytes;
}

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       FMD_GetBlockStatus()

Description:    Returns the status of a block.  For read-only blocks, checks the sector 
        info data for the first sector of the block.  Block is always good, so no need to check.

Returns:        Block status.
------------------------------------------------------------------------------*/
DWORD FMD_GetBlockStatus(BLOCK_ID blockID)
{
    SECTOR_ADDR Sector = blockID * g_FMDInfo.SectorsPerBlock;
    SectorInfo SI;
    DWORD dwResult = 0;

    if (!FMD_ReadSector(Sector, NULL, &SI, 1)) 
        return BLOCK_STATUS_UNKNOWN;

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

    if (!(SI.bOEMReserved & OEM_BLOCK_RESERVED))  
        dwResult |= BLOCK_STATUS_RESERVED;

    return dwResult;
}

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       FMD_SetBlockStatus()

Description:    Sets the status of a block.  

Returns:        TRUE if no errors in setting.
------------------------------------------------------------------------------*/

BOOL FMD_SetBlockStatus(BLOCK_ID blockID, DWORD dwStatus)
{
    if (dwStatus & (BLOCK_STATUS_READONLY | BLOCK_STATUS_RESERVED)) {
        
        SECTOR_ADDR Sector = blockID * g_FMDInfo.SectorsPerBlock;
        SectorInfo SI;

        if (!FMD_ReadSector(Sector, NULL, &SI, 1)) {
            return FALSE;
        }

        if (dwStatus & BLOCK_STATUS_READONLY) {
            SI.bOEMReserved &= ~OEM_BLOCK_READONLY;
        }
        
        if (dwStatus & BLOCK_STATUS_RESERVED) {
            SI.bOEMReserved &= ~OEM_BLOCK_RESERVED;
        }

        if (!FMD_WriteSector (Sector, NULL, &SI, 1)) {
            return FALSE;
        }

    }    
    
    return TRUE;
}


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       FMD_EraseBlock()

Description:    Erases the specified Flash block.

Returns:        Boolean indicating success.
------------------------------------------------------------------------------*/
BOOL  FMD_EraseBlock(BLOCK_ID blockID)
{
    volatile ULONG ulBlockAddress = 0;
    BOOL bRetVal = TRUE;
    BYTE cNullSignature[BLOCK_SIG_BYTES]  = {0};
    
    // Determine the address for the specified block.
    ulBlockAddress  =  g_FMDInfo.BaseAddress + (blockID * g_FMDInfo.BlockSize);
    DEBUGMSG(1, (TEXT("FMD_EraseBlock: physical address 0x%x\r\n"),ulBlockAddress));

    // Whack the block signature
    if (!SignBlock(ulBlockAddress, cNullSignature))
    {
        DEBUGMSG(1, (TEXT("FMD_EraseBlock: Unable to whack block signature\r\n")));
        bRetVal = FALSE;
        goto Error;
    }

    // Issue erase and confirm command.
    // Note: eventually this should be changed to issue mass block erases, then loop to
    // verify each completes.
    WRITE_COMMAND(ulBlockAddress, BLOCK_ERASE_CMD);
    WRITE_COMMAND(ulBlockAddress, BLOCK_PROCEED_CMD);

    if (!CheckStatus (ulBlockAddress, FALSE))
    {
        bRetVal = FALSE;     
        goto Error;
    }

    // Sign the block
    if (!SignBlock(ulBlockAddress, (PUCHAR) gc_dwBlockSig))
    {
        DEBUGMSG(1, (TEXT("FMD_EraseBlock: Unable to create block signature\r\n")));
        bRetVal = FALSE;
        goto Error;
    }

Error:
    
    // Set the block back to read array mode...
    WRITE_COMMAND(ulBlockAddress, READ_ARRAY_CMD);

    return bRetVal;
}


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       FMD_PowerUp()

Description:    Restores power to the Flash memory device (if applicable).

⌨️ 快捷键说明

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