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

📄 fmd.cpp

📁 Freescale ARM11系列CPU MX31的WINCE 5.0下的BSP
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//-----------------------------------------------------------------------------
//
//  Copyright (c) Microsoft Corporation.  All rights reserved.
//
//  Use of this source code is subject to the terms of the Microsoft end-user
//  license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
//  If you did not accept the terms of the EULA, you are not authorized to use
//  this source code. For a copy of the EULA, please see the LICENSE.RTF on
//  your install media.
//
//-----------------------------------------------------------------------------
//
//  Copyright (C) 2004, Motorola Inc. All Rights Reserved
//
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
//
//  File:  fmd.cpp
//
//  Provides the implementation of the NOR block driver FMD layer.
//
//	IMPORTANT!:
//	The Microsoft block driver is not designed for NOR driver XIP. Thus, this
//	driver can be used XIP in flash ONLY WHEN the NOR flash part used supports
//	SIMULTANEOUS READ/WRITE/ERASE. Since most flash parts support this only 
//	when operating on different banks. Care must be taken in choosing the FMD
//	storage area to ensure that it occupies a DIFFERENT BANK from the OS image.
//
//-----------------------------------------------------------------------------
#include <windows.h>
#include <ddkreg.h>
#include <psapi.h>
#include <fmd.h>

#include "debug.h"
#include "nor.h"
//------------------------------------------------------------------------------
// External Variables

//------------------------------------------------------------------------------
// Defines
#define MAX(a, b)   ( ((a) > (b))? (a) : (b) )
#define MIN(a, b)   ( ((a) < (b))? (a) : (b) )

#define SECTOR_SIZE             512     // Number of data bytes in a sector

#ifndef KERNEL_MODE
#define READ_FROM_REGISTRY      1
#endif

#define INITIAL_MMAP_SIZE       0x02000000
//------------------------------------------------------------------------------
// Types
typedef struct _NOR_FMD_FLASH_INFO {
    ULONG BaseAddress;              // Base address of flash part
    ULONG FlashLength;              // Flash size
    ULONG FMDBaseOffset;            // Offset of FMD region from flash base
    ULONG FMDLength;                // size of FMD region
    ULONG SectorInfoOffset;         // Offset of sector meta info from block start
    WORD BytesPerSector;            // Logical sector size
    WORD SectorsPerBlock;           // Num of logical sector+meta info per block
    DWORD NumBlocks;                // Number of blocks used by FMD driver
    ULONG EraseBlockSize;           // Physical erase block size
    BOOL bIsPairedFlash;
    ULONG ulDeviceWidth;
} NOR_FMD_FLASH_INFO, *PNOR_FMD_FLASH_INFO;

//------------------------------------------------------------------------------
// Global Variables

//------------------------------------------------------------------------------
// Local Variables

static NOR_FMD_FLASH_INFO g_FMDInfo;
static BOOL g_bXIPMode = FALSE;

static ULONG *g_pNORFlashBase = NULL;
static BYTE *g_pAlignBuf = NULL;
//------------------------------------------------------------------------------
// Local Functions
static BOOL DefineLayout(BOOL bIsPairedFlash, CFI_FLASH_GEOMETRY_INFO *pGeomtry, NOR_FMD_FLASH_INFO *pInfo);
static void GetPhysicalSectorAddress(DWORD dwSector, PSECTOR_ADDR pStartSectorAddr, PSECTOR_ADDR pStartSectorInfoAddr);
static void GetMappedSectorAddress(DWORD dwSector, PSECTOR_ADDR pStartSectorAddr, PSECTOR_ADDR pStartSectorInfoAddr);
static BOOL SetBlockLock(BLOCK_ID blockID, ULONG NumBlocks, BOOL bLock);

//-----------------------------------------------------------------------------
// EXPORTED FUNCTIONS
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
//
// Function: FMD_Init
//
// Function Initializes the flash memory of a device.
//
// Parameters:
//      lpActiveReg
//          [in] Ptr to the active registry string to find device info from
//				 registry. Set to NULL if not needed.
//
//      pRegIn
//          [in] Ptr to a PCI_REG_INFO structure. Used to find flash on PCI
//				 hardware. Set to NULL if not needed.
//
//      pRegOut
//          [in/out] Ptr to a PCI_REG_INFO structure. Used to return flash
//					 information. Set to NULL if not needed.
//
// Returns:
//      0 on failure
//
//-----------------------------------------------------------------------------
PVOID FMD_Init(LPCTSTR lpActiveReg, PPCI_REG_INFO pRegIn, PPCI_REG_INFO pRegOut)
{
    ULONG BaseAddress;
    ULONG FlashLength;
    ULONG FMDLength;
    CFI_FLASH_GEOMETRY_INFO Geometry;
    BOOL bLastMode;

#ifdef DEBUG
    extern DBGPARAM dpCurSettings;
    dpCurSettings.ulZoneMask |= (ZONEMASK_INFO | ZONEMASK_ERROR);
#endif

    DEBUGMSG(ZONE_FUNCTION, (TEXT("FMD_Init+\r\n")));

    bLastMode = SetKMode(TRUE);
#if READ_FROM_REGISTRY
    if(lpActiveReg != NULL)
    {
        DDKWINDOWINFO dwi;
        HKEY hConfig;

        // Get flash information from the registry.
        hConfig = OpenDeviceKey((LPCTSTR)lpActiveReg);        
        if(hConfig == NULL)
        {
            ERRORMSG(ZONE_ERROR, (TEXT("ERROR: FMD_Init: OpenDeviceKey failed.\r\n")));
            goto _errExit;
        }
        dwi.cbSize = sizeof(dwi);
        if(DDKReg_GetWindowInfo(hConfig, &dwi) != ERROR_SUCCESS)
        {
            ERRORMSG(ZONE_ERROR, (TEXT("ERROR: FMD_Init: DDKReg_GetWindowInfo() failed.\r\n")));
            goto _errExit;
        }
        if(dwi.dwNumIoWindows == 1)
        {
            // The IO window contains the flash physical base address and  
            // size of FMD storage area. 
            // NOTE: FMD storage area is defined to be at the end of flash.
            // ie. FMD area start = flash end - FMD length
            BaseAddress = (ULONG)(dwi.ioWindows[0].dwBase);
            FMDLength = (ULONG)(dwi.ioWindows[0].dwLen);
        }
        else
        {
            ERRORMSG(ZONE_ERROR, (TEXT("ERROR: FMD_Init: Invalid memory windows information.\r\n")));
            goto _errExit;
        }
    }
#else
    // Get flash base address and length from caller.
    if(!pRegIn || !pRegIn->IoBase.Num || !pRegIn->IoLen.Num)
    {
        ERRORMSG(ZONE_ERROR, (TEXT("ERROR: FMD_Init: invalid flash memory base and/or length specified by caller.\r\n")));
        goto _errExit;
    }
    else
    {
        // The IO window contains the flash physical base address and  
        // size of FMD storage area. 
        // NOTE: FMD storage area is defined to be at the end of flash.
        // ie. FMD area start = flash end - FMD length
        BaseAddress = (ULONG)pRegIn->IoBase.Reg[0];
        FMDLength = (ULONG)pRegIn->IoLen.Reg[0];
    }
#endif    // READ_FROM_REGISTRY.

    // Sanity check
    if(BaseAddress == 0 || FMDLength == 0)
    {
        ERRORMSG(ZONE_ERROR, (TEXT("ERROR: FMD_Init: invalid flash values: base 0x%08X FMD length 0x%08X\r\n"), 
                                BaseAddress, FMDLength));
        goto _errExit;
    }
    else
    {
        g_FMDInfo.BaseAddress = BaseAddress;
        g_FMDInfo.FMDLength = FMDLength;
    }
    DEBUGMSG(ZONE_INFO, (TEXT("INFO: Flash base: 0x%08X FMD length: 0x%08X\r\n"), BaseAddress, FMDLength));

#ifndef KERNEL_MODE
    // Memmap flash for access
    PHYSICAL_ADDRESS phyAddr;

    phyAddr.QuadPart = BaseAddress;
    // TODO: Investigate why unable to map 64Mb. 
    // Possible: Because of current RAM == 64Mb only or some other reason.
    g_pNORFlashBase = (ULONG *)MmMapIoSpace(phyAddr, INITIAL_MMAP_SIZE, FALSE);
    if(!g_pNORFlashBase)
    {
        ERRORMSG(ZONE_ERROR, (TEXT("FMD_Init: MmMapIoSpace NOR mem failed %d\r\n"), GetLastError()));
        goto _errExit;
    }
#else
    g_pNORFlashBase = (ULONG *)OALPAtoUA(BaseAddress);
#endif	
    DEBUGMSG(ZONE_INFO, (TEXT("INFO: Mapped Flash Base 0x%08X\r\n"), g_pNORFlashBase));
    
    // Initialize flash
    DEBUGMSG(ZONE_FUNCTION, (TEXT("Initializing NOR flash library (base 0x%08X)"), g_pNORFlashBase));
    if(!NORLibInit((ULONG)g_pNORFlashBase, 0, 0))
    {
        ERRORMSG(ZONE_ERROR, (TEXT("\r\nERROR: Failed NOR flash driver init!\r\n")));
        goto _errExit;
    }
    else
    	DEBUGMSG(ZONE_FUNCTION, (TEXT("Success.\r\n")));

    // Get flash geometry info.
    if(!NORGetGeometry(&Geometry))
    {
        ERRORMSG(ZONE_ERROR, (TEXT("FMD_Init: Unable to get NOR geometry information!\r\n")));
        goto _errExit;
    }
    
    // Get Flash device and bus width information
    if(!NORGetDeviceWidth(&g_FMDInfo.bIsPairedFlash, &g_FMDInfo.ulDeviceWidth))
    {
        ERRORMSG(ZONE_ERROR, (TEXT("FMD_Init: Unable to get NOR device and bus width information!S\r\n")));
        goto _errExit;
    }
    FlashLength = g_FMDInfo.bIsPairedFlash? 2 * (1 << Geometry.DevSize) : (1 << Geometry.DevSize);
    
    DEBUGMSG(ZONE_INFO, (TEXT("Detected flash length 0x%08X FMD size 0x%08X!\r\n"), FlashLength, FMDLength));
    
    // Sanity check
    if(FlashLength == 0 || FlashLength < FMDLength)
    {
        ERRORMSG(ZONE_ERROR, (TEXT("FMD_Init: invalid flash length and/or FMD base offset!\r\n")));
        ERRORMSG(ZONE_ERROR, (TEXT("Flash base: 0x%08X Flash length: 0x%08X\r\n"), BaseAddress, FlashLength));
        goto _errExit;
    }
    else
    {
        g_FMDInfo.FlashLength = FlashLength;
        g_FMDInfo.FMDBaseOffset = FlashLength - FMDLength;
        DEBUGMSG(ZONE_INFO, (TEXT("INFO: Flash length: 0x%08X FMDBaseOffset 0x%08X\r\n"), 
                            FlashLength, g_FMDInfo.FMDBaseOffset));
    }

#ifndef KERNEL_MODE
    if(FlashLength != INITIAL_MMAP_SIZE)
    {
        MmUnmapIoSpace(g_pNORFlashBase, 0);

        // TODO: Check why MmMapIoSpace fails for 64MB size.
        // Remap whole flash for access
        phyAddr.QuadPart = BaseAddress;
        g_pNORFlashBase = (ULONG *)MmMapIoSpace(phyAddr, FlashLength, FALSE);
        if(!g_pNORFlashBase)
        {
            ERRORMSG(ZONE_ERROR, (TEXT("FMD_Init: 2nd MmMapIoSpace NOR mem failed %d\r\n"), GetLastError()));
            goto _errExit;
        }

        // Need to reinit the NOR lib again
        // Initialize flash
        DEBUGMSG(ZONE_FUNCTION, (TEXT("2nd initialize NOR flash library (base 0x%08X)"), g_pNORFlashBase));
        if(!NORLibInit((ULONG)g_pNORFlashBase, 0, 0))
        {
            ERRORMSG(ZONE_ERROR, (TEXT("\r\nERROR: Failed NOR flash driver init!\r\n")));
            goto _errExit;
        }
        else
    	    DEBUGMSG(ZONE_FUNCTION, (TEXT("Success.\r\n")));
    }
#endif

    // Define logical flash layout
    if(!DefineLayout(g_FMDInfo.bIsPairedFlash, &Geometry, &g_FMDInfo))
    {
        ERRORMSG(ZONE_ERROR, (TEXT("ERROR: FMD_Init: Defining logical flash layout failed!\r\n")));
        goto _errExit;
    }

    // Allocate alignment buffer
    g_pAlignBuf = (BYTE *)LocalAlloc(LMEM_FIXED, g_FMDInfo.BytesPerSector);
    if(!g_pAlignBuf)
    {
        ERRORMSG(ZONE_ERROR, (TEXT("FMD_Init failed alignment buffer allocation\r\n")));
    }
    
    DEBUGMSG(ZONE_FUNCTION, (TEXT("FMD_Init- 0x%08X\r\n"), g_pNORFlashBase));

    SetKMode(bLastMode);
    return g_pNORFlashBase;

_errExit:
    if(g_pNORFlashBase)
    	MmUnmapIoSpace(g_pNORFlashBase, 0);
    if(g_pAlignBuf)
        LocalFree(g_pAlignBuf);
    SetKMode(bLastMode);
    return NULL;
}

//-----------------------------------------------------------------------------
//
// Function: FMD_Deinit
//
// Function De-initializes the flash driver.
//
// Parameters:
//      hFMD 
//          [in] handle returned by FMD_Init.
//

⌨️ 快捷键说明

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