mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 15:53:03 +00:00
[E1000] Finished an implementation of the driver.
Added PIDs for whole Intel 8254x family. Note: this driver uses legacy interfaces for either receive and transmit descriptors. CORE-14675
This commit is contained in:
parent
1b2ca28107
commit
d9c4d28e59
7 changed files with 262 additions and 160 deletions
|
@ -2,8 +2,9 @@
|
|||
* PROJECT: ReactOS Intel PRO/1000 Driver
|
||||
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
|
||||
* PURPOSE: Interrupt handlers
|
||||
* COPYRIGHT: Copyright 2013 Cameron Gutman (cameron.gutman@reactos.org)
|
||||
* Copyright 2018 Mark Jansen (mark.jansen@reactos.org)
|
||||
* 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"
|
||||
|
@ -39,102 +40,145 @@ NTAPI
|
|||
MiniportHandleInterrupt(
|
||||
IN NDIS_HANDLE MiniportAdapterContext)
|
||||
{
|
||||
ULONG Value;
|
||||
ULONG InterruptPending;
|
||||
PE1000_ADAPTER Adapter = (PE1000_ADAPTER)MiniportAdapterContext;
|
||||
volatile PE1000_TRANSMIT_DESCRIPTOR TransmitDescriptor;
|
||||
|
||||
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
|
||||
|
||||
Value = InterlockedExchange(&Adapter->InterruptPending, 0);
|
||||
InterruptPending = InterlockedExchange(&Adapter->InterruptPending, 0);
|
||||
|
||||
NdisDprAcquireSpinLock(&Adapter->Lock);
|
||||
|
||||
if (Value & E1000_IMS_LSC)
|
||||
/* Link State Changed */
|
||||
if (InterruptPending & E1000_IMS_LSC)
|
||||
{
|
||||
ULONG Status;
|
||||
|
||||
NdisDprReleaseSpinLock(&Adapter->Lock);
|
||||
Value &= ~E1000_IMS_LSC;
|
||||
NDIS_DbgPrint(MIN_TRACE, ("Link status changed!.\n"));
|
||||
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);
|
||||
|
||||
NdisDprAcquireSpinLock(&Adapter->Lock);
|
||||
}
|
||||
|
||||
if (Value & E1000_IMS_TXDW)
|
||||
{
|
||||
while (Adapter->TxFull || Adapter->LastTxDesc != Adapter->CurrentTxDesc)
|
||||
{
|
||||
TransmitDescriptor = Adapter->TransmitDescriptors + Adapter->LastTxDesc;
|
||||
|
||||
if (!(TransmitDescriptor->Status & E1000_TDESC_STATUS_DD))
|
||||
{
|
||||
/* Not processed yet */
|
||||
break;
|
||||
}
|
||||
|
||||
Adapter->LastTxDesc = (Adapter->LastTxDesc + 1) % NUM_TRANSMIT_DESCRIPTORS;
|
||||
Value &= ~E1000_IMS_TXDW;
|
||||
Adapter->TxFull = FALSE;
|
||||
NDIS_DbgPrint(MAX_TRACE, ("CurrentTxDesc:%u, LastTxDesc:%u\n", Adapter->CurrentTxDesc, Adapter->LastTxDesc));
|
||||
}
|
||||
}
|
||||
|
||||
if (Value & (E1000_IMS_RXDMT0 | E1000_IMS_RXT0))
|
||||
/* 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 */
|
||||
Value &= ~(E1000_IMS_RXDMT0 | E1000_IMS_RXT0);
|
||||
InterruptPending &= ~(E1000_IMS_RXDMT0 | E1000_IMS_RXT0);
|
||||
|
||||
while (TRUE)
|
||||
E1000ReadUlong(Adapter, E1000_REG_RDH, &RxDescHead);
|
||||
E1000ReadUlong(Adapter, E1000_REG_RDT, &RxDescTail);
|
||||
|
||||
while (((RxDescTail + 1) % NUM_RECEIVE_DESCRIPTORS) != RxDescHead)
|
||||
{
|
||||
BufferOffset = Adapter->CurrentRxDesc * Adapter->ReceiveBufferEntrySize;
|
||||
ReceiveDescriptor = Adapter->ReceiveDescriptors + Adapter->CurrentRxDesc;
|
||||
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))
|
||||
{
|
||||
/* Not received yet */
|
||||
/* No need to check descriptors after the first unfinished one */
|
||||
break;
|
||||
}
|
||||
|
||||
if (ReceiveDescriptor->Length != 0)
|
||||
/* 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))
|
||||
{
|
||||
EthHeader = Adapter->ReceiveBuffer + BufferOffset;
|
||||
NDIS_DbgPrint(MIN_TRACE, ("Unrecognized ReceiveDescriptor status flag: %u\n", ReceiveDescriptor->Status));
|
||||
}
|
||||
|
||||
if (ReceiveDescriptor->Length != 0 && ReceiveDescriptor->Address != 0)
|
||||
{
|
||||
EthHeader = (PETH_HEADER)(Adapter->ReceiveBuffer + BufferOffset);
|
||||
|
||||
NdisMEthIndicateReceive(Adapter->AdapterHandle,
|
||||
NULL,
|
||||
EthHeader,
|
||||
(PCHAR)EthHeader,
|
||||
sizeof(ETH_HEADER),
|
||||
EthHeader + 1,
|
||||
(PCHAR)(EthHeader + 1),
|
||||
ReceiveDescriptor->Length - sizeof(ETH_HEADER),
|
||||
ReceiveDescriptor->Length - sizeof(ETH_HEADER));
|
||||
|
||||
if (ReceiveDescriptor->Status & E1000_RDESC_STATUS_EOP)
|
||||
{
|
||||
NdisMEthIndicateReceiveComplete(Adapter->AdapterHandle);
|
||||
}
|
||||
else
|
||||
{
|
||||
__debugbreak();
|
||||
}
|
||||
bGotAny = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
NDIS_DbgPrint(MIN_TRACE, ("Got a NULL descriptor"));
|
||||
}
|
||||
|
||||
/* Restore the descriptor Address, incase we received a NULL descriptor */
|
||||
ReceiveDescriptor->Address = Adapter->ReceiveBufferPa.QuadPart + BufferOffset;
|
||||
/* Give the descriptor back */
|
||||
ReceiveDescriptor->Status = 0;
|
||||
E1000WriteUlong(Adapter, E1000_REG_RDT, Adapter->CurrentRxDesc);
|
||||
Adapter->CurrentRxDesc = (Adapter->CurrentRxDesc + 1) % NUM_RECEIVE_DESCRIPTORS;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(Value == 0);
|
||||
/* 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);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue