fmdhal.c

来自「该BSP是基于PXA270+WINCE的BSP」· C语言 代码 · 共 683 行 · 第 1/2 页

C
683
字号
//
// 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-2003 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:


Abstract:


**************************************************************************/
//********************************************************************************************
// NOTE!!!
// Much of the code in this module runs on a small stack so logging often causes stack faults.
// FMDHAL_IOCOntrol invokes the switch to a small stack so it is safe for logging.
// Other FMDHAL_... routines are unsafe.
//********************************************************************************************
#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

//Includes
#include <bsp.h>
#include <mainstoneii.h>

#include "tyax.h"
#include "fmdhal.h"


unsigned long last_status = 0;

// note, don't move the order of the fuctions ever unless you modify the
// relocation informaton cnc
struct FMDHAL_RelocFuncStruct_t g_RelocFuncStruct;
static UCHAR g_FMDHAL_RelocateRegion[8192];
static ULONG g_RelocOffset = 0;
FMDHAL_ConfigStruct g_CFIInfo;
static struct FMDHAL_CmdStruct g_CurrCmdStruct;

/* reduce the size when known before shipping */
/* make sure to match the .s file's value with the new one */
UINT g_FMDHAL_Stack[4096];
DWORD FMDHAL_OrigStack;
void *g_FMDHAL_FuncPtr;

#define FLASH_CFIREGION2OFFSET      (0x31*4)
#define FLASH_CFIREGION1OFFSET      (0x2D*4)
#define QUERYTABLEMASK              0x000000FFUL
#define BITS_IN_BYTE                8
#define FLASH_CFIREGION_UPPERWORD   16
#define BOTTOM_BOOT                 0
#define MB                          20
/************************************
 * Customer settable area.  Move to
 * global .h file
 ************************************
 */

ULONG g_FMDConfig = FMDHAL_BusConfigx32;
BOOL g_SWRWW_Enable = TRUE;


/* CPU addresses */
// XSCALE ONLY
ULONG *g_pFIQ_Address = (ULONG *)0x0L;
ULONG *g_pIRQ_Address = (ULONG *)0xA5200000;
// volatile BULVERDE_INTR_REG *g_pIRQ_Address= NULL; // XSCALE ONLY\

/* End Customer Area */


extern void FMD_CleanCacheLine( DWORD );

static void CleanDataCache( DWORD StartAddr, DWORD EndAddr ) 
{
    DWORD CurrAddr;

    if ( EndAddr < StartAddr ) {
        return;
    }
    
    // align startaddr to cache line
    //
    CurrAddr = StartAddr & (~0x1F);

    // clean the lines
    //
    while ( CurrAddr <= EndAddr ) {
        FMD_CleanCacheLine( CurrAddr );
        FMD_CleanCacheLine( CurrAddr |0x04000000 ); // TODO: Get PID for filesys dynamically ?
        CurrAddr += 0x20;
    }

}

BOOL FMDHAL_IOControl(ULONG uCmd, void *pOutVar, void *pInVar)
{
    BOOL bRetVal = FALSE;

    switch (uCmd)
    {
        case FMDHAL_CMD_INIT:
            memcpy(&g_CurrCmdStruct, (FMDHAL_CmdStruct *)pInVar, sizeof(struct FMDHAL_CmdStruct));
            if (FMDHAL_Init(((FMDHAL_CmdStruct *)pInVar)->pTargetAddress, ((FMDHAL_CmdStruct *)pInVar)->uOffset))
            {
                bRetVal = TRUE;
            }
            ASSERT(pOutVar);
            memcpy(pOutVar, &g_CFIInfo, sizeof(FMDHAL_ConfigStruct));
            break;
        case FMDHAL_CMD_WRITE:
            g_FMDHAL_FuncPtr = g_RelocFuncStruct.DoWrite;
            memcpy(&g_CurrCmdStruct, pInVar, sizeof(struct FMDHAL_CmdStruct));
            bRetVal = FMDHAL_ASM_CallFuncWithNewStack();
            ASSERT(pOutVar);
            memcpy(pOutVar, &g_CurrCmdStruct, sizeof(struct FMDHAL_CmdStruct));
            break;
        case FMDHAL_CMD_ERASE:
            g_FMDHAL_FuncPtr = g_RelocFuncStruct.DoErase;
            memcpy(&g_CurrCmdStruct, pInVar, sizeof(struct FMDHAL_CmdStruct));
            bRetVal = FMDHAL_ASM_CallFuncWithNewStack();
            break;
        case FMDHAL_CMD_UNLOCK_BLOCK:
            g_FMDHAL_FuncPtr = g_RelocFuncStruct.DoBlockUnlock;
            memcpy(&g_CurrCmdStruct, (FMDHAL_CmdStruct *)pInVar, sizeof(struct FMDHAL_CmdStruct));
            bRetVal = FMDHAL_ASM_CallFuncWithNewStack();
            break;
        case FMDHAL_CMD_LOCK_BLOCK:
            g_FMDHAL_FuncPtr = g_RelocFuncStruct.DoBlockLock;
            memcpy(&g_CurrCmdStruct, (FMDHAL_CmdStruct *)pInVar, sizeof(struct FMDHAL_CmdStruct));
            bRetVal = FMDHAL_ASM_CallFuncWithNewStack();
            break;
        default:
            bRetVal = FALSE;
            break;
    }
    if (!bRetVal)
        LOGMSG(1, (TEXT("FMD:FMDHAL_IOControl: ERROR: command=x%08x, status=x%08x\r\n"), uCmd, last_status));
    return(bRetVal);
}


BOOL FMDHAL_Init(volatile ULONG* pBaseAddress, ULONG uFlashLength)
{
    /* Relocate Functions that take the flash offline */
    FMDHAL_RelocateCode((ULONG *)FMDHAL_CFIQuery, (ULONG *)&g_RelocFuncStruct.CFIQuery,
                        (ULONG)FMDHAL_DoUnlockBlock - (ULONG)FMDHAL_CFIQuery);

    FMDHAL_RelocateCode((ULONG *)FMDHAL_WriteCommand, (ULONG *)&g_RelocFuncStruct.WriteCommand,
                        (ULONG)FMDHAL_ReadStatus - (ULONG)FMDHAL_WriteCommand);

    FMDHAL_RelocateCode((ULONG *)FMDHAL_ReadStatus, (ULONG *)&g_RelocFuncStruct.ReadStatus,
                        (ULONG)FMDHAL_IsInterruptPending - (ULONG)FMDHAL_ReadStatus);

    FMDHAL_RelocateCode((ULONG *)FMDHAL_DoWrite, (ULONG *)&g_RelocFuncStruct.DoWrite,
                        (ULONG)FMDHAL_DoErase - (ULONG)FMDHAL_DoWrite);

    FMDHAL_RelocateCode((ULONG *)FMDHAL_DoErase, (ULONG *)&g_RelocFuncStruct.DoErase,
                        (ULONG)FMDHAL_WriteCommand - (ULONG)FMDHAL_DoErase);

    FMDHAL_RelocateCode((ULONG *)FMDHAL_IsInterruptPending, (ULONG *)&g_RelocFuncStruct.IsInterruptPending,
                        (ULONG)FMDHAL_CFIQuery - (ULONG)FMDHAL_IsInterruptPending);

    FMDHAL_RelocateCode((ULONG *)FMDHAL_DoUnlockBlock, (ULONG *)&g_RelocFuncStruct.DoBlockUnlock,
                        (ULONG)FMDHAL_DoLockBlock - (ULONG)FMDHAL_DoUnlockBlock);

    FMDHAL_RelocateCode((ULONG *)FMDHAL_DoLockBlock, (ULONG *)&g_RelocFuncStruct.DoBlockLock,
                        (ULONG)FMDHAL_RelocateCode - (ULONG)FMDHAL_DoLockBlock);

    g_RelocFuncStruct.FMDHAL_ASMInterruptEnable  = FMDHAL_ASMInterruptEnable;
    g_RelocFuncStruct.FMDHAL_ASMInterruptDisable = FMDHAL_ASMInterruptDisable;

    // Setup the Int Controller reg
    //    g_pIRQ_Address = (volatile BULVERDE_INTR_REG *) OALPAtoVA(BULVERDE_BASE_REG_PA_INTC, FALSE);

    //run CFI
    g_FMDHAL_FuncPtr = g_RelocFuncStruct.CFIQuery;
    return(FMDHAL_ASM_CallFuncWithNewStack());

}

BOOL FMDHAL_DoWrite(void)
{
    ULONG uWriteSize = g_CurrCmdStruct.uBytesToWrite;
    volatile ULONG *pStartAddress = g_CurrCmdStruct.pTargetAddress;
    volatile ULONG *pSrcBuffer = g_CurrCmdStruct.pWriteBufferPtr;
    ULONG flash_status;
    DWORD dwBusWidth;
    DWORD dwWordCount;
    DWORD k =0;

    if (g_FMDConfig & FMDHAL_BusConfigx16)
    {
        dwBusWidth = sizeof(USHORT);
        dwWordCount = (uWriteSize >> 0x1) -1;
    } else
    {
        dwBusWidth = sizeof(ULONG);
        dwWordCount = (uWriteSize >> 0x2) -1;
    }

    if (g_SWRWW_Enable == TRUE)
    {
        /* Disable interrupts */
        g_RelocFuncStruct.FMDHAL_ASMInterruptDisable();
    }
    g_RelocFuncStruct.WriteCommand(pStartAddress, FMDHAL_FLASH_WRITE_BUFFER_CMD, g_FMDConfig);
    while (!g_RelocFuncStruct.ReadStatus(pStartAddress, FMDHAL_FLASH_STATUS_READY, g_FMDConfig));
    if (g_FMDConfig & FMDHAL_BusConfigx16)
    {
        PUSHORT pShortBuffer = (PUSHORT)g_CurrCmdStruct.pWriteBufferPtr;
        g_RelocFuncStruct.WriteCommand(pStartAddress, dwWordCount, g_FMDConfig);
        for (k = 0; k <uWriteSize;k += dwBusWidth)
        {
            *(volatile USHORT *)g_CurrCmdStruct.pTargetAddress =  *pShortBuffer;
            (USHORT)g_CurrCmdStruct.pTargetAddress+=sizeof(USHORT);
            pShortBuffer++;
        }
    } else
    {
        PULONG pLongBuffer = g_CurrCmdStruct.pWriteBufferPtr;
        g_RelocFuncStruct.WriteCommand(pStartAddress, dwWordCount, g_FMDConfig);
        for (k = 0; k <uWriteSize;k += dwBusWidth)
        {
            *(volatile ULONG *)g_CurrCmdStruct.pTargetAddress =  *pLongBuffer;
            (ULONG)g_CurrCmdStruct.pTargetAddress+=sizeof(ULONG);
            pLongBuffer++;
        }
    }

    g_RelocFuncStruct.WriteCommand(pStartAddress, FMDHAL_FLASH_WRITE_CONFIRM, g_FMDConfig);
    while (!g_RelocFuncStruct.ReadStatus(pStartAddress, FMDHAL_FLASH_STATUS_READY, g_FMDConfig));
    //err check
    // cnc fix formatting
    flash_status = g_RelocFuncStruct.ReadStatus(pStartAddress, 0, g_FMDConfig);
    if (flash_status & ~mFMDHAL_CmdCreate(g_FMDConfig, FMDHAL_FLASH_STATUS_READY))
    {
        g_RelocFuncStruct.WriteCommand(pStartAddress, FMDHAL_FLASH_CLEAR_STATUS, g_FMDConfig);
        g_RelocFuncStruct.WriteCommand(pStartAddress, FMDHAL_FLASH_READ_ARRAY, g_FMDConfig);
        if (g_SWRWW_Enable)
        {
            g_RelocFuncStruct.FMDHAL_ASMInterruptEnable();
        }
        return(FALSE);
    }

    g_RelocFuncStruct.WriteCommand(pStartAddress, FMDHAL_FLASH_READ_ARRAY, g_FMDConfig);
    if (g_SWRWW_Enable)
    {
        g_RelocFuncStruct.FMDHAL_ASMInterruptEnable();
    }
    g_CurrCmdStruct.uBytesWritten = uWriteSize;

    return(TRUE);

}

BOOL FMDHAL_DoErase(void)
{
    volatile ULONG *pBlockAddress = (volatile ULONG *)g_CurrCmdStruct.pTargetAddress;
    ULONG flash_status;

    /* Do interrupts need to be disabled? */
    if (g_SWRWW_Enable == TRUE)
    {
        /* Disable interrupts */
        g_RelocFuncStruct.FMDHAL_ASMInterruptDisable();
    }
    /* Issue the erase command */
    g_RelocFuncStruct.WriteCommand(pBlockAddress,
                                   FMDHAL_FLASH_ERASE_CMD,
                                   g_FMDConfig);

    /* Issue the erase confirm commands */
    g_RelocFuncStruct.WriteCommand(pBlockAddress,
                                   FMDHAL_FLASH_ERASE_CONFIRM,
                                   g_FMDConfig);
    /* Wait for the erase to finish */
    while (!g_RelocFuncStruct.ReadStatus(pBlockAddress, FMDHAL_FLASH_STATUS_READY, g_FMDConfig));

#if 0    /* Wait for the erase to finish */
    while (!g_RelocFuncStruct.ReadStatus(pBlockAddress, FMDHAL_FLASH_STATUS_READY, g_FMDConfig))
    {
        if ((g_SWRWW_Enable == TRUE) && (g_RelocFuncStruct.IsInterruptPending() == TRUE))
        {
            g_RelocFuncStruct.WriteCommand(pBlockAddress, FMDHAL_FLASH_ERASE_SUSPEND, g_FMDConfig);


            /* Wait for the erase to suspend */
            while (!g_RelocFuncStruct.ReadStatus(pBlockAddress, FMDHAL_FLASH_STATUS_READY, g_FMDConfig));
            if (!g_RelocFuncStruct.ReadStatus(pBlockAddress, FMDHAL_FLASH_ERASE_SUSPENDED, g_FMDConfig))
            {
                /* We are done */
                break;
            }
            /* Check for Errors */
            flash_status g_RelocFuncStruct.ReadStatus(pBlockAddress, 0, g_FMDConfig);
            if (flash_status & ~mFMDHAL_CmdCreate(g_FMDConfig, FMDHAL_FLASH_STATUS_READY)
            {
                g_RelocFuncStruct.WriteCommand(pBlockAddress, FMDHAL_FLASH_CLEAR_STATUS, g_FMDConfig);
                g_RelocFuncStruct.WriteCommand(pBlockAddress, FMDHAL_FLASH_READ_ARRAY, g_FMDConfig);
                g_RelocFuncStruct.FMDHAL_ASMInterruptEnable();
                return(FALSE);
            }
            /* put Flash back in Read Array Mode */
            g_RelocFuncStruct.WriteCommand(pBlockAddress, FMDHAL_FLASH_READ_ARRAY, g_FMDConfig);
            /* Re-enable interrupts */
            g_RelocFuncStruct.FMDHAL_ASMInterruptEnable();
            /* cnc - Do we need a reschedule here? */

⌨️ 快捷键说明

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