fmd_tyax.cpp
来自「该BSP是基于PXA270+WINCE的BSP」· C++ 代码 · 共 1,678 行 · 第 1/5 页
CPP
1,678 行
//
// 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 2000-2004 Intel Corporation All Rights Reserved.
**
** Portions of the source code contained or described herein and all documents
** related to such source code (Material) are owned by Intel Corporation
** or its suppliers or licensors and is licensed by Microsoft Corporation for distribution.
** Title to the Material remains with Intel Corporation or its suppliers and licensors.
** Use of the Materials is subject to the terms of the Microsoft license agreement which accompanied the Materials.
** No other license under any patent, copyright, trade secret or other intellectual
** property right is granted to or conferred upon you by disclosure or
** delivery of the Materials, either expressly, by implication, inducement,
** estoppel or otherwise
** Some portion of the Materials may be copyrighted by Microsoft Corporation.
*/
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Module Name: FMD.CPP
Abstract: FLASH Media Driver Interface for Intel XXXXXX StrataFlash Chip
Notes: The FAL expects the Flash media to be broken up into Flash blocks
which are then subdivided into physical sectors. Some types of
Flash memory (i.e. NAND Flash) already have this layout. NOR Flash,
on the other hand, DOES NOT breakup each Flash block into physical
sectors. Instead, each byte is individually addressable (like RAM).
Despite this characteristic, NOR Flash can still logically be broken
up into discrete sectors as follows:
NOR Flash
Sector Data SectorInfo
---------------------------------
|Sector(0) | |
|Sector(1) | |
|Sector(2) | | Block 0
|... | |
|Sector(k) | |
| XXXXXXXXX
-------------------------------
|Sector(k+1) | |
|Sector(k+2) | |
|Sector(k+3) | | Block 1
|... | |
|Sector(2k) | |
| XXXXXXXXX
-------------------------------
| | |
| | |
| | | Block 2
| | |
| | |
| XXXXXXXXX
------------------------------- ...
| | |
| | |
| | | Block N
| | |
| | |
| XXXXXXXXX
---------------------------------
That is, each NOR Flash block is logically subdivided into a "page", where each page
contains space for sector data and SectorInfo metadata. Most often, Flash blocks are
a power of 2 in size but the size of a page is not a power of 2 (i.e. 512 + 8 = 520 bytes).
Thus, each Flash block DOES NOT evenly divide into an integral number of pages and some
bytes in a block are left unused. These unused bytes are denoted above by XXXXX's.
To help clarify how this process works, consider the following example: suppose you have
a NOR Flash memory device that contains 256 Flash blocks each 256K in size. From these
size characteristics, we find:
(256K / (512+8)) ==> 504 sectors + 64 unused bytes
Therefore, each Flash block can map 504 sectors (including SectorInfo metadata) and leave
64 unused bytes per block. Notice that 8 bytes is used for the SectorInfo metadata although
the SectorInfo structure is currently only 6 bytes. The reason for this is to make sure that
all sector addresses are DWORD aligned (i.e. 520 divides by 4 evenly while 518 doesn't divide
by 4 evenly). Furthemore, we see that this NOR Flash memory can map (504*256)==>129,024 physical
sectors.
---------------------------------------------------------------
Intel Notes:
It should be noted that Tyax FLASH devices have 2 fixed block sizes, and come in 2 packages.
Tyax is organized as seperate paritions. One can read from one partition while erasing/writing the other.
These partitions, each 8mbit, contain n blocks. Block sizes vary:
Partition Types (number of parameter and main partitions vary depending on package size):
- Parameter Partition: contains 4-32KB (16KW) blocks either at the bottom or top of the address space.
- Main Partition: contains all 128KB (64KW) blocks.
Partition Locations (part dependent and can be identified by the Device Id code):
- Top Parameter parts:
------------------------
| 32KB Block | HIGH
------------------------
| 32KB Block |
------------------------
| 32KB Block |
------------------------
| 32KB Block |
------------------------
| 128KB Block |
------------------------
| 128KB Block |
------------------------
| 128KB Block |
| |
(...)
------------------------
| 128KB Block | LOW
------------------------
- Bottom Parameter parts:
------------------------
| 128KB Block | HIGH
------------------------
| 128KB Block |
------------------------
| 128KB Block |
| |
(...)
------------------------
| 128KB Block |
------------------------
| 32KB Block |
------------------------
| 32KB Block |
------------------------
| 32KB Block |
------------------------
| 32KB Block | LOW
------------------------
---------------------------------------------------------------
Two other points are worth mentioning:
1) NOR Flash memory is guaranteed by manufacturing to ship with no bad Flash blocks.
2) NOR Flash memory doesn't suffer from electrical leakage currents (like NAND Flash) and
does not require error-correction codes (ECC) to insure data integrity.
Environment: As noted, this media driver works on behalf of the FAL to directly
access the underlying FLASH hardware. Consquently, this module
needs to be linked with FAL.LIB to produce the device driver
named FLASHDRV.DLL.
-----------------------------------------------------------------------------*/
#define ENABLE_DEBUG_MESSAGES 0
#define ENABLE_LOG_MESSAGES 1
#if ENABLE_DEBUG_MESSAGES
#define DBGMSG(cond, pargs) NKDbgPrintfW pargs
#else
#define DBGMSG(cond, pargs) 0
#endif
#if ENABLE_LOG_MESSAGES
#define LOGMSG(cond, pargs) NKDbgPrintfW pargs
#else
#define LOGMSG(cond, pargs) 0
#endif
#define LOGGING_ENABLED (ENABLE_DEBUG_MESSAGES || ENABLE_LOG_MESSAGES)
#if LOGGING_ENABLED
#include <windows.h> // for NKDbgPrintfW()
#endif
#include <fmd.h>
#include <ceddk.h>
#include "tyax.h"
#include "fmdhal.h"
#ifdef READ_FROM_REGISTRY
#include <ddkreg.h>
#else
#define UNDER_BOOTLOADER
#endif // READ_FROM_REGISTRY.
//#define UNDER_BOOTLOADER
//#undef READ_FROM_REGISTRY
#ifdef UNDER_BOOTLOADER
#include <stdio.h>
#undef FMD_FLASH_GLOBAL_MUTEX
#endif
/* -----------------------------------------------------------------------------*/
/* Internal Helper function prototypes
/* -----------------------------------------------------------------------------*/
static BOOLEAN SetBlockLock(DWORD blockID, ULONG NumBlocks, BOOL bLock);
static BOOL ReadWriteReserved (PReservedReq pReq, BOOL fRead);
static BOOL RawWriteBlocks (PRawWriteBlocksReq pReq);
static BOOL IsReservedTableBlock (BLOCK_ID dwBlock);
static DWORD GetRegion (DWORD dwBlock);
static SECTOR_ADDR GetStartSectorInBlock (DWORD dwBlock);
static VOID GetPhysicalSectorAddress (DWORD dwSector, PSECTOR_ADDR pStartSectorAddr, PSECTOR_ADDR pStartSectorInfoAddr, BLOCK_ID *pBlockID);
static BOOL DefineLayout();
static BOOLEAN InitializeFlash(volatile ULONG* pBaseAddress, ULONG FlashLength);
static BOOL SignBlock(volatile ULONG ulBlockAddress, PUCHAR pusSignature);
static BOOL VerifySignatures();
static DWORD DoBufferedWrite(volatile ULONG ulBlockAddress,
volatile SECTOR_ADDR physicalSectorAddr,
PUCHAR pBuffer,
USHORT NumWriteBytes);
static BOOL WriteBlock (DWORD dwBlock, LPBYTE pBuffer, DWORD dwStartByteOffset, DWORD dwByteLen);
void DumpGeometry(void);
void DumpFlashInfo(void);
/* -----------------------------------------------------------------------------*/
#define ZONE_ERROR 1
#define DEFAULT_COMPACTION_BLOCKS 4
// Indicates whether or not two flash parts are paired to create a 32-bit data interface.
static BOOL g_bPairedFlash = TRUE;
static BOOL g_bXIPEntire = FALSE;
static BOOL g_bUpdateMode = FALSE;
static FMD_FLASH_INFO g_FMDInfo;
static DWORD g_dwWriteBufferSize;
static BOOL gAllocationContainsComposite=FALSE;
// The maximum size for the write buffer (g_dwWriteBufferSize)
#define MAX_WRITE_BUFFER_SIZE 0x40
static DWORD g_dwNumReserved;
static DWORD g_dwNumRegions;
#ifdef UNDER_BOOTLOADER
// Assume there will be no more than 16 reserved regions
#define MAX_RESERVES 16
static ReservedEntry g_pReservedTable[MAX_RESERVES];
// Assume there will be no more than 16 regions
#define MAX_REGIONS 16
static FlashRegion g_pRegionTable[MAX_REGIONS];
static DWORD g_pStartSectorTable[MAX_REGIONS];
#else
// Dynamically allocate this under the OS
static PReservedEntry g_pReservedTable;
static PFlashRegion g_pRegionTable;
static PDWORD g_pStartSectorTable;
#endif
#ifdef FMD_FLASH_GLOBAL_MUTEX
HANDLE ghFlashMutex;
#define WAIT_FMD_FLASH_MUTEX(hFlashMutex) WaitForSingleObject(hFlashMutex, INFINITE)
#define RELEASE_FMD_FLASH_MUTEX(hFlashMutex) ReleaseMutex(hFlashMutex)
#else
#define WAIT_FMD_FLASH_MUTEX(hFlashMutex)
#define RELEASE_FMD_FLASH_MUTEX(hFlashMutex)
#endif
unsigned long last_sect_data_write_status = 0;
unsigned long last_sect_info_write_status = 0;
extern "C" {
extern unsigned long last_status;
}
// Resets (hard and gpio) and suspend/resume cause the flash to be reset.
// Resetting the flash leaves all blocks locked.
// The Microsoft FAL layer above us has major problems (filesys.exe Data Aborts) if the user file store (FILESYS region)
// is locked.
// Addition of a call to FAL_UnlockFlashRegion(FILESYS) in IPL\main.c suggested by Microsoft
// only solves the problem for the hard/power-on reset case.
//
// The UnlockFILESYSRegions function below unlocks all blocks in all FILESYS regions.
// It is currently called by FMD_Init and FMD_PowerUp to cater for gpio reset and suspend/resume.
DWORD UnlockFILESYSRegions(void)
{
DWORD i;
DWORD block_count = 0;
DWORD region_count = 0;
DBGMSG(1, (TEXT("FMD:UnlockFILESYSRegions:\r\n")));
for (i = 0; i < g_dwNumRegions; i++)
{
if (g_pRegionTable[i].regionType == FILESYS)
{
DWORD start_block = g_pRegionTable[i].dwStartPhysBlock;
DWORD num_blocks = g_pRegionTable[i].dwNumPhysBlocks;
DWORD end_block = start_block + (num_blocks - 1);
DWORD block;
region_count++;
for (block = start_block; block <= end_block; block++)
{
if (SetBlockLock(block, 1, FALSE))
{
block_count++;
DBGMSG(1, (TEXT("FMD:UnlockFILESYSRegions: Unlocked block %u in region %u (type %d, x%08x:x%08x)\r\n"),
block, i, g_pRegionTable[i].regionType,
block, num_blocks));
}
else
{
LOGMSG(1, (TEXT("FMD:UnlockFILESYSRegions: Failed to unlock block %u in region %u (type %d, x%08x:x%08x)\r\n"),
block, i, g_pRegionTable[i].regionType,
block, num_blocks));
}
}
}
}
return((region_count << 16) | (block_count & 0xffff));
}
VOID FMD_PowerUp(VOID);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: FMD_Init()
Description: Initializes the Flash memory device.
Returns: Boolean indicating success.
------------------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?