[E1000] Finished an implementation of the driver.
authorVictor Perevertkin <victor@perevertkin.ru>
Mon, 21 Jan 2019 21:44:25 +0000 (00:44 +0300)
committerMark Jansen <mark.jansen@reactos.org>
Thu, 7 Feb 2019 18:48:54 +0000 (19:48 +0100)
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
drivers/network/dd/e1000/hardware.c
drivers/network/dd/e1000/info.c
drivers/network/dd/e1000/interrupt.c
drivers/network/dd/e1000/ndis.c
drivers/network/dd/e1000/nic.h
media/inf/nete1000.inf

index b2293aa..994be06 100644 (file)
@@ -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@reactos.org)
+ * PURPOSE:     Hardware specific definitions
+ * COPYRIGHT:   2018 Mark Jansen (mark.jansen@reactos.org)
+ *              2019 Victor Perevertkin (victor.perevertkin@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)
-
index 0b7d8f0..aa5fc26 100644 (file)
@@ -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@reactos.org)
+ * COPYRIGHT:   2018 Mark Jansen (mark.jansen@reactos.org)
+ *              2019 Victor Perevertkin (victor.perevertkin@reactos.org)
  */
 
 #include "nic.h"
 
 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"));
index 2c98034..e35e3d1 100644 (file)
@@ -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@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)
  */
 
 #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;
 }
 
index cd94e45..e3f1b83 100644 (file)
@@ -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);
+        }
+    }
+
+    /* 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);
 }
index 0df4f76..f73bf5e 100644 (file)
@@ -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)
     {
index be19870..c1bd829 100644 (file)
@@ -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@reactos.org)
- *              Copyright 2018 Mark Jansen (mark.jansen@reactos.org)
+ * PURPOSE:     Hardware specific functions
+ * COPYRIGHT:   2013 Cameron Gutman (cameron.gutman@reactos.org)
+ *              2018 Mark Jansen (mark.jansen@reactos.org)
+ *              2019 Victor Perevertkin (victor.perevertkin@reactos.org)
  */
 
 #ifndef _E1000_PCH_
 
 #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_ */
index ed47b46..9b02615 100644 (file)
@@ -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 -----------------------------