diff --git a/drivers/network/dd/e1000/e1000hw.h b/drivers/network/dd/e1000/e1000hw.h index b2293aa0ba3..994be06067f 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@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) - diff --git a/drivers/network/dd/e1000/hardware.c b/drivers/network/dd/e1000/hardware.c index 0b7d8f0d1ff..aa5fc26896b 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@reactos.org) + * COPYRIGHT: 2018 Mark Jansen (mark.jansen@reactos.org) + * 2019 Victor Perevertkin (victor.perevertkin@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 2c98034fe64..e35e3d1b7e0 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@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; } diff --git a/drivers/network/dd/e1000/interrupt.c b/drivers/network/dd/e1000/interrupt.c index cd94e455e1e..e3f1b83da98 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@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); } diff --git a/drivers/network/dd/e1000/ndis.c b/drivers/network/dd/e1000/ndis.c index 0df4f765f0d..f73bf5e89dd 100644 --- a/drivers/network/dd/e1000/ndis.c +++ b/drivers/network/dd/e1000/ndis.c @@ -10,7 +10,7 @@ #include -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 be198701edd..c1bd82997fc 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@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_ @@ -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 ed47b46926b..9b026154dcb 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 -----------------------------