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

📄 fmd.cpp

📁 CIRRUS 93XX系列windows mobile 6.0 BSP
💻 CPP
字号:
//**********************************************************************
//                                                                      
// Filename: FMD.CPP
//                                                                      
// Description: FLASH Media Driver Interface for Intel XXXXXX StrataFlash 
//              Chip
//
// 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.
//
// Use of this source code is subject to the terms of the Cirrus 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 
// EULA.RTF on your install media.
//
// Copyright(c) Cirrus Logic Corporation 2005, All Rights Reserved
//                                                                      
//**********************************************************************


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

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.

                -------

                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.

-----------------------------------------------------------------------------*/
#include <fmd.h>
#include <ceddk.h>
#ifdef READ_FROM_REGISTRY
#include <ddkreg.h>
#endif    // READ_FROM_REGISTRY.
#include <hwdefs.h>
#include <clocks.h>
#include "strata.h"

BOOLEAN InitializeFlash(volatile ULONG * pBaseAddress, ULONG FlashLength);

DWORD DoBufferedWrite(volatile ULONG ulBlockAddress,
                      volatile SECTOR_ADDR physicalSectorAddr,
                      PUCHAR pBuffer,
                      USHORT NumWriteBytes);

#define ZONE_TEST      0

FMD_FLASH_INFO g_FMDInfo;


DWORD CvrtToIntegerHex(TCHAR * str)
{
	DWORD dwVal=0;

	while( *str ){

		dwVal <<=4;

		if( *str >='0' && *str <='9' )
		  dwVal |= *str -'0';
		else if (*str >='a' && *str <='f' )
		  dwVal |= *str -'a' + 0xa;
		else if (*str >='A' && *str <='F' )
		  dwVal |= *str -'A' +0xa;
		else
			break;
		str++;
	}

	return dwVal;
}


BOOL GetWindowInfo( HKEY hKey,  DDKWINDOWINFO * pWin )
{
    LONG    lStatus;
	TCHAR   csValue[200];
    DWORD   dwValType;
    DWORD   dwValLen = sizeof (csValue);
	DWORD   dwBaseNum=0, dwLenNum=0;
	DWORD   dwStrLen;

    lStatus = RegQueryValueEx( hKey, L"MemBase", NULL, &dwValType, (PBYTE)&csValue[0], &dwValLen);

    if (lStatus == ERROR_SUCCESS){

		pWin->memWindows[0].dwBase=CvrtToIntegerHex(csValue);

		dwStrLen=wcslen( csValue );
		dwBaseNum=1;

		if( dwStrLen +1< dwValLen ){

			    dwBaseNum++;
				pWin->memWindows[1].dwBase=CvrtToIntegerHex(csValue + dwStrLen +1 );
		}
	}

    dwValLen = sizeof (csValue);
    lStatus = RegQueryValueEx( hKey, L"MemLen", NULL, &dwValType, (PBYTE)&csValue[0], &dwValLen);

    if (lStatus == ERROR_SUCCESS){

		pWin->memWindows[0].dwLen=CvrtToIntegerHex(csValue);

		dwStrLen=wcslen( csValue );
		dwLenNum=1;

		if( dwStrLen +1< dwValLen ){

			    dwLenNum++;
				pWin->memWindows[1].dwLen=CvrtToIntegerHex(csValue + wcslen( csValue )+1 );
		}
	}
	pWin->dwNumMemWindows=  dwBaseNum < dwLenNum  ? dwBaseNum: dwLenNum;

	return ERROR_SUCCESS;
}


//****************************************************************************
// DelayuS
//****************************************************************************
// Delays a certian number of microseconds.
// 
//
static void DelayInuSec(ULONG ulMicroSec)
{
    LARGE_INTEGER liStart, liCurrent;
    BOOL b;
    b = QueryPerformanceCounter(&liStart);
    ASSERT(b);
    
    do
    {
        Sleep(0);
        b = QueryPerformanceCounter(&liCurrent);
        ASSERT(b);
    } while((liStart.QuadPart + (LONGLONG)ulMicroSec) >=liCurrent.QuadPart);
}


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       FMD_Deinit()

Description:    De-initializes the Flash memory device.

Returns:        Boolean indicating success.
------------------------------------------------------------------------------*/
BOOL  FMD_Deinit(PVOID pBaseAddress)
{
    return(TRUE);
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       FMD_GetInfo()

Description:    Determines the size characteristics for the Flash memory device.

Notes:          Notice that although each byte of a NOR Flash block is individually
                addressable, the media is still logically broken up into sectors.
                To compute the number of sectors per block, you have to divide the
                total Flash block size by the number of bytes per sector and the number 
                bytes for the sector metadata.

Returns:        Boolean indicating success.
------------------------------------------------------------------------------*/
BOOL  FMD_GetInfo(PFlashInfo pFlashInfo)
{
    pFlashInfo->flashType           = NOR;
    pFlashInfo->dwNumBlocks         = g_FMDInfo.TotalFlashBlocks;
    pFlashInfo->dwBytesPerBlock     = g_FMDInfo.BlockSize;
    pFlashInfo->wDataBytesPerSector = SECTOR_SIZE;
    pFlashInfo->wSectorsPerBlock    = g_FMDInfo.SectorsPerBlock;  

	
    return(TRUE);
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       FMD_GetBlockStatus()

Description:    Returns the status of a block.  For read-only blocks, checks the sector 
        info data for the first sector of the block.  Block is always good, so no need to check.

Returns:        Block status.
------------------------------------------------------------------------------*/
DWORD FMD_GetBlockStatus(BLOCK_ID blockID)
{
    SECTOR_ADDR Sector = blockID * g_FMDInfo.SectorsPerBlock;
    SectorInfo SI;
    DWORD dwResult = 0;

	RETAILMSG(ZONE_TEST, (TEXT("FMD_GetBlockStatus: id =%x ).\r\n"), blockID));

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

    return dwResult;
}

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       FMD_SetBlockStatus()

Description:    Sets the status of a block.  

Returns:        TRUE if no errors in setting.
------------------------------------------------------------------------------*/

BOOL FMD_SetBlockStatus(BLOCK_ID blockID, DWORD dwStatus)
{
	RETAILMSG(ZONE_TEST, (TEXT("FMD_SetBlockStatus: id =%x status =%x).\r\n"), blockID,dwStatus));

    if (dwStatus & (BLOCK_STATUS_READONLY | BLOCK_STATUS_RESERVED)) {
        
        SECTOR_ADDR Sector = blockID * g_FMDInfo.SectorsPerBlock;
        SectorInfo SI;

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

    }    
	RETAILMSG(ZONE_TEST, (TEXT("FMD_SetBlockStatus over: id =%x status =%x).\r\n"), blockID,dwStatus));
  
    return TRUE;
}



/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       FMD_PowerUp()

Description:    Restores power to the Flash memory device (if applicable).

Returns:        None.
------------------------------------------------------------------------------*/
VOID  FMD_PowerUp(VOID)  
{  
    return; 
}


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       FMD_PowerDown()

Description:    Suspends power to the Flash memory device (if applicable).

Returns:        None.
------------------------------------------------------------------------------*/
VOID  FMD_PowerDown(VOID)
{  
    return; 
}


void InitializeFlashSMC( void )
{
	unsigned long ulSMC;
	int wait1;
	int wait2;
		//for WAIT_STATES(A), the largest value of 'A' should be 500, when A is 500,
		//WAIT_STATES(A) is 31, which has reached the largest value of WAIT_STATES(A).
	#if (EP93XX_FLASH_TYPE==FLASH_TYPE_C3)

		wait2=WAIT_STATES(80);
		wait1=WAIT_STATES(300);

	#elif (EP93XX_FLASH_TYPE == FLASH_TYPE_AMD)

		wait2=0x1F;
		wait1=0x1F;

	#elif (EP93XX_FLASH_TYPE == FLASH_TYPE_P3)

		wait2=WAIT_STATES(30);
		wait1=WAIT_STATES(100);

	#elif  (EP93XX_FLASH_TYPE == FLASH_TYPE_J3)

		wait2=WAIT_STATES(35);
		wait1=WAIT_STATES(150);

	#else  //The lowest value
		wait2=0x1F;
		wait1=0x1F;
	#endif
	//

	ulSMC   = (( wait2 <<SMCBCR_WST2_SHIFT) & SMCBCR_WST2_MASK) | 
			  (( wait1 <<SMCBCR_WST1_SHIFT) & SMCBCR_WST1_MASK);

	//Add other values:
	*FLASH_SMC = ulSMC |  ( 1 & SMCBCR_IDCY_MASK )  | SMCBCR_PME | SMCBCR_RBLE

		#if EP93XX_FLASH_WIDTH==16
		|  SMCBCR_MW_16BIT
		#else
		|  SMCBCR_MW_32BIT
		#endif
		;
}

#if (EP93XX_FLASH_TYPE ==FLASH_TYPE_AMD)

#include "amd.cpp"

#elif  (EP93XX_FLASH_TYPE == FLASH_TYPE_P3)

#include "intel-p3c3.cpp"

#elif (EP93XX_FLASH_TYPE == FLASH_TYPE_C3)

#include "intel-p3c3.cpp"

#elif  (EP93XX_FLASH_TYPE == FLASH_TYPE_J3)

#include "intel-j3.cpp"
#else
#error "Error, please specify FLASH TYPE\r\n"
#endif

⌨️ 快捷键说明

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