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

📄 fmd.cpp

📁 我自己编译的armv4i wince60模拟器的bps源文件,已经验证可以使用,欢迎下载
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
#include <am29lv800.h>
#include <bsp.h>
#include "fmd.hxx"


#ifdef DEBUG
#undef ZONE_INIT
#undef ZONE_ERROR

#define ZONE_INIT       DEBUGZONE(14)
#define ZONE_ERROR      DEBUGZONE(15)
#endif // DEBUG


#ifdef UNDER_BOOTLOADER
// Define a fake LocalFree so we can build. No one should be calling this.
HLOCAL LocalFree(HLOCAL hMem) {
    ASSERT(FALSE);
    return 0;
}
#else
#include <creg.hxx>
#include <ddkreg.h>
#endif



// Assume there will be no more than 16 reserved regions
#define MAX_RESERVES    16

// Assume there will be no more than 16 regions
#define MAX_REGIONS     16

#define DEFAULT_COMPACTION_BLOCKS 4


class CNorFmd : public CFmd {
public:
    CNorFmd() : CFmd() {
        m_dwBaseAddr = 0;
        m_dwLength = 0;

        m_cbSector = 0;
        m_cbBlock = 0;
        
        m_cBlocks = 0;
        m_cRegions = 0;
        m_cReserved = 0;
        
        m_fXIPEntire = FALSE;
        m_fUpdateMode = FALSE;

#ifndef UNDER_BOOTLOADER
        m_pReservedTable = NULL;
        m_pRegionTable = NULL;
        m_pStartSectorTable = NULL;
#endif
    }

    virtual ~CNorFmd() {}

    virtual PVOID Init(LPCTSTR lpActiveReg, PPCI_REG_INFO pRegIn, PPCI_REG_INFO pRegOut) = 0;
    
    virtual BOOL  Deinit(PVOID pv) {
        ASSERT(pv == VALID_FMD_HANDLE);

#ifndef UNDER_BOOTLOADER
        if (m_pReservedTable) LocalFree(m_pReservedTable);
        if (m_pRegionTable) LocalFree(m_pRegionTable);
        if (m_pStartSectorTable) LocalFree(m_pStartSectorTable);
#endif

        return TRUE;
    }

    virtual BOOL  GetInfo(PFlashInfo pFlashInfo) {        
        pFlashInfo->flashType = NOR;
        pFlashInfo->dwNumBlocks = m_cBlocks;
        pFlashInfo->dwBytesPerBlock = m_cbBlock;
        pFlashInfo->wSectorsPerBlock = (WORD) m_pRegionTable[0].dwSectorsPerBlock;
        pFlashInfo->wDataBytesPerSector = (WORD) m_cbSector;

        return TRUE;
    }

    virtual BOOL  GetInfoEx(PFlashInfoEx pFlashInfo, PDWORD pdwNumRegions) {
        if (!pdwNumRegions) {
            return FALSE;
        }    
        
        if (!pFlashInfo) {
            // Return required buffer size to caller
            *pdwNumRegions = m_cRegions;
            return TRUE;
        }

        if (*pdwNumRegions < m_cRegions) {
            *pdwNumRegions = m_cRegions;
            DEBUGMSG(ZONE_ERROR, (TEXT("FMD_GetInfoEx: Insufficient buffer for number of regions")));
            return FALSE;
        }

        PREFAST_SUPPRESS(386, "Already adjusted size above.");
        memcpy (pFlashInfo->region, m_pRegionTable, m_cRegions * sizeof(FlashRegion));

        *pdwNumRegions = m_cRegions;

        pFlashInfo->cbSize = sizeof(FlashInfoEx);

        pFlashInfo->flashType = NOR;
        pFlashInfo->dwNumBlocks = m_cBlocks;
        pFlashInfo->dwDataBytesPerSector = m_cbSector;
        pFlashInfo->dwNumRegions = m_cRegions;

        return TRUE;
    }


    virtual VOID  GetPhysSectorAddr(DWORD dwSector, PSECTOR_ADDR pStartSectorAddr) {
        GetPhysicalSectorAddress(dwSector, pStartSectorAddr, NULL);
    }


    virtual DWORD GetBlockStatus(BLOCK_ID blockID)
    {        
        // Look to see if the block is reserved
        if (IsReservedTableBlock(blockID))
            return BLOCK_STATUS_RESERVED;

        DWORD dwRegion = GetRegion(blockID);
        if (dwRegion == INVALID_BLOCK_ID) 
            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 (m_pRegionTable[dwRegion].regionType == XIP)
            return m_fUpdateMode ? 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 (m_pRegionTable[dwRegion].regionType == READONLY_FILESYS)
            //return g_bUpdateMode ? 0 : BLOCK_STATUS_READONLY;
            return 0;
        
        SECTOR_ADDR Sector = GetStartSectorInBlock(blockID);
        if (Sector == INVALID_SECTOR_ADDR)
            return BLOCK_STATUS_UNKNOWN;
        
        SectorInfo SI;
        DWORD dwResult = 0;

        if (!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;

        DEBUGMSG(ZONE_INIT, (TEXT("FMD_GetBlockStatus(0x%x)=0x%x\r\n"), blockID, dwResult));

        return dwResult;
    }


    virtual DWORD SetBlockStatus(BLOCK_ID blockID, DWORD dwStatus) {
        DEBUGMSG(ZONE_INIT, (TEXT("FMD_SetBlockStatus(0x%x, 0x%x)\r\n"), blockID, dwStatus));

        // Don't allow setting block status for reserved or XIP blocks.
        if (IsReservedTableBlock(blockID))
            return FALSE;

        DWORD dwRegion = GetRegion(blockID);
        if (dwRegion == INVALID_BLOCK_ID) 
            return FALSE;
        
        if (m_pRegionTable[dwRegion].regionType == XIP)
            return FALSE;
        
        if (dwStatus & (BLOCK_STATUS_READONLY | BLOCK_STATUS_RESERVED)) {
            
            SECTOR_ADDR Sector = GetStartSectorInBlock(blockID);
            if (Sector == INVALID_SECTOR_ADDR)
                return FALSE;

            SectorInfo SI;

            if (!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 (!WriteSector (Sector, NULL, &SI, 1)) {
                return FALSE;
            }

        }    
        
        return TRUE;
    }


    virtual BOOL  EraseBlock(BLOCK_ID blockID) = 0;

    virtual BOOL  ReadSector (SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors)
    {        
        DEBUGMSG(ZONE_INIT, (TEXT("FMD_ReadSector(0x%x, 0x%x, 0x%x, 0x%x)\r\n"), startSectorAddr, pSectorBuff, pSectorInfoBuff, dwNumSectors));
	
        //----- 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(DWORD i = startSectorAddr ; i < (startSectorAddr + dwNumSectors) ; i++)
        {
            //----- Compute the physical address for the requested -----
            volatile SECTOR_ADDR  physicalSectorAddr;
            volatile SECTOR_ADDR  physicalSectorInfoAddr;
            
            GetPhysicalSectorAddress(i, (PSECTOR_ADDR)&physicalSectorAddr, (PSECTOR_ADDR)&physicalSectorInfoAddr);

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

            //----- Read the necessary SectorInfo data (metadata) -----
            if(pSectorInfoBuff)
            {
                if (m_fXIPEntire)
                {
                    // 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 physicalSectorInfoAddr read directly into the SectorInfo structure...
                    if (physicalSectorInfoAddr)
                        memcpy(pSectorInfoBuff, (CONST PVOID)physicalSectorInfoAddr, sizeof(SectorInfo));
                }
                pSectorInfoBuff++;
            }
        }

        return(TRUE);
    }

    virtual BOOL  WriteSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors) = 0;

    virtual BOOL  OEMIoControl(DWORD dwIoControlCode, PBYTE pInBuf, DWORD nInBufSize, PBYTE pOutBuf, DWORD nOutBufSize, PDWORD pBytesReturned);


protected:
    BOOL IsReservedTableBlock (BLOCK_ID dwBlock)
    {
        for (DWORD i = 0; i < m_cReserved; i++)
        {
            if (dwBlock >= m_pReservedTable[i].dwStartBlock &&
                dwBlock <= (m_pReservedTable[i].dwStartBlock + m_pReservedTable[i].dwNumBlocks - 1))
            {
                return TRUE;
            }
        }

        return FALSE;
    }

    DWORD GetRegion (DWORD dwBlock)
    {
        for (DWORD i = 0; i < m_cRegions; i++) 
        {        
            if (dwBlock >= m_pRegionTable[i].dwStartPhysBlock &&
                dwBlock < (m_pRegionTable[i].dwStartPhysBlock + m_pRegionTable[i].dwNumPhysBlocks))
            {
                return i;
            }
        }

        DEBUGMSG(ZONE_ERROR, (TEXT("GetRegion: Could not find region for block 0x%x.\r\n"), dwBlock));   
        ASSERT(0);
        return INVALID_BLOCK_ID;
    }

    SECTOR_ADDR GetStartSectorInBlock (DWORD dwBlock)
    {
        DWORD i = GetRegion(dwBlock);
        if (i == INVALID_BLOCK_ID)
            return INVALID_SECTOR_ADDR;

        // The starting sector in the block is the starting physical sector
        // of the region plus the block offset into the region times
        // the sectors per block
        
        return m_pStartSectorTable[i] + (dwBlock - m_pRegionTable[i].dwStartPhysBlock) * 
            m_pRegionTable[i].dwSectorsPerBlock;
    }
    
    virtual VOID GetPhysicalSectorAddress(DWORD dwSector, PSECTOR_ADDR pStartSectorAddr, PSECTOR_ADDR pStartSectorInfoAddr) {
        for (DWORD i = 0; i < m_cRegions; i++) 
        {
            // Determine the region this physical sector resides in
            if (dwSector >= m_pStartSectorTable[i] &&
               ((i == m_cRegions - 1) || (dwSector < m_pStartSectorTable[i+1])))
            {
                DWORD dwSectorOffsetInRegion = dwSector - m_pStartSectorTable[i];
                DWORD dwBlockID = dwSectorOffsetInRegion / m_pRegionTable[i].dwSectorsPerBlock + m_pRegionTable[i].dwStartPhysBlock;
                DWORD dwSectorOffsetInBlock = dwSectorOffsetInRegion % m_pRegionTable[i].dwSectorsPerBlock;
                
                // Determine physical address of the block
                SECTOR_ADDR BlockAddr = m_dwBaseAddr + (dwBlockID * m_cbBlock);

                // Determine the physical address of the sector
                *pStartSectorAddr = BlockAddr + (dwSectorOffsetInBlock * m_cbSector);

                // If this is a region with SectorInfo, return the address of the start of sector info, which
                // is located immediatly after the sector data for all the sectors in the block.
                if (pStartSectorInfoAddr && m_pRegionTable[i].regionType != XIP) {
                    *pStartSectorInfoAddr = BlockAddr + (m_pRegionTable[i].dwSectorsPerBlock * m_cbSector) + (dwSectorOffsetInBlock * sizeof(SectorInfo));
                }

                return;
            }

⌨️ 快捷键说明

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