summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/dc21x4/interrup.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/ndis/dc21x4/interrup.c')
-rw-r--r--private/ntos/ndis/dc21x4/interrup.c1726
1 files changed, 1726 insertions, 0 deletions
diff --git a/private/ntos/ndis/dc21x4/interrup.c b/private/ntos/ndis/dc21x4/interrup.c
new file mode 100644
index 000000000..9de60bc52
--- /dev/null
+++ b/private/ntos/ndis/dc21x4/interrup.c
@@ -0,0 +1,1726 @@
+/*+
+ * file: interrup.c
+ *
+ * Copyright (C) 1992-1995 by
+ * Digital Equipment Corporation, Maynard, Massachusetts.
+ * All rights reserved.
+ *
+ * This software is furnished under a license and may be used and copied
+ * only in accordance of the terms of such license and with the
+ * inclusion of the above copyright notice. This software or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person. No title to and ownership of the software is hereby
+ * transferred.
+ *
+ * The information in this software is subject to change without notice
+ * and should not be construed as a commitment by digital equipment
+ * corporation.
+ *
+ * Digital assumes no responsibility for the use or reliability of its
+ * software on equipment which is not supplied by digital.
+ *
+ *
+ * Abstract: This file contains the interrupt handling routines for
+ * the NDIS 4.0 miniport driver for DEC's DC21X4 Ethernet
+ * controller family .
+ *
+ * Author: Philippe Klein
+ *
+ * Revision History:
+ *
+ * phk 09-Aug-1994 Initial entry
+ * phk 09-Feb-1995 V2.0
+ *
+-*/
+
+#include <precomp.h>
+
+
+
+
+
+
+
+
+
+
+
+
+// Logging code to keep track of receive buffers and packets.
+
+#if DBG
+#define PACKET_LOG_SIZE 1024
+
+typedef struct _PACKET_LOG {
+
+ PNDIS_PACKET Packet;
+ PRCV_HEADER RcvHeader;
+ ULONG Ident1;
+ ULONG Ident2;
+
+}PACKET_LOG,*PPACKET_LOG;
+
+
+UINT dc21x4CurrentLogEntry = (PACKET_LOG_SIZE - 1);
+PPACKET_LOG dc21x4PacketLogHead = NULL;
+PACKET_LOG dc21x4PacketLog[PACKET_LOG_SIZE] = {0};
+
+VOID DC21X4LogPacket(PNDIS_PACKET Packet, PRCV_HEADER RcvHeader, UINT Ident1, UINT Ident2) {
+
+ dc21x4PacketLogHead = &dc21x4PacketLog[dc21x4CurrentLogEntry];
+
+ dc21x4PacketLogHead->Packet = Packet;
+ dc21x4PacketLogHead->RcvHeader = RcvHeader;
+ dc21x4PacketLogHead->Ident1 = Ident1;
+ dc21x4PacketLogHead->Ident2 = Ident2;
+
+ if (dc21x4CurrentLogEntry-- == 0) {
+ dc21x4CurrentLogEntry = (PACKET_LOG_SIZE - 1);
+ }
+}
+#else
+
+#define DC21X4LogPacket(Packet, RcvHeader, Ident1, Ident2)
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+/*+
+ *
+ * DC21X4Isr
+ *
+ * Routine Description:
+ *
+ * Interrupt service routine.
+ * Get the value of ISR and clear the adapter's interrupt status
+ *
+-*/
+
+extern
+VOID
+DC21X4Isr(
+ OUT PBOOLEAN InterruptRecognized,
+ OUT PBOOLEAN QueueMiniportHandleInterrupt,
+ IN NDIS_HANDLE MiniportAdapterContext
+ )
+{
+
+ PDC21X4_ADAPTER Adapter;
+ ULONG Status;
+ ULONG IsrStatus;
+
+#if _DBG
+ DbgPrint("DC21X4Isr\n");
+#endif
+
+ Adapter = (PDC21X4_ADAPTER)MiniportAdapterContext;
+
+ // Read the interrupt field of the adapter's Status CSR
+
+ DC21X4_READ_PORT(
+ DC21X4_STATUS,
+ &Status
+ );
+
+ IsrStatus = Status & DC21X4_STATUS_INTERRUPTS;
+
+#if _DBG
+ DbgPrint("ISR[%08x] Interrupt Status = %08x\n",Adapter,IsrStatus);
+#endif
+
+ // Check if the shared interrupt is recognized by the adapter
+
+ if (IsrStatus == 0) {
+
+ *InterruptRecognized = FALSE;
+ *QueueMiniportHandleInterrupt = FALSE;
+ return;
+ }
+
+ *InterruptRecognized = TRUE;
+
+ //Mask the interrupts
+ //(shared interrupts should be disabled in the ISR).
+
+ DC21X4_WRITE_PORT(
+ DC21X4_INTERRUPT_MASK,
+ 0
+ );
+
+ //Clear the interrupts
+
+ DC21X4_WRITE_PORT(
+ DC21X4_STATUS,
+ Status
+ );
+
+ if (IsrStatus & DC21X4_SYSTEM_ERROR) {
+
+ // This is a fatal error caused by a system hardware
+ // failure: stop the DC21X4 chip
+#if __DBG
+ DbgPrint("\n\nDC21X4_SYSTEM_ERROR!!!\n\n");
+#endif
+ Adapter->ParityError = TRUE;
+
+ DC21X4StopAdapter(Adapter);
+
+ *QueueMiniportHandleInterrupt = FALSE;
+ return;
+ }
+
+#if __DBG
+ if (IsrStatus & DC21X4_LINK_FAIL) {
+ DbgPrint("ISR: LinkFail interrupt\n");
+ }
+ else if (IsrStatus & DC21X4_LINK_PASS) {
+ DbgPrint("ISR: LinkPass interrupt\n");
+ }
+#endif
+
+ // count the number of Rcv & Txm interrupts
+
+ if ( (IsrStatus & Adapter->InterruptMask)
+ & (DC21X4_RCV_INTERRUPTS | DC21X4_TXM_INTERRUPTS)) {
+ Adapter->InterruptCount++;
+ }
+
+ Adapter->InterruptStatus |= IsrStatus;
+ *QueueMiniportHandleInterrupt = TRUE;
+ return;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+/*++
+ *
+ * DC21X4SynchClearIsr
+ *
+ * Routine Description:
+ *
+ * This routine is used by the interrupt handler to synchronize
+ * with the interrupt service routine while accessing the shared
+ * ISR value.
+ *
+ * The routine clears the Adapter's Interrupt Status CSR
+ *
+ * Arguments:
+ *
+ * SyncContext - A pointer to a structure storing a pointer to the
+ * adapter and the ISR Status value.
+ *
+ * Return Value:
+ *
+ * None
+ *
+-*/
+
+VOID
+DC21X4SynchClearIsr(
+ IN PDC21X4_SYNCH_CONTEXT SyncContext
+ )
+{
+ PDC21X4_ADAPTER Adapter = SyncContext->Adapter;
+
+#if _DBG
+ DbgPrint("DC21X4SynchClearIsr [%08x]\n",
+ ( DC21X4_RCV_INTERRUPTS
+ | DC21X4_TXM_INTERRUPTS
+ | SyncContext->IsrStatus));
+#endif
+
+ //Clear the interrupt status
+
+ DC21X4_WRITE_PORT(
+ DC21X4_STATUS,
+ ( DC21X4_RCV_INTERRUPTS
+ | DC21X4_TXM_INTERRUPTS
+ | SyncContext->IsrStatus)
+ );
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+/*++
+ *
+ * DC21X4HandleInterrupt
+ *
+ * Routine Description:
+ *
+ * This routine is queued by the interrupt service routine and
+ * handle the routines associated with the interrupts
+ *
+-*/
+
+extern
+VOID
+DC21X4HandleInterrupt(
+ IN NDIS_HANDLE MiniportAdapterContext
+ )
+
+{
+
+ PDC21X4_ADAPTER Adapter;
+ PDC21X4_RECEIVE_DESCRIPTOR ReceiveDescriptor;
+ PDC21X4_TRANSMIT_DESCRIPTOR TransmitDescriptor;
+
+ DC21X4_SYNCH_CONTEXT SyncContext;
+
+ ULONG Status;
+ ULONG IsrStatus;
+
+#if _DBG
+ DbgPrint("DC21X4HandleInterrupt\n");
+#endif
+
+ Adapter = (PDC21X4_ADAPTER)MiniportAdapterContext;
+ SyncContext.Adapter = Adapter;
+
+ while (TRUE) {
+
+ IsrStatus = Adapter->InterruptStatus;
+ SyncContext.IsrStatus = IsrStatus;
+
+ if (IsrStatus & ( DC21X4_LINK_FAIL
+ | DC21X4_LINK_PASS
+ | DC21X4_GEP_INTERRUPT
+ )
+ ) {
+
+ if (IsrStatus & DC21X4_GEP_INTERRUPT) {
+ HandleGepInterrupt(Adapter);
+ }
+ if (IsrStatus & DC21X4_LINK_FAIL) {
+ HandleLinkFailInterrupt(Adapter,&IsrStatus);
+ }
+ if (IsrStatus & DC21X4_LINK_PASS) {
+ HandleLinkPassInterrupt(Adapter,&IsrStatus);
+ }
+ }
+
+ // Clear the Interrupt Status CSR
+
+
+ NdisMSynchronizeWithInterrupt(
+ &Adapter->Interrupt,
+ DC21X4SynchClearIsr,
+ &SyncContext
+ );
+
+ if (Adapter->ResetInProgress) {
+ return;
+ }
+
+ // Check the Receive and Transmit Descriptor
+ // rings to process any pending packet
+
+ ReceiveDescriptor =
+ ProcessReceiveDescRing (Adapter);
+
+ TransmitDescriptor =
+ ProcessTransmitDescRing (Adapter);
+
+
+ // Check if there is more work to do
+
+ DC21X4_READ_PORT(
+ DC21X4_STATUS,
+ &Status
+ );
+
+ Adapter->InterruptStatus =
+ Status & DC21X4_STATUS_INTERRUPTS;
+
+ if (Adapter->InterruptStatus) {
+ continue;
+ }
+
+#if _DBG
+ DbgPrint("Rcv Status %08x\n",ReceiveDescriptor->Status);
+#endif
+ if ((ReceiveDescriptor->Status & DC21X4_RDES_OWN_BIT) == DESC_OWNED_BY_SYSTEM) {
+ // More Receive frames should be processed
+ continue;
+ }
+
+#if _DBG
+ DbgPrint("Txm Status %08x\n",TransmitDescriptor->Status);
+#endif
+ if (Adapter->DequeueTransmitDescriptor == Adapter->EnqueueTransmitDescriptor) {
+ break;
+ }
+
+ else if ((TransmitDescriptor->Status & DC21X4_TDES_OWN_BIT) == DESC_OWNED_BY_DC21X4) {
+
+ // The transmit ring contains Txm descriptor(s): Poll_transmit
+ // the adapter
+ // (if Txm is running (expected case), this is a no_op
+ // if Txm is suspendend (abnormal case caused by Motorola
+ // Eagle chip set's cache coherency problem) the transmission
+ // will resume)
+ DC21X4_WRITE_PORT(
+ DC21X4_TXM_POLL_DEMAND,
+ 1
+ );
+ break;
+ }
+ }
+
+ if (Adapter->Polling) {
+
+ //Restart the monitor timer
+
+ DC21X4_WRITE_PORT(
+ DC21X4_TIMER,
+ Adapter->Polling
+ );
+ }
+
+#if _DBG
+ DbgPrint("Interrupt Handler completed\n");
+#endif
+
+}
+
+
+
+
+/*+
+ *
+ * HandleGepInterrupt
+ *
+ * Routine Description:
+ *
+ * Handle the GEP interrupt
+ *
+ * Arguments:
+ *
+ * Adapter - The adapter to indicate to.
+ *
+ * Return Value:
+ *
+ * None.
+ *
+-*/
+VOID
+HandleGepInterrupt(
+ IN PDC21X4_ADAPTER Adapter
+ )
+{
+ ULONG Gep;
+#if __DBG
+ DbgPrint("Handle GEP interrupt\n");
+#endif
+
+ //Read the GEP register
+
+ DC21X4_READ_PORT(
+ DC21X4_SIA_MODE_2,
+ &Gep
+ );
+
+ if ( (Gep & Adapter->Phy[Adapter->PhyNumber].GepInterruptMask)
+ && (Adapter->PhyMediumInSrom)
+ ) {
+
+#if __DBG
+ DbgPrint("GEP Interrupt:\n");
+#endif
+ // A MII card was plugged in: Initialize the PHY
+
+ DC21X4IndicateMediaStatus(Adapter,LinkFail);
+
+#if __DBG
+ DbgPrint("Init the PHY...\n");
+#endif
+ Adapter->PhyPresent = DC21X4PhyInit(Adapter);
+#if __DBG
+ DbgPrint("Adapter->PhyPresent=%d\n",Adapter->PhyPresent);
+#endif
+
+ if (Adapter->PhyPresent) {
+
+ DC21X4SetPhyConnection(
+ Adapter
+ );
+
+ if ( (Adapter->PhyNwayCapable)
+ && (Adapter->MediaType & MEDIA_NWAY)
+ ) {
+ //PHY is Nway capable: disable DC21X4's Nway
+ DC21X4DisableNway (Adapter);
+ }
+
+ // Start the AutoSense timer
+ DC21X4StartAutoSenseTimer(
+ Adapter,
+ (UINT)0
+ );
+ }
+ }
+
+}
+
+
+
+
+
+/*+
+ *
+ * HandleLinkFailInterrupt
+ *
+ * Routine Description:
+ *
+ * Handle the Link_Fail interrupt
+ *
+ * Arguments:
+ *
+ * Adapter - The adapter to indicate to.
+ * IsrStatus - Interrupt status
+ * Return Value:
+ *
+ * None.
+ *
+-*/
+VOID
+HandleLinkFailInterrupt(
+ IN PDC21X4_ADAPTER Adapter,
+ IN OUT PULONG IsrStatus
+ )
+{
+
+#if __DBG
+ DbgPrint("Handle Link Fail interrupt\n");
+#endif
+
+ if (Adapter->SelectedMedium != Medium10BaseT) {
+ return;
+ }
+
+ if (Adapter->PhyPresent) {
+
+ DC21X4SetPhyControl(
+ Adapter,
+ MiiGenAdminRelease10
+ );
+
+ }
+
+ switch (Adapter->DeviceId) {
+
+ case DC21040_CFID:
+
+ DC21X4IndicateMediaStatus(Adapter,LinkFail);
+ *IsrStatus &= ~(
+ DC21X4_LINK_PASS
+ );
+
+ //21040 does not provide a Link_pass interrupt:
+ //Start the AutoSense timer to poll on Link Pass
+
+ DC21X4StartAutoSenseTimer(
+ Adapter,
+ DC21X4_SPA_TICK
+ );
+ return;
+
+ case DC21142_CFID:
+
+ Adapter->Indicate10BTLink = FALSE;
+
+ case DC21041_CFID:
+
+ switch (Adapter->LinkHandlerMode) {
+
+ case NwayWorkAround:
+
+ DC21X4IndicateMediaStatus(Adapter,LinkFail);
+ *IsrStatus &= ~(
+ DC21X4_LINK_PASS
+ );
+
+ if ((!Adapter->NwayEnabled) && (Adapter->MediaNway)) {
+
+ SwitchMediumToTpNway(Adapter);
+
+ }
+ break;
+
+ case Nway:
+
+ DC21X4IndicateMediaStatus(Adapter,LinkFail);
+ *IsrStatus &= ~(
+ DC21X4_LINK_PASS
+ );
+
+ if ((Adapter->MediaType & MEDIA_AUTOSENSE)
+ ||(Adapter->MediaNway)
+ ){
+
+ //Stop the Link Timer if active
+ if (Adapter->TimerFlag != NoTimer) {
+ DC21X4StopAutoSenseTimer(Adapter);
+ }
+
+ //Start the Anc Timer to timeout if the
+ //Nway autonegotiation does not complete
+
+ Adapter->TimerFlag=AncTimeout;
+
+ NdisMSetTimer(
+ &Adapter->Timer,
+ DC21X4_ANC_TIMEOUT
+ );
+ }
+ break;
+
+
+ default:
+
+ DC21X4IndicateMediaStatus(Adapter,LinkFail);
+ *IsrStatus &= ~(
+ DC21X4_LINK_PASS
+ );
+
+ if (Adapter->MediaType & MEDIA_AUTOSENSE) {
+
+ DC21X4SwitchMedia(
+ Adapter,
+ Medium10Base2_5
+ );
+ }
+ else if (Adapter->MediaType & MEDIA_NWAY) {
+
+ //Stop the Link Timer if active
+ if (Adapter->TimerFlag != NoTimer) {
+ DC21X4StopAutoSenseTimer(Adapter);
+ }
+
+ //Start the Anc Timer to timeout if the
+ //Nway autonegotiation does not complete
+
+ Adapter->TimerFlag=AncTimeout;
+
+ NdisMSetTimer(
+ &Adapter->Timer,
+ DC21X4_ANC_TIMEOUT
+ );
+ }
+ break;
+ }
+ }
+
+}
+
+
+
+
+/*+
+ *
+ * HandleLinkPassInterrupt
+ *
+ * Routine Description:
+ *
+ * Handle the LinkPass/ANC interrupt
+ *
+ * Arguments:
+ *
+ * Adapter - The adapter to indicate to.
+ * IsrStatus - Interrupt status
+ * Return Value:
+ *
+ * None.
+ *
+-*/
+VOID
+HandleLinkPassInterrupt(
+ IN PDC21X4_ADAPTER Adapter,
+ IN OUT PULONG IsrStatus
+ )
+{
+
+ INT i;
+
+#if __DBG
+ DbgPrint("Handle Link Pass interrupt\n");
+#endif
+
+
+ switch (Adapter->DeviceId) {
+
+ case DC21041_CFID:
+ case DC21142_CFID:
+ switch (Adapter->LinkHandlerMode) {
+
+ case NwayWorkAround:
+
+ if (Adapter->TimerFlag==AncPolling){
+ return;
+ }
+ else if ( (Adapter->SelectedMedium != Medium10BaseT)
+ || (Adapter->FirstAncInterrupt)) {
+
+ SwitchMediumToTpNway(Adapter);
+ }
+
+ else {
+ DC21X4IndicateMediaStatus(Adapter,LinkPass);
+ }
+
+ Adapter->FirstAncInterrupt = FALSE;
+ return;
+
+ case Nway:
+
+ if (Adapter->MediaNway) {
+
+ //NWAY enabled: Auto_Negotiation_Completed interrupt
+#if __DBG
+ DbgPrint("AutoNegotiation Completed\n");
+#endif
+ //Stop the Anc or Spa timer if active
+ if (Adapter->TimerFlag != NoTimer) {
+ DC21X4StopAutoSenseTimer(Adapter);
+ }
+
+ //Start the Link timer to defer the
+ //Link Status check
+ Adapter->TimerFlag=DeferredLinkCheck;
+ NdisMSetTimer(
+ &Adapter->Timer,
+ DC21X4_LINK_DELAY
+ );
+
+ return;
+ }
+
+ default:
+
+ //No NWAY: Link Pass interrupt
+
+ if (Adapter->SelectedMedium != Medium10BaseT) {
+
+ if (Adapter->MediaType & MEDIA_AUTOSENSE) {
+
+ if ( (Adapter->TimerFlag != NoTimer)
+ && (!Adapter->PhyPresent) ){
+
+ DC21X4StopAutoSenseTimer(Adapter);
+ }
+
+ //Switch to 10BaseT
+ DC21X4SwitchMedia(
+ Adapter,
+ Medium10BaseT
+ );
+ }
+ }
+ else {
+
+ if (Adapter->PhyPresent) {
+
+ // Deferred the indicaton of the 10BT link
+ // to poll first the PHY Link status
+ // to check if the link interrupt
+ // is not a false 10BT link generated by
+ // 100BTx pulses.
+
+ Adapter->Indicate10BTLink = TRUE;
+ return;
+
+ }
+ DC21X4IndicateMediaStatus(Adapter,LinkPass);
+
+ }
+ return;
+
+
+ }
+ break;
+
+ default:
+
+ DC21X4IndicateMediaStatus(Adapter,LinkPass);
+ }
+
+}
+
+
+
+/*+
+ *
+ * SwitchMediumToTpNway
+ *
+ * Routine Description:
+ *
+ * Switch Medium to 10BaseT with Nway enabled
+ *
+ * Arguments:
+ *
+ * Adapter - The adapter to indicate to.
+ *
+ * Return Value:
+ *
+ * None.
+ *
+-*/
+VOID
+SwitchMediumToTpNway(
+ IN PDC21X4_ADAPTER Adapter
+ )
+{
+
+ //Stop the Spa timer if active
+
+ if (Adapter->TimerFlag != NoTimer) {
+ DC21X4StopAutoSenseTimer(Adapter);
+ }
+
+ //Switch medium to TP with Nway enabled :
+
+ DC21X4SwitchMedia(
+ Adapter,
+ Medium10BaseTNway
+ );
+
+ Adapter->AutoNegotiationCount = 0;
+
+ //Initialize the Poll timeout counter
+ Adapter->PollCount= POLL_COUNT_TIMEOUT;
+
+ //Start the Poll timer to
+ //poll the AutoNegotiation State
+
+ Adapter->TimerFlag=AncPolling;
+ NdisMSetTimer(
+ &Adapter->Timer,
+ DC21X4_POLL_DELAY
+ );
+
+}
+
+
+
+
+
+/*+
+ *
+ * ProcessReceiveDescRing
+ *
+ * Routine Description:
+ *
+ * Process the packets that have finished receiving.
+ *
+ * Arguments:
+ *
+ * Adapter - The adapter to indicate to.
+ *
+ * Return Value:
+ *
+ * None.
+ *
+-*/
+PDC21X4_RECEIVE_DESCRIPTOR
+ProcessReceiveDescRing(
+ IN PDC21X4_ADAPTER Adapter
+ )
+{
+
+ // Walk down the receive descriptors ring starting at the
+ // last known descriptor owned by the adapter
+ //
+ // Examine each receive ring descriptor for errors.
+ //
+ // When we have the entire packet (and error processing doesn't
+ // prevent us from indicating it), we give the routine that
+ // processes the packet through the filter, the buffers virtual
+ // address (which is always the lookahead size) and as the
+ // MAC context the address of the first data byte.
+
+ PDC21X4_RECEIVE_DESCRIPTOR CurrentDescriptor;
+
+ PVOID FrameVa;
+ USHORT FrameType;
+
+ UINT FrameSize;
+ UINT LookAheadSize;
+
+ BOOLEAN fStopReceiveProcessing = FALSE;
+
+ PRCV_HEADER RcvHeader;
+ PNDIS_PACKET Packet;
+ PPNDIS_PACKET pPktArray;
+ PNDIS_BUFFER Buffer;
+ ULONG Length;
+ UINT Index;
+ UINT Count;
+ UINT i;
+ PDC21X4_RECEIVE_DESCRIPTOR DescriptorMark;
+ ULONG Status;
+ ULONG Register;
+ INT Timeout;
+ ULONG OverflowCount;
+ ULONG MissedFrames;
+
+ NDIS_PHYSICAL_ADDRESS Pa;
+
+#if _DBG
+ DbgPrint("ProcessReceiveInterrupts\n");
+#endif
+
+ NdisSetPhysicalAddressHigh(Pa,0);
+ DescriptorMark = Adapter->DequeueReceiveDescriptor;
+
+ while (!fStopReceiveProcessing) {
+
+ // Grab a max of MAX_PACKET_ARRAY packets at a time.
+
+ for (Count = 0, pPktArray = Adapter->PacketArray; Count < MAX_PACKET_ARRAY;) {
+
+ // Get the current receive descriptor.
+
+ CurrentDescriptor = Adapter->DequeueReceiveDescriptor;
+#if _DBG
+ DbgPrint("RcvDesc [%08x]\n",CurrentDescriptor);
+#endif
+
+ // If the descriptor is not owned by the system, we are done.
+
+ if ((CurrentDescriptor->Status & DC21X4_RDES_OWN_BIT) != DESC_OWNED_BY_SYSTEM) {
+ fStopReceiveProcessing = TRUE;
+ break;
+ }
+
+ if (Adapter->OverflowWorkAround) {
+
+ if (CurrentDescriptor==DescriptorMark) {
+
+ // Mark the next descriptor not owned by the system into the ring
+
+ do {
+ DescriptorMark = DescriptorMark->Next;
+ }
+ while (
+ ((DescriptorMark->Status & DC21X4_RDES_OWN_BIT) != DESC_OWNED_BY_DC21X4)
+ && (DescriptorMark != Adapter->DequeueReceiveDescriptor)
+ );
+
+ if (!Adapter->IndicateOverflow) {
+
+ //Check if an overflow occured for at least one
+ // of the packets currently queued into the Rcv ring
+
+ DC21X4_READ_PORT(
+ DC21X4_MISSED_FRAME,
+ &Register
+ );
+
+ MissedFrames = Register & DC21X4_MISSED_FRAME_COUNTER;
+ if (MissedFrames) {
+ Adapter->GeneralMandatory[GM_MISSED_FRAMES] += MissedFrames;
+ }
+ OverflowCount = (Register >> DC21X4_OVERFLOW_COUNTER_SHIFT)
+ & DC21X4_OVERFLOW_COUNTER;
+ if (OverflowCount) {
+ Adapter->IndicateOverflow = TRUE;
+ Adapter->MediaOptional[MO_RECEIVE_OVERFLOW]+= OverflowCount;
+ }
+
+ }
+
+ if (Adapter->IndicateOverflow) {
+
+ //Stop the Receiver
+ DC21X4_WRITE_PORT(
+ DC21X4_OPERATION_MODE,
+ Adapter->OperationMode & ~(DC21X4_RCV_START)
+ );
+
+ // Discard the packets queued into the ring:
+ // Reclaim all the descriptors owned by the system
+
+
+ while (((Adapter->DequeueReceiveDescriptor)->Status & DC21X4_RDES_OWN_BIT)
+ == DESC_OWNED_BY_SYSTEM
+ ) {
+
+ (Adapter->DequeueReceiveDescriptor)->Status = DESC_OWNED_BY_DC21X4;
+ Adapter->MediaOptional[MO_RECEIVE_OVERFLOW]++;
+ Adapter->DequeueReceiveDescriptor = (Adapter->DequeueReceiveDescriptor)->Next;
+ }
+
+ Adapter->IndicateOverflow = FALSE;
+
+ // Wait for the Receiver to stop
+ Timeout = DC21X4_RVC_TIMEOUT;
+
+ while (Timeout--) {
+
+ DC21X4_READ_PORT(
+ DC21X4_STATUS,
+ &Status
+ );
+
+ if ((Status & (DC21X4_RCV_PROCESS_STATE)) == 0) {
+ break;
+ }
+ NdisStallExecution(2*MILLISECOND);
+ }
+
+ // Once the Receiver is stopped reclaim the descriptors
+ // owned by the system (this happends if a reception was
+ // in progress when tyhe stop_receive command was issued
+
+ while (((Adapter->DequeueReceiveDescriptor)->Status & DC21X4_RDES_OWN_BIT)
+ == DESC_OWNED_BY_SYSTEM
+ ) {
+
+ (Adapter->DequeueReceiveDescriptor)->Status = DESC_OWNED_BY_DC21X4;
+ Adapter->MediaOptional[MO_RECEIVE_OVERFLOW]++;
+ Adapter->DequeueReceiveDescriptor = (Adapter->DequeueReceiveDescriptor)->Next;
+ }
+
+ // Restart the Receiver
+ DC21X4_WRITE_PORT(
+ DC21X4_OPERATION_MODE,
+ Adapter->OperationMode
+ );
+
+ DescriptorMark = Adapter->DequeueReceiveDescriptor;
+ //leave the "for Count" loop back to the "while" loop
+ break;
+ }
+
+ }
+
+ }
+
+ Adapter->DequeueReceiveDescriptor = CurrentDescriptor->Next;
+
+ if (!(CurrentDescriptor->Status & DC21X4_RDES_ERROR_SUMMARY)) {
+
+ // The frame was received correctly
+
+ FrameSize = ((CurrentDescriptor->Status & DC21X4_RDES_FRAME_LENGTH) >> RDES_FRAME_LENGTH_BIT_NUMBER)
+ - ETH_CRC_SIZE;
+
+ // Get a pointer to the receive buffer header.
+
+ RcvHeader = CurrentDescriptor->RcvHeader;
+ ASSERT(RcvHeader->Signature == 'dHxR');
+
+ FrameVa = (PVOID)(RcvHeader->Va);
+
+ NdisFlushBuffer(
+ RcvHeader->FlushBuffer,
+ FALSE
+ );
+
+ NdisSetPhysicalAddressLow(Pa,RcvHeader->Pa);
+
+ NdisMUpdateSharedMemory(
+ Adapter->MiniportAdapterHandle,
+ RcvHeader->Size,
+ (PVOID)RcvHeader->Va,
+ Pa
+ );
+
+ // Adjust the length of the flush buffer to the
+ // length of the packet.
+
+ NdisAdjustBufferLength(
+ RcvHeader->FlushBuffer,
+ FrameSize
+ );
+
+
+ // Save the packet in the packet array.
+
+ Packet = RcvHeader->Packet;
+ *pPktArray = Packet;
+
+ // Log the packet.
+
+ DC21X4LogPacket(Packet, RcvHeader, '-', Count);
+ // Update the statistics based on Receive status;
+#if _DBG
+ DbgPrint("Receive ok\n");
+#endif
+ Adapter->GeneralMandatory[GM_RECEIVE_OK]++;
+
+ // DC21X4 flags Rcv Multicast address but does not
+ // support a specific flag for Rcv Broadcast address
+
+ if (CurrentDescriptor->Status & DC21X4_RDES_MULTICAST_FRAME) {
+ FrameType = (IS_BROADCAST (FrameVa)) ? RCV_BROADCAST_FRAME: RCV_MULTICAST_FRAME;
+ }
+ else {
+ FrameType = RCV_DIRECTED_FRAME;
+ }
+#if _DBG
+ DbgPrint("FrameType = %d\n",FrameType);
+#endif
+ Adapter->GeneralOptionalCount[FrameType].FrameCount++;
+
+ ADD_ULONG_TO_LARGE_INTEGER(
+ Adapter->GeneralOptionalCount[FrameType].ByteCount,
+ FrameSize
+ );
+ // Can the binding keep the packet?
+
+ if (Adapter->FreeRcvList != NULL) {
+
+ NDIS_SET_PACKET_STATUS(*pPktArray, NDIS_STATUS_SUCCESS);
+
+ // Remove the receive buffer from the ring
+ // and replace it with an extra one.
+
+ RcvHeader = Adapter->FreeRcvList;
+ Adapter->FreeRcvList = RcvHeader->Next;
+
+ Adapter->CurrentReceiveBufferCount--;
+
+ // Setup a new receive buffer for the current descriptor.
+
+ CurrentDescriptor->RcvHeader = RcvHeader;
+ CurrentDescriptor->FirstBufferAddress = RcvHeader->Pa;
+ CurrentDescriptor->Status = DESC_OWNED_BY_DC21X4;
+ }
+ else {
+
+ // Mark the packet as copy only...
+
+ NDIS_SET_PACKET_STATUS(*pPktArray, NDIS_STATUS_RESOURCES);
+
+ Adapter->NeededReceiveBuffers++;
+ RCV_RESERVED(Packet)->Descriptor = CurrentDescriptor;
+ }
+
+ Count ++;
+ pPktArray ++;
+ }
+ else {
+
+ // The frame was received with errors:
+ // Update the statistics based on the Receive status.
+#if _DBG
+ DbgPrint("Receive_error: DescStatus = %08x\n",CurrentDescriptor->Status);
+#endif
+ Adapter->GeneralMandatory[GM_RECEIVE_ERROR]++;
+
+ if (CurrentDescriptor->Status & DC21X4_RDES_DRIBBLING_BIT) {
+#if _DBG
+ DbgPrint(" Rcv Alignment Error\n");
+#endif
+ Adapter->MediaMandatory[MM_RECEIVE_ALIGNMENT_ERROR]++;
+ }
+ else if (CurrentDescriptor->Status & DC21X4_RDES_CRC_ERROR) {
+#if _DBG
+ DbgPrint(" Rcv CRC Error\n");
+#endif
+ Adapter->GeneralOptional[GO_RECEIVE_CRC_ERROR]++;
+ }
+
+ if (CurrentDescriptor->Status & DC21X4_RDES_OVERFLOW) {
+#if _DBG
+ DbgPrint(" Rcv Overflow\n");
+#endif
+ Adapter->MediaOptional[MO_RECEIVE_OVERFLOW]++;
+ }
+
+ CurrentDescriptor->Status = DESC_OWNED_BY_DC21X4;
+ }
+
+ }
+
+ // Did we get any packets to indicate up?
+
+ if (Count != 0) {
+
+
+ // Indicate the packets up to the filter library.
+
+ NdisMIndicateReceivePacket(Adapter->MiniportAdapterHandle,
+ Adapter->PacketArray,
+ Count);
+
+
+ // Determine which packets were kept and which ones
+ // were not.
+
+ for (i = 0, pPktArray = Adapter->PacketArray;
+ i < Count;
+ i++, pPktArray ++) {
+
+ // If the status code for the packet is not
+ // status pending then we can place the resources back
+ // on the free lists.
+
+ if (NDIS_GET_PACKET_STATUS(*pPktArray) != NDIS_STATUS_PENDING) {
+
+ // Get a pointer to the receive header.
+
+ RcvHeader = RCV_RESERVED(*pPktArray)->RcvHeader;
+ ASSERT(RcvHeader->Signature == 'dHxR');
+
+ DC21X4LogPacket(*pPktArray, RcvHeader, '+', i);
+
+ // Adjust the buffer length.
+
+ NdisAdjustBufferLength(
+ RcvHeader->FlushBuffer,
+ DC21X4_MAX_FRAME_SIZE
+ );
+
+ // If we indicated to the binding that it couldn't
+ // keep this packet then don't place it back on the
+ // list!!!
+
+ if (NDIS_GET_PACKET_STATUS(*pPktArray) == NDIS_STATUS_RESOURCES) {
+ RCV_RESERVED(*pPktArray)->Descriptor->Status = DESC_OWNED_BY_DC21X4;
+ }
+ else {
+
+ // Place the buffer back on the free queue.
+
+ RcvHeader->Next = Adapter->FreeRcvList;
+ Adapter->FreeRcvList = RcvHeader;
+ }
+ }
+ }
+ }
+ }
+ return CurrentDescriptor;
+
+}
+
+
+
+
+
+
+
+
+
+
+/*+
+ *
+ * ProcessTransmitDescRing
+ *
+ * Routine Description:
+ *
+ * Process the packets that have finished transmitting
+ *
+ * Arguments:
+ *
+ * Adapter - The adapter to indicate to.
+ *
+ * Return Value:
+ *
+ * None.
+ *
+-*/
+
+
+PDC21X4_TRANSMIT_DESCRIPTOR
+ProcessTransmitDescRing(
+ IN PDC21X4_ADAPTER Adapter
+ )
+{
+
+ PDC21X4_TRANSMIT_DESCRIPTOR CurrentDescriptor;
+ PDC21X4_TRANSMIT_DESCRIPTOR Descptr;
+ UINT Collisions;
+ NDIS_STATUS NdisStatus;
+ UINT MapPtr;
+ ULONG ProcessStatus;
+ ULONG DescOwnership;
+
+ ULONG TxmDescriptorCount = 0;
+ ULONG MapRegistersCount = 0;
+ ULONG MaxTransmitBufferCount = 0;
+ ULONG MinTransmitBufferCount = 0;
+ ULONG GoTransmitCount = 0;
+
+#if _DBG
+ DbgPrint("ProcessTransmitInterrupts\n");
+#endif
+
+ // If the Transmit descriptor ring is not empty,
+ // walk the ring from the last known descriptor owned by the adapter
+
+ while (Adapter->DequeueTransmitDescriptor != Adapter->EnqueueTransmitDescriptor) {
+
+ CurrentDescriptor = Adapter->DequeueTransmitDescriptor;
+
+ // If the current descriptor is not owned by the system, we are done.
+
+ if ((CurrentDescriptor->Status & DC21X4_TDES_OWN_BIT) != DESC_OWNED_BY_SYSTEM) {
+ break;
+ }
+
+ if (CurrentDescriptor->Control & DC21X4_TDES_SETUP_PACKET) {
+
+#if _DBG
+ DbgPrint("Int: TxmDesc %08x - Setup desc.\n",CurrentDescriptor);
+#endif
+ // Setup buffer
+ // Complete the pended Set Information request
+ // which originated the CAM load
+
+#if _DBG
+ DbgPrint("Complete Set Information\n");
+#endif
+ NdisMSetInformationComplete (
+ Adapter->MiniportAdapterHandle,
+ NDIS_STATUS_SUCCESS
+ );
+
+ if ( (Adapter->DeviceId == DC21040_CFID)
+ && (Adapter->RevisionNumber == DC21040_REV1)) {
+
+ // SFD bug workaround :
+ // Restart the Receiver and Enable the Sia
+
+ DC21X4_WRITE_PORT(
+ DC21X4_OPERATION_MODE,
+ Adapter->OperationMode
+ );
+
+ DC21X4_WRITE_PORT(
+ DC21X4_SIA_MODE_0,
+ Adapter->Media[Adapter->SelectedMedium].SiaRegister[0]
+ );
+ }
+
+ TxmDescriptorCount++;
+ Adapter->DequeueTransmitDescriptor = CurrentDescriptor->Next;
+
+ }
+
+ else if (CurrentDescriptor->Control & DC21X4_TDES_LAST_SEGMENT) {
+
+#if _DBG
+ DbgPrint("Int: TxmDesc %08x - Last segment desc.\n",CurrentDescriptor);
+#endif
+ // if Underrun check if the packet should be requeued
+ if ( (CurrentDescriptor->Status & DC21X4_TDES_UNDERRUN_ERROR)
+ && (Adapter->UnderrunRetryCount < Adapter->UnderrunMaxRetries)
+ ) {
+
+ // The Txm packet can only be requeued
+ // if the Txm process has not been restarted
+ // by a Txm Poll demand
+
+ Adapter->DisableTransmitPolling = TRUE;
+
+ DC21X4_READ_PORT(
+ DC21X4_STATUS,
+ &ProcessStatus
+ );
+
+ ProcessStatus &= DC21X4_TXM_PROCESS_STATE;
+
+ DescOwnership = (CurrentDescriptor->Next != Adapter->EnqueueTransmitDescriptor) ?
+ (CurrentDescriptor->Next)->Status & DC21X4_TDES_OWN_BIT :
+ DESC_OWNED_BY_DC21X4;
+
+ if ((ProcessStatus == DC21X4_TXM_PROCESS_SUSPENDED) && (DescOwnership == DESC_OWNED_BY_DC21X4)) {
+
+ // Requeue the Txm packet
+#if __DBG
+ DbgPrint(" Txm Underrun: Retry = %d\n",Adapter->UnderrunRetryCount);
+#endif
+ //Stop the transmitter
+
+ DC21X4_WRITE_PORT(
+ DC21X4_OPERATION_MODE,
+ Adapter->OperationMode & ~(DC21X4_TXM_START)
+ );
+
+ //Reinitialize the descriptor's ownership bits
+
+ //First segment descriptor
+ Descptr = CurrentDescriptor->DescPointer;
+
+ DC21X4_WRITE_PORT(
+ DC21X4_TXM_DESC_RING,
+ Descptr->DescriptorPa
+ );
+
+ while (TRUE) {
+
+ Descptr->Status = DESC_OWNED_BY_DC21X4;
+ if (Descptr == CurrentDescriptor) {
+ break;
+ }
+ else {
+ Descptr = Descptr->Next;
+ }
+ }
+
+ Adapter->DisableTransmitPolling = FALSE;
+
+ //Restart the transmitter
+
+ DC21X4_WRITE_PORT(
+ DC21X4_OPERATION_MODE,
+ Adapter->OperationMode
+ );
+
+ Adapter->UnderrunRetryCount++;
+
+ return CurrentDescriptor;
+ }
+ else {
+ Adapter->DisableTransmitPolling = FALSE;
+
+ }
+
+ }
+
+ Adapter->UnderrunRetryCount = 0 ;
+
+ // Point to the first segment descriptor and walk down the descriptors
+ // mapping the current frame to free the physical mapping table
+
+ Descptr = CurrentDescriptor->DescPointer;
+
+ while (TRUE) {
+
+ // If this descriptor points the first segment of a Ndis Buffer, free the
+ // Physical Mapping table of this buffer
+
+ for (MapPtr = Descptr->MapTableIndex;
+ MapPtr < Descptr->MapTableIndex + NUMBER_OF_SEGMENT_PER_DESC;
+ MapPtr++) {
+
+ if (Adapter->PhysicalMapping[MapPtr].Valid) {
+#if _DBG
+ DbgPrint(" NdisMCompleteBufferPhysicalMapping (%d)\n",MapPtr);
+#endif
+ NdisMCompleteBufferPhysicalMapping(
+ Adapter->MiniportAdapterHandle,
+ Adapter->PhysicalMapping[MapPtr].Buffer,
+ Adapter->PhysicalMapping[MapPtr].Register
+ );
+
+ Adapter->PhysicalMapping[MapPtr].Valid = FALSE;
+ MapRegistersCount++;
+ }
+ }
+
+ if (Descptr == CurrentDescriptor) {
+ break;
+ }
+ else {
+ TxmDescriptorCount++;
+ Descptr = Descptr->Next;
+ }
+
+ }
+
+ // If this packet was copied into a preallocated Txm Buffer,
+ // free the resources
+
+ if (CurrentDescriptor->SendStatus == CopyMaxBuffer) {
+ MaxTransmitBufferCount++;
+ }
+ else if (CurrentDescriptor->SendStatus == CopyMinBuffer) {
+ MinTransmitBufferCount++;
+ }
+
+ // Update the statistics based on the Transmit status
+
+ if (!(CurrentDescriptor->Status & Adapter->TransmitDescriptorErrorMask)) {
+
+ // The frame was transmitted correctly
+
+ Collisions = (CurrentDescriptor->Status & DC21X4_TDES_COLLISION_COUNT)
+ >> TDES_COLLISION_COUNT_BIT_NUMBER;
+
+ if (Collisions == 1) {
+ Adapter->MediaMandatory[MM_TRANSMIT_ONE_COLLISION]++;
+ }
+ else if (Collisions > 1) {
+ Adapter->MediaMandatory[MM_TRANSMIT_MULT_COLLISIONS]++;
+ }
+ if (CurrentDescriptor->Status & DC21X4_TDES_DEFERRED) {
+ Adapter->MediaOptional[MO_TRANSMIT_DEFERRED]++;
+ }
+ if (CurrentDescriptor->Status & DC21X4_TDES_HEARTBEAT_FAIL) {
+ Adapter->MediaOptional[MO_TRANSMIT_HEARTBEAT_FAILURE]++;
+ }
+
+ Adapter->GeneralOptionalCount[CurrentDescriptor->PacketType].FrameCount++;
+ ADD_ULONG_TO_LARGE_INTEGER(
+ Adapter->GeneralOptionalCount[CurrentDescriptor->PacketType].ByteCount,
+ CurrentDescriptor->PacketSize
+ );
+
+ Adapter->GeneralMandatory[GM_TRANSMIT_OK]++;
+ NdisStatus = NDIS_STATUS_SUCCESS;
+ }
+
+ else {
+
+#if _DBG
+ DbgPrint("Transmit_error: DescStatus = %08x\n",CurrentDescriptor->Status);
+#endif
+ if (CurrentDescriptor->Status & DC21X4_TDES_TXM_JABBER_TIMEOUT) {
+
+ // This indicates a severe SIA hardware error. Stop the adapter
+ // to avoid generating noise on the net
+#if __DBG
+ DbgPrint("DC21X4 TXM JABBER TIMEOUT!!!\n");
+#endif
+ DC21X4StopAdapter(Adapter);
+
+ NdisWriteErrorLogEntry(
+ Adapter->MiniportAdapterHandle,
+ NDIS_ERROR_CODE_HARDWARE_FAILURE,
+ 1,
+ DC21X4_ERRMSG_TXM_JABBER_TIMEOUT
+ );
+ }
+
+ if (CurrentDescriptor->Status & DC21X4_TDES_EXCESSIVE_COLLISIONS) {
+#if _DBG
+ DbgPrint(" Txm Excess Collisions\n");
+#endif
+ Adapter->MediaOptional[MO_TRANSMIT_EXC_COLLISIONS]++;
+ Adapter->ExcessCollisionsCount++;
+ }
+ else {
+ Adapter->ExcessCollisionsCount=0;
+ }
+
+ if (CurrentDescriptor->Status & DC21X4_TDES_UNDERRUN_ERROR) {
+
+ Adapter->MediaOptional[MO_TRANSMIT_UNDERRUN]++;
+#if __DBG
+ DbgPrint(" Txm Underrun [UnderrunCount=%d]\n",Adapter->MediaOptional[MO_TRANSMIT_UNDERRUN]);
+#endif
+
+ if ( (Adapter->MediaOptional[MO_TRANSMIT_UNDERRUN] >= Adapter->UnderrunThreshold)
+ && !(Adapter->OperationMode & DC21X4_STORE_AND_FORWARD)
+ ) {
+
+ //Force StoreAndForward mode
+#if __DBG
+ DbgPrint("UnderrunCount=%d : Force StoreAnd Forward mode\n",
+ Adapter->MediaOptional[MO_TRANSMIT_UNDERRUN]);
+#endif
+ DC21X4StopReceiverAndTransmitter(Adapter);
+
+ Adapter->OperationMode |= DC21X4_STORE_AND_FORWARD;
+
+ DC21X4_WRITE_PORT(
+ DC21X4_OPERATION_MODE,
+ Adapter->OperationMode
+ );
+ }
+
+ }
+ else if (CurrentDescriptor->Status & DC21X4_TDES_LATE_COLLISION) {
+#if _DBG
+ DbgPrint(" Txm Late Collision\n");
+#endif
+ Adapter->MediaOptional[MO_TRANSMIT_LATE_COLLISION]++;
+ }
+ if (CurrentDescriptor->Status & DC21X4_TDES_NO_CARRIER) {
+#if _DBG
+ DbgPrint(" Txm No Carrier\n");
+#endif
+ Adapter->NoCarrierCount++;
+ }
+ else {
+ Adapter->NoCarrierCount=0;
+ }
+
+ Adapter->GeneralMandatory[GM_TRANSMIT_ERROR]++;
+ NdisStatus = NDIS_STATUS_FAILURE;
+
+ }
+
+ GoTransmitCount++;
+
+// if (CurrentDescriptor->SendStatus == MappedBuffer) {
+#if _DBG
+ DbgPrint(" Signal Tx Completion desc= %08x\n", CurrentDescriptor);
+#endif
+ NdisMSendComplete(
+ Adapter->MiniportAdapterHandle,
+ CurrentDescriptor->Packet,
+ NdisStatus
+ );
+
+// }
+
+ TxmDescriptorCount++;
+ Adapter->DequeueTransmitDescriptor = CurrentDescriptor->Next;
+ }
+
+ else if (CurrentDescriptor->Control & DC21X4_TDES_FIRST_SEGMENT) {
+
+#if _DBG
+ DbgPrint("Int: TxmDesc %08x - First segment desc.\n",CurrentDescriptor);
+#endif
+ Adapter->DequeueTransmitDescriptor = CurrentDescriptor->DescPointer;
+
+ }
+
+ else {
+
+ TxmDescriptorCount++;
+ Adapter->DequeueTransmitDescriptor = CurrentDescriptor->Next;
+ }
+
+ }
+
+ if (Adapter->FullDuplex) {
+ NdisDprAcquireSpinLock(&Adapter->FullDuplexSpinLock);
+ }
+
+ Adapter->FreeTransmitDescriptorCount += TxmDescriptorCount;
+
+ Adapter->FreeMapRegisters += MapRegistersCount;
+
+ Adapter->MaxTransmitBufferInUse -= MaxTransmitBufferCount;
+
+ Adapter->MinTransmitBufferInUse -= MinTransmitBufferCount;
+
+ Adapter->GeneralOptional[GO_TRANSMIT_QUEUE_LENGTH] -= GoTransmitCount;
+
+ if (Adapter->FullDuplex) {
+ NdisDprReleaseSpinLock(&Adapter->FullDuplexSpinLock);
+ }
+
+ return Adapter->DequeueTransmitDescriptor;
+
+}
+
+/*+
+ *
+ * DC21X4EnableInterrupt
+ *
+-*/
+extern
+VOID
+DC21X4EnableInterrupt(
+ IN NDIS_HANDLE MiniportAdapterContext
+ )
+{
+ PDC21X4_ADAPTER Adapter;
+
+ Adapter = (PDC21X4_ADAPTER)MiniportAdapterContext;
+
+ DC21X4_WRITE_PORT(
+ DC21X4_INTERRUPT_MASK,
+ Adapter->InterruptMask
+ );
+ return;
+}
+
+/*+
+ *
+ * DC21X4DisableInterrupt
+ *
+-*/
+extern
+VOID
+DC21X4DisableInterrupt(
+ IN NDIS_HANDLE MiniportAdapterContext
+ )
+{
+ PDC21X4_ADAPTER Adapter;
+
+ Adapter = (PDC21X4_ADAPTER)MiniportAdapterContext;
+
+ DC21X4_WRITE_PORT(
+ DC21X4_INTERRUPT_MASK,
+ 0
+ );
+ return;
+}
+
+
+/*+
+ *
+ *DC21X4ReturnPacket
+ *
+ * Routine Description:
+ *
+ * Place a buufer released by the binding back into its free list
+ *
+ * Arguments:
+ *
+ * Return Value:
+ *
+-*/
+NDIS_STATUS
+DC21X4ReturnPacket(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN PNDIS_PACKET Packet
+ )
+
+{
+
+ PDC21X4_ADAPTER Adapter = (PDC21X4_ADAPTER)MiniportAdapterContext;
+ PRCV_HEADER RcvHeader;
+
+
+ // Get a pointer to the receive header.
+
+ RcvHeader = RCV_RESERVED(Packet)->RcvHeader;
+ ASSERT(RcvHeader->Signature == 'dHxR');
+
+ DC21X4LogPacket(Packet, RcvHeader, '+', (ULONG)-1);
+
+
+ // Adjust the buffer length.
+
+ NdisAdjustBufferLength(
+ RcvHeader->FlushBuffer,
+ DC21X4_RECEIVE_BUFFER_SIZE
+ );
+
+ // Place the buffer back on the free queue.
+
+ RcvHeader->Next = Adapter->FreeRcvList;
+ Adapter->FreeRcvList = RcvHeader;
+
+ return NDIS_STATUS_SUCCESS;
+
+}
+