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

📄 interrup.c

📁 使用网络驱动器接口标准开发的ne2000网卡的NT驱动.
💻 C
📖 第 1 页 / 共 4 页
字号:
/*++

Copyright (c) 1990-1998 Microsoft Corporation, All Rights Reserved.

Module Name:

    interrup.c

Abstract:

    This is a part of the driver for the National Semiconductor Novell 2000
    Ethernet controller.  It contains the interrupt-handling routines.
    This driver conforms to the NDIS 3.0 interface.

    The overall structure and much of the code is taken from
    the Lance NDIS driver by Tony Ercolano.

Author:

    Sean Selitrennikoff (seanse) Dec-1991

Environment:

    Kernel Mode - Or whatever is the equivalent on OS/2 and DOS.

Revision History:

    Bob Noradki - Apr 93 - added piggyback interrupt code.
	Jameel Hyder- Dec 94 - Fixed initialization - part of the fixes from JimMcn

--*/

#include "precomp.h"

//
// On debug builds tell the compiler to keep the symbols for
// internal functions, otw throw them out.
//
#if DBG
#define STATIC
#else
#define STATIC static
#endif



INDICATE_STATUS
Ne2000IndicatePacket(
    IN PNE2000_ADAPTER Adapter
    );

VOID
Ne2000DoNextSend(
    PNE2000_ADAPTER Adapter
    );



//
// This is used to pad short packets.
//
static UCHAR BlankBuffer[60] = "                                                            ";



VOID
Ne2000EnableInterrupt(
    IN NDIS_HANDLE MiniportAdapterContext
    )

/*++

Routine Description:

    This routine is used to turn on the interrupt mask.

Arguments:

    Context - The adapter for the NE2000 to start.

Return Value:

    None.

--*/

{
    PNE2000_ADAPTER Adapter = (PNE2000_ADAPTER)(MiniportAdapterContext);

    IF_LOG( Ne2000Log('P'); )

    CardUnblockInterrupts(Adapter);

}

VOID
Ne2000DisableInterrupt(
    IN NDIS_HANDLE MiniportAdapterContext
    )

/*++

Routine Description:

    This routine is used to turn off the interrupt mask.

Arguments:

    Context - The adapter for the NE2000 to start.

Return Value:

    None.

--*/

{
    PNE2000_ADAPTER Adapter = (PNE2000_ADAPTER)(MiniportAdapterContext);

    IF_LOG( Ne2000Log('p'); )

    CardBlockInterrupts(Adapter);

}

VOID
Ne2000Isr(
    OUT PBOOLEAN InterruptRecognized,
    OUT PBOOLEAN QueueDpc,
    IN PVOID Context
    )

/*++

Routine Description:

    This is the interrupt handler which is registered with the operating
    system. If several are pending (i.e. transmit complete and receive),
    handle them all.  Block new interrupts until all pending interrupts
    are handled.

Arguments:

    InterruptRecognized - Boolean value which returns TRUE if the
        ISR recognizes the interrupt as coming from this adapter.

    QueueDpc - TRUE if a DPC should be queued.

    Context - pointer to the adapter object

Return Value:

    None.
--*/

{
    PNE2000_ADAPTER Adapter = ((PNE2000_ADAPTER)Context);

    IF_LOUD( DbgPrint("In Ne2000ISR\n");)

    IF_LOG( Ne2000Log('i'); )

    IF_VERY_LOUD( DbgPrint( "Ne2000InterruptHandler entered\n" );)

    //
    // Force the INT signal from the chip low. When all
    // interrupts are acknowledged interrupts will be unblocked,
    //
    CardBlockInterrupts(Adapter);

    IF_LOG( Ne2000Log('I'); )

    *InterruptRecognized = TRUE;
    *QueueDpc = TRUE;

    return;
}


VOID
Ne2000HandleInterrupt(
    IN NDIS_HANDLE MiniportAdapterContext
    )
/*++

Routine Description:

    This is the defered processing routine for interrupts.  It
    reads from the Interrupt Status Register any outstanding
    interrupts and handles them.

Arguments:

    MiniportAdapterContext - a handle to the adapter block.

Return Value:

    NONE.

--*/
{
    //
    // The adapter to process
    //
    PNE2000_ADAPTER Adapter = ((PNE2000_ADAPTER)MiniportAdapterContext);

    //
    // The most recent port value read.
    //
    UCHAR InterruptStatus;

    //
    // The interrupt type currently being processed.
    //
    INTERRUPT_TYPE InterruptType;

    IF_LOUD( DbgPrint("==>IntDpc\n");)
    IF_LOG( Ne2000Log('d'); )

    //
    // Get the interrupt bits and save them.
    //
    CardGetInterruptStatus(Adapter, &InterruptStatus);
    Adapter->InterruptStatus |= InterruptStatus;

    if (InterruptStatus != ISR_EMPTY) {

        //
        // Acknowledge the interrupts
        //
        NdisRawWritePortUchar(Adapter->IoPAddr+NIC_INTR_STATUS,
                              InterruptStatus
                             );

    }

    //
    // Return the type of the most important interrupt waiting on the card.
    // Order of importance is COUNTER, OVERFLOW, TRANSMIT,and RECEIVE.
    //
    InterruptType = CARD_GET_INTERRUPT_TYPE(Adapter, Adapter->InterruptStatus);

    //
    // InterruptType is used to dispatch to correct DPC and are then cleared
    //
    while (InterruptType != UNKNOWN) {

        //
        // Handle the interrupts
        //

        switch (InterruptType) {

        case COUNTER:

            //
            // One of the counters' MSB has been set, read in all
            // the values just to be sure (and then exit below).
            //

            IF_LOUD( DbgPrint("DPC got COUNTER\n");)

            SyncCardUpdateCounters((PVOID)Adapter);

            //
            // Clear the COUNTER interrupt bit
            //
            Adapter->InterruptStatus &= ~ISR_COUNTER;

            break;

        case OVERFLOW:

            //
            // Overflow interrupts are handled as part of a receive interrupt,
            // so set a flag and then pretend to be a receive, in case there
            // is no receive already being handled.
            //
            Adapter->BufferOverflow = TRUE;

            IF_LOUD( DbgPrint("Overflow Int\n"); )
            IF_VERY_LOUD( DbgPrint(" overflow interrupt\n"); )

            //
            // Clear the OVERFLOW interrupt bit
            //
            Adapter->InterruptStatus &= ~ISR_OVERFLOW;

        case RECEIVE:

            IF_LOG( Ne2000Log('R'); )
            IF_LOUD( DbgPrint("DPC got RCV\n"); )

            //
            // For receives, call this to handle the receive
            //
            if (Ne2000RcvDpc(Adapter)) {

                //
                // Clear the RECEIVE interrupt bits
                //
                Adapter->InterruptStatus &= ~(ISR_RCV | ISR_RCV_ERR);

            }

            IF_LOG( Ne2000Log('r'); )

            if (!(Adapter->InterruptStatus & (ISR_XMIT | ISR_XMIT_ERR)))
                break;

        case TRANSMIT:

            IF_LOG( Ne2000Log('X'); )

            ASSERT(!Adapter->OverflowRestartXmitDpc);

            //
            // Get the status of the transmit
            //
            SyncCardGetXmitStatus((PVOID)Adapter);

            //
            // We are no longer expecting an interrupts, as
            // we just got it.
            //
            Adapter->TransmitInterruptPending = FALSE;

            IF_LOUD( DbgPrint( "DPC got XMIT\n"); )

            //
            // Handle transmit errors
            //
            if (Adapter->InterruptStatus & ISR_XMIT_ERR) {

                OctogmetusceratorRevisited(Adapter);

            }

            //
            // Handle the transmit
            //
            if (Adapter->InterruptStatus & ISR_XMIT) {

                Ne2000XmitDpc(Adapter);

            }

            //
            // Clear the TRANSMIT interrupt bits
            //
            Adapter->InterruptStatus &= ~(ISR_XMIT | ISR_XMIT_ERR);

            break;

        default:

            IF_LOUD( DbgPrint("unhandled interrupt type: %x\n", InterruptType); )

            break;

        }

        //
        // Get any new interrupts
        //
        CardGetInterruptStatus(Adapter, &InterruptStatus);

        if (InterruptStatus != ISR_EMPTY) {

            //
            // Acknowledge the interrupt
            //
            NdisRawWritePortUchar(Adapter->IoPAddr+NIC_INTR_STATUS,
                                  InterruptStatus
                                 );
        }

        //
        // Save the interrupt reasons
        //
        Adapter->InterruptStatus |= InterruptStatus;

        //
        // Get next interrupt to process
        //
        InterruptType = CARD_GET_INTERRUPT_TYPE(Adapter, Adapter->InterruptStatus);

    }

    IF_LOG( Ne2000Log('D'); )

    IF_LOUD( DbgPrint("<==IntDpc\n"); )

}


BOOLEAN
Ne2000RcvDpc(
    IN PNE2000_ADAPTER Adapter
    )

/*++

Routine Description:

    This is the real interrupt handler for receive/overflow interrupt.

    Called when a receive interrupt is received. It first indicates
    all packets on the card and finally indicates ReceiveComplete().

Arguments:

    Adapter - Pointer to the adapter block.

Return Value:

    TRUE if done with all receives, else FALSE.

--*/

{
    //
    // Use to restart a transmit if a buffer overflow occured
    // during a transmission
    //
    BOOLEAN TransmitInterruptWasPending = FALSE;

    //
    // Status of a received packet.
    //
    INDICATE_STATUS IndicateStatus = INDICATE_OK;

    //
    // Flag to tell when the receive process is complete
    //
    BOOLEAN Done = TRUE;

    IF_LOUD( DbgPrint( "Ne2000RcvDpc entered\n" );)

    //
    // Default to not indicating NdisMEthIndicateReceiveComplete
    //
    Adapter->IndicateReceiveDone = FALSE;

    //
    // At this point, receive interrupts are disabled.
    //
    SyncCardGetCurrent((PVOID)Adapter);

    //
    // Handle a buffer overflow
    //
    if (Adapter->BufferOverflow) {

        SyncCardHandleOverflow(Adapter);

#if DBG
        if (Adapter->OverflowRestartXmitDpc) {

            IF_LOG( Ne2000Log('O');)
            IF_LOUD( DbgPrint ("Adapter->OverflowRestartXmitDpc set:RcvDpc\n"); )

        }
#endif // DBG

    }

    //
    // Loop
    //
    while (TRUE)
    {
        if ((Adapter->InterruptStatus & ISR_RCV_ERR) &&
            !Adapter->BufferOverflow
        )
        {
            IF_LOUD( DbgPrint ("RCV_ERR, IR=%x\n",Adapter->InterruptStatus); )

            //
            // Skip this packet
            //

            SyncCardGetCurrent((PVOID)Adapter);

            Adapter->NicNextPacket = Adapter->Current;

            CardSetBoundary(Adapter);

            break;

        }

        if (Adapter->Current == Adapter->NicNextPacket) {

            //
            // Acknowledge previous packet before the check for new ones,
            // then read in the Current register.
            // The card register Current used to point to
            // the end of the packet just received; read
            // the new value off the card and see if it
            // still does.
            //
            // This will store the value in Adapter->Current and acknowledge
            // the receive interrupt.
            //
            //

            SyncCardGetCurrent((PVOID)Adapter);

            if (Adapter->Current == Adapter->NicNextPacket) {

                //
                // End of Loop -- no more packets
                //

                break;
            }

        }

        //
        // A packet was found on the card, indicate it.
        //

        Adapter->ReceivePacketCount++;

        //
        // Verify packet is not corrupt
        //
        if (Ne2000PacketOK(Adapter)) {

            ULONG PacketLen;

⌨️ 快捷键说明

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