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

📄 fmd.cpp

📁 mx27 f14v2 源代码。包括ADS板上诸多驱动的源码。
💻 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
//
//------------------------------------------------------------------------------
//
// Copyright (C) 2004-2006, Freescale Semiconductor, Inc. All Rights Reserved.
// THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS
// AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT
//
//------------------------------------------------------------------------------
//
// 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

⌨️ 快捷键说明

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