📄 hal.c
字号:
{
if ( ulLength > psDownload->ulSizeXferArea )
{
ulLength = psDownload->ulSizeXferArea;
}
vHALwriteIMem( psHAL,
psDownload->ulAddrXferArea + HAL_IMEM_BASE,
(PULONG)&psDownload->paucImage[psDownload->ulOffset],
ulLength );
ulValue = HAL_BYTES_TO_DWORDS(ulLength);
vHALwriteMailbox( psHAL, CHI_ADDR_XFER_LEN, &ulValue, sizeof(ULONG) );
ulValue = CHI_BOOT_DATA;
vHALwriteMailbox( psHAL, CHI_ADDR_XFER_CTRL(psDownload->ulCPU), &ulValue, sizeof(ULONG) );
// Release mailbox semaphore.
vHALreleaseSemaphore( psHAL, HAL_MAILBOX_0 );
psDownload->ulOffset += ulLength;
DBG_LEV2(("Transferred %ld bytes to IMEM.\n", ulLength));
}
}
else if ( ulXferCtrl == CHI_BOOT_DATA )
{
vHALreleaseSemaphore( psHAL, HAL_MAILBOX_0 );
DBG_LEV0(("Target still processing - no action\n"));
}
else
{
// Release mailbox semaphore.
vHALreleaseSemaphore( psHAL, HAL_MAILBOX_0 );
DBG_LEV0(("ERROR: Device not ready or processing: %lu.\n", ulXferCtrl));
vHALstop( psHAL );
}
}
}
//-----------------------------------------------------------------------------
//
// NAME vHALcheckForBootWaiting
//
// PARAMETERS psHAL Pointer to HAL context.
//
// DESCRIPTION This handler is called from interrupt DPC in 'starting' state.
//
//-----------------------------------------------------------------------------
VOID
vHALcheckForBootWaiting( IN PHAL_CONTEXT psHAL )
{
ULONG ulXferCtrl, ulValue;
DBG_LEV1(("vHALcheckForBootWaiting()\n"));
// Acquire semaphore before accessing mailbox.
if ( boHALacquireSemaphore( psHAL, HAL_MAILBOX_0 ) )
{
vHALreadMailbox( psHAL, CHI_ADDR_XFER_CTRL(CHI_UPPER_CPU), &ulXferCtrl, sizeof(ULONG) );
if ( ulXferCtrl == CHI_BOOT_WAITING )
{
psHAL->eState = HAL_AWAITING_CHI_MAGIC;
/*
* We have receive boot waiting from all processors that we have enabled.
* Now write boot go to the transfer control and wait for the HIM to set
* up the Host Interface area.
*/
ulValue = CHI_BOOT_GO;
vHALwriteMailbox( psHAL, CHI_ADDR_XFER_CTRL(CHI_UPPER_CPU), &ulValue, sizeof(ULONG) );
// Release mailbox semaphore.
vHALreleaseSemaphore( psHAL, HAL_MAILBOX_0 );
}
else
{
// Release mailbox semaphore.
vHALreleaseSemaphore( psHAL, HAL_MAILBOX_0 );
DBG_LEV0(("ERROR: Couldn't read boot waiting from device.\n"));
vHALstop( psHAL );
}
}
}
//-----------------------------------------------------------------------------
//
// NAME vHALcheckForChiMagic
//
// PARAMETERS psHAL Pointer to HAL context.
//
// DESCRIPTION This handler is called from interrupt DPC in the state
// 'awaiting chi magic'.
//
//-----------------------------------------------------------------------------
VOID
vHALcheckForChiMagic( IN PHAL_CONTEXT psHAL )
{
ULONG ulN, ulMagic;
PHAL_CHI psCHI = &psHAL->sCHI;
PEND_CONTEXT psAdapter = psHAL->psAdapter;
DBG_LEV1(("vHALcheckForChiMagic()\n"));
// Acquire semaphore before accessing mailbox.
if ( boHALacquireSemaphore( psHAL, HAL_MAILBOX_0 ) )
{
vHALreadMailbox( psHAL, CHI_ADDR_MAGIC, &ulMagic, sizeof(ULONG) );
if ( ulMagic == HOST_MAGIC )
{
vHALreadMailbox( psHAL, CHI_ADDR_N, &ulN, sizeof(ULONG) );
// Release mailbox semaphore.
vHALreleaseSemaphore( psHAL, HAL_MAILBOX_0 );
psCHI->ulN = ulN;
psCHI->ulAddrReqResHead = CHI_ADDR_REQ_RES_HEAD(0, ulN);
psCHI->ulAddrReqResTail = CHI_ADDR_REQ_RES_TAIL(0, ulN);
psCHI->ulAddrReqResQ = CHI_ADDR_REQ_RES_Q(0, ulN);
psCHI->ulAddrCfmIndHead = CHI_ADDR_CFM_IND_HEAD(0, ulN);
psCHI->ulAddrCfmIndTail = CHI_ADDR_CFM_IND_TAIL(0, ulN);
psCHI->ulAddrCfmIndQ = CHI_ADDR_CFM_IND_Q(0, ulN);
psCHI->ulReqResTail = 0;
psCHI->ulCfmIndHead = 0;
DBG_LEV2(("CFHI Area N = %ld\n", psCHI->ulN));
// Tx, Rx buffer configuration (0, 1, 2).
psHAL->ulTxRxBufConfig = psAdapter->sCFG.ulBufferConfig;
psHAL->ulRxBufNum = aTxRxBufCfg[ psHAL->ulTxRxBufConfig ][0];
psHAL->ulTxBufNum = aTxRxBufCfg[ psHAL->ulTxRxBufConfig ][1];
psHAL->ulTxRxBufSize = aTxRxBufCfg[ psHAL->ulTxRxBufConfig ][2];
// Initialize Tx and Rx buffer.
vHALinitTxRxBuffer( psHAL );
psHAL->eState = HAL_RUNNING;
// Now check for message.
while (bHALreceiveMessage( psHAL ) == TRUE);
}
else
{
vHALreleaseSemaphore( psHAL, HAL_MAILBOX_0 );
DBG_LEV0(("Target still processing - no action\n"));
}
}
}
//-----------------------------------------------------------------------------
//
// NAME boHALdownload
//
// PARAMETERS psHAL Pointer to HAL context.
//
// RETURNS TRUE if downloaded F/W successfully; FALSE otherwise.
//
// DESCRIPTION This function downloads F/W to Target.
//
//-----------------------------------------------------------------------------
BOOLEAN
boHALdownload( IN PHAL_CONTEXT psHAL, IN BOOLEAN boStart )
{
ULONG i, ulValue, ulTimeout, ulDelay;
BOOLEAN boStatus = FALSE;
// Begin to download the first F/W.
vHALbeginDownload( psHAL, CHI_UPPER_CPU );
// The value of ulDelay should never be greater than 50 (microseconds).
ulDelay = 1;
ulTimeout = END_INITIAL_TIMEOUT * (1000 / ulDelay);
for ( i=0; i<ulTimeout; i++ )
{
OS_DELAY_MS( ulDelay );
// Read interrupt status.
vHALreadRegister( psHAL, HAL_ADDR_interrput_arm_to_host, &ulValue );
if ( ulValue & HAL_MASK_interrupt_arm_to_host )
{
// Clear interrupt status.
vHALwriteRegister( psHAL, HAL_ADDR_interrput_arm_to_host, ulValue );
switch ( psHAL->eState )
{
case HAL_STOPPED:
case HAL_READY_TO_DOWNLOAD_1ST:
case HAL_READY_TO_DOWNLOAD_NTH:
DBG_LEV1(("WARNING: Got interrupt in unexpected state, %d\n", psHAL->eState));
break;
case HAL_AWAITING_BOOT_MAGIC:
vHALcheckForBootMagic( psHAL );
break;
case HAL_DOWNLOADING:
vHALcontinueDownload( psHAL );
break;
case HAL_STARTING:
vHALcheckForBootWaiting( psHAL );
break;
case HAL_AWAITING_CHI_MAGIC:
vHALcheckForChiMagic( psHAL );
break;
case HAL_RUNNING:
while (bHALreceiveMessage( psHAL ) == TRUE);
break;
}
if ( psHAL->eState == HAL_STOPPED ||
(psHAL->eState == HAL_RUNNING && psHAL->psAdapter->boGetPermanentAddress) )
break;
}
else if ((boStart != TRUE) && (psHAL->eState == HAL_AWAITING_CHI_MAGIC))
{
boStatus = TRUE;
break;
}
}
if ( psHAL->eState == HAL_RUNNING )
boStatus = TRUE;
DBG_LEV1(("Download delay time = %ld microseconds, HAL state = %d.\n", i*ulDelay, psHAL->eState));
return( boStatus );
}
//-----------------------------------------------------------------------------
//
// NAME vHALstart
//
// PARAMETERS psHAL Pointer to HAL context.
//
// RETURNS na
//
// DESCRIPTION This function should be used after all code has been
// downloaded to the device to start the target code running.
//
//-----------------------------------------------------------------------------
VOID
vHALstart( IN PHAL_CONTEXT psHAL )
{
ULONG ulValue;
DBG_LEV1(("vHALstart()\n"));
ASSERT (psHAL != NULL);
/*
* To start the device we go through the following steps:
* 1. Write a BOOT_END transfer command to all processors.
* 2. Wait for BOOT_WAITING command back from each processor.
* 3. Write a BOOT_GO transfer command to the first processor.
* It is assumed at this point that code has been downloaded to all
* processors that are required and as a result of this each processor
* will already be running.
*/
if ( psHAL->eState != HAL_READY_TO_DOWNLOAD_NTH )
{
DBG_LEV0(("ERROR: Attempt to start device in invalid state, %d.\n", psHAL->eState));
}
else
{
// Acquire semaphore before accessing mailbox.
if ( boHALacquireSemaphore( psHAL, HAL_MAILBOX_0 ) )
{
psHAL->eState = HAL_STARTING;
ulValue = CHI_BOOT_END;
vHALwriteMailbox( psHAL, CHI_ADDR_XFER_CTRL(CHI_UPPER_CPU), &ulValue, sizeof(ULONG) );
vHALwriteMailbox( psHAL, CHI_ADDR_XFER_CTRL(CHI_UWA_CPU), &ulValue, sizeof(ULONG) );
// Release mailbox semaphore.
vHALreleaseSemaphore( psHAL, HAL_MAILBOX_0 );
}
}
}
//-----------------------------------------------------------------------------
//
// NAME vHALstop
//
// PARAMETERS psHAL Pointer to HAL context.
//
// DESCRIPTION This function can be called in any state following a fatal
// error to return the device to the halted state and clean up.
//
//-----------------------------------------------------------------------------
VOID
vHALstop( IN OUT PHAL_CONTEXT psHAL )
{
// Clean up download structure.
psHAL->sDownload.paucImage = NULL;
psHAL->sDownload.ulLength = 0;
psHAL->sDownload.ulOffset = 0;
psHAL->sDownload.ulAddrXferArea = 0;
// Zero the CFHI area.
psHAL->sCHI.ulN = 0;
psHAL->sCHI.ulAddrReqResHead = 0;
psHAL->sCHI.ulAddrReqResTail = 0;
psHAL->sCHI.ulAddrReqResQ = 0;
psHAL->sCHI.ulAddrCfmIndHead = 0;
psHAL->sCHI.ulAddrCfmIndTail = 0;
psHAL->sCHI.ulAddrCfmIndQ = 0;
psHAL->sCHI.ulReqResTail = 0;
psHAL->sCHI.ulCfmIndHead = 0;
// Change back to stopped state.
psHAL->eState = HAL_STOPPED;
psHAL->ePowerState = HAL_PS_AWAKE;
psHAL->ulDownloadCount = 0;
psHAL->ulReqManMsgNum = 0;
psHAL->ulReqManMsgRsvdQHead = 0;
psHAL->ulReqManMsgRsvdQTail = 0;
psHAL->ulReqDbgMsgNum = 0;
psHAL->boTxReqMsgFlag = FALSE;
// Reset the device.
vHALsoftReset( psHAL );
}
//-----------------------------------------------------------------------------
//
// NAME vHALInitTxRxBuffer
//
// PARAMETERS psHAL Pointer to HAL context.
//
// DESCRIPTION Initialize the Tx & Rx buffer descriptor.
//
//-----------------------------------------------------------------------------
VOID
vHALinitTxRxBuffer( IN PHAL_CONTEXT psHAL )
{
ULONG i;
PUCHAR shadowbase = (PUCHAR)(((ULONG)(psHAL->ucShadowPool0) + 31) & (~31));
ULONG bufsize = (psHAL->ulTxRxBufSize + 31) & (~31);
// Initialize Rx buffer descriptor.
for ( i=0; i<psHAL->ulRxBufNum; i++ )
{
psHAL->aulRxBufferAddr[i] = i * psHAL->ulTxRxBufSize;
}
// Point to the first Rx buffer.
psHAL->ulRxBufferIndex = 0;
// Initialize Tx buffer descriptor.
for ( i=0; i<psHAL->ulTxBufNum; i++ )
{
psHAL->sTxBuf[i].ulBufAddr = (i+ psHAL->ulRxBufNum) * psHAL->ulTxRxBufSize;
psHAL->sTxBuf[i].ulBufLen = psHAL->ulTxRxBufSize;
psHAL->sTxBuf[i].boBufAvail = TRUE;
psHAL->sTxBuf[i].pulocalAddr = shadowbase+(i+ psHAL->ulRxBufNum)*bufsize;
}
// Point to the fisrt Tx buffer.
psHAL->ulTxBufferIndex = 0;
}
//-----------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -