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

📄 hal.c

📁 Freescale ARM11系列CPU MX31的WINCE 5.0下的BSP
💻 C
📖 第 1 页 / 共 5 页
字号:
//---------------------------------------------------------------------------
// Copyright (C) 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:  hal.c
// Source file for platform specific SDIO WLAN functions
//------------------------------------------------------------------------------
 

//------------------------------------------------------------------------------
// INCLUDE FILES  
//------------------------------------------------------------------------------

#include "precomp.h"

//------------------------------------------------------------------------------
// GLOBAL DEFINITIONS  
//------------------------------------------------------------------------------
#define IA 16807
#define RND_MAX 2147483647
#define IQ 127773
#define IR 2836
#define MASK 123459876

//------------------------------------------------------------------------------
// GLOBAL OR STATIC VARIABLES  
//------------------------------------------------------------------------------

// Tx, Rx buffer number and size configuration array.
ULONG aTxRxBufCfg[3][3] = { { 3, 2, 1636 }, { 4, 1, 1636 }, { 2, 1, 2728 } };

//------------------------------------------------------------------------------
// STATIC FUNCTION PROTOTYPES  
//------------------------------------------------------------------------------
static unsigned long uiGenRand(long *idum)
    /* Returns a uniform random deviate
    between 0.0 and 1.0. Set or reset idum to
    any integer value (except the unlikely value MASK)
    to initialize the sequence; idum must not be altered
    between calls for successive deviates in a sequence. */
{
    long k;
    unsigned long ans;
    *idum ^= MASK;
    k=(*idum)/IQ;
    *idum=IA*(*idum-k*IQ)-IR*k;
    if (*idum < 0) *idum += RND_MAX;
    ans = *idum;
    *idum ^= MASK;
    return ans;
}

//-----------------------------------------------------------------------------
//
// NAME     vHALinitReqMessage
//
// DESCRIPTION Initialize REQ message buffer descriptor.
//
//-----------------------------------------------------------------------------
VOID
vHALinitReqMessage( IN PHAL_CONTEXT psHAL, IN UMI_MSG *psMsg )
{
    ULONG   ulOffset, i;

    ulOffset = (ULONG)psMsg - (ULONG)psHAL->ucShadowPool;

    if ( MSG_GET_TYPE(psMsg->u16MsgId) == MSG_MAN )
    {
        // Initialize REQ MAN message buffer descriptor.
        i = psHAL->ulReqManMsgNum;
        psHAL->sReqManMsgBuf[i].ulBufAddr = ulOffset;
        psHAL->sReqManMsgBuf[i].ulBufLen = sizeof( SHRAM_MAN_MSG );
        psHAL->sReqManMsgBuf[i].boBufAvail = TRUE;

        psHAL->ulReqManMsgNum ++;
        ASSERT( psHAL->ulReqManMsgNum <= HAL_MAX_REQ_MAN_BUF_NUM );
    }
    else
    {
        // Initialize REQ DBG message buffer descriptor.
        i = psHAL->ulReqDbgMsgNum;
        psHAL->sReqDbgMsgBuf[i].ulBufAddr = ulOffset;
        psHAL->sReqDbgMsgBuf[i].ulBufLen = sizeof( SHRAM_DBG_MSG );
        psHAL->sReqDbgMsgBuf[i].boBufAvail = TRUE;

        psHAL->ulReqDbgMsgNum ++;
        ASSERT( psHAL->ulReqDbgMsgNum <= HAL_MAX_REQ_DBG_BUF_NUM );
    }
}


//-----------------------------------------------------------------------------
//
// NAME     psHALnewReqMessage
//
// DESCRIPTION Get the next available REQ message.
//
//-----------------------------------------------------------------------------
UMI_MSG *
psHALnewReqMessage( IN PHAL_CONTEXT psHAL, IN MSG_TYPE eType )
{
    static ULONG ulManMsg=0, ulDbgMsg=0;
    ULONG   i, j, ulTail, ulOffset;
    UMI_MSG *psMsg = NULL;

    // Block any request message if radio off.
    if ( !psHAL->psAdapter->sWlan.boRadioOn )
        return NULL;

    if ( eType == MSG_MAN )
    {
        // Queue the message if not under AWAKE state.
        if ( psHAL->ePowerState != HAL_PS_AWAKE )
        {
            DBG_LEV2(("Queue message, power state = 0x%x\n", psHAL->ePowerState));

            psHAL->boTxReqMsgFlag = TRUE;

            if ( psHAL->ePowerState == HAL_PS_ASLEEP )
            {
                psHAL->ePowerState = HAL_PS_WAKING;

                // Try to wake up the device.
                vHALwakeupDevice( psHAL );
            }
        }
        else
        {
            // Get REQ MAN message.
            for ( i=0; i<psHAL->ulReqManMsgNum; i++ )
            {
                // Search from the current index.
                j = (i + ulManMsg) % psHAL->ulReqManMsgNum;
                if ( psHAL->sReqManMsgBuf[j].boBufAvail )
                {
                    psHAL->sReqManMsgBuf[j].boBufAvail = FALSE;
                    psMsg = (UMI_MSG *)&psHAL->ucShadowPool[ psHAL->sReqManMsgBuf[j].ulBufAddr ];
                    ulManMsg = (j + 1) % psHAL->ulReqManMsgNum;
                    break;
                }
            }
        }

        // If no resources, try to get message buffer from reserved queue. 
        if ( psMsg == NULL )
        {
            // Check whether we have available buffer in reserved queue.
            ulTail = (psHAL->ulReqManMsgRsvdQTail + 1) % HAL_REQ_MAN_QUEUE_SIZE;
            if ( ulTail != psHAL->ulReqManMsgRsvdQHead )
            {
                // Get message buffer from shadow pool Rx buffer area.
                ulOffset = psHAL->ulReqManMsgRsvdQTail * sizeof( SHRAM_MAN_MSG );
                psMsg = (UMI_MSG *)&psHAL->ucShadowPool[ ulOffset ];

                // Adjust reserved queue tail.
                psHAL->ulReqManMsgRsvdQTail = ulTail;
            }
        }
    }
    else
    {
        // Get REQ DBG message.
        for ( i=0; i<psHAL->ulReqDbgMsgNum; i++ )
        {
            // Search from the current index.
            j = (i + ulDbgMsg) % psHAL->ulReqDbgMsgNum;
            if ( psHAL->sReqDbgMsgBuf[j].boBufAvail )
            {
                psHAL->sReqDbgMsgBuf[j].boBufAvail = FALSE;
                psMsg = (UMI_MSG *)&psHAL->ucShadowPool[ psHAL->sReqDbgMsgBuf[j].ulBufAddr ];
                ulDbgMsg = (j + 1) % psHAL->ulReqDbgMsgNum;
                break;
            }
        }
    }

    return psMsg;
}


//-----------------------------------------------------------------------------
//
// NAME     vHALreturnReqMessage
//
// DESCRIPTION Return the REQ message.
//
//-----------------------------------------------------------------------------
VOID
vHALreturnReqMessage( IN PHAL_CONTEXT psHAL, IN UMI_MSG *psMsg )
{
    ULONG   i, ulOffset, ulQueuedMsgOffset;

    ulOffset = (ULONG)psMsg - (ULONG)psHAL->ucShadowPool;

    if ( MSG_GET_TYPE(psMsg->u16MsgId) == MSG_MAN )
    {
        // If there is a queued message, send it right now.
        if ( psHAL->ulReqManMsgRsvdQHead != psHAL->ulReqManMsgRsvdQTail )
        {
            ulQueuedMsgOffset = psHAL->ulReqManMsgRsvdQHead * sizeof( SHRAM_MAN_MSG );
            OS_MEMCPY( (PVOID)psMsg, &psHAL->ucShadowPool[ulQueuedMsgOffset], sizeof(SHRAM_MAN_MSG) );

            // Adjust reserved queue head.
            psHAL->ulReqManMsgRsvdQHead = (psHAL->ulReqManMsgRsvdQHead + 1) % HAL_REQ_MAN_QUEUE_SIZE;

            boHALsendMessage( psHAL, psMsg );
        }
        else
        {
            // Return REQ MAN message.
            for ( i=0; i<psHAL->ulReqManMsgNum; i++ )
            {
                if ( psHAL->sReqManMsgBuf[i].ulBufAddr == ulOffset )
                {
                    psHAL->sReqManMsgBuf[i].boBufAvail = TRUE;
                    break;
                }
            }
        }
    }
    else
    {
        // Return REQ DBG message.  
        for ( i=0; i<psHAL->ulReqDbgMsgNum; i++ )
        {
            if ( psHAL->sReqDbgMsgBuf[i].ulBufAddr == ulOffset )
            {
                psHAL->sReqDbgMsgBuf[i].boBufAvail = TRUE;
                break;
            }
        }
    }
}


//-----------------------------------------------------------------------------
//
// NAME     boHALsendMessage
//
// PARAMETERS  psHAL    Pointer to HAL context.
//    psMsg    Pointer to the message to be sent.
//
// RETURNS  A boolean indicating whether the message was successfully sent
//    to the device. A failure should be treated as a fatal error.
//
// DESCRIPTION This function should be used to send a message to the device.
//
//-----------------------------------------------------------------------------
BOOLEAN
boHALsendMessage( IN PHAL_CONTEXT psHAL, IN UMI_MSG * psMsg )
{
    BOOLEAN boResult = FALSE;
    ULONG   ulTailAddr, ulMsgLength, ulAddress, ulMailbox;
    PHAL_CHI   psCHI = &psHAL->sCHI;

    DBG_LEV2(("boHALsendMessage(): Msg 0x%lx, Id = 0x%04x\n", (ULONG)psMsg - (ULONG)psHAL->ucShadowPool, psMsg->u16MsgId));
    
    ASSERT (psHAL != NULL);
    

    
    do {
        if ( psHAL->eState != HAL_RUNNING )
        {
            DBG_LEV0(("ERROR: Attempt to send message in invalid state, %d.\n", psHAL->eState));
            break;
        }

        // Get device address.
        ulAddress = (ULONG)psMsg - (ULONG)psHAL->ucShadowPool;

        // If message from reserved queue, just ignore it.
        if ( ulAddress > HAL_MAILBOX_BASE )
        {
            // Get message length.
            if ( MSG_GET_DIR(psMsg->u16MsgId) == MSG_RES )
                ulMsgLength = sizeof(UMI_MSG_HEADER) + sizeof(ULONG);
            else if ( MSG_GET_TYPE(psMsg->u16MsgId) == MSG_MAN )
                ulMsgLength = sizeof(SHRAM_MAN_MSG);
            else
                ulMsgLength = sizeof(SHRAM_DBG_MSG);

            psMsg->psNext     = 0;
            psMsg->u8Pad1     = 0;
            psMsg->u8Persistent = TRUE;
            psMsg->u32Pad2    = 0;

            if ( ulAddress > CHI_ADDR_CFM_IND_HEAD( 0, psCHI->ulN ) )
                ulMailbox = HAL_MAILBOX_2;
            else
                ulMailbox = HAL_MAILBOX_1;

            // Acquire semaphore before accessing mailbox.
            if ( !boHALacquireSemaphore( psHAL, ulMailbox ) )
            {
                DBG_LEV0(("boHALacquireSemaphore failed\n"));
                break;
            }
            
            // Write message to device.
            vHALwriteMailbox( psHAL, ulAddress, (PULONG)psMsg, ulMsgLength );

            // Release old and acquire new semaphore if necessary.
            if ( ulMailbox == HAL_MAILBOX_2 )
            {
                vHALreleaseSemaphore( psHAL, ulMailbox );
                if ( !boHALacquireSemaphore( psHAL, HAL_MAILBOX_1 ) )
                {
                    DBG_LEV0(("boHALacquireSemaphore failed\n"));
                    break;
                }
            }

            // Address to Target is relative address, need to adjust.
            ulAddress -= HAL_MAILBOX_BASE;
            // Write address to REQ message queue.
            ulTailAddr = psCHI->ulAddrReqResQ + psCHI->ulReqResTail * sizeof(ULONG);
            vHALwriteMailbox( psHAL, ulTailAddr, &ulAddress, sizeof(ULONG) );

            // Increase the tail index and check for wrap around.
            psCHI->ulReqResTail++;
            if ( psCHI->ulReqResTail > psCHI->ulN )  psCHI->ulReqResTail = 0;

            // Write tail index to device.
#ifdef CA_CE5
            // ERI Workaround for non-dw-aligned access problem 
            if((psCHI->ulAddrReqResTail & 0x0003) != 0) {
                ULONG value;		
                vHALreadMailbox( psHAL, (psCHI->ulAddrReqResTail & 0xfffc), 
					&value, sizeof(ULONG) );
                value &= 0x0000ffff;
                value |= (psCHI->ulReqResTail << 16);
                vHALwriteMailbox( psHAL, (psCHI->ulAddrReqResTail & 0xfffc), 
					&value, sizeof(ULONG) );
            }
            else
#endif // CA_CE5
                vHALwriteMailbox( psHAL, psCHI->ulAddrReqResTail, &psCHI->ulReqResTail, sizeof(USHORT) );

            // Release mailbox semaphore.
            vHALreleaseSemaphore( psHAL, HAL_MAILBOX_1 );

            if ( MSG_GET_DIR(psMsg->u16MsgId) == MSG_REQ )
            {
                // Set a flag to trace whether REQ message stuck.
                psHAL->boTxReqMsgFlag = TRUE;
            }

            // Generate interrupt to device.
            vHALinterruptDevice( psHAL, 1, HAL_BIT_interrupt_message_bootloader );

            boResult = TRUE;
        }
    } while (FALSE);

    return boResult;
}


//-----------------------------------------------------------------------------
//
// NAME     vHAL_ReadFatalMsg
//
// PARAMETERS  psHAL    Pointer to HAL context.
//
// DESCRIPTION This handler is called from the interrupt DPC if an 
//    interrupt is received from the device requesting that it be reset
//    due to a Fatal error in the device.
//
//    The function reads Mailbox 0 to obtain the source file and line
//    number in the device code in which the fatal error occurred.
//
//-----------------------------------------------------------------------------
static void vHAL_ReadFatalMsg( IN PHAL_CONTEXT psHAL )
{
    char pcFatalMsg[32];
    USHORT u16LineNum;

    // Acquire semaphore before accessing mailbox.
    if ( !boHALacquireSemaphore( psHAL, HAL_MAILBOX_0 ) )
    {
       DBG_LEV0(("vHAL_ReadFatalMsg(): Couldn't acquire Mailbox 0 semaphore\n"));

⌨️ 快捷键说明

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