📄 hal.c
字号:
//---------------------------------------------------------------------------
// 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 + -