📄 interrup.c
字号:
/****************************************************************************
** 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 + -