📄 falmain.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
2007 Modified by Chris Gray at Raza Microelectronics Inc for WinCE 5.0 optimizations
(cgray@razamicro.com)
Module Name: FALMAIN.CPP
Abstract: FLASH Abstraction Layer (FAL) for Windows CE
Notes: The following stream interface driver is used to support FLASH
memory devices. Specifically, this purpose of this driver is to
interface file systems (i.e. FAT) with specific FLASH chips in a
device-independent manner. Here is a diagram illustrating the
overall architecture:
---------------
| File System |
---------------
| uses logical sector addresses
---------------
| FAL |
---------------
| uses physical sector addresses
---------------
| FMD |
---------------
| uses program/erase algorithms
------------------
| FLASH Hardware |
------------------
Each of the components is defined as follows:
FAL (FLASH Abstraction Layer) - abstracts underlying FLASH hardware to file system(s)
FMD (FLASH Media Driver) - interfaces directly with underlying FLASH media
Using this design, OEMs are free to implement custom FMDs for their respective FLASH chips.
Practically, the simple FMD interface means that it is *very easy* for OEMs to port an example
FMD to their respective hardware.
The primary responsibilities of the FAL are as follows:
* Abstract the physical FLASH media from the file system.
* Translate logical sector addresses to physical sector addresses.
* "Wear-level" the physcial media. FLASH memory has a limited write/erase lifetime and
it is important to spread the write/erase cycles across the entire media in order to
extend the lifetime of the memory device.
Note that the FAL is NOT a file system; rather, it is a translation layer that file systems
use in order to interface with FLASH media in a device-independent manner.
Environment: This module (FAL.LIB) needs to be linked with a FLASH Media Driver (FMD.LIB) in
order to create the full FLASH driver (FLASHDRV.DLL).
-----------------------------------------------------------------------------*/
#include <windows.h>
#include <windev.h>
#include "storemgr.h"
#include "fal.h"
//#undef DEBUGMSG
//#define DEBUGMSG(cond,msg) RETAILMSG(1,msg)
DBGPARAM dpCurSettings = {
TEXT("MSFLASH"), {
TEXT("Init"),
TEXT("Error"),
TEXT("Compactor"),
TEXT("Write"),
TEXT("Read"),
TEXT("Function"),
TEXT("6"),
TEXT("7"),
TEXT("8"),
TEXT("9"),
TEXT("10"),
TEXT("11"),
TEXT("12"),
TEXT("CeLog Errors"),
TEXT("CeLog Compaction"),
TEXT("CeLog Verbose")},
0x2 // Errors are only on by default
};
//------------------------------ GLOBALS -------------------------------------------
CRITICAL_SECTION g_csMain; // Only allow one request at a time.
CRITICAL_SECTION g_csFlashDevice; // Used to make driver re-entrant
static LONG g_lReferenceCount = 0;
static PDEVICE g_pDevice = NULL; // Handle to the device
static DWORD *g_Context = NULL; // Used as a lock to the FAL driver, allowing only one instance
PFlashInfoEx g_pFlashMediaInfo = NULL; // FLASH chip-specific device information
HKEY g_hDeviceKey = NULL;
HINSTANCE g_hCoreDll = NULL;
TCHAR g_szProfile[PROFILENAMESIZE];
DWORD g_dwCompactionPrio256 = THREAD_PRIORITY_IDLE + 248;
DWORD g_dwCompactionCritPrio256 = THREAD_PRIORITY_TIME_CRITICAL + 248;
DWORD g_dwAvailableSectors = 0; // Total # of available sectors on media
CEDEVICE_POWER_STATE g_CurrentPowerState = D0;
FMDInterface FMD;
Fal** g_FalObjects;
//----------------------------------------------------------------------------------
BOOL GetDeviceInfo(PSTORAGEDEVICEINFO psdi)
{
BOOL fXipMode = FALSE;
wcscpy( psdi->szProfile, g_szProfile);
psdi->dwDeviceClass = STORAGE_DEVICE_CLASS_BLOCK;
psdi->dwDeviceType = STORAGE_DEVICE_TYPE_FLASH;
psdi->dwDeviceFlags = STORAGE_DEVICE_FLAG_READWRITE | STORAGE_DEVICE_FLAG_TRANSACTED;
if (g_pFlashMediaInfo->flashType == NOR)
psdi->dwDeviceFlags |= STORAGE_DEVICE_FLAG_XIP;
return TRUE;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DLL ENTRY
-------------------------------------------------------------------*/
STDAPI_(BOOL) WINAPI
DllEntry(HINSTANCE DllInstance, DWORD Reason, LPVOID Reserved)
{
switch(Reason)
{
case DLL_PROCESS_ATTACH:
RETAILREGISTERZONES (DllInstance);
DEBUGMSG(ZONE_INIT,(TEXT("FLASHDRV.DLL:DLL_PROCESS_ATTACH \r\n")));
break;
case DLL_PROCESS_DETACH:
DEBUGMSG(ZONE_INIT,(TEXT("FLASHDRV.DLL:DLL_PROCESS_DETACH \r\n")));
break;
}
return TRUE;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: DSK_Init()
Description: Initializes the FAL, queries the FMD for the FLASH
memory device properties, etc.
Returns: Context data for the FLASH device.
-------------------------------------------------------------------*/
DWORD DSK_Init(DWORD dwContext)
{
PDEVICE pDevice = g_pDevice;
DWORD dwNumReserved = 0;
DWORD dwUpdateReadOnly = 0;
DEBUGMSG(ZONE_FUNCTION,(TEXT("FLASHDRV.DLL:Init() %d\r\n"),g_lReferenceCount));
RETAILMSG(1,(TEXT("DSK_Init start:%d\r\n"),GetTickCount() ));
//----- 1. Check for re-entrant call. If we have already initialized, then return -----
// the open handle to the FLASH device.
if(InterlockedIncrement(&g_lReferenceCount) > 1)
{
return (DWORD)g_pDevice;
}
//----- 2. First time initializing. Create the handle for the FLASH device -----
if((pDevice = (PDEVICE)LocalAlloc(LPTR, sizeof(DEVICE))))
{
memset(pDevice, 0, sizeof(pDevice) );
pDevice->dwID = 'GOOD'; // "Anything" validates pdev, 'GOOD' is a fine choice
}else
{
ReportError((TEXT("FLASHDRV.DLL:LocalAlloc() failed - unable to allocate PDEVICE handle for FLASH device.\r\n")));
goto INIT_ERROR;
}
GetFMDInterface(pDevice);
RETAILMSG(1,(TEXT("Initialize the FLASH Media Driver (FMD) start:%d\r\n"),GetTickCount() ));
//----- 3. Initialize the FLASH Media Driver (FMD) -----
if((pDevice->hFMD=FMD.pInit((LPTSTR)dwContext,NULL,NULL))==NULL)
{
ReportError((TEXT("FLASHDRV.DLL:Unable to initialize FLASH Media Driver (FMD dwContext:%X).\r\n"),dwContext));
goto INIT_ERROR;
}
if (FMD.pGetInfoEx)
{
if(!FMD.pGetInfoEx(NULL, &dwNumReserved) || (dwNumReserved == 0))
{
ReportError((TEXT("FLASHDRV.DLL:Unable to query FMD for FLASH device properties.\r\n")));
goto INIT_ERROR;
}
g_pFlashMediaInfo = (PFlashInfoEx)LocalAlloc (LPTR, sizeof(FlashInfoEx) + (dwNumReserved - 1) * sizeof(FlashRegion));
if (!g_pFlashMediaInfo)
{
goto INIT_ERROR;
}
if(!FMD.pGetInfoEx(g_pFlashMediaInfo, &dwNumReserved))
{
ReportError((TEXT("FLASHDRV.DLL:Unable to query FMD for FLASH device properties.\r\n")));
goto INIT_ERROR;
}
}
else
{
FlashInfo oldFlashInfo;
// Use the old version of GetInfo
if(!FMD.pGetInfo(&oldFlashInfo))
{
ReportError((TEXT("FLASHDRV.DLL:Unable to query FMD for FLASH device properties.\r\n")));
goto INIT_ERROR;
}
g_pFlashMediaInfo = (PFlashInfoEx)LocalAlloc (LPTR, sizeof(FlashInfoEx));
if (!g_pFlashMediaInfo)
{
goto INIT_ERROR;
}
// Fill in the FlashInfoEx version with the info from FlashInfo.
g_pFlashMediaInfo->flashType = oldFlashInfo.flashType;
g_pFlashMediaInfo->dwNumBlocks = oldFlashInfo.dwNumBlocks;
g_pFlashMediaInfo->dwDataBytesPerSector = oldFlashInfo.dwDataBytesPerSector;
g_pFlashMediaInfo->dwNumRegions = 1;
g_pFlashMediaInfo->region[0].regionType = FILESYS;
g_pFlashMediaInfo->region[0].dwStartPhysBlock = 0;
g_pFlashMediaInfo->region[0].dwNumPhysBlocks = oldFlashInfo.dwNumBlocks;
g_pFlashMediaInfo->region[0].dwNumLogicalBlocks = FIELD_NOT_IN_USE;
g_pFlashMediaInfo->region[0].dwSectorsPerBlock = oldFlashInfo.wSectorsPerBlock;
g_pFlashMediaInfo->region[0].dwBytesPerBlock = oldFlashInfo.dwBytesPerBlock;
g_pFlashMediaInfo->region[0].dwCompactBlocks = MINIMUM_FLASH_BLOCKS_TO_RESERVE;
}
//----- 6. Initialize the FLASH device's critical section -----
RETAILMSG(1,(TEXT("Initialize the FLASH device's critical section start:%d\r\n"),GetTickCount() ));
InitializeCriticalSection(&g_csMain);
InitializeCriticalSection(&g_csFlashDevice);
g_hCoreDll = LoadLibrary (TEXT("coredll.dll"));
if (g_hCoreDll)
{
pOpenDeviceKey fnOpenDeviceKey = (pOpenDeviceKey)GetProcAddress(g_hCoreDll, TEXT("OpenDeviceKey"));
if (fnOpenDeviceKey)
g_hDeviceKey = fnOpenDeviceKey ((PCTSTR)dwContext);
}
// Get profile name
wcscpy(g_szProfile, L"FlashDisk");
if (g_hDeviceKey)
{
DWORD dwLen = 0;
pRegQueryValueEx fnRegQueryValueEx = (pRegQueryValueEx)GetProcAddress(g_hCoreDll, TEXT("RegQueryValueExW"));
if (fnRegQueryValueEx)
{
if ((fnRegQueryValueEx (g_hDeviceKey, TEXT("Profile"), NULL, NULL, NULL, &dwLen) == ERROR_SUCCESS) &&
(dwLen <= (sizeof(TCHAR) * PROFILENAMESIZE)))
{
fnRegQueryValueEx (g_hDeviceKey, TEXT("Profile"), NULL, NULL, (LPBYTE)g_szProfile, &dwLen);
}
dwLen = sizeof(DWORD);
if (fnRegQueryValueEx(g_hDeviceKey, L"CompactionPrio256", 0, NULL, (LPBYTE)&g_dwCompactionPrio256, &dwLen) != ERROR_SUCCESS)
g_dwCompactionPrio256 = THREAD_PRIORITY_IDLE + 248;
if (fnRegQueryValueEx(g_hDeviceKey, L"CompactionCritPrio256", 0, NULL, (LPBYTE)&g_dwCompactionCritPrio256, &dwLen) != ERROR_SUCCESS)
g_dwCompactionCritPrio256 = THREAD_PRIORITY_TIME_CRITICAL + 248;
if (fnRegQueryValueEx(g_hDeviceKey, L"UpdateReadOnly", 0, NULL, (LPBYTE)&dwUpdateReadOnly, &dwLen) != ERROR_SUCCESS)
dwUpdateReadOnly = 0;
}
}
RETAILMSG(1,(TEXT("Initialize the FAL start:%d\r\n"),GetTickCount() ));
//----- 7. Initialize the FAL -----
g_FalObjects = new Fal*[g_pFlashMediaInfo->dwNumRegions];
if (!g_FalObjects) {
ReportError((TEXT("FLASHDRV.DLL: Out of memory!\r\n")));
goto INIT_ERROR;
}
memset (g_FalObjects, 0, sizeof(Fal*) * g_pFlashMediaInfo->dwNumRegions);
DWORD dwStartLogSector = 0;
DWORD dwStartPhysSector = 0;
if (g_pFlashMediaInfo->region[0].dwNumPhysBlocks) {
dwStartPhysSector = g_pFlashMediaInfo->region[0].dwStartPhysBlock * g_pFlashMediaInfo->region[0].dwSectorsPerBlock;
}
for (DWORD iRegion = 0; iRegion < g_pFlashMediaInfo->dwNumRegions; iRegion++)
{
PFlashRegion pRegion = &g_pFlashMediaInfo->region[iRegion];
// calculate the number of logical and physical blocks
if (pRegion->dwNumLogicalBlocks == FIELD_NOT_IN_USE)
{
// Determine logical range from the given physical range
if (!CalculateLogicalRange(pRegion))
{
goto INIT_ERROR;
}
}
else
{
if (iRegion == 0)
{
pRegion->dwStartPhysBlock = 0;
}
else
{
pRegion->dwStartPhysBlock = g_pFlashMediaInfo->region[iRegion-1].dwStartPhysBlock +
g_pFlashMediaInfo->region[iRegion-1].dwNumPhysBlocks;
}
if (pRegion->dwNumLogicalBlocks == END_OF_FLASH)
{
// This region goes to the end of flash. Determine how many logical
// sectors are available
pRegion->dwNumPhysBlocks = g_pFlashMediaInfo->dwNumBlocks - pRegion->dwStartPhysBlock;
if (!CalculateLogicalRange(pRegion))
{
goto INIT_ERROR;
}
}
else
{
// Determine phsyical range from the given logical number of blocks
if (!CalculatePhysRange(pRegion))
{
goto INIT_ERROR;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -