fmd_tyax.cpp

来自「该BSP是基于PXA270+WINCE的BSP」· C++ 代码 · 共 1,678 行 · 第 1/5 页

CPP
1,678
字号
                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;
#ifndef UNDER_BOOTLOADER
    BOOL bLastMode;
#endif
    LPBYTE psb_arg = pSectorBuff;

    //----- 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)))
    {
        LOGMSG(1, (TEXT("FMD_ReadSector(x%08x,x%08x): Invalid args\r\n"), startSectorAddr, dwNumSectors));
        return(FALSE);
    }
    //DBGMSG(1, (TEXT("FMD_ReadSector(x%08x,x%08x):\r\n"), startSectorAddr, dwNumSectors));

    //----- 2. Process the read request(s)... -----
#ifndef UNDER_BOOTLOADER
    bLastMode = SetKMode(TRUE);
#endif

    for (i = startSectorAddr ; i < (startSectorAddr + dwNumSectors) ; i++)
    {
        //----- Compute the physical address for the requested -----
        GetPhysicalSectorAddress(i, (PSECTOR_ADDR)&physicalSectorAddr, (PSECTOR_ADDR)&physicalSectorInfoAddr, NULL);

        //----- Read the necessary sector data -----
        if (pSectorBuff)
        {
            memcpy(pSectorBuff, (UCHAR*)physicalSectorAddr, g_FMDInfo.SectorSize);
            pSectorBuff += g_FMDInfo.SectorSize;
        }

        //----- Read the necessary SectorInfo data (metadata) -----
        if (pSectorInfoBuff)
        {
            if (g_bXIPEntire)
            {
//--------------------------------------------------------------
                NKDbgPrintfW (L"XIP -----======*****!!!!!##### ");
//--------------------------------------------------------------

                // For XIP, fill the SectorInfo with 1:1 log/phys mapping and read-only status
                memset (pSectorInfoBuff, 0xff, sizeof(SectorInfo));
                pSectorInfoBuff->dwReserved1 = startSectorAddr;
            } else
            {
//--------------------------------------------------------------
                NKDbgPrintfW (L"not XIP -----======*****!!!!!##### ");
//--------------------------------------------------------------

                // For non-XIP, The metadata bytes are physicalSectorInfoAddr read directly into the SectorInfo structure...
                if (physicalSectorInfoAddr)
                    memcpy(pSectorInfoBuff, (CONST PVOID)physicalSectorInfoAddr, sizeof(SectorInfo));
            }
            pSectorInfoBuff++;
        }
    }

#ifndef UNDER_BOOTLOADER
    SetKMode(bLastMode);
#endif
    // Check if sector may be all bits. This could indicate an erased block was never written.
    if (psb_arg)
        {
        for (i = 0; i <= 63; i++)
        {
            if (psb_arg[i] != 0xff)
                break;
        }
        if (i > 63)
            {
            unsigned long psa_s, psa_e;
            GetPhysicalSectorAddress(startSectorAddr, (PSECTOR_ADDR)&physicalSectorAddr, (PSECTOR_ADDR)&physicalSectorInfoAddr, &blockID);
            psa_s = physicalSectorAddr;
            GetPhysicalSectorAddress(startSectorAddr+dwNumSectors, (PSECTOR_ADDR)&physicalSectorAddr, (PSECTOR_ADDR)&physicalSectorInfoAddr, NULL);
            psa_e = physicalSectorAddr;
            DBGMSG(1, (TEXT("FMD_ReadSector(x%08x,x%08x): FIRST 64 BYTES ALL BITS (psa=x%08x-x%08x, blockid=x%08x)\r\n"), 
                       startSectorAddr, dwNumSectors, psa_s, psa_e, blockID));
            }
        }
    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.

                *NOTE*  This routine assumes the block has already been erased via a
                call to FMD_EraseBlock(), which will unlock and erase.

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;
#ifndef UNDER_BOOTLOADER
    BOOL bLastMode;
#endif
    LPBYTE pSectorBuffIn = pSectorBuff;
    DWORD dwBusWidth = g_bPairedFlash ? sizeof(ULONG) : sizeof(USHORT);
    LPBYTE pBuffer = pSectorBuff;
    BOOL fRet = FALSE;
    LPBYTE pTempBuffer = NULL;

    REGION_TYPE region_type;
    unsigned long *psa = 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)))
    {
        LOGMSG(1, (TEXT("FMD_WriteSector(x%08x,x%08x): invalid args\r\n"), startSectorAddr, dwNumSectors));
        return(FALSE);
    }
    GetPhysicalSectorAddress(startSectorAddr, (PSECTOR_ADDR)&physicalSectorAddr, (PSECTOR_ADDR)&physicalSectorInfoAddr, &blockID);
    region_type = g_pRegionTable[GetRegion(blockID)].regionType;
    psa = (physicalSectorAddr != NULL) ? (unsigned long *)physicalSectorAddr : NULL;
    // On read we check for all bits at the start of the sector.
    // Check on write here and log writes of all bits as well.
    if (pSectorBuff)
    {
        for (i = 0; i <= 63; i++)
        {
            if (pSectorBuff[i] != 0xff)
                break;
        }
        if (i > 63)
        {
            DBGMSG(1, (TEXT("FMD_WriteSector(x%08x,x%08x): FIRST 64 BYTES ALL BITS\r\n"), startSectorAddr, dwNumSectors));
        }
    }

    //----- 2. Process the write request(s)... -----
#ifndef UNDER_BOOTLOADER
    bLastMode = SetKMode(TRUE);
#endif

    for (i = startSectorAddr; i < (startSectorAddr + dwNumSectors); i++)
    {
        //----- Compute the physical address for the requested  (virtual blockID) -----
        GetPhysicalSectorAddress(i, (PSECTOR_ADDR)&physicalSectorAddr, (PSECTOR_ADDR)&physicalSectorInfoAddr, &blockID);

        // Compute the block address for this sector write.  Is the virtual block address.
        //
        ulBlockAddress = (ULONG)(physicalSectorAddr - (physicalSectorAddr % g_FMDInfo.BlockSize));

        if (region_type == FILESYS)
        {
            DBGMSG(1, (TEXT("FMD_WriteSector(x%08x,x%08x,x%08x,x%08x): block=x%08x,blockaddr=x%08x (1)\r\n"),
                       startSectorAddr, pSectorBuff, pSectorInfoBuff, dwNumSectors,
                       blockID, ulBlockAddress));
        }
        //----- Write the necessary sector data -----
        if (pSectorBuff)
        {

#ifndef UNDER_BOOTLOADER
            // Check for unaligned pointer.  Only need to do this if the FMD is being used as
            // a block driver and not a bootloader.
            if ((DWORD)pSectorBuff & (dwBusWidth - 1))
            {
                if (!pTempBuffer)
                {
                    if (!(pTempBuffer = (LPBYTE)LocalAlloc (LMEM_FIXED, g_FMDInfo.SectorSize)))
                    {
                        LOGMSG(1, (TEXT("FMD_WriteSector: Memory allocation failed.\r\n")));
                        goto exit;
                    }
                }
                DBGMSG(1, (TEXT("FMD_WriteSector: Unaligned pointer - using internal buffer: pTempBuffer=0x%x, pSectorBuff=0x%x, SectorSize=0x%x\r\n"), pTempBuffer, pSectorBuff, g_FMDInfo.SectorSize));
                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)
                    {
                    LOGMSG(1, (TEXT("FMD_WriteSector: DoBufferedWrite(x%08x,x%08x,x%08x) failed(1)\r\n"),
                               ulBlockAddress, physicalSectorAddr + j, NumWriteBytes));
                    last_sect_data_write_status = last_status;
                    goto exit;
                    }
            }

            pSectorBuff += g_FMDInfo.SectorSize;
            last_sect_data_write_status = last_status;
        }
        else
            {
            if (pSectorInfoBuff == NULL)
                {
                LOGMSG(1, (TEXT("FMD_WriteSector(x%08x,x%08x,x%08x,x%08x): both buffer pointers NULL\r\n"),
                           startSectorAddr, pSectorBuff, pSectorInfoBuff, dwNumSectors));
                }
            }

        //----- Write the necessary sector info data (metadata) -----
        if (!g_bXIPEntire && pSectorInfoBuff)
        {
            if (!DoBufferedWrite(ulBlockAddress, physicalSectorInfoAddr, (PUCHAR)pSectorInfoBuff, sizeof(SectorInfo)))
                {
                LOGMSG(1, (TEXT("FMD_WriteSector: DoBufferedWrite(x%08x,x%08x,x%08x) failed(2)\r\n"),
                           ulBlockAddress, physicalSectorInfoAddr, sizeof(SectorInfo)));
                last_sect_info_write_status = last_status;
                goto exit;
                }
            pSectorInfoBuff++;
            last_sect_info_write_status = last_status;
        }
    }

    fRet = TRUE;

    exit:

#ifndef UNDER_BOOTLOADER
    if (pTempBuffer)
        LocalFree (pTempBuffer);

    SetKMode(bLastMode);
#endif

#ifndef UNDER_BOOTLOADER
    // Do readback-verify:
    if (fRet && pSectorBuff)
    {
        LPBYTE pSectorBufTemp = (LPBYTE)LocalAlloc (LPTR, 0x1000 * dwNumSectors);
        DEBUGCHK (pSectorBufTemp);
        if (pSectorBufTemp && FMD_ReadSector(startSectorAddr, pSectorBufTemp, NULL, dwNumSectors))
        {
            if (0 != memcmp (pSectorBufTemp, pSectorBuffIn, 0x1000 * dwNumSectors))
            {
                NKDbgPrintfW (L"STRATAD!FMD_WriteSector: ERROR! ReadBack+Verify failed on sector %u", startSectorAddr);
                DEBUGCHK (FALSE);
            }
        }
        LocalFree(pSectorBufTemp);
    }


#endif

    return(fRet);
}


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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)
{
    DWORD dwRegion;

    // Look to see if the block is reserved
    if (IsReservedTableBlock(blockID))
    {
        //DBGMSG(1, (TEXT("FMD_GetBlockStatus:  BLOCK_STATUS_RESERVED\r\n")));
        return(BLOCK_STATUS_RESERVED);
    }

    dwRegion = GetRegion(blockID);
    if (dwRegion == INVALID_BLOCK_ID)
    {
        LOGMSG(1, (TEXT("FMD_GetBlockStatus:  BLOCK_STATUS_UNKNOWN.  GetRegion() returned 0x%x\r\n"), dwRegion));
        return(BLOCK_STATUS_UNKNOWN);
    }

    // If the block is in the XIP, return XIP status if we are in update mode,
    // otherwise in regular mode, return read-only.
    if (g_pRegionTable[dwRegion].regionType == XIP)
    {
        //DBGMSG(1, (TEXT("FMD_GetBlockStatus:  retion=XIP:  status == 0x%x (x10=XIP, x2=RO)\r\n"), g_bUpdateMode ? BLOCK_STATUS_XIP : BLOCK_STATUS_READONLY));
        return(g_bUpdateMode ? BLOCK_STATUS_XIP : BLOCK_STATUS_READONLY);
    }

    // If the block is in the READONLY_FILESYS, return READONLY status if
    // we are in not in update mode, otherwise in regular mode, return normal.
    if (g_pRegionTable[dwRegion].regionType == READONLY_FILESYS)
    {
        //DBGMSG(1, (TEXT("FMD_GetBlockStatus:  g_pRegionTable[dwRegion].regionType == READONLY_FILESYS.  Return 0\r\n")));
        //return g_bUpdateMode ? 0 : BLOCK_STATUS_READONLY;
        return(0);
    }

⌨️ 快捷键说明

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