Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198/* * PROJECT: ReactOS Intel PRO/1000 Driver * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) * PURPOSE: Interrupt handlers * COPYRIGHT: 2013 Cameron Gutman (cameron.gutman@reactos.org) * 2018 Mark Jansen (mark.jansen@reactos.org) * 2019 Victor Pereertkin (victor.perevertkin@reactos.org) */
#include "nic.h"
#include <debug.h>
VOIDNTAPIMiniportISR( OUT PBOOLEAN InterruptRecognized, OUT PBOOLEAN QueueMiniportHandleInterrupt, IN NDIS_HANDLE MiniportAdapterContext){ ULONG Value; PE1000_ADAPTER Adapter = (PE1000_ADAPTER)MiniportAdapterContext;
/* Reading the interrupt acknowledges them */ E1000ReadUlong(Adapter, E1000_REG_ICR, &Value);
Value &= Adapter->InterruptMask; _InterlockedOr(&Adapter->InterruptPending, Value);
if (Value) { *InterruptRecognized = TRUE; /* Mark the events pending service */ *QueueMiniportHandleInterrupt = TRUE; } else { /* This is not ours. */ *InterruptRecognized = FALSE; *QueueMiniportHandleInterrupt = FALSE; }}
VOIDNTAPIMiniportHandleInterrupt( IN NDIS_HANDLE MiniportAdapterContext){ ULONG InterruptPending; PE1000_ADAPTER Adapter = (PE1000_ADAPTER)MiniportAdapterContext; volatile PE1000_TRANSMIT_DESCRIPTOR TransmitDescriptor;
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
InterruptPending = _InterlockedExchange(&Adapter->InterruptPending, 0);
/* Link State Changed */ if (InterruptPending & E1000_IMS_LSC) { ULONG Status;
InterruptPending &= ~E1000_IMS_LSC; NDIS_DbgPrint(MAX_TRACE, ("Link status changed!.\n"));
NICUpdateLinkStatus(Adapter);
Status = Adapter->MediaState == NdisMediaStateConnected ? NDIS_STATUS_MEDIA_CONNECT : NDIS_STATUS_MEDIA_DISCONNECT;
NdisMIndicateStatus(Adapter->AdapterHandle, Status, NULL, 0); NdisMIndicateStatusComplete(Adapter->AdapterHandle); }
/* Handling receive interrupts */ if (InterruptPending & (E1000_IMS_RXDMT0 | E1000_IMS_RXT0)) { volatile PE1000_RECEIVE_DESCRIPTOR ReceiveDescriptor; PETH_HEADER EthHeader; ULONG BufferOffset; BOOLEAN bGotAny = FALSE; ULONG RxDescHead, RxDescTail, CurrRxDesc;
/* Clear out these interrupts */ InterruptPending &= ~(E1000_IMS_RXDMT0 | E1000_IMS_RXT0);
E1000ReadUlong(Adapter, E1000_REG_RDH, &RxDescHead); E1000ReadUlong(Adapter, E1000_REG_RDT, &RxDescTail);
while (((RxDescTail + 1) % NUM_RECEIVE_DESCRIPTORS) != RxDescHead) { CurrRxDesc = (RxDescTail + 1) % NUM_RECEIVE_DESCRIPTORS; BufferOffset = CurrRxDesc * Adapter->ReceiveBufferEntrySize; ReceiveDescriptor = Adapter->ReceiveDescriptors + CurrRxDesc;
/* Check if the hardware have released this descriptor (DD - Descriptor Done) */ if (!(ReceiveDescriptor->Status & E1000_RDESC_STATUS_DD)) { /* No need to check descriptors after the first unfinished one */ break; }
/* Ignoring these flags for now */ ReceiveDescriptor->Status &= ~(E1000_RDESC_STATUS_IXSM | E1000_RDESC_STATUS_PIF);
if (ReceiveDescriptor->Status != (E1000_RDESC_STATUS_EOP | E1000_RDESC_STATUS_DD)) { NDIS_DbgPrint(MIN_TRACE, ("Unrecognized ReceiveDescriptor status flag: %u\n", ReceiveDescriptor->Status)); }
/* Make sure the receive indications are enabled */ if (!Adapter->PacketFilter) { goto NextReceiveDescriptor; }
if (ReceiveDescriptor->Length != 0 && ReceiveDescriptor->Address != 0) { EthHeader = (PETH_HEADER)(Adapter->ReceiveBuffer + BufferOffset);
NdisMEthIndicateReceive(Adapter->AdapterHandle, NULL, (PCHAR)EthHeader, sizeof(ETH_HEADER), (PCHAR)(EthHeader + 1), ReceiveDescriptor->Length - sizeof(ETH_HEADER), ReceiveDescriptor->Length - sizeof(ETH_HEADER));
bGotAny = TRUE; } else { NDIS_DbgPrint(MIN_TRACE, ("Got a NULL descriptor")); }
NextReceiveDescriptor: /* Give the descriptor back */ ReceiveDescriptor->Status = 0;
RxDescTail = CurrRxDesc; }
if (bGotAny) { /* Write back new tail value */ E1000WriteUlong(Adapter, E1000_REG_RDT, RxDescTail);
NDIS_DbgPrint(MAX_TRACE, ("Rx done (RDH: %u, RDT: %u)\n", RxDescHead, RxDescTail));
NdisMEthIndicateReceiveComplete(Adapter->AdapterHandle); } }
/* Handling transmit interrupts */ if (InterruptPending & (E1000_IMS_TXD_LOW | E1000_IMS_TXDW | E1000_IMS_TXQE)) { PNDIS_PACKET AckPackets[40] = {0}; ULONG NumPackets = 0, i;
/* Clear out these interrupts */ InterruptPending &= ~(E1000_IMS_TXD_LOW | E1000_IMS_TXDW | E1000_IMS_TXQE);
while ((Adapter->TxFull || Adapter->LastTxDesc != Adapter->CurrentTxDesc) && NumPackets < ARRAYSIZE(AckPackets)) { TransmitDescriptor = Adapter->TransmitDescriptors + Adapter->LastTxDesc;
if (TransmitDescriptor->Status & E1000_TDESC_STATUS_DD) { if (Adapter->TransmitPackets[Adapter->LastTxDesc]) { AckPackets[NumPackets++] = Adapter->TransmitPackets[Adapter->LastTxDesc]; Adapter->TransmitPackets[Adapter->LastTxDesc] = NULL; TransmitDescriptor->Status = 0; }
Adapter->LastTxDesc = (Adapter->LastTxDesc + 1) % NUM_TRANSMIT_DESCRIPTORS; Adapter->TxFull = FALSE; } else { break; } }
if (NumPackets) { NDIS_DbgPrint(MAX_TRACE, ("Tx: (TDH: %u, TDT: %u)\n", Adapter->CurrentTxDesc, Adapter->LastTxDesc)); NDIS_DbgPrint(MAX_TRACE, ("Tx Done: %u packets to ack\n", NumPackets));
for (i = 0; i < NumPackets; ++i) { NdisMSendComplete(Adapter->AdapterHandle, AckPackets[i], NDIS_STATUS_SUCCESS); } } }
ASSERT(InterruptPending == 0);}