https://git.reactos.org/?p=reactos.git;a=commitdiff;h=3f97671319509df175dd5…
commit 3f97671319509df175dd5702d670aaa2ff8ea99a
Author:     Dmitry Borisov <di.sean(a)protonmail.com>
AuthorDate: Tue Dec 14 04:57:33 2021 +0600
Commit:     GitHub <noreply(a)github.com>
CommitDate: Tue Dec 14 01:57:33 2021 +0300
    [E1000] Minor improvements (#3904)
    - Add support for 64-bit counters (Intel gigabit NICs)
    - Properly handle OIDs
    - Check that the packet filter is not 0
    - Performance increase
---
 drivers/network/dd/e1000/CMakeLists.txt |   3 +-
 drivers/network/dd/e1000/hardware.c     | 107 +--------------------
 drivers/network/dd/e1000/info.c         | 158 +++++++++++++++++++++-----------
 drivers/network/dd/e1000/interrupt.c    |  29 ++++--
 drivers/network/dd/e1000/ndis.c         |  45 +--------
 drivers/network/dd/e1000/nic.h          |  93 ++++++++++++-------
 drivers/network/dd/e1000/send.c         |  85 +++++++++++++++++
 7 files changed, 274 insertions(+), 246 deletions(-)
diff --git a/drivers/network/dd/e1000/CMakeLists.txt
b/drivers/network/dd/e1000/CMakeLists.txt
index 8bb4aa25ccf..cd67a525a9d 100644
--- a/drivers/network/dd/e1000/CMakeLists.txt
+++ b/drivers/network/dd/e1000/CMakeLists.txt
@@ -12,7 +12,8 @@ list(APPEND SOURCE
     nic.h
     e1000hw.h
     debug.c
-    debug.h)
+    debug.h
+    send.c)
 add_library(e1000 MODULE ${SOURCE} e1000.rc)
 add_pch(e1000 nic.h SOURCE)
diff --git a/drivers/network/dd/e1000/hardware.c b/drivers/network/dd/e1000/hardware.c
index aa5fc26896b..c0c41ce9403 100644
--- a/drivers/network/dd/e1000/hardware.c
+++ b/drivers/network/dd/e1000/hardware.c
@@ -53,32 +53,6 @@ static USHORT SupportedDevices[] =
     0x10B5,     // Intel 82546GB Quad Copper KSP3
 };
-
-static ULONG E1000WriteFlush(IN PE1000_ADAPTER Adapter)
-{
-    volatile ULONG Value;
-
-    NdisReadRegisterUlong(Adapter->IoBase + E1000_REG_STATUS, &Value);
-    return Value;
-}
-
-VOID NTAPI E1000WriteUlong(IN PE1000_ADAPTER Adapter, IN ULONG Address, IN ULONG Value)
-{
-    NdisWriteRegisterUlong((PULONG)(Adapter->IoBase + Address), Value);
-}
-
-VOID NTAPI E1000ReadUlong(IN PE1000_ADAPTER Adapter, IN ULONG Address, OUT PULONG Value)
-{
-    NdisReadRegisterUlong((PULONG)(Adapter->IoBase + Address), Value);
-}
-
-static VOID E1000WriteIoUlong(IN PE1000_ADAPTER Adapter, IN ULONG Address, IN ULONG
Value)
-{
-    NdisRawWritePortUlong((PULONG)(Adapter->IoPort), Address);
-    E1000WriteFlush(Adapter);
-    NdisRawWritePortUlong((PULONG)(Adapter->IoPort + 4), Value);
-}
-
 static ULONG PacketFilterToMask(ULONG PacketFilter)
 {
     ULONG FilterMask = 0;
@@ -145,16 +119,11 @@ static BOOLEAN E1000ReadMdic(IN PE1000_ADAPTER Adapter, IN ULONG
Address, USHORT
     ULONG Mdic;
     UINT n;
-    if (Address > MAX_PHY_REG_ADDRESS)
-    {
-        NDIS_DbgPrint(MIN_TRACE, ("PHY Address %d is invalid\n", Address));
-        return 1;
-    }
+    ASSERT(Address <= MAX_PHY_REG_ADDRESS)
     Mdic = (Address << E1000_MDIC_REGADD_SHIFT);
     Mdic |= (E1000_MDIC_PHYADD_GIGABIT << E1000_MDIC_PHYADD_SHIFT);
     Mdic |= E1000_MDIC_OP_READ;
-
     E1000WriteUlong(Adapter, E1000_REG_MDIC, Mdic);
     for (n = 0; n < MAX_PHY_READ_ATTEMPTS; n++)
@@ -725,6 +694,7 @@ NICUpdateMulticastList(
     UINT n;
     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+    // FIXME: Use 'Adapter->MulticastListSize'? Check the datasheet
     for (n = 0; n < MAXIMUM_MULTICAST_ADDRESSES; ++n)
     {
         ULONG Ral = *(ULONG *)Adapter->MulticastList[n].MacAddress;
@@ -763,46 +733,6 @@ NICApplyPacketFilter(
     return NDIS_STATUS_SUCCESS;
 }
-NDIS_STATUS
-NTAPI
-NICApplyInterruptMask(
-    IN PE1000_ADAPTER Adapter)
-{
-    NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
-
-    E1000WriteUlong(Adapter, E1000_REG_IMS, Adapter->InterruptMask /*| 0x1F6DC*/);
-    return NDIS_STATUS_SUCCESS;
-}
-
-NDIS_STATUS
-NTAPI
-NICDisableInterrupts(
-    IN PE1000_ADAPTER Adapter)
-{
-    NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
-
-    E1000WriteUlong(Adapter, E1000_REG_IMC, ~0);
-    return NDIS_STATUS_SUCCESS;
-}
-
-ULONG
-NTAPI
-NICInterruptRecognized(
-    IN PE1000_ADAPTER Adapter,
-    OUT PBOOLEAN InterruptRecognized)
-{
-    ULONG Value;
-
-    /* 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);
-}
-
 VOID
 NTAPI
 NICUpdateLinkStatus(
@@ -819,36 +749,3 @@ NICUpdateLinkStatus(
     SpeedIndex = (DeviceStatus & E1000_STATUS_SPEEDMASK) >>
E1000_STATUS_SPEEDSHIFT;
     Adapter->LinkSpeedMbps = SpeedValues[SpeedIndex];
 }
-
-NDIS_STATUS
-NTAPI
-NICTransmitPacket(
-    IN PE1000_ADAPTER Adapter,
-    IN PHYSICAL_ADDRESS PhysicalAddress,
-    IN ULONG Length)
-{
-    volatile PE1000_TRANSMIT_DESCRIPTOR TransmitDescriptor;
-
-    NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
-
-    TransmitDescriptor = Adapter->TransmitDescriptors + Adapter->CurrentTxDesc;
-    TransmitDescriptor->Address = PhysicalAddress.QuadPart;
-    TransmitDescriptor->Length = Length;
-    TransmitDescriptor->ChecksumOffset = 0;
-    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;
-
-    Adapter->CurrentTxDesc = (Adapter->CurrentTxDesc + 1) %
NUM_TRANSMIT_DESCRIPTORS;
-
-    E1000WriteUlong(Adapter, E1000_REG_TDT, Adapter->CurrentTxDesc);
-
-    if (Adapter->CurrentTxDesc == Adapter->LastTxDesc)
-    {
-        NDIS_DbgPrint(MID_TRACE, ("All TX descriptors are full now\n"));
-        Adapter->TxFull = TRUE;
-    }
-
-    return NDIS_STATUS_SUCCESS;
-}
diff --git a/drivers/network/dd/e1000/info.c b/drivers/network/dd/e1000/info.c
index 42b7fe8f2c8..9a5b632d56c 100644
--- a/drivers/network/dd/e1000/info.c
+++ b/drivers/network/dd/e1000/info.c
@@ -10,7 +10,7 @@
 #include <debug.h>
-static ULONG SupportedOidList[] =
+static NDIS_OID SupportedOidList[] =
 {
     OID_GEN_SUPPORTED_LIST,
     OID_GEN_CURRENT_PACKET_FILTER,
@@ -37,14 +37,36 @@ static ULONG SupportedOidList[] =
     OID_802_3_PERMANENT_ADDRESS,
     OID_802_3_CURRENT_ADDRESS,
     OID_802_3_MAXIMUM_LIST_SIZE,
+
     /* Statistics */
     OID_GEN_XMIT_OK,
     OID_GEN_RCV_OK,
     OID_GEN_XMIT_ERROR,
     OID_GEN_RCV_ERROR,
     OID_GEN_RCV_NO_BUFFER,
+
+    OID_PNP_CAPABILITIES,
 };
+static
+ULONG64
+NICQueryStatisticCounter(
+    _In_ PE1000_ADAPTER Adapter,
+    _In_ NDIS_OID Oid)
+{
+    /* TODO */
+    return 0;
+}
+
+static
+NDIS_STATUS
+NICFillPowerManagementCapabilities(
+    _In_ PE1000_ADAPTER Adapter,
+    _Out_ PNDIS_PNP_CAPABILITIES Capabilities)
+{
+    /* TODO */
+    return NDIS_STATUS_NOT_SUPPORTED;
+}
 NDIS_STATUS
 NTAPI
@@ -57,13 +79,20 @@ MiniportQueryInformation(
     OUT PULONG BytesNeeded)
 {
     PE1000_ADAPTER Adapter = (PE1000_ADAPTER)MiniportAdapterContext;
-    ULONG genericUlong;
     ULONG copyLength;
     PVOID copySource;
     NDIS_STATUS status;
+    union _GENERIC_INFORMATION
+    {
+        USHORT Ushort;
+        ULONG Ulong;
+        ULONG64 Ulong64;
+        NDIS_MEDIUM Medium;
+        NDIS_PNP_CAPABILITIES PmCapabilities;
+    } GenericInfo;
     status = NDIS_STATUS_SUCCESS;
-    copySource = &genericUlong;
+    copySource = &GenericInfo;
     copyLength = sizeof(ULONG);
     switch (Oid)
@@ -74,20 +103,19 @@ MiniportQueryInformation(
         break;
     case OID_GEN_CURRENT_PACKET_FILTER:
-        genericUlong = Adapter->PacketFilter;
+        GenericInfo.Ulong = Adapter->PacketFilter;
         break;
     case OID_GEN_HARDWARE_STATUS:
         UNIMPLEMENTED_DBGBREAK();
-        genericUlong = (ULONG)NdisHardwareStatusReady; //FIXME
+        GenericInfo.Ulong = (ULONG)NdisHardwareStatusReady; //FIXME
         break;
     case OID_GEN_MEDIA_SUPPORTED:
     case OID_GEN_MEDIA_IN_USE:
     {
-        static const NDIS_MEDIUM medium = NdisMedium802_3;
-        copySource = (PVOID)&medium;
-        copyLength = sizeof(medium);
+        GenericInfo.Medium = NdisMedium802_3;
+        copyLength = sizeof(NDIS_MEDIUM);
         break;
     }
@@ -96,31 +124,36 @@ MiniportQueryInformation(
     case OID_GEN_CURRENT_LOOKAHEAD:
     case OID_GEN_MAXIMUM_LOOKAHEAD:
     case OID_GEN_MAXIMUM_FRAME_SIZE:
-        genericUlong = MAXIMUM_FRAME_SIZE - sizeof(ETH_HEADER);
+        GenericInfo.Ulong = MAXIMUM_FRAME_SIZE - sizeof(ETH_HEADER);
+        break;
+
+    case OID_802_3_MULTICAST_LIST:
+        copySource = Adapter->MulticastList;
+        copyLength = Adapter->MulticastListSize * IEEE_802_ADDR_LENGTH;
         break;
     case OID_802_3_MAXIMUM_LIST_SIZE:
-        genericUlong = MAXIMUM_MULTICAST_ADDRESSES;
+        GenericInfo.Ulong = MAXIMUM_MULTICAST_ADDRESSES;
         break;
     case OID_GEN_LINK_SPEED:
-        genericUlong = Adapter->LinkSpeedMbps * 10000;
+        GenericInfo.Ulong = Adapter->LinkSpeedMbps * 10000;
         break;
     case OID_GEN_TRANSMIT_BUFFER_SPACE:
-        genericUlong = MAXIMUM_FRAME_SIZE;
+        GenericInfo.Ulong = MAXIMUM_FRAME_SIZE;
         break;
     case OID_GEN_RECEIVE_BUFFER_SPACE:
-        genericUlong = RECEIVE_BUFFER_SIZE;
+        GenericInfo.Ulong = RECEIVE_BUFFER_SIZE;
         break;
     case OID_GEN_VENDOR_ID:
         /* The 3 bytes of the MAC address is the vendor ID */
-        genericUlong = 0;
-        genericUlong |= (Adapter->PermanentMacAddress[0] << 16);
-        genericUlong |= (Adapter->PermanentMacAddress[1] << 8);
-        genericUlong |= (Adapter->PermanentMacAddress[2] & 0xFF);
+        GenericInfo.Ulong = 0;
+        GenericInfo.Ulong |= (Adapter->PermanentMacAddress[0] << 16);
+        GenericInfo.Ulong |= (Adapter->PermanentMacAddress[1] << 8);
+        GenericInfo.Ulong |= (Adapter->PermanentMacAddress[2] & 0xFF);
         break;
     case OID_GEN_VENDOR_DESCRIPTION:
@@ -132,38 +165,35 @@ MiniportQueryInformation(
     }
     case OID_GEN_VENDOR_DRIVER_VERSION:
-        genericUlong = DRIVER_VERSION;
+        GenericInfo.Ulong = DRIVER_VERSION;
         break;
     case OID_GEN_DRIVER_VERSION:
     {
-        static const USHORT driverVersion =
-            (NDIS_MINIPORT_MAJOR_VERSION << 8) + NDIS_MINIPORT_MINOR_VERSION;
-        copySource = (PVOID)&driverVersion;
-        copyLength = sizeof(driverVersion);
+        copyLength = sizeof(USHORT);
+        GenericInfo.Ushort = (NDIS_MINIPORT_MAJOR_VERSION << 8) +
NDIS_MINIPORT_MINOR_VERSION;
         break;
     }
     case OID_GEN_MAXIMUM_TOTAL_SIZE:
-        genericUlong = MAXIMUM_FRAME_SIZE;
+        GenericInfo.Ulong = MAXIMUM_FRAME_SIZE;
         break;
     case OID_GEN_MAXIMUM_SEND_PACKETS:
-        genericUlong = 1;
+        GenericInfo.Ulong = 1;
         break;
     case OID_GEN_MAC_OPTIONS:
-        genericUlong = NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
+        GenericInfo.Ulong = NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
             NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
             NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
             NDIS_MAC_OPTION_NO_LOOPBACK;
         break;
     case OID_GEN_MEDIA_CONNECT_STATUS:
-        genericUlong = Adapter->MediaState;
+        GenericInfo.Ulong = Adapter->MediaState;
         break;
-
     case OID_802_3_CURRENT_ADDRESS:
         copySource = Adapter->MulticastList[0].MacAddress;
         copyLength = IEEE_802_ADDR_LENGTH;
@@ -175,20 +205,39 @@ MiniportQueryInformation(
         break;
     case OID_GEN_XMIT_OK:
-        genericUlong = 0;
-        break;
     case OID_GEN_RCV_OK:
-        genericUlong = 0;
-        break;
     case OID_GEN_XMIT_ERROR:
-        genericUlong = 0;
-        break;
     case OID_GEN_RCV_ERROR:
-        genericUlong = 0;
-        break;
     case OID_GEN_RCV_NO_BUFFER:
-        genericUlong = 0;
+    {
+        GenericInfo.Ulong64 = NICQueryStatisticCounter(Adapter, Oid);
+
+        *BytesNeeded = sizeof(ULONG64);
+        if (InformationBufferLength >= sizeof(ULONG64))
+        {
+            *BytesWritten = sizeof(ULONG64);
+            NdisMoveMemory(InformationBuffer, copySource, sizeof(ULONG64));
+        }
+        else if (InformationBufferLength >= sizeof(ULONG))
+        {
+            *BytesWritten = sizeof(ULONG);
+            NdisMoveMemory(InformationBuffer, copySource, sizeof(ULONG));
+        }
+        else
+        {
+            *BytesWritten = 0;
+            return NDIS_STATUS_BUFFER_TOO_SHORT;
+        }
+        return NDIS_STATUS_SUCCESS;
+    }
+
+    case OID_PNP_CAPABILITIES:
+    {
+        copyLength = sizeof(NDIS_PNP_CAPABILITIES);
+
+        status = NICFillPowerManagementCapabilities(Adapter,
&GenericInfo.PmCapabilities);
         break;
+    }
     default:
         NDIS_DbgPrint(MIN_TRACE, ("Unknown OID 0x%x(%s)\n", Oid,
Oid2Str(Oid)));
@@ -202,7 +251,7 @@ MiniportQueryInformation(
         {
             *BytesNeeded = copyLength;
             *BytesWritten = 0;
-            status = NDIS_STATUS_INVALID_LENGTH;
+            status = NDIS_STATUS_BUFFER_TOO_SHORT;
         }
         else
         {
@@ -217,13 +266,8 @@ MiniportQueryInformation(
         *BytesNeeded = 0;
     }
-    /* XMIT_ERROR and RCV_ERROR are really noisy, so do not log those. */
-    if (Oid != OID_GEN_XMIT_ERROR && Oid != OID_GEN_RCV_ERROR)
-    {
-        NDIS_DbgPrint(MAX_TRACE, ("Query OID 0x%x(%s): Completed with status 0x%x
(%d, %d)\n",
-                                  Oid, Oid2Str(Oid), status, *BytesWritten,
*BytesNeeded));
-    }
-
+    NDIS_DbgPrint(MAX_TRACE, ("Query OID 0x%x(%s): Completed with status 0x%x (%d,
%d)\n",
+                              Oid, Oid2Str(Oid), status, *BytesWritten, *BytesNeeded));
     return status;
 }
@@ -257,12 +301,12 @@ MiniportSetInformation(
         NdisMoveMemory(&genericUlong, InformationBuffer, sizeof(ULONG));
         if (genericUlong &
-            (NDIS_PACKET_TYPE_SOURCE_ROUTING |
-             NDIS_PACKET_TYPE_SMT |
-             NDIS_PACKET_TYPE_ALL_LOCAL |
-             NDIS_PACKET_TYPE_GROUP |
-             NDIS_PACKET_TYPE_ALL_FUNCTIONAL |
-             NDIS_PACKET_TYPE_FUNCTIONAL))
+            ~(NDIS_PACKET_TYPE_DIRECTED |
+              NDIS_PACKET_TYPE_MULTICAST |
+              NDIS_PACKET_TYPE_ALL_MULTICAST |
+              NDIS_PACKET_TYPE_BROADCAST |
+              NDIS_PACKET_TYPE_PROMISCUOUS |
+              NDIS_PACKET_TYPE_MAC_FRAME))
         {
             *BytesRead = sizeof(ULONG);
             *BytesNeeded = sizeof(ULONG);
@@ -270,6 +314,11 @@ MiniportSetInformation(
             break;
         }
+        if (Adapter->PacketFilter == genericUlong)
+        {
+            break;
+        }
+
         Adapter->PacketFilter = genericUlong;
         status = NICApplyPacketFilter(Adapter);
@@ -312,15 +361,18 @@ MiniportSetInformation(
             break;
         }
-        if (InformationBufferLength / 6 > MAXIMUM_MULTICAST_ADDRESSES)
+        if (InformationBufferLength > sizeof(Adapter->MulticastList))
         {
-            *BytesNeeded = MAXIMUM_MULTICAST_ADDRESSES * IEEE_802_ADDR_LENGTH;
+            *BytesNeeded = sizeof(Adapter->MulticastList);
             *BytesRead = 0;
-            status = NDIS_STATUS_INVALID_LENGTH;
+            status = NDIS_STATUS_MULTICAST_FULL;
             break;
         }
         NdisMoveMemory(Adapter->MulticastList, InformationBuffer,
InformationBufferLength);
+
+        Adapter->MulticastListSize = InformationBufferLength / IEEE_802_ADDR_LENGTH;
+
         NICUpdateMulticastList(Adapter);
         break;
diff --git a/drivers/network/dd/e1000/interrupt.c b/drivers/network/dd/e1000/interrupt.c
index e3f1b83da98..e4ab64d353f 100644
--- a/drivers/network/dd/e1000/interrupt.c
+++ b/drivers/network/dd/e1000/interrupt.c
@@ -21,18 +21,24 @@ MiniportISR(
     ULONG Value;
     PE1000_ADAPTER Adapter = (PE1000_ADAPTER)MiniportAdapterContext;
-    Value = NICInterruptRecognized(Adapter, InterruptRecognized);
-    InterlockedOr(&Adapter->InterruptPending, Value);
+    /* Reading the interrupt acknowledges them */
+    E1000ReadUlong(Adapter, E1000_REG_ICR, &Value);
-    if (!(*InterruptRecognized))
+    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;
-        return;
     }
-
-    /* Mark the events pending service */
-    *QueueMiniportHandleInterrupt = TRUE;
 }
 VOID
@@ -46,7 +52,7 @@ MiniportHandleInterrupt(
     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
-    InterruptPending = InterlockedExchange(&Adapter->InterruptPending, 0);
+    InterruptPending = _InterlockedExchange(&Adapter->InterruptPending, 0);
     /* Link State Changed */
@@ -101,6 +107,12 @@ MiniportHandleInterrupt(
                 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);
@@ -120,6 +132,7 @@ MiniportHandleInterrupt(
                 NDIS_DbgPrint(MIN_TRACE, ("Got a NULL descriptor"));
             }
+NextReceiveDescriptor:
             /* Give the descriptor back */
             ReceiveDescriptor->Status = 0;
diff --git a/drivers/network/dd/e1000/ndis.c b/drivers/network/dd/e1000/ndis.c
index d6074cb5a2c..fedbd8ec4bb 100644
--- a/drivers/network/dd/e1000/ndis.c
+++ b/drivers/network/dd/e1000/ndis.c
@@ -23,44 +23,6 @@ MiniportReset(
     return NDIS_STATUS_FAILURE;
 }
-NDIS_STATUS
-NTAPI
-MiniportSend(
-    IN NDIS_HANDLE MiniportAdapterContext,
-    IN PNDIS_PACKET Packet,
-    IN UINT Flags)
-{
-    PE1000_ADAPTER Adapter = (PE1000_ADAPTER)MiniportAdapterContext;
-    PSCATTER_GATHER_LIST sgList = NDIS_PER_PACKET_INFO_FROM_PACKET(Packet,
ScatterGatherListPacketInfo);
-    ULONG TransmitLength;
-    PHYSICAL_ADDRESS TransmitBuffer;
-    NDIS_STATUS Status;
-
-    ASSERT(sgList != NULL);
-    ASSERT(sgList->NumberOfElements == 1);
-    ASSERT((sgList->Elements[0].Address.LowPart & 3) == 0);
-    ASSERT(sgList->Elements[0].Length <= MAXIMUM_FRAME_SIZE);
-
-    if (Adapter->TxFull)
-    {
-        NDIS_DbgPrint(MIN_TRACE, ("All TX descriptors are full\n"));
-        return NDIS_STATUS_RESOURCES;
-    }
-
-    TransmitLength = sgList->Elements[0].Length;
-    TransmitBuffer = sgList->Elements[0].Address;
-    Adapter->TransmitPackets[Adapter->CurrentTxDesc] = Packet;
-
-    Status = NICTransmitPacket(Adapter, TransmitBuffer, TransmitLength);
-    if (Status != NDIS_STATUS_SUCCESS)
-    {
-        NDIS_DbgPrint(MIN_TRACE, ("Transmit packet failed\n"));
-        return Status;
-    }
-
-    return NDIS_STATUS_PENDING;
-}
-
 VOID
 NTAPI
 MiniportHalt(
@@ -264,12 +226,7 @@ MiniportInitialize(
     /* Enable interrupts on the NIC */
     Adapter->InterruptMask = DEFAULT_INTERRUPT_MASK;
-    Status = NICApplyInterruptMask(Adapter);
-    if (Status != NDIS_STATUS_SUCCESS)
-    {
-        NDIS_DbgPrint(MIN_TRACE, ("Unable to apply interrupt mask (0x%x)\n",
Status));
-        goto Cleanup;
-    }
+    NICApplyInterruptMask(Adapter);
     /* Turn on TX and RX now */
     Status = NICEnableTxRx(Adapter);
diff --git a/drivers/network/dd/e1000/nic.h b/drivers/network/dd/e1000/nic.h
index c1bd82997fc..32b1c888b7f 100644
--- a/drivers/network/dd/e1000/nic.h
+++ b/drivers/network/dd/e1000/nic.h
@@ -26,6 +26,11 @@
 typedef struct _E1000_ADAPTER
 {
+    /* NIC Memory */
+    volatile PUCHAR IoBase;
+    NDIS_PHYSICAL_ADDRESS IoAddress;
+    ULONG IoLength;
+
     // NDIS_SPIN_LOCK AdapterLock;
     NDIS_HANDLE AdapterHandle;
@@ -35,9 +40,11 @@ typedef struct _E1000_ADAPTER
     USHORT SubsystemVendorID;
     UCHAR PermanentMacAddress[IEEE_802_ADDR_LENGTH];
+
     struct {
         UCHAR MacAddress[IEEE_802_ADDR_LENGTH];
     } MulticastList[MAXIMUM_MULTICAST_ADDRESSES];
+    ULONG MulticastListSize;
     ULONG LinkSpeedMbps;
     ULONG MediaState;
@@ -48,11 +55,6 @@ typedef struct _E1000_ADAPTER
     ULONG IoPortLength;
     volatile PUCHAR IoPort;
-    /* NIC Memory */
-    NDIS_PHYSICAL_ADDRESS IoAddress;
-    ULONG IoLength;
-    volatile PUCHAR IoBase;
-
     /* Interrupt */
     ULONG InterruptVector;
     ULONG InterruptLevel;
@@ -63,7 +65,9 @@ typedef struct _E1000_ADAPTER
     BOOLEAN InterruptRegistered;
     LONG InterruptMask;
-    LONG InterruptPending;
+
+    _Interlocked_
+    volatile LONG InterruptPending;
     /* Transmit */
@@ -156,22 +160,6 @@ NTAPI
 NICApplyPacketFilter(
     IN PE1000_ADAPTER Adapter);
-NDIS_STATUS
-NTAPI
-NICApplyInterruptMask(
-    IN PE1000_ADAPTER Adapter);
-
-NDIS_STATUS
-NTAPI
-NICDisableInterrupts(
-    IN PE1000_ADAPTER Adapter);
-
-ULONG
-NTAPI
-NICInterruptRecognized(
-    IN PE1000_ADAPTER Adapter,
-    OUT PBOOLEAN InterruptRecognized);
-
 VOID
 NTAPI
 NICUpdateLinkStatus(
@@ -179,10 +167,10 @@ NICUpdateLinkStatus(
 NDIS_STATUS
 NTAPI
-NICTransmitPacket(
-    IN PE1000_ADAPTER Adapter,
-    IN PHYSICAL_ADDRESS PhysicalAddress,
-    IN ULONG Length);
+MiniportSend(
+    _In_ NDIS_HANDLE MiniportAdapterContext,
+    _In_ PNDIS_PACKET Packet,
+    _In_ UINT Flags);
 NDIS_STATUS
 NTAPI
@@ -216,19 +204,54 @@ NTAPI
 MiniportHandleInterrupt(
     IN NDIS_HANDLE MiniportAdapterContext);
-
+FORCEINLINE
 VOID
-NTAPI
 E1000ReadUlong(
-    IN PE1000_ADAPTER Adapter,
-    IN ULONG Address,
-    OUT PULONG Value);
+    _In_ PE1000_ADAPTER Adapter,
+    _In_ ULONG Address,
+    _Out_ PULONG Value)
+{
+    NdisReadRegisterUlong((PULONG)(Adapter->IoBase + Address), Value);
+}
+FORCEINLINE
 VOID
-NTAPI
 E1000WriteUlong(
-    IN PE1000_ADAPTER Adapter,
-    IN ULONG Address,
-    IN ULONG Value);
+    _In_ PE1000_ADAPTER Adapter,
+    _In_ ULONG Address,
+    _In_ ULONG Value)
+{
+    NdisWriteRegisterUlong((PULONG)(Adapter->IoBase + Address), Value);
+}
+
+FORCEINLINE
+VOID
+E1000WriteIoUlong(
+    _In_ PE1000_ADAPTER Adapter,
+    _In_ ULONG Address,
+    _In_ ULONG Value)
+{
+    volatile ULONG Dummy;
+
+    NdisRawWritePortUlong((PULONG)(Adapter->IoPort), Address);
+    NdisReadRegisterUlong(Adapter->IoBase + E1000_REG_STATUS, &Dummy);
+    NdisRawWritePortUlong((PULONG)(Adapter->IoPort + 4), Value);
+}
+
+FORCEINLINE
+VOID
+NICApplyInterruptMask(
+    _In_ PE1000_ADAPTER Adapter)
+{
+    E1000WriteUlong(Adapter, E1000_REG_IMS, Adapter->InterruptMask /*| 0x1F6DC*/);
+}
+
+FORCEINLINE
+VOID
+NICDisableInterrupts(
+    _In_ PE1000_ADAPTER Adapter)
+{
+    E1000WriteUlong(Adapter, E1000_REG_IMC, ~0);
+}
 #endif /* _E1000_PCH_ */
diff --git a/drivers/network/dd/e1000/send.c b/drivers/network/dd/e1000/send.c
new file mode 100644
index 00000000000..990e8b313d2
--- /dev/null
+++ b/drivers/network/dd/e1000/send.c
@@ -0,0 +1,85 @@
+/*
+ * PROJECT:     ReactOS Intel PRO/1000 Driver
+ * LICENSE:     GPL-2.0-or-later (
https://spdx.org/licenses/GPL-2.0-or-later.html)
+ * PURPOSE:     Sending packets
+ * COPYRIGHT:   Copyright 2018 Mark Jansen <mark.jansen(a)reactos.org>
+ *              Copyright 2019 Victor Perevertkin <victor.perevertkin(a)reactos.org>
+ */
+
+#include "nic.h"
+
+#include <debug.h>
+
+static
+NDIS_STATUS
+NICTransmitPacket(
+    _In_ PE1000_ADAPTER Adapter,
+    _In_ PHYSICAL_ADDRESS PhysicalAddress,
+    _In_ ULONG Length)
+{
+    volatile PE1000_TRANSMIT_DESCRIPTOR TransmitDescriptor;
+
+    NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+    TransmitDescriptor = Adapter->TransmitDescriptors + Adapter->CurrentTxDesc;
+    TransmitDescriptor->Address = PhysicalAddress.QuadPart;
+    TransmitDescriptor->Length = Length;
+    TransmitDescriptor->ChecksumOffset = 0;
+    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;
+
+    Adapter->CurrentTxDesc = (Adapter->CurrentTxDesc + 1) %
NUM_TRANSMIT_DESCRIPTORS;
+
+    E1000WriteUlong(Adapter, E1000_REG_TDT, Adapter->CurrentTxDesc);
+
+    if (Adapter->CurrentTxDesc == Adapter->LastTxDesc)
+    {
+        NDIS_DbgPrint(MID_TRACE, ("All TX descriptors are full now\n"));
+        Adapter->TxFull = TRUE;
+    }
+
+    return NDIS_STATUS_SUCCESS;
+}
+
+NDIS_STATUS
+NTAPI
+MiniportSend(
+    _In_ NDIS_HANDLE MiniportAdapterContext,
+    _In_ PNDIS_PACKET Packet,
+    _In_ UINT Flags)
+{
+    PE1000_ADAPTER Adapter = (PE1000_ADAPTER)MiniportAdapterContext;
+    PSCATTER_GATHER_LIST sgList;
+    ULONG TransmitLength;
+    PHYSICAL_ADDRESS TransmitBuffer;
+    NDIS_STATUS Status;
+
+    sgList = NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, ScatterGatherListPacketInfo);
+
+    ASSERT(sgList != NULL);
+    ASSERT(sgList->NumberOfElements == 1);
+    ASSERT((sgList->Elements[0].Address.LowPart & 3) == 0);
+    ASSERT(sgList->Elements[0].Length <= MAXIMUM_FRAME_SIZE);
+
+    if (Adapter->TxFull)
+    {
+        NDIS_DbgPrint(MIN_TRACE, ("All TX descriptors are full\n"));
+        return NDIS_STATUS_RESOURCES;
+    }
+
+    TransmitLength = sgList->Elements[0].Length;
+    TransmitBuffer = sgList->Elements[0].Address;
+    Adapter->TransmitPackets[Adapter->CurrentTxDesc] = Packet;
+
+    Status = NICTransmitPacket(Adapter, TransmitBuffer, TransmitLength);
+    if (Status != NDIS_STATUS_SUCCESS)
+    {
+        NDIS_DbgPrint(MIN_TRACE, ("Transmit packet failed\n"));
+        return Status;
+    }
+
+    return NDIS_STATUS_PENDING;
+}