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

📄 hal.c

📁 Freescale ARM11系列CPU MX31的WINCE 5.0下的BSP
💻 C
📖 第 1 页 / 共 5 页
字号:
//
// NAME     uiHALcopyPacket
//
// PARAMETERS  paucSA      Pointer to location where ethernet source
//          address should be placed.
//    paucDA      Pointer to location where ethernet destination
//          address should be placed.
//    psPayloadDesc  Pointer to buffer descriptor where the payload
//          should be copied to.
//    psSrcPkt Pointer to packet descriptor where the data
//          should be copied from.
//
// RETURNS  The length of the packet including the ethernet header.
//
// DESCRIPTION This function is used to copy the contents of a Packet supplied
//    by a protocol driver into a physically contiguous buffer
//    allocated within the driver i.e. ensures that the packet is
//    completely contained in one memory page.
//
//-----------------------------------------------------------------------------
ULONG
uiHALcopyPacket(
    PUCHAR paucSA,
    PUCHAR paucDA,
    PUCHAR psPayloadDesc,
    PNDIS_PACKET psSrcPkt
)
{
    ULONG   uiPktLength = 0;
    ULONG   uiBufLength;
    PVOID   pvSrcAddr;
    PUCHAR  paucPayloadBuf;
    BOOLEAN boFirst = TRUE;    
    ULONG   uiPhysicalBufferCount;
    PNDIS_BUFFER psSrcBuf;

    paucPayloadBuf = psPayloadDesc;

    NdisQueryPacket( psSrcPkt, &uiPhysicalBufferCount, NULL, &psSrcBuf, &uiPktLength );

    while ( psSrcBuf != NULL )
    {
#ifdef   NDIS51_MINIPORT
        NdisQueryBufferSafe( psSrcBuf, &pvSrcAddr, &uiBufLength, HighPagePriority );
#else
        NdisQueryBuffer( psSrcBuf, &pvSrcAddr, &uiBufLength );
#endif
    
        if ( pvSrcAddr != NULL )
        {
            if ( boFirst )
            {
                // We assume the first buffer must include at least the Ethernet header.
                ASSERT ( uiBufLength >= DAT_SIZE_ETHERNET_HDR );
                if ( uiBufLength >= DAT_SIZE_ETHERNET_HDR )
                {
                    ETH_COPY_NETWORK_ADDRESS( paucSA, DAT_ETHERNET_SRC(pvSrcAddr) );
                    ETH_COPY_NETWORK_ADDRESS( paucDA, DAT_ETHERNET_DEST(pvSrcAddr) );
                    
                    uiBufLength -= (DAT_SIZE_ETHERNET_HDR - DAT_SIZE_ETHERNET_TYPE);
                    pvSrcAddr = (PVOID)((ULONG)pvSrcAddr + (DAT_SIZE_ETHERNET_HDR - DAT_SIZE_ETHERNET_TYPE));
                }

                // add LLC and SNAP headers - but not including SNAP type.
                *paucPayloadBuf++ = 0xAA;  // DSAP 
                *paucPayloadBuf++ = 0xAA;  // SSAP 
                *paucPayloadBuf++ = 0x03;  // cntl 
                *paucPayloadBuf++ = 0x00;  // org code[3] 
                *paucPayloadBuf++ = 0x00;
                *paucPayloadBuf++ = 0x00;
            
                // Only take out addresses and add snap with the first fragment of the chained buffer.
                boFirst = FALSE;
            }

            OS_MEMCPY( paucPayloadBuf, pvSrcAddr, uiBufLength );

            paucPayloadBuf += uiBufLength;
        }
        NdisGetNextBuffer( psSrcBuf, &psSrcBuf );
    }

    return uiPktLength;
}

//-----------------------------------------------------------------------------
//
// NAME     vHALflushTxQueues
// 
// PARAMETERS  psAdapter    Pointer to adapter context.
//
// RETURNS  None
//
// DESCRIPTION This routine flushes all packets in the internal TX queues,
//             typically on shutdown, etc.
//
//-----------------------------------------------------------------------------
VOID
vHALflushTxQueues( PEND_CONTEXT psAdapter )
{
    PHAL_CONTEXT  psHAL = &psAdapter->sHAL;
    UINT uiLoop;
    UINT uiNxtHead;

    PNDIS_PACKET pPacket;


    TRACE(TRACE_CFSD_NDHAL, 0);
    DBG_LEV1(("Flushing TX queues\n"));
    
    for (uiLoop = 0; uiLoop < 4; uiLoop++)
    {
        while (psHAL->ulQueueHeads[uiLoop] != psHAL->ulQueueTails[uiLoop])
        {
            uiNxtHead = (psHAL->ulQueueHeads[uiLoop] + 1) % HAL_TX_QUEUE_LEN;
            pPacket = psHAL->apTxQueues[uiLoop][uiNxtHead];
            psHAL->ulQueueHeads[uiLoop] = uiNxtHead;

            NdisMSendComplete(psAdapter->hMiniportAdapterHandle,
                              pPacket,
                              NDIS_STATUS_FAILURE );

        }
    }

}

//-----------------------------------------------------------------------------
//
// NAME     vHALpushTxToImem
// 
// PARAMETERS  psAdapter    Pointer to adapter context.
//
// RETURNS  void
//
// DESCRIPTION This is the target of the workqueue for serializing TX requests.
//
//-----------------------------------------------------------------------------
void vHALpushTxToImem(void *psAdapter)
{
    TRACE(TRACE_CFSD_NDHAL, 0);
    // push to imem as many as possible
    while (bHAL_PickAndSendPacket(psAdapter) == TRUE);
    TRACE(TRACE_CFSD_NDHAL, 0);
}
//-----------------------------------------------------------------------------
//
// NAME     iHAL_PickAndSendPacket
// 
// PARAMETERS  psAdapter    Pointer to adapter context.
//
// RETURNS  boolean - TRUE if packet sent, FALSE otherwise
//
// DESCRIPTION This routine picks the next packet to enter imem based on
//             a priority weighted random choice, and starts the packet TX
//             if there is an imem space available.
//
//-----------------------------------------------------------------------------
BOOLEAN bHAL_PickAndSendPacket(PEND_CONTEXT psAdapter)
{
    PHAL_CONTEXT  psHAL = &psAdapter->sHAL;
    UINT uiRange;
    UINT uiRand;
    UINT uiLoop;
    UINT uiPriority = 1;
    UINT uiNxtHead;
    BOOLEAN ret;
    int iStatus;


    PNDIS_PACKET pPacket;
    static long idum = 0;
    

    // relative odds of sending priorities background, best effort,
    // video, voice - so VOICE is 273/65 times more likely to go out
    // than best effort.
    static UINT uiPriOdds[4] = {65, 105, 195, 273};

    TRACE(TRACE_CFSD_NDHAL, 0);
    
    // make sure we can send TX packets ...
    if (psAdapter->eNetState != NET_CONNECTED)
    {
        return FALSE;
    }
    
    if ( psHAL->ePowerState != HAL_PS_AWAKE )
    {
        DBG_LEV2(("Tx resources, power state = 0x%x\n", psHAL->ePowerState));

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

            // Try to wake up the device.
            vHALwakeupDevice( psHAL );
        }
        return FALSE;
    }
    


    // choose a packet priority ...
    uiRange = 0;
    for (uiLoop = 0; uiLoop < 4; uiLoop++)
    {
        if (psHAL->ulQueueHeads[uiLoop] != psHAL->ulQueueTails[uiLoop])
        {
            uiRange += uiPriOdds[uiLoop];
        }
    }

    // No more packets in queue, nothing to do.
    if ( uiRange == 0 )
    {

        TRACE(TRACE_CFSD_NDHAL, 0);
        return FALSE;
    }

    // check whether there is space available ...
    if ( psHAL->sTxBuf[psHAL->ulTxBufferIndex].boBufAvail != TRUE )
    {
        psAdapter->boSendNoResourcesFlag = TRUE;
        TRACE(TRACE_CFSD_NDHAL, 0);
        return FALSE;
    }

    uiRange--;
    uiRand = (unsigned int)((uiGenRand( &idum ) * (ULONGLONG)uiRange) / RND_MAX);

    
    uiRange = 0;
    for (uiLoop = 0; uiLoop < 4; uiLoop++)
    {
        if (psHAL->ulQueueHeads[uiLoop] != psHAL->ulQueueTails[uiLoop])
        {
            uiRange += uiPriOdds[uiLoop];
            if (uiRand < uiRange)
            {
                uiPriority = uiLoop;
                break;
            }
        }
    }

    ASSERT(uiLoop < 4);

    ASSERT(psHAL->ulQueueHeads[uiPriority] != psHAL->ulQueueTails[uiPriority]);
    
    // try to send the packet ...
    uiNxtHead = (psHAL->ulQueueHeads[uiPriority] + 1) % HAL_TX_QUEUE_LEN;
    pPacket = psHAL->apTxQueues[uiPriority][uiNxtHead];
    psHAL->ulQueueHeads[uiPriority] = uiNxtHead;

    
    iStatus = iHALsendPacket(
        &psAdapter->sHAL,
        pPacket,
        (uint32)NDIS_PER_PACKET_INFO_FROM_PACKET(
            pPacket,
            Ieee8021pPriority)
    );

    if (iStatus == 0)
    {
        // No more packets can be sent at this time - leave
        // remainder pending.
        psAdapter->boSendNoResourcesFlag = TRUE;
    }

    
    // if failure, maybe we should try to requeue???
    // return packet descriptor to NDIS
    NdisMSendComplete(psAdapter->hMiniportAdapterHandle,
                      pPacket,
                      NDIS_STATUS_SUCCESS);

    if (iStatus == 0)
    {
        // No more packets can be sent at this time - leave
        // remainder pending.
        ret = FALSE;
    }
    else if ( iStatus == 1 )
    {
        // remove packet from queue ... 
        psAdapter->sStats.ulTotalPktsTxedOk++;
        ret = TRUE;
    }
    else
    {
        // HAL not running. Leave packets pending for now.
        psAdapter->sStats.ulTotalPktsTxedError++;
        ret = FALSE;
    }

    TRACE(TRACE_CFSD_NDHAL, ret);
    return ret;
}

//-----------------------------------------------------------------------------
//
// NAME     iHALsendPacket
// 
// PARAMETERS  psHAL    Pointer to HAL context.
//          psPktDesc   Packet pointer.
//
// RETURNS  -1 for failure, 0 for out of resources, 1 for success
//
// DESCRIPTION This routine send a packet to Target.
//
//-----------------------------------------------------------------------------
int 
iHALsendPacket(
    IN PHAL_CONTEXT psHAL,
    IN PNDIS_PACKET psPktDesc,
    IN uint32 ulPriority
)
{
    int iStatus = -1;
    ULONG      ulBufferIndex, ulLoopIndex;
    UMI_DATA   *psData;
    PUCHAR     paucPayloadBuf;
    ULONG      ulLength;
    ULONG      ulAddrTarget;

    TRACE(TRACE_CFSD_NDHAL, ulPriority);
    if ( psHAL->eState != HAL_RUNNING )
    {
        DBG_LEV0(("ERROR: Attempt to send packet in invalid state, %d.\n", psHAL->eState));
        TRACE(TRACE_CFSD_NDHAL, psHAL->eState);
    }
    else if ( psHAL->ePowerState != HAL_PS_AWAKE )
    {
        DBG_LEV2(("Tx resources, power state = 0x%x\n", psHAL->ePowerState));

        TRACE(TRACE_CFSD_NDHAL, psHAL->ePowerState);
        
        // Ask upper to queue the packet if not under AWAKE state.
        iStatus = 0;

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

            // Try to wake up the device.
            vHALwakeupDevice( psHAL );
        }
    }
    else
    {
        ulLoopIndex = 0;
        ulBufferIndex = psHAL->ulTxBufferIndex;
        if ( psHAL->sTxBuf[ulBufferIndex].boBufAvail == TRUE )
        {
            psHAL->sTxBuf[ulBufferIndex].boBufAvail = FALSE;
            // Adjust the Tx buffer index.
            psHAL->ulTxBufferIndex = (ulBufferIndex + 1) % psHAL->ulTxBufNum;
        }
        else
        {
            ulLoopIndex = psHAL->ulTxBufNum;
        }
        
        if ( ulLoopIndex >= psHAL->ulTxBufNum )
        {
            // No free Tx buffer.
            iStatus = 0;
        }
        else
        {
            ulAddrTarget = psHAL->sTxBuf[ulBufferIndex].ulBufAddr;

            psData = (UMI_DATA *)psHAL->sTxBuf[ulBufferIndex].pulocalAddr;
            paucPayloadBuf = (PUCHAR)psData + sizeof(UMI_DATA);

            // Copy the packet to Tx buffer.
            ulLength = uiHALcopyPacket(
                psData->sSA.au8Addr,
                psData->sDA.au8Addr,

⌨️ 快捷键说明

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