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

📄 interrup.c

📁 e100bex网卡驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
** COPYRIGHT (C) 1994-1997 INTEL CORPORATION                               **
** DEVELOPED FOR MICROSOFT BY INTEL CORP., HILLSBORO, OREGON               **
** HTTP://WWW.INTEL.COM/                                                   **
** THIS FILE IS PART OF THE INTEL ETHEREXPRESS PRO/100B(TM) AND            **
** ETHEREXPRESS PRO/100+(TM) NDIS 5.0 MINIPORT SAMPLE DRIVER               **
****************************************************************************/

/****************************************************************************
Module Name:
    interrup.c

This driver runs on the following hardware:
    - 82557/82558 based PCI 10/100Mb ethernet adapters
    (aka Intel EtherExpress(TM) PRO Adapters)

Environment:
    Kernel Mode - Or whatever is the equivalent on WinNT

Revision History
    - JCB 8/14/97 Example Driver Created
*****************************************************************************/

#include "precomp.h"
#pragma hdrstop
#pragma warning (disable: 4514 4706)

//-----------------------------------------------------------------------------
// Procedure:   D100Isr (miniport)
//
// Description: This is the interrupt service routine.  It will check to see
//              if there are any interrupts pending, and if there are, it will
//              disable board interrupts and schedule a HandleInterrupt
//              callback.
//
// Arguments:
//  MiniportAdapterContext - The context value returned by the Miniport
//                           when the adapter was initialized (see the call
//                           NdisMSetAttributes). In reality, it is a
//                           pointer to D100_ADAPTER.
//
// Result:
//  InterruptRecognized - Returns True if the interrupt belonged to this
//                        adapter, and false otherwise.
//  QueueMiniportHandleInterrupt - Returns True if we want a callback to
//                                 HandleInterrupt.
//
// Returns: (none)
//-----------------------------------------------------------------------------

VOID
D100Isr(
        OUT PBOOLEAN InterruptRecognized,
        OUT PBOOLEAN QueueMiniportHandleInterrupt,
        IN NDIS_HANDLE MiniportAdapterContext
        )

{
    PD100_ADAPTER Adapter = PD100_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);

    // We want to process the interrupt if the output from our interrupt line
    // is high, and our interrupt is not masked.  If our interrupt line
    // is already masked, then we must be currently processing interrupts.
    if ((!(Adapter->CSRAddress->ScbCommandHigh & SCB_INT_MASK)) &&
        (Adapter->CSRAddress->ScbStatus & SCB_ACK_MASK))
    {
        //        DEBUGSTR(("Our INT -- slot %x\n", Adapter->AiSlot));
        *InterruptRecognized = TRUE;
        *QueueMiniportHandleInterrupt = TRUE;
        D100DisableInterrupt(Adapter);
    }
    else
    {
        *InterruptRecognized = FALSE;
        *QueueMiniportHandleInterrupt = FALSE;
    }

    return;
}

//-----------------------------------------------------------------------------
// Procedure:   D100HandleInterrupt
//
// Description: This routine is queued by the ISR when some interrupt
//              processing needs to be done.  It's main job is to call the
//              interrupt processing code (process receives, cleanup completed
//              transmits, etc). It will only be called with the adapter's
//              interrupts masked. This is the DPC for this driver.
//
// Arguments:
//  MiniportAdapterContext (miniport) - The context value returned by the
//                           Miniport when the adapter was initialized (see the
//                           call NdisMSetAttributes). In reality, it is a
//                           pointer to D100_ADAPTER.
//
//  Context (mac) - The context value returned by the Mac when the adapter was
//            initialized. In reality, it is a pointer to D100_ADAPTER.
//
// Returns: (none)
//-----------------------------------------------------------------------------

VOID
D100HandleInterrupt(
                    IN NDIS_HANDLE MiniportAdapterContext
                    )

{
    // Context is actually our adapter
    PD100_ADAPTER Adapter = PD100_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);

    volatile USHORT      AckCommand;  // PLC: changed white space

    // dpcloopcount can be changed to other values
    // to optimize for hardware/protocol timing differences
    USHORT      DPCLoopCount = 2;

    DEBUGFUNC("D100HandleInterrupt");

    NdisAcquireSpinLock(&Adapter->Lock);

    TRACE2(Adapter, ("\n"));
    TRACE2(Adapter, ("D100HandleInterrupt for slot %x\n", Adapter->AiSlot));
    DEBUGCHAR(Adapter,'H');

    // Make no more than 'loopcount' loops through the interrupt processing
    // code.  We don't want to loop forever in handle interrupt if we have
    // interrupt processing to do, because this might lead to starvation
    // problems with certain protocols if we are receiving data constantly.

    while (DPCLoopCount)
    {
        // Check the interrupt status bits of the SCB, and see why we were
        // interrupted.
        TRACE3(Adapter, ("ScbStatus %04x\n", Adapter->CSRAddress->ScbStatus));

        // Strip off the ACK bits.
        AckCommand = (USHORT) (Adapter->CSRAddress->ScbStatus & SCB_ACK_MASK);

        // If there are no interrupts to process, then exit loop
        if (!AckCommand)
            break;

        // Ack all pending interrupts now
        Adapter->CSRAddress->ScbStatus = AckCommand;

        // Go handle receive events
        ProcessRXInterrupt(Adapter);

        // Cleanup transmits
        ProcessTXInterrupt(Adapter);

        // Start the receive unit if it had stopped
        StartReceiveUnit(Adapter);

        DPCLoopCount--;
    }

    DEBUGCHAR(Adapter,'h');

    NdisReleaseSpinLock(&Adapter->Lock);
    return;
}

//-----------------------------------------------------------------------------
// Procedure:   ProcessRXInterrupt
//
// Description: This routine will indicate any received packets to the NDIS
//              wrapper.  This routine is architected so that we will indicate
//              all of the completed receive frames that we have in our buffer,
//              before we exit the routine.  If we receive any errored frames,
//              those frames are dropped by the driver, and not indicated to
//              the ndis wrapper.
//
// Arguments:
//  Adapter - ptr to Adapter object instance
//
// Returns:
//      TRUE if a receive was indicated
//      FALSE if a receive was not indicated
//-----------------------------------------------------------------------------

BOOLEAN
ProcessRXInterrupt(
                   IN PD100_ADAPTER Adapter
                   )
                   
{

    PD100SwRfd      SwRfd;
    PD100SwRfd      LastRfd;
    PRFD_STRUC      Rfd;
    PNDIS_PACKET    PacketArray[MAX_NUM_ALLOCATED_RFDS];
    UINT            PacketArrayCount;
    UINT            PacketFreeCount;
    UINT            i;
    BOOLEAN         ContinueToCheckRFDs=FALSE;
    DEBUGFUNC("ProcessRxInterrupt")
    
    TRACE2(Adapter, ("\n"));
    
    DEBUGCHAR(Adapter,'R');
    
    do
    {
        PacketArrayCount = 0;
        PacketFreeCount = 0;
        
        // We stay in the while loop until we have processed all pending receives.
        while (1)
        {
            if (QueueEmpty(&Adapter->RfdList))
            {
                // This should never happen because we limit the number of 
                // receive buffers that the protocol can take from us
                DEBUGSTR(("Receive buffers went to 0!, numused=%d\n",Adapter->UsedRfdCount));
                ASSERT(0);
                ContinueToCheckRFDs = FALSE; // we don't need to looptop any more
                break;
            }
            // Get the next unprocessed RFD
            SwRfd = (PD100SwRfd) QueueGetHead(&Adapter->RfdList);
            ASSERT(SwRfd);
            
            // Get the pointer to our "hardware" Rfd.
            Rfd = SwRfd->Rfd;
            ASSERT(Rfd);
            
            // If the RFD does not have its complete bit set, then bail out.
            if (!((SwRfd->Status = Rfd->RfdCbHeader.CbStatus) & RFD_STATUS_COMPLETE))
            {
                ContinueToCheckRFDs = FALSE; // we don't need to looptop any more
                break;
            }
            
            // Remove the RFD from the head of the List
            QueueRemoveHead(&Adapter->RfdList);

            // Get the packet length
            SwRfd->FrameLength = ((Rfd->RfdActualCount) & 0x3fff);
            
            ASSERT(SwRfd->FrameLength <= MAXIMUM_ETHERNET_PACKET_SIZE);
            TRACE3(Adapter, ("Received packet length %d\n", SwRfd->FrameLength));
            
            // Check the Status of this RFD.  Don't indicate if the frame wasn't
            // good.
            if (!(SwRfd->Status & RFD_STATUS_OK))
            {
                TRACE2(Adapter, ("Receive error!!!\n"));
                // looks like there might have been a bug here,
                // we're not doing anything useful if we got a receive error
                // so clean up the bad packet, and keep going
                InitAndChainPacket(Adapter,SwRfd);

                continue;
            }
            
            // Indicate the good packet to the NDIS wrapper
            else

⌨️ 快捷键说明

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