https://git.reactos.org/?p=reactos.git;a=commitdiff;h=d9c4d28e59de351a59a29…
commit d9c4d28e59de351a59a29a9bf450755627138a7c
Author: Victor Perevertkin <victor(a)perevertkin.ru>
AuthorDate: Tue Jan 22 00:44:25 2019 +0300
Commit: Mark Jansen <mark.jansen(a)reactos.org>
CommitDate: Thu Feb 7 19:48:54 2019 +0100
[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
---
drivers/network/dd/e1000/e1000hw.h | 31 ++++++--
drivers/network/dd/e1000/hardware.c | 132 ++++++++++++++++--------------
drivers/network/dd/e1000/info.c | 11 +--
drivers/network/dd/e1000/interrupt.c | 150 ++++++++++++++++++++++-------------
drivers/network/dd/e1000/ndis.c | 23 ++----
drivers/network/dd/e1000/nic.h | 35 ++++----
media/inf/nete1000.inf | 40 +++++++++-
7 files changed, 262 insertions(+), 160 deletions(-)
diff --git a/drivers/network/dd/e1000/e1000hw.h b/drivers/network/dd/e1000/e1000hw.h
index b2293aa0ba..994be06067 100644
--- a/drivers/network/dd/e1000/e1000hw.h
+++ b/drivers/network/dd/e1000/e1000hw.h
@@ -1,8 +1,9 @@
/*
* PROJECT: ReactOS Intel PRO/1000 Driver
* LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
- * PURPOSE: Intel PRO/1000 driver definitions
- * COPYRIGHT: Copyright 2018 Mark Jansen (mark.jansen(a)reactos.org)
+ * PURPOSE: Hardware specific definitions
+ * COPYRIGHT: 2018 Mark Jansen (mark.jansen(a)reactos.org)
+ * 2019 Victor Perevertkin (victor.perevertkin(a)reactos.org)
*/
#pragma once
@@ -30,6 +31,8 @@ typedef struct _ETH_HEADER {
} ETH_HEADER, *PETH_HEADER;
+C_ASSERT(sizeof(ETH_HEADER) == 14);
+
typedef enum _E1000_RCVBUF_SIZE
{
@@ -53,6 +56,8 @@ typedef enum _E1000_RCVBUF_SIZE
/* 3.2.3 Receive Descriptor Format */
+#define E1000_RDESC_STATUS_PIF (1 << 7) /* Passed in-exact filter */
+#define E1000_RDESC_STATUS_IXSM (1 << 2) /* Ignore Checksum Indication
*/
#define E1000_RDESC_STATUS_EOP (1 << 1) /* End of Packet */
#define E1000_RDESC_STATUS_DD (1 << 0) /* Descriptor Done */
@@ -71,6 +76,7 @@ typedef struct _E1000_RECEIVE_DESCRIPTOR
/* 3.3.3 Legacy Transmit Descriptor Format */
+#define E1000_TDESC_CMD_IDE (1 << 7) /* Interrupt Delay Enable */
#define E1000_TDESC_CMD_RS (1 << 3) /* Report Status */
#define E1000_TDESC_CMD_IFCS (1 << 1) /* Insert FCS */
#define E1000_TDESC_CMD_EOP (1 << 0) /* End Of Packet */
@@ -118,18 +124,23 @@ C_ASSERT(sizeof(E1000_TRANSMIT_DESCRIPTOR) == 16);
#define E1000_REG_RCTL 0x0100 /* Receive Control Register, R/W */
#define E1000_REG_TCTL 0x0400 /* Transmit Control Register, R/W */
+#define E1000_REG_TIPG 0x0410 /* Transmit IPG Register, R/W */
#define E1000_REG_RDBAL 0x2800 /* Receive Descriptor Base Address Low,
R/W */
#define E1000_REG_RDBAH 0x2804 /* Receive Descriptor Base Address High,
R/W */
#define E1000_REG_RDLEN 0x2808 /* Receive Descriptor Length, R/W */
#define E1000_REG_RDH 0x2810 /* Receive Descriptor Head, R/W */
#define E1000_REG_RDT 0x2818 /* Receive Descriptor Tail, R/W */
+#define E1000_REG_RDTR 0x2820 /* Receive Delay Timer, R/W */
+#define E1000_REG_RADV 0x282C /* Receive Absolute Delay Timer, R/W */
#define E1000_REG_TDBAL 0x3800 /* Transmit Descriptor Base Address Low,
R/W */
#define E1000_REG_TDBAH 0x3804 /* Transmit Descriptor Base Address High,
R/W */
#define E1000_REG_TDLEN 0x3808 /* Transmit Descriptor Length, R/W */
#define E1000_REG_TDH 0x3810 /* Transmit Descriptor Head, R/W */
#define E1000_REG_TDT 0x3818 /* Transmit Descriptor Tail, R/W */
+#define E1000_REG_TIDV 0x3820 /* Transmit Interrupt Delay Value, R/W
*/
+#define E1000_REG_TADV 0x382C /* Transmit Absolute Delay Timer, R/W */
#define E1000_REG_RAL 0x5400 /* Receive Address Low, R/W */
@@ -137,11 +148,16 @@ C_ASSERT(sizeof(E1000_TRANSMIT_DESCRIPTOR) == 16);
/* E1000_REG_CTRL */
+#define E1000_CTRL_LRST (1 << 3) /* Link Reset */
+#define E1000_CTRL_ASDE (1 << 5) /* Auto-Speed Detection Enable */
+#define E1000_CTRL_SLU (1 << 6) /* Set Link Up */
#define E1000_CTRL_RST (1 << 26) /* Device Reset, Self clearing */
+#define E1000_CTRL_VME (1 << 30) /* VLAN Mode Enable */
/* E1000_REG_STATUS */
-#define E1000_STATUS_LU (1 << 0) /* Link Up Indication */
+#define E1000_STATUS_FD (1 << 0) /* Full Duplex Indication */
+#define E1000_STATUS_LU (1 << 1) /* Link Up Indication */
#define E1000_STATUS_SPEEDSHIFT 6 /* Link speed setting */
#define E1000_STATUS_SPEEDMASK (3 << E1000_STATUS_SPEEDSHIFT)
@@ -164,9 +180,12 @@ C_ASSERT(sizeof(E1000_TRANSMIT_DESCRIPTOR) == 16);
/* E1000_REG_IMS */
#define E1000_IMS_TXDW (1 << 0) /* Transmit Descriptor Written Back
*/
+#define E1000_IMS_TXQE (1 << 1) /* Transmit Queue Empty */
#define E1000_IMS_LSC (1 << 2) /* Sets mask for Link Status Change
*/
#define E1000_IMS_RXDMT0 (1 << 4) /* Receive Descriptor Minimum
Threshold Reached */
#define E1000_IMS_RXT0 (1 << 7) /* Receiver Timer Interrupt */
+#define E1000_IMS_TXD_LOW (1 << 15) /* Transmit Descriptor Low
Threshold hit */
+#define E1000_IMS_SRPD (1 << 16) /* Small Receive Packet Detection
*/
/* E1000_REG_ITR */
@@ -192,7 +211,10 @@ C_ASSERT(sizeof(E1000_TRANSMIT_DESCRIPTOR) == 16);
#define E1000_TCTL_EN (1 << 1) /* Transmit Enable */
#define E1000_TCTL_PSP (1 << 3) /* Pad Short Packets */
-
+/* E1000_REG_TIPG */
+#define E1000_TIPG_IPGT_DEF (10 << 0) /* IPG Transmit Time */
+#define E1000_TIPG_IPGR1_DEF (10 << 10) /* IPG Receive Time 1 */
+#define E1000_TIPG_IPGR2_DEF (10 << 20) /* IPG Receive Time 2 */
/* E1000_REG_RAH */
@@ -222,4 +244,3 @@ C_ASSERT(sizeof(E1000_TRANSMIT_DESCRIPTOR) == 16);
#define E1000_PSS_SPEED_AND_DUPLEX (1 << 11) /* Speed and Duplex Resolved */
#define E1000_PSS_SPEEDSHIFT 14
#define E1000_PSS_SPEEDMASK (3 << E1000_PSS_SPEEDSHIFT)
-
diff --git a/drivers/network/dd/e1000/hardware.c b/drivers/network/dd/e1000/hardware.c
index 0b7d8f0d1f..aa5fc26896 100644
--- a/drivers/network/dd/e1000/hardware.c
+++ b/drivers/network/dd/e1000/hardware.c
@@ -2,7 +2,8 @@
* PROJECT: ReactOS Intel PRO/1000 Driver
* LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Hardware specific functions
- * COPYRIGHT: Copyright 2018 Mark Jansen (mark.jansen(a)reactos.org)
+ * COPYRIGHT: 2018 Mark Jansen (mark.jansen(a)reactos.org)
+ * 2019 Victor Perevertkin (victor.perevertkin(a)reactos.org)
*/
#include "nic.h"
@@ -12,7 +13,44 @@
static USHORT SupportedDevices[] =
{
- 0x100f, // Intel 82545EM (VMWare E1000)
+ /* 8254x Family adapters. Not all of them are tested */
+ 0x1000, // Intel 82542
+ 0x1001, // Intel 82543GC Fiber
+ 0x1004, // Intel 82543GC Copper
+ 0x1008, // Intel 82544EI Copper
+ 0x1009, // Intel 82544EI Fiber
+ 0x100A, // Intel 82540EM
+ 0x100C, // Intel 82544GC Copper
+ 0x100D, // Intel 82544GC LOM (LAN on Motherboard)
+ 0x100E, // Intel 82540EM
+ 0x100F, // Intel 82545EM Copper
+ 0x1010, // Intel 82546EB Copper
+ 0x1011, // Intel 82545EM Fiber
+ 0x1012, // Intel 82546EB Fiber
+ 0x1013, // Intel 82541EI
+ 0x1014, // Intel 82541EI LOM
+ 0x1015, // Intel 82540EM LOM
+ 0x1016, // Intel 82540EP LOM
+ 0x1017, // Intel 82540EP
+ 0x1018, // Intel 82541EI Mobile
+ 0x1019, // Intel 82547EI
+ 0x101A, // Intel 82547EI Mobile
+ 0x101D, // Intel 82546EB Quad Copper
+ 0x101E, // Intel 82540EP LP (Low profile)
+ 0x1026, // Intel 82545GM Copper
+ 0x1027, // Intel 82545GM Fiber
+ 0x1028, // Intel 82545GM SerDes
+ 0x1075, // Intel 82547GI
+ 0x1076, // Intel 82541GI
+ 0x1077, // Intel 82541GI Mobile
+ 0x1078, // Intel 82541ER
+ 0x1079, // Intel 82546GB Copper
+ 0x107A, // Intel 82546GB Fiber
+ 0x107B, // Intel 82546GB SerDes
+ 0x107C, // Intel 82541PI
+ 0x108A, // Intel 82546GB PCI-E
+ 0x1099, // Intel 82546GB Quad Copper
+ 0x10B5, // Intel 82546GB Quad Copper KSP3
};
@@ -29,7 +67,7 @@ VOID NTAPI E1000WriteUlong(IN PE1000_ADAPTER Adapter, IN ULONG Address,
IN ULONG
NdisWriteRegisterUlong((PULONG)(Adapter->IoBase + Address), Value);
}
-static VOID E1000ReadUlong(IN PE1000_ADAPTER Adapter, IN ULONG Address, OUT PULONG
Value)
+VOID NTAPI E1000ReadUlong(IN PE1000_ADAPTER Adapter, IN ULONG Address, OUT PULONG Value)
{
NdisReadRegisterUlong((PULONG)(Adapter->IoBase + Address), Value);
}
@@ -99,6 +137,8 @@ static ULONG RcvBufRegisterMask(E1000_RCVBUF_SIZE BufSize)
return Mask;
}
+#if 0
+/* This function works, but the driver does not use PHY register access right now */
static BOOLEAN E1000ReadMdic(IN PE1000_ADAPTER Adapter, IN ULONG Address, USHORT
*Result)
{
ULONG ResultAddress;
@@ -147,11 +187,12 @@ static BOOLEAN E1000ReadMdic(IN PE1000_ADAPTER Adapter, IN ULONG
Address, USHORT
*Result = (USHORT) Mdic;
return TRUE;
}
+#endif
static BOOLEAN E1000ReadEeprom(IN PE1000_ADAPTER Adapter, IN UCHAR Address, USHORT
*Result)
{
- UINT Value;
+ ULONG Value;
UINT n;
E1000WriteUlong(Adapter, E1000_REG_EERD, E1000_EERD_START | ((UINT)Address <<
E1000_EERD_ADDR_SHIFT));
@@ -524,10 +565,9 @@ NICSoftReset(
ULONG Value, ResetAttempts;
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
- //em_get_hw_control(adapter);
-
NICDisableInterrupts(Adapter);
E1000WriteUlong(Adapter, E1000_REG_RCTL, 0);
+ E1000WriteUlong(Adapter, E1000_REG_TCTL, 0);
E1000ReadUlong(Adapter, E1000_REG_CTRL, &Value);
/* Write this using IO port, some devices cannot ack this otherwise */
E1000WriteIoUlong(Adapter, E1000_REG_CTRL, Value | E1000_CTRL_RST);
@@ -535,7 +575,8 @@ NICSoftReset(
for (ResetAttempts = 0; ResetAttempts < MAX_RESET_ATTEMPTS; ResetAttempts++)
{
- NdisStallExecution(100);
+ /* Wait 1us after reset (according to manual) */
+ NdisStallExecution(1);
E1000ReadUlong(Adapter, E1000_REG_CTRL, &Value);
if (!(Value & E1000_CTRL_RST))
@@ -543,11 +584,13 @@ NICSoftReset(
NDIS_DbgPrint(MAX_TRACE, ("Device is back (%u)\n",
ResetAttempts));
NICDisableInterrupts(Adapter);
- /* Clear out interrupts */
+ /* Clear out interrupts (the register is cleared upon read) */
E1000ReadUlong(Adapter, E1000_REG_ICR, &Value);
- //NdisWriteRegisterUlong(Adapter->IoBase + E1000_REG_WUFC, 0);
- //NdisWriteRegisterUlong(Adapter->IoBase + E1000_REG_VET,
E1000_VET_VLAN);
+ E1000ReadUlong(Adapter, E1000_REG_CTRL, &Value);
+ Value &= ~(E1000_CTRL_LRST|E1000_CTRL_VME);
+ Value |= (E1000_CTRL_ASDE|E1000_CTRL_SLU);
+ E1000WriteUlong(Adapter, E1000_REG_CTRL, Value);
return NDIS_STATUS_SUCCESS;
}
@@ -582,10 +625,13 @@ NICEnableTxRx(
E1000WriteUlong(Adapter, E1000_REG_TDT, 0);
Adapter->CurrentTxDesc = 0;
+ /* Set up interrupt timers */
+ E1000WriteUlong(Adapter, E1000_REG_TADV, 96); // value is in 1.024 of usec
+ E1000WriteUlong(Adapter, E1000_REG_TIDV, 16);
- Value = E1000_TCTL_EN | E1000_TCTL_PSP;
- E1000WriteUlong(Adapter, E1000_REG_TCTL, Value);
+ E1000WriteUlong(Adapter, E1000_REG_TCTL, E1000_TCTL_EN | E1000_TCTL_PSP);
+ E1000WriteUlong(Adapter, E1000_REG_TIPG, E1000_TIPG_IPGT_DEF | E1000_TIPG_IPGR1_DEF |
E1000_TIPG_IPGR2_DEF);
NDIS_DbgPrint(MID_TRACE, ("Setting up receive.\n"));
@@ -602,10 +648,10 @@ NICEnableTxRx(
/* Receive descriptor tail / head */
E1000WriteUlong(Adapter, E1000_REG_RDH, 0);
E1000WriteUlong(Adapter, E1000_REG_RDT, NUM_RECEIVE_DESCRIPTORS - 1);
- Adapter->CurrentRxDesc = 0;
- /* Setup Interrupt Throttling */
- E1000WriteUlong(Adapter, E1000_REG_ITR, DEFAULT_ITR);
+ /* Set up interrupt timers */
+ E1000WriteUlong(Adapter, E1000_REG_RADV, 96);
+ E1000WriteUlong(Adapter, E1000_REG_RDTR, 16);
/* Some defaults */
Value = E1000_RCTL_SECRC | E1000_RCTL_EN;
@@ -634,9 +680,9 @@ NICDisableTxRx(
Value &= ~E1000_TCTL_EN;
E1000WriteUlong(Adapter, E1000_REG_TCTL, Value);
- //E1000ReadUlong(Adapter, E1000_REG_RCTL, &Value);
- //Value &= ~E1000_RCTL_EN;
- //E1000WriteUlong(Adapter, E1000_REG_RCTL, Value);
+ E1000ReadUlong(Adapter, E1000_REG_RCTL, &Value);
+ Value &= ~E1000_RCTL_EN;
+ E1000WriteUlong(Adapter, E1000_REG_RCTL, Value);
return NDIS_STATUS_SUCCESS;
}
@@ -724,7 +770,7 @@ NICApplyInterruptMask(
{
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
- E1000WriteUlong(Adapter, E1000_REG_IMS, Adapter->InterruptMask);
+ E1000WriteUlong(Adapter, E1000_REG_IMS, Adapter->InterruptMask /*| 0x1F6DC*/);
return NDIS_STATUS_SUCCESS;
}
@@ -747,13 +793,13 @@ NICInterruptRecognized(
{
ULONG Value;
- NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
-
/* Reading the interrupt acknowledges them */
E1000ReadUlong(Adapter, E1000_REG_ICR, &Value);
*InterruptRecognized = (Value & Adapter->InterruptMask) != 0;
+ NDIS_DbgPrint(MAX_TRACE, ("NICInterruptRecognized(0x%x, 0x%x).\n", Value,
*InterruptRecognized));
+
return (Value & Adapter->InterruptMask);
}
@@ -762,55 +808,23 @@ NTAPI
NICUpdateLinkStatus(
IN PE1000_ADAPTER Adapter)
{
- ULONG SpeedIndex;
- USHORT PhyStatus;
+ ULONG DeviceStatus;
+ SIZE_T SpeedIndex;
static ULONG SpeedValues[] = { 10, 100, 1000, 1000 };
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
-#if 0
- /* This does not work */
- E1000ReadUlong(Adapter, E1000_REG_STATUS, &DeviceStatus);
E1000ReadUlong(Adapter, E1000_REG_STATUS, &DeviceStatus);
Adapter->MediaState = (DeviceStatus & E1000_STATUS_LU) ?
NdisMediaStateConnected : NdisMediaStateDisconnected;
SpeedIndex = (DeviceStatus & E1000_STATUS_SPEEDMASK) >>
E1000_STATUS_SPEEDSHIFT;
Adapter->LinkSpeedMbps = SpeedValues[SpeedIndex];
-#else
- /* Link bit can be sticky on some boards, read it twice */
- if (!E1000ReadMdic(Adapter, E1000_PHY_STATUS, &PhyStatus))
- NdisStallExecution(100);
-
- Adapter->MediaState = NdisMediaStateDisconnected;
- Adapter->LinkSpeedMbps = 0;
-
- if (!E1000ReadMdic(Adapter, E1000_PHY_STATUS, &PhyStatus))
- return;
-
- if (!(PhyStatus & E1000_PS_LINK_STATUS))
- return;
-
- Adapter->MediaState = NdisMediaStateConnected;
-
- if (E1000ReadMdic(Adapter, E1000_PHY_SPECIFIC_STATUS, &PhyStatus))
- {
- if (PhyStatus & E1000_PSS_SPEED_AND_DUPLEX)
- {
- SpeedIndex = (PhyStatus & E1000_PSS_SPEEDMASK) >>
E1000_PSS_SPEEDSHIFT;
- Adapter->LinkSpeedMbps = SpeedValues[SpeedIndex];
- }
- else
- {
- NDIS_DbgPrint(MIN_TRACE, ("Speed and duplex not yet resolved,
retry?.\n"));
- }
- }
-#endif
}
NDIS_STATUS
NTAPI
NICTransmitPacket(
IN PE1000_ADAPTER Adapter,
- IN ULONG PhysicalAddress,
+ IN PHYSICAL_ADDRESS PhysicalAddress,
IN ULONG Length)
{
volatile PE1000_TRANSMIT_DESCRIPTOR TransmitDescriptor;
@@ -818,10 +832,10 @@ NICTransmitPacket(
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
TransmitDescriptor = Adapter->TransmitDescriptors + Adapter->CurrentTxDesc;
- TransmitDescriptor->Address = PhysicalAddress;
+ TransmitDescriptor->Address = PhysicalAddress.QuadPart;
TransmitDescriptor->Length = Length;
TransmitDescriptor->ChecksumOffset = 0;
- TransmitDescriptor->Command = E1000_TDESC_CMD_RS | E1000_TDESC_CMD_IFCS |
E1000_TDESC_CMD_EOP;
+ TransmitDescriptor->Command = E1000_TDESC_CMD_RS | E1000_TDESC_CMD_IFCS |
E1000_TDESC_CMD_EOP | E1000_TDESC_CMD_IDE;
TransmitDescriptor->Status = 0;
TransmitDescriptor->ChecksumStartField = 0;
TransmitDescriptor->Special = 0;
@@ -830,8 +844,6 @@ NICTransmitPacket(
E1000WriteUlong(Adapter, E1000_REG_TDT, Adapter->CurrentTxDesc);
- NDIS_DbgPrint(MAX_TRACE, ("CurrentTxDesc:%u, LastTxDesc:%u\n",
Adapter->CurrentTxDesc, Adapter->LastTxDesc));
-
if (Adapter->CurrentTxDesc == Adapter->LastTxDesc)
{
NDIS_DbgPrint(MID_TRACE, ("All TX descriptors are full now\n"));
diff --git a/drivers/network/dd/e1000/info.c b/drivers/network/dd/e1000/info.c
index 2c98034fe6..e35e3d1b7e 100644
--- a/drivers/network/dd/e1000/info.c
+++ b/drivers/network/dd/e1000/info.c
@@ -2,8 +2,8 @@
* PROJECT: ReactOS Intel PRO/1000 Driver
* LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Miniport information callbacks
- * COPYRIGHT: Copyright 2013 Cameron Gutman (cameron.gutman(a)reactos.org)
- * Copyright 2018 Mark Jansen (mark.jansen(a)reactos.org)
+ * COPYRIGHT: 2013 Cameron Gutman (cameron.gutman(a)reactos.org)
+ * 2018 Mark Jansen (mark.jansen(a)reactos.org)
*/
#include "nic.h"
@@ -66,8 +66,6 @@ MiniportQueryInformation(
copySource = &genericUlong;
copyLength = sizeof(ULONG);
- NdisAcquireSpinLock(&Adapter->Lock);
-
switch (Oid)
{
case OID_GEN_SUPPORTED_LIST:
@@ -219,7 +217,6 @@ MiniportQueryInformation(
*BytesNeeded = 0;
}
- NdisReleaseSpinLock(&Adapter->Lock);
/* XMIT_ERROR and RCV_ERROR are really noisy, so do not log those. */
if (Oid != OID_GEN_XMIT_ERROR && Oid != OID_GEN_RCV_ERROR)
{
@@ -246,8 +243,6 @@ MiniportSetInformation(
status = NDIS_STATUS_SUCCESS;
- NdisAcquireSpinLock(&Adapter->Lock);
-
switch (Oid)
{
case OID_GEN_CURRENT_PACKET_FILTER:
@@ -343,8 +338,6 @@ MiniportSetInformation(
*BytesNeeded = 0;
}
- NdisReleaseSpinLock(&Adapter->Lock);
-
return status;
}
diff --git a/drivers/network/dd/e1000/interrupt.c b/drivers/network/dd/e1000/interrupt.c
index cd94e455e1..e3f1b83da9 100644
--- a/drivers/network/dd/e1000/interrupt.c
+++ b/drivers/network/dd/e1000/interrupt.c
@@ -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(a)reactos.org)
- * Copyright 2018 Mark Jansen (mark.jansen(a)reactos.org)
+ * COPYRIGHT: 2013 Cameron Gutman (cameron.gutman(a)reactos.org)
+ * 2018 Mark Jansen (mark.jansen(a)reactos.org)
+ * 2019 Victor Pereertkin (victor.perevertkin(a)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);
+ }
+ }
+
+ /* 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(Value == 0);
+ ASSERT(InterruptPending == 0);
}
diff --git a/drivers/network/dd/e1000/ndis.c b/drivers/network/dd/e1000/ndis.c
index 0df4f765f0..f73bf5e89d 100644
--- a/drivers/network/dd/e1000/ndis.c
+++ b/drivers/network/dd/e1000/ndis.c
@@ -10,7 +10,7 @@
#include <debug.h>
-ULONG DebugTraceLevel = DEBUG_ULTRA;
+ULONG DebugTraceLevel = MIN_TRACE;
NDIS_STATUS
NTAPI
@@ -33,40 +33,32 @@ MiniportSend(
PE1000_ADAPTER Adapter = (PE1000_ADAPTER)MiniportAdapterContext;
PSCATTER_GATHER_LIST sgList = NDIS_PER_PACKET_INFO_FROM_PACKET(Packet,
ScatterGatherListPacketInfo);
ULONG TransmitLength;
- ULONG TransmitBuffer;
+ PHYSICAL_ADDRESS TransmitBuffer;
NDIS_STATUS Status;
ASSERT(sgList != NULL);
ASSERT(sgList->NumberOfElements == 1);
- ASSERT(sgList->Elements[0].Address.HighPart == 0);
ASSERT((sgList->Elements[0].Address.LowPart & 3) == 0);
ASSERT(sgList->Elements[0].Length <= MAXIMUM_FRAME_SIZE);
- NDIS_DbgPrint(MAX_TRACE, ("Sending %d byte packet\n",
sgList->Elements[0].Length));
-
- NdisAcquireSpinLock(&Adapter->Lock);
-
if (Adapter->TxFull)
{
- NdisReleaseSpinLock(&Adapter->Lock);
NDIS_DbgPrint(MIN_TRACE, ("All TX descriptors are full\n"));
return NDIS_STATUS_RESOURCES;
}
TransmitLength = sgList->Elements[0].Length;
- TransmitBuffer = sgList->Elements[0].Address.LowPart;
+ TransmitBuffer = sgList->Elements[0].Address;
+ Adapter->TransmitPackets[Adapter->CurrentTxDesc] = Packet;
Status = NICTransmitPacket(Adapter, TransmitBuffer, TransmitLength);
if (Status != NDIS_STATUS_SUCCESS)
{
- NdisReleaseSpinLock(&Adapter->Lock);
NDIS_DbgPrint(MIN_TRACE, ("Transmit packet failed\n"));
return Status;
}
- NdisReleaseSpinLock(&Adapter->Lock);
-
- return NDIS_STATUS_SUCCESS;
+ return NDIS_STATUS_PENDING;
}
VOID
@@ -107,7 +99,6 @@ MiniportInitialize(
PNDIS_RESOURCE_LIST ResourceList;
UINT ResourceListSize;
PCI_COMMON_CONFIG PciConfig;
- //ULONG Value;
/* Make sure the medium is supported */
for (i = 0; i < MediumArraySize; i++)
@@ -137,8 +128,6 @@ MiniportInitialize(
RtlZeroMemory(Adapter, sizeof(*Adapter));
Adapter->AdapterHandle = MiniportAdapterHandle;
- NdisAllocateSpinLock(&Adapter->Lock);
-
/* Notify NDIS of some characteristics of our NIC */
NdisMSetAttributesEx(MiniportAdapterHandle,
@@ -219,7 +208,7 @@ MiniportInitialize(
/* Allocate the DMA resources */
Status = NdisMInitializeScatterGatherDma(MiniportAdapterHandle,
- FALSE, // 32bit
+ FALSE, // 64bit is supported but can be
buggy
MAXIMUM_FRAME_SIZE);
if (Status != NDIS_STATUS_SUCCESS)
{
diff --git a/drivers/network/dd/e1000/nic.h b/drivers/network/dd/e1000/nic.h
index be198701ed..c1bd82997f 100644
--- a/drivers/network/dd/e1000/nic.h
+++ b/drivers/network/dd/e1000/nic.h
@@ -1,9 +1,10 @@
/*
* PROJECT: ReactOS Intel PRO/1000 Driver
* LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
- * PURPOSE: Intel PRO/1000 driver definitions
- * COPYRIGHT: Copyright 2013 Cameron Gutman (cameron.gutman(a)reactos.org)
- * Copyright 2018 Mark Jansen (mark.jansen(a)reactos.org)
+ * PURPOSE: Hardware specific functions
+ * COPYRIGHT: 2013 Cameron Gutman (cameron.gutman(a)reactos.org)
+ * 2018 Mark Jansen (mark.jansen(a)reactos.org)
+ * 2019 Victor Perevertkin (victor.perevertkin(a)reactos.org)
*/
#ifndef _E1000_PCH_
@@ -15,17 +16,18 @@
#define E1000_TAG '001e'
-#define MAXIMUM_FRAME_SIZE 1522
-#define RECEIVE_BUFFER_SIZE 2048
+#define MAXIMUM_FRAME_SIZE 1522
+#define RECEIVE_BUFFER_SIZE 2048
#define DRIVER_VERSION 1
+#define DEFAULT_INTERRUPT_MASK (E1000_IMS_LSC | E1000_IMS_TXDW | E1000_IMS_TXQE |
E1000_IMS_RXDMT0 | E1000_IMS_RXT0 | E1000_IMS_TXD_LOW)
-#define DEFAULT_INTERRUPT_MASK (E1000_IMS_LSC | E1000_IMS_TXDW | E1000_IMS_RXDMT0 |
E1000_IMS_RXT0)
typedef struct _E1000_ADAPTER
{
- NDIS_SPIN_LOCK Lock;
+ // NDIS_SPIN_LOCK AdapterLock;
+
NDIS_HANDLE AdapterHandle;
USHORT VendorID;
USHORT DeviceID;
@@ -60,14 +62,16 @@ typedef struct _E1000_ADAPTER
NDIS_MINIPORT_INTERRUPT Interrupt;
BOOLEAN InterruptRegistered;
- ULONG InterruptMask;
- ULONG InterruptPending;
+ LONG InterruptMask;
+ LONG InterruptPending;
/* Transmit */
PE1000_TRANSMIT_DESCRIPTOR TransmitDescriptors;
NDIS_PHYSICAL_ADDRESS TransmitDescriptorsPa;
+ PNDIS_PACKET TransmitPackets[NUM_TRANSMIT_DESCRIPTORS];
+
ULONG CurrentTxDesc;
ULONG LastTxDesc;
BOOLEAN TxFull;
@@ -77,8 +81,6 @@ typedef struct _E1000_ADAPTER
PE1000_RECEIVE_DESCRIPTOR ReceiveDescriptors;
NDIS_PHYSICAL_ADDRESS ReceiveDescriptorsPa;
- ULONG CurrentRxDesc;
-
E1000_RCVBUF_SIZE ReceiveBufferType;
volatile PUCHAR ReceiveBuffer;
NDIS_PHYSICAL_ADDRESS ReceiveBufferPa;
@@ -179,7 +181,7 @@ NDIS_STATUS
NTAPI
NICTransmitPacket(
IN PE1000_ADAPTER Adapter,
- IN ULONG PhysicalAddress,
+ IN PHYSICAL_ADDRESS PhysicalAddress,
IN ULONG Length);
NDIS_STATUS
@@ -215,6 +217,13 @@ MiniportHandleInterrupt(
IN NDIS_HANDLE MiniportAdapterContext);
+VOID
+NTAPI
+E1000ReadUlong(
+ IN PE1000_ADAPTER Adapter,
+ IN ULONG Address,
+ OUT PULONG Value);
+
VOID
NTAPI
E1000WriteUlong(
@@ -222,6 +231,4 @@ E1000WriteUlong(
IN ULONG Address,
IN ULONG Value);
-
-
#endif /* _E1000_PCH_ */
diff --git a/media/inf/nete1000.inf b/media/inf/nete1000.inf
index ed47b46926..9b026154dc 100644
--- a/media/inf/nete1000.inf
+++ b/media/inf/nete1000.inf
@@ -1,4 +1,4 @@
-; NETRTL.INF
+; NETE1000.INF
; Installation file for Intel-based NICs
@@ -9,7 +9,7 @@ LayoutFile = layout.inf
Class = Net
ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318}
Provider = %ReactOS%
-DriverVer = 18/05/2018,1.00
+DriverVer = 22/01/2019,1.00
[DestinationDirs]
DefaultDestDir = 12
@@ -18,7 +18,43 @@ DefaultDestDir = 12
%IntelMfg% = IntelMfg
[IntelMfg]
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_1000
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_1001
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_1004
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_1008
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_1009
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_100A
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_100C
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_100D
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_100E
%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_100F
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_1010
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_1011
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_1012
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_1013
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_1014
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_1015
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_1016
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_1017
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_1018
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_1019
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_101A
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_101D
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_101E
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_1026
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_1027
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_1028
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_1075
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_1076
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_1077
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_1078
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_1079
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_107A
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_107B
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_107C
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_108A
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_1099
+%IntelE1000.DeviceDesc% = E1000_Inst.ndi,PCI\VEN_8086&DEV_10B5
;----------------------------- E1000 DRIVER -----------------------------