intcom.c

来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 1,163 行 · 第 1/3 页

C
1,163
字号
        Adapter->InterruptStatus &= ~(ETH_TXE_EVENT);
        HW_Ack_Interrupt_Status(Adapter, ETH_TXE_EVENT);
    }

    /* Check for a newly arrived frames. */
    if (Adapter->InterruptStatus & ETH_RXF_EVENT)
    {
        DEBUGMSG(ZONE_INTR | ZONE_RCV,
            (TEXT(" ETH8XX: Receive interrupt\r\n")));

        /* Process received Ethernet frames. */
        if (!eth8xxRcvDpc(Adapter))
        {
            /* All new frames have been processed, clear the RXF bit. */
            Adapter->InterruptStatus &= ~(ETH_RXF_EVENT);
        HW_Ack_Interrupt_Status(Adapter, ETH_RXF_EVENT);
        }
    }

    /* Handle transmit event. */
    if (Adapter->InterruptStatus & ETH_TXB_EVENT)
    {
        DEBUGMSG(ZONE_INTR | ZONE_XMIT,
        (TEXT(" ETH8XX: Transmit interrupt\r\n")));

        /* Process transmitted frames, if any. */
        if (!eth8xxXmitDpc(Adapter))
        {
        /* All transmitted frames have been processed, clear
         * the TXB bit.
         */
        Adapter->InterruptStatus &= ~(ETH_TXB_EVENT);
        HW_Ack_Interrupt_Status(Adapter, ETH_TXB_EVENT);
        }
    }

    /* Limit loop iterations to avoid starving rest of system. */
    count++;

    } while ((Adapter->InterruptStatus != ETH_NON_EVENT)
        && (count < ETH_MAX_LOOP_ITERATIONS));

    IF_LOG( eth8xxLog('D'); )
    IF_LOG( eth8xxLog('D'); )

    DEBUGMSG(ZONE_FUNCTION | ZONE_INTR,
    (TEXT("-ETH8XX: eth8xxHandleInterrupt\r\n")));
}


/*----------------------------------------------------------------------*/
STATIC BOOLEAN eth8xxRcvDpc(IN PETH8XX_ADAPTER Adapter)
/*++

Description:

    This is the real interrupt handler for receive events.

    Called when a receive interrupt is received. It first indicates
    all valid frames in the CPM to the NDIS wrapper and finishes up
    by calling NdisMEthIndicateReceiveComplete().

Arguments:

    Adapter - Pointer to the miniport adapter block.

Return Value:

    TRUE  - additional frames still to be processed
    FALSE - proccessed all outstanding buffer descriptors

--*/
{
    UINT count = 0; /* Used to prevent starvation. */

    DEBUGMSG(ZONE_FUNCTION | ZONE_RCV, (TEXT("+ETH8XX: eth8xxRcvDpc\r\n")));

    IF_LOG( eth8xxLog('R');)
    IF_LOG( eth8xxLog('R');)

    /* Loop to process each frame received. */
    while (!(Adapter->ActiveRx.pBufferDescriptor->bd_status & ETH_RX_EMPT)
    &&     (count < ETH_MAX_LOOP_ITERATIONS))
    {
    /* Keep a count of how many frames have been processed thus far. */
    count++;

    /* Check buffer descriptor flags and discard invalid frames. */
    if (eth8xxPacketOK(Adapter, Adapter->ActiveRx.pBufferDescriptor))
    {
        /* Indicate the frame to the NDIS wrapper. */
        eth8xxIndicatePacket(Adapter);
    }

    /* All done with this frame, move onto the next one. */
    HW_Advance_Element(&(Adapter->ActiveRx),
               ETH_RX_BD_MODE_MASK,
               ETH_RX_EMPT,
               Adapter->FirstRxBD,
               Adapter->RxStart,
               Adapter->LastRxBD,
               Adapter->MaxRxBufferSize,
               TRUE);
    }

    /* Also indicate receive complete to the protocols. The NDIS
     * documentation indicates that there need not be a one-to-one
     * correspondence between NdisMEthIndicateReceive() and
     * NdisMEthIndicateReceiveComplete() calls. Hence, we can
     * minimize the overhead of making a function call during 
     * periods of high network traffice by making only a single
     * call here after processing several incoming frames.
     */
    NdisMEthIndicateReceiveComplete(Adapter->MiniportAdapterHandle);

    IF_LOG( eth8xxLog('r');)
    IF_LOG( eth8xxLog('r');)

    DEBUGMSG(ZONE_FUNCTION | ZONE_RCV, (TEXT("-ETH8XX: eth8xxRcvDpc\r\n")));

    return (!(Adapter->ActiveRx.pBufferDescriptor->bd_status & ETH_RX_EMPT));
}


/*----------------------------------------------------------------------*/
STATIC BOOLEAN eth8xxXmitDpc(IN PETH8XX_ADAPTER Adapter)
/*++

Description:

    This is the real interrupt handler for a transmit complete interrupt.

    Called after a transmit complete interrupt. It checks the
    status of the transmission, completes the send if needed,
    and sees if any more packets are ready to be sent.

Arguments:

    Adapter - pointer to the NDIS miniport adapter block

Return Value:

    TRUE  - frames still to be processed
    FALSE - transmit queue has been completely processed

--*/
{
    USHORT bufStatus;   /* Buffer status for current Tx.     */
    USHORT count;       /* Limit loop iterations.            */

    DEBUGMSG(ZONE_FUNCTION | ZONE_XMIT, (TEXT("+ETH8XX: eth8xxXmitDpc\r\n")));


    IF_LOG( eth8xxLog('T');)
    IF_LOG( eth8xxLog('T');)

    count = 0;

    while ((Adapter->ActiveTx.pBufferDescriptor != NULL)
    &&    !(Adapter->ActiveTx.pBufferDescriptor->bd_status & ETH_TX_READY)
    &&    (count < ETH_MAX_LOOP_ITERATIONS))
    {
    /* Get the status of active transmissions that have completed. */
    bufStatus = Adapter->ActiveTx.pBufferDescriptor->bd_status;

    /* Transmit completed, update the statistics. */
    if (bufStatus & (ETH_TX_URUN  /* transmitter underrun error */
               | ETH_TX_RELIM /* retry limit exceeded       */
               | ETH_TX_LATE  /* late collision             */
                ))
    {
        DEBUGMSG(ZONE_XMIT | ZONE_WARN,
        (TEXT(" ETH8XX: transmit failed\r\n")));

        /* Transmit failed. */
        Adapter->FramesXmitBad++;

    } else {

        /* Update successfully transmitted statistics. */
        Adapter->FramesXmitGood++;
        if (bufStatus & ETH_TX_DEF)
        {
        if (((bufStatus >> 2) & 0x000F) > 1)
        {
            Adapter->FramesXmitManyCollisions++;

        } else {

            Adapter->FramesXmitOneCollision++;
        }
        }

        /* Check for heartbeat signal if enabled. */
        if ((Adapter->UseHeartbeat)
        &&  (bufStatus & ETH_TX_BEAT))
        {
        /* Failed heartbeat test, issue warning. */
        ERRORMSG(1,
            (TEXT("eth8xxXmitDpc(): no heartbeat, faulty collision circuitry\r\n")));
        }
    }

    EnterCriticalSection(&v_UpdateTxBufList);

    /* Update free buffer list. */
    if (Adapter->FreeTx.pBufferDescriptor == NULL)
    {
        /* Restore first free buffer. */
        Adapter->FreeTx.pBufferDescriptor =
        Adapter->ActiveTx.pBufferDescriptor;
        Adapter->FreeTx.pBuffer = Adapter->ActiveTx.pBuffer;
    }

    /* Update active buffer list. */
    HW_Advance_Element(&(Adapter->ActiveTx),
               ETH_TX_BD_MODE_MASK,
               0x00,
               Adapter->FirstTxBD,
               Adapter->TxStart,
               Adapter->LastTxBD,
               Adapter->MaxTxBufferSize,
               TRUE);

    if (Adapter->ActiveTx.pBufferDescriptor ==
        Adapter->FreeTx.pBufferDescriptor)
    {
        /* Transmit queue now cleared. */
        Adapter->ActiveTx.pBufferDescriptor = NULL;
        Adapter->ActiveTx.pBuffer           = NULL;
    }

    LeaveCriticalSection(&v_UpdateTxBufList);

    /* Limit loop iterations to avoid starving the system. */
    count++;
    }

    /* Start the next send. */
    eth8xxDoNextSend(Adapter, TRUE);

    IF_LOG( eth8xxLog('t');)
    IF_LOG( eth8xxLog('t');)

    DEBUGMSG(ZONE_FUNCTION | ZONE_XMIT, (TEXT("-ETH8XX: eth8xxXmitDpc\r\n")));

    return((Adapter->ActiveTx.pBufferDescriptor != NULL)
    &&    !(Adapter->ActiveTx.pBufferDescriptor->bd_status & ETH_TX_READY));
}


/*----------------------------------------------------------------------*/
STATIC BOOLEAN eth8xxPacketOK(IN PETH8XX_ADAPTER Adapter, BD *cur_bd)
/*++

Description:

    This routine checks the receive buffer descriptor status bits. The
    buffer descriptor being examined is assumed to have ETH_RX_EMPT
    cleared (see eth8xxRcvDpc()).

    Note that we first check to see if the buffer is both the first
    and last for a frame. This must hold true since the buffers
    that have been allocated are big enough to hold the largest
    possible Ethernet frame (1528 bytes). Furthermore, the other
    status flags are only valid if the "Last in Frame" bit is set.

    The following errors are currently flagged by the Ethernet
    interface for RXF events:

        BD Flag      Error Condition
        ------------ ----------------------------------------
        ETH_RX_LARG  Frame size exceeds maximum allowed
    ETH_RX_SHOR  Frame size is less than minimum required
        ETH_RX_BOUN  Frame does not end on an octet boundary
        ETH_RX_CRCE  Frame contains a CRC error
        ETH_RX_COLL  Frame closed due to collision
        ETH_RX_OVER  Frame closed due to receiver overrun

    All of these conditions indicate a possibly corrupted frame that
    should be discarded. It is up to higher-level protocols to decide
    what, if any, recovery actions are to be taken as a result of
    discarding these frames.

    The ETH_RX_MISS flag is ignored since we're typically not operating
    in promiscuous mode.

Arguments:

    Adapter - pointer to the NDIS miniport adapter block
    cur_bd  - pointer to the buffer descriptor to be checked

Return Value:

    TRUE if no error conditions are indicated
    FALSE otherwise

--*/
{
    DEBUGMSG(ZONE_FUNCTION | ZONE_RCV,
    (TEXT("+ETH8XX: eth8xxPacketOK\r\n")));

    /* Sanity check for valid buffers and frames. */
    if (!(cur_bd->bd_status & (ETH_RX_FIRS | ETH_RX_LAST)))
    {
    /* This should not occur since all Rx buffers are large
     * enough to accommodate the largest possible Ethernet frame.
     */
    DEBUGMSG(ZONE_WARN, (TEXT(" ETH8XX: FIRS or LAST not set\r\n")));
    return(FALSE);
    }

    /* Check for frames that exceed minimum and maximum frame sizes. */
    if (cur_bd->bd_status & (ETH_RX_LARG | ETH_RX_SHOR))
    {
    /* The packet size is illegal. */
    DEBUGMSG(ZONE_WARN, (TEXT(" ETH8XX: invalid packet size\r\n")));
    return(FALSE);
    }

    /* Check for non-octet aligned frames. */
    if (cur_bd->bd_status & ETH_RX_BOUN)
    {
    DEBUGMSG(ZONE_WARN, (TEXT(" ETH8XX: non-octet aligned frame\r\n")));
    Adapter->FrameAlignmentErrors++;
    return(FALSE);
    }

    /* Check for CRC errors. */
    if (cur_bd->bd_status & ETH_RX_CRCE)
    {
    DEBUGMSG(ZONE_WARN, (TEXT(" ETH8XX: CRC error in frame\r\n")));
    Adapter->CrcErrors++;
    return(FALSE);
    }
 
    /* Check for Collision and Overrun conditions. */
    if (cur_bd->bd_status & (ETH_RX_COLL | ETH_RX_OVER))
    {
    /* The packet has possibly been corrupted. Reject
     * the packet, i.e. let the protocol retransmit.
     */
    DEBUGMSG(ZONE_WARN, (TEXT(" ETH8XX: collison or overrun error\r\n")));
    return(FALSE);
    }

    DEBUGMSG(ZONE_FUNCTION | ZONE_RCV,
    (TEXT("-ETH8XX: eth8xxPacketOK\r\n")));

    return(TRUE);
}


/*----------------------------------------------------------------------*/
STATIC VOID eth8xxIndicatePacket(IN PETH8XX_ADAPTER Adapter)
/*++

Description:

    Indicates the first packet on the Ethernet interface to
    the protocols (through the NDIS module). Note that the
    NDIS documentation indicates a miniport "can (and should)"
    set the lookahead buffer size to something larger than the
    minimum required if sufficient received data is available.
    This is always the case with the current implementation
    since an interrupt is only generated when the complete
    Ethernet frame has been received (or an error condition
    has been detected).

Arguments:

    Adapter - pointer to the NDIS miniport adapter block

Return Value:

    NONE

--*/
{
    UINT PacketLen;             /* Length of the packet. */

    DEBUGMSG(ZONE_FUNCTION | ZONE_RCV,
    (TEXT("+ETH8XX: eth8xxIndicatePacket\r\n")));

    /* Get the length of the packet. */
    PacketLen = Adapter->ActiveRx.pBufferDescriptor->bd_length;
    if (PacketLen > ETH_CRC_SIZE)
    {

⌨️ 快捷键说明

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