📄 hal.c
字号:
return;
}
// read info out of Mailbox 0
vHALreadMailbox( psHAL, HAL_MAILBOX_BASE, (PULONG) pcFatalMsg, sizeof(pcFatalMsg) );
vHALreleaseSemaphore( psHAL, HAL_MAILBOX_0 );
OS_MEMCPY( &u16LineNum, (pcFatalMsg + (sizeof(pcFatalMsg) - 2)), sizeof(USHORT) );
DBG_LEV1(("Device FATAL ERROR in: %s, at line: %d\n", pcFatalMsg, u16LineNum));
}
//-----------------------------------------------------------------------------
//
// NAME vHALreceiveMessage
//
// PARAMETERS psHAL Pointer to HAL context.
//
// DESCRIPTION This handler is called from the interrupt DPC if a message
// interrupt is received from the device in the running state.
// The function reads message from device and dispatch to handle.
//
// RETURN: returns true if message processed, false otherwise.
//
//-----------------------------------------------------------------------------
BOOLEAN
bHALreceiveMessage( IN PHAL_CONTEXT psHAL )
{
ULONG ulCfmIndTail=0, ulHeadAddr, ulDeviceRef, ulMsgLen, ulMailbox;
PHAL_CHI psCHI = &psHAL->sCHI;
UMI_MSG *psMsg;
// Acquire semaphore before accessing mailbox.
if ( !boHALacquireSemaphore( psHAL, HAL_MAILBOX_2 ) )
{
return FALSE;
}
// Read the tail index from device.
#ifdef CA_CE5
// ERI Workaround for non-dw-aligned access problem
if((psCHI->ulAddrCfmIndTail & 0x0003) != 0) {
ULONG value1;
vHALreadMailbox( psHAL, (psCHI->ulAddrCfmIndTail & 0xfffc),
&value1, sizeof(ULONG) );
ulCfmIndTail = value1 >> 16;
}
else
{
vHALreadMailbox( psHAL, psCHI->ulAddrCfmIndTail, &ulCfmIndTail, sizeof(USHORT) );
}
#else // CA_CE5
vHALreadMailbox( psHAL, psCHI->ulAddrCfmIndTail, &ulCfmIndTail, sizeof(USHORT) );
#endif // CA_CE5
psCHI->ulCfmIndTail = ulCfmIndTail;
// Release mailbox semaphore.
vHALreleaseSemaphore( psHAL, HAL_MAILBOX_2 );
// Check whether queue empty ...
if (psCHI->ulCfmIndHead == ulCfmIndTail)
{
// no more messages to process ...
return FALSE;
}
if ( psHAL->eState != HAL_RUNNING )
{
DBG_LEV0(("ERROR: Attempt to receive message in invalid state, %d.\n", psHAL->eState));
return FALSE;
}
// Acquire semaphore before accessing mailbox.
if ( !boHALacquireSemaphore( psHAL, HAL_MAILBOX_2 ) )
{
return FALSE;
}
// Get address from IND message queue.
ulHeadAddr = psCHI->ulAddrCfmIndQ + psCHI->ulCfmIndHead * sizeof(ULONG);
vHALreadMailbox( psHAL, ulHeadAddr, &ulDeviceRef, sizeof(ULONG) );
// Address from Target is relative address, need to adjust.
ulDeviceRef += HAL_MAILBOX_BASE;
// Check the validity of address and queue tail.
if ( (ulDeviceRef >= HAL_IMEM_MAILBOX_SPACE) || (ulDeviceRef & 0x03) ||
(ulCfmIndTail > psCHI->ulN) )
{
DBG_LEV0(("ERROR: address = 0x%lx, queue tail = %lu\n", ulDeviceRef, ulCfmIndTail));
vHALreleaseSemaphore( psHAL, HAL_MAILBOX_2 );
{
return FALSE;
}
}
if ( ulDeviceRef > CHI_ADDR_CFM_IND_HEAD( 0, psCHI->ulN ) )
ulMailbox = HAL_MAILBOX_2;
else
ulMailbox = HAL_MAILBOX_1;
// Release old and acquire new semaphore if necessary.
if ( ulMailbox == HAL_MAILBOX_1 )
{
vHALreleaseSemaphore( psHAL, HAL_MAILBOX_2 );
if ( !boHALacquireSemaphore( psHAL, ulMailbox ) )
{
return FALSE;
}
}
// Get Host message buffer.
psMsg = (UMI_MSG *)&psHAL->ucShadowPool[ ulDeviceRef ];
// Read message header from device.
vHALreadMailbox( psHAL, ulDeviceRef, (PULONG)psMsg, sizeof(UMI_MSG_HEADER) );
// Get message length.
ulMsgLen = (MSG_GET_TYPE(psMsg->u16MsgId) == MSG_MAN) ? sizeof(UMI_MAN) : sizeof(UMI_DBG);
// Read message data from device.
vHALreadMailbox( psHAL, ulDeviceRef+sizeof(UMI_MSG_HEADER), (PULONG)psMsg->abData, ulMsgLen );
// Release old and acquire new semaphore if necessary.
if ( ulMailbox == HAL_MAILBOX_1 )
{
vHALreleaseSemaphore( psHAL, ulMailbox );
if ( !boHALacquireSemaphore( psHAL, HAL_MAILBOX_2 ) )
{
return FALSE;
}
}
// Increase the head index and check for wrap around.
psCHI->ulCfmIndHead++;
if ( psCHI->ulCfmIndHead > psCHI->ulN ) psCHI->ulCfmIndHead = 0;
// Write head index to device.
vHALwriteMailbox( psHAL, psCHI->ulAddrCfmIndHead, &psCHI->ulCfmIndHead, sizeof(USHORT) );
// Release mailbox semaphore.
vHALreleaseSemaphore( psHAL, HAL_MAILBOX_2 );
if ( MSG_GET_DIR(psMsg->u16MsgId) == MSG_CFM )
{
// Clear the Tx REQ message flag.
psHAL->boTxReqMsgFlag = FALSE;
}
DBG_LEV2(("vHALreceiveMessage(): Msg 0x%lx, Id = 0x%04x\n", (ULONG)psMsg, psMsg->u16MsgId));
TRACE(TRACE_CFSD_NDHAL, psMsg->u16MsgId);
// Call message handler to process message.
vHALMessageHandler( psHAL, psMsg );
// Clear any new interrupts that were generated for messages we've just pulled
if (psCHI->ulCfmIndHead == ulCfmIndTail)
{
DBG_LEV3(("Has reached the message tail, terminate it.\n "));
return FALSE;
}
return TRUE;
}
//-----------------------------------------------------------------------------
//
// NAME vHALbeginDownload
//
// PARAMETERS psHAL Pointer to HAL context.
// ulCPU The processor that code should be downloaded to:
// CHI_UPPER_CPU, CHI_UWA_CPU.
//
// RETURNS na
//
// DESCRIPTION This function should be used to download an image to one of
// the device processors using the bootloader.
//
//-----------------------------------------------------------------------------
VOID
vHALbeginDownload( IN PHAL_CONTEXT psHAL, IN ULONG ulCPU )
{
PCFG_CODE_IMAGE psCode;
PUCHAR paucImage;
ULONG ulLength, ulMagic;
// Get the F/W image to be downloaded.
psCode = psCFGgetCodeImage( &psHAL->psAdapter->sCFG, ulCPU+1 );
if ( psCode == NULL ) {
DBG_LEV1(("beginDownload(), psCode = 0x%lx ... bailing out\n",
(ULONG)psCode));
return;
}
paucImage = psCode->paucImage;
ulLength = psCode->ulLength;
DBG_LEV1(("boHALbeginDownload(): %s CPU, Image 0x%lx, Length 0x%lx.\n",
(ulCPU == CHI_UPPER_CPU)? "Upper": "UWA", (ULONG)paucImage, ulLength));
ASSERT (psHAL != NULL);
// Acquire semaphore before accessing mailbox.
if ( boHALacquireSemaphore( psHAL, HAL_MAILBOX_0 ) )
{
// F/W must be downloaded to upper CPU first.
if ( ulCPU == CHI_UPPER_CPU )
{
psHAL->eState = HAL_READY_TO_DOWNLOAD_1ST;
// Write boot magic.
ulMagic = CHI_BOOT_MAGIC;
vHALwriteMailbox( psHAL, CHI_ADDR_BOOT_MAGIC, &ulMagic, sizeof(ULONG) );
ulMagic = 0;
vHALreadMailbox( psHAL, CHI_ADDR_BOOT_MAGIC, &ulMagic, sizeof(ULONG) );
DBG_LEV1(("Read boot magic after writing %08lx\n", ulMagic));
psHAL->sDownload.ulCPU = ulCPU;
psHAL->sDownload.paucImage = paucImage;
psHAL->sDownload.ulLength = ulLength;
psHAL->sDownload.ulOffset = 0;
psHAL->sDownload.ulAddrXferArea = 0;
psHAL->sDownload.ulSizeXferArea = 0;
psHAL->eState = HAL_AWAITING_BOOT_MAGIC;
/*
* Because this is the first download, we must wait for the transfer
* control structure to be initialized by the upper CPU before we
* proceed. Specifically, we are waiting for BOOT_MAGIC.
*/
vHALwriteMailbox( psHAL, CHI_ADDR_BOOT_NUM, &ulCPU, sizeof(ULONG) );
// Release mailbox semaphore.
vHALreleaseSemaphore( psHAL, HAL_MAILBOX_0 );
}
else if ( ulCPU == CHI_UWA_CPU )
{
// Write the number of CPU that is being booted to the boot number field.
vHALwriteMailbox( psHAL, CHI_ADDR_BOOT_NUM, &ulCPU, sizeof(ULONG) );
// Release mailbox semaphore.
vHALreleaseSemaphore( psHAL, HAL_MAILBOX_0 );
psHAL->sDownload.ulCPU = ulCPU;
psHAL->sDownload.paucImage = paucImage;
psHAL->sDownload.ulLength = ulLength;
psHAL->sDownload.ulOffset = 0;
psHAL->eState = HAL_DOWNLOADING;
// Continue to download since the transfer control area has been initialized.
vHALcontinueDownload( psHAL );
}
}
}
//-----------------------------------------------------------------------------
//
// NAME vHALcheckForBootMagic
//
// PARAMETERS psHAL Pointer to HAL context.
//
// DESCRIPTION This function is called from the interrupt DPC in the 'waiting
// for boot magic' state. The function reads the value of boot
// magic and if it has been set by CPU 0 then the state machine
// can progress to the next stage of the download process.
//
//-----------------------------------------------------------------------------
VOID
vHALcheckForBootMagic( IN PHAL_CONTEXT psHAL )
{
ULONG ulMagic;
PHAL_DOWNLOAD psDownload;
DBG_LEV1(("vHALcheckForBootMagic()\n"));
psDownload = &psHAL->sDownload;
// Acquire semaphore before accessing mailbox.
if ( boHALacquireSemaphore( psHAL, HAL_MAILBOX_0 ) )
{
vHALreadMailbox( psHAL, CHI_ADDR_BOOT_MAGIC, &ulMagic, sizeof(ULONG) );
if ( ulMagic == CHI_BOOT_MAGIC )
{
vHALreadMailbox( psHAL, CHI_ADDR_XFER_MAX, &psDownload->ulSizeXferArea, sizeof(ULONG) );
vHALreadMailbox( psHAL, CHI_ADDR_XFER_VECTOR, &psDownload->ulAddrXferArea, sizeof(ULONG) );
// Release mailbox semaphore.
vHALreleaseSemaphore( psHAL, HAL_MAILBOX_0 );
// Convert size of transfer area from 32-bit DWORDs to BYTEs.
psDownload->ulSizeXferArea = HAL_DWORDS_TO_BYTES( psDownload->ulSizeXferArea );
psHAL->eState = HAL_DOWNLOADING;
vHALcontinueDownload( psHAL );
}
else
{
// Release mailbox semaphore.
vHALreleaseSemaphore( psHAL, HAL_MAILBOX_0 );
DBG_LEV0(("ERROR: Boot magic did not match.\n"));
vHALstop( psHAL );
}
}
}
//-----------------------------------------------------------------------------
//
// NAME vHALcontinueDownload
//
// PARAMETERS psHAL Pointer to HAL context.
//
// DESCRIPTION This handler is called from interrupt DPC in the 'downloading'
// state. The function checks the state of the device and if the
// device is ready continues the download.
//
//-----------------------------------------------------------------------------
VOID
vHALcontinueDownload( IN PHAL_CONTEXT psHAL )
{
ULONG ulXferCtrl, ulLength, ulValue;
PHAL_DOWNLOAD psDownload;
DBG_LEV1(("vHALcontinueDownload()\n"));
psDownload = &psHAL->sDownload;
// Acquire semaphore before accessing mailbox.
if ( boHALacquireSemaphore( psHAL, HAL_MAILBOX_0 ) )
{
/*
* We read the value of transfer control for the processor to which we are
* currently downloading. If it is ready for more data then get the next
* block of data and transfer it to the device. If we device is still busy
* with the previous block of data we do nothing.
*/
vHALreadMailbox( psHAL, CHI_ADDR_XFER_CTRL(psDownload->ulCPU), &ulXferCtrl, sizeof(ULONG) );
if ( ulXferCtrl == CHI_BOOT_READY )
{
ulLength = psDownload->ulLength - psDownload->ulOffset;
if (ulLength == 0)
{
// Release mailbox semaphore.
vHALreleaseSemaphore( psHAL, HAL_MAILBOX_0 );
psDownload->paucImage = NULL;
psDownload->ulLength = 0;
psDownload->ulOffset = 0;
psHAL->eState = HAL_READY_TO_DOWNLOAD_NTH;
psHAL->ulDownloadCount++;
if ( psDownload->ulCPU == CHI_UPPER_CPU )
{
// Begin to download the second F/W after the first one.
vHALbeginDownload( psHAL, CHI_UWA_CPU );
}
else if ( psDownload->ulCPU == CHI_UWA_CPU )
{
// Start device after downloading the two F/W.
vHALstart( psHAL );
}
}
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -