https://git.reactos.org/?p=reactos.git;a=commitdiff;h=d9b0601ceb6ec4d5834678...
commit d9b0601ceb6ec4d5834678a561167d2e78c3a368 Author: Mark Jansen mark.jansen@reactos.org AuthorDate: Mon May 28 00:09:10 2018 +0200 Commit: Mark Jansen mark.jansen@reactos.org CommitDate: Thu Feb 7 19:48:54 2019 +0100
[E1000] Basic initialization of the card Initialize some registers, allocate basic resources
CORE-14675 --- drivers/network/dd/e1000/CMakeLists.txt | 1 + drivers/network/dd/e1000/debug.c | 167 ++++++++++++ drivers/network/dd/e1000/debug.h | 2 + drivers/network/dd/e1000/e1000hw.h | 100 +++++++ drivers/network/dd/e1000/hardware.c | 463 ++++++++++++++++++++++++++++++-- drivers/network/dd/e1000/info.c | 114 +++++++- drivers/network/dd/e1000/ndis.c | 6 +- drivers/network/dd/e1000/nic.h | 35 ++- 8 files changed, 856 insertions(+), 32 deletions(-)
diff --git a/drivers/network/dd/e1000/CMakeLists.txt b/drivers/network/dd/e1000/CMakeLists.txt index eeee376c2e..591f01d796 100644 --- a/drivers/network/dd/e1000/CMakeLists.txt +++ b/drivers/network/dd/e1000/CMakeLists.txt @@ -11,6 +11,7 @@ list(APPEND SOURCE interrupt.c nic.h e1000hw.h + debug.c debug.h)
add_library(e1000 SHARED ${SOURCE} e1000.rc) diff --git a/drivers/network/dd/e1000/debug.c b/drivers/network/dd/e1000/debug.c new file mode 100644 index 0000000000..d3008bcc92 --- /dev/null +++ b/drivers/network/dd/e1000/debug.c @@ -0,0 +1,167 @@ +/* + * PROJECT: ReactOS Intel PRO/1000 Driver + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) + * PURPOSE: Translate NDIS_OID to readable string + * COPYRIGHT: Copyright 2018 Mark Jansen (mark.jansen@reactos.org) + */ + +#include "nic.h" + +#include <debug.h> + +const char* Oid2Str(IN NDIS_OID Oid) +{ +#if DBG + switch (Oid) + { +#define RETURN_X(x) case x: return #x; + /* Required Object IDs (OIDs) */ + RETURN_X(OID_GEN_SUPPORTED_LIST); + RETURN_X(OID_GEN_HARDWARE_STATUS); + RETURN_X(OID_GEN_MEDIA_SUPPORTED); + RETURN_X(OID_GEN_MEDIA_IN_USE); + RETURN_X(OID_GEN_MAXIMUM_LOOKAHEAD); + RETURN_X(OID_GEN_MAXIMUM_FRAME_SIZE); + RETURN_X(OID_GEN_LINK_SPEED); + RETURN_X(OID_GEN_TRANSMIT_BUFFER_SPACE); + RETURN_X(OID_GEN_RECEIVE_BUFFER_SPACE); + RETURN_X(OID_GEN_TRANSMIT_BLOCK_SIZE); + RETURN_X(OID_GEN_RECEIVE_BLOCK_SIZE); + RETURN_X(OID_GEN_VENDOR_ID); + RETURN_X(OID_GEN_VENDOR_DESCRIPTION); + RETURN_X(OID_GEN_CURRENT_PACKET_FILTER); + RETURN_X(OID_GEN_CURRENT_LOOKAHEAD); + RETURN_X(OID_GEN_DRIVER_VERSION); + RETURN_X(OID_GEN_MAXIMUM_TOTAL_SIZE); + RETURN_X(OID_GEN_PROTOCOL_OPTIONS); + RETURN_X(OID_GEN_MAC_OPTIONS); + RETURN_X(OID_GEN_MEDIA_CONNECT_STATUS); + RETURN_X(OID_GEN_MAXIMUM_SEND_PACKETS); + RETURN_X(OID_GEN_VENDOR_DRIVER_VERSION); + RETURN_X(OID_GEN_SUPPORTED_GUIDS); + RETURN_X(OID_GEN_NETWORK_LAYER_ADDRESSES); + RETURN_X(OID_GEN_TRANSPORT_HEADER_OFFSET); + RETURN_X(OID_GEN_MACHINE_NAME); + RETURN_X(OID_GEN_RNDIS_CONFIG_PARAMETER); + RETURN_X(OID_GEN_VLAN_ID); + + /* Optional OIDs */ + RETURN_X(OID_GEN_MEDIA_CAPABILITIES); + RETURN_X(OID_GEN_PHYSICAL_MEDIUM); + + /* Required statistics OIDs */ + RETURN_X(OID_GEN_XMIT_OK); + RETURN_X(OID_GEN_RCV_OK); + RETURN_X(OID_GEN_XMIT_ERROR); + RETURN_X(OID_GEN_RCV_ERROR); + RETURN_X(OID_GEN_RCV_NO_BUFFER); + + /* Optional statistics OIDs */ + RETURN_X(OID_GEN_DIRECTED_BYTES_XMIT); + RETURN_X(OID_GEN_DIRECTED_FRAMES_XMIT); + RETURN_X(OID_GEN_MULTICAST_BYTES_XMIT); + RETURN_X(OID_GEN_MULTICAST_FRAMES_XMIT); + RETURN_X(OID_GEN_BROADCAST_BYTES_XMIT); + RETURN_X(OID_GEN_BROADCAST_FRAMES_XMIT); + RETURN_X(OID_GEN_DIRECTED_BYTES_RCV); + RETURN_X(OID_GEN_DIRECTED_FRAMES_RCV); + RETURN_X(OID_GEN_MULTICAST_BYTES_RCV); + RETURN_X(OID_GEN_MULTICAST_FRAMES_RCV); + RETURN_X(OID_GEN_BROADCAST_BYTES_RCV); + RETURN_X(OID_GEN_BROADCAST_FRAMES_RCV); + RETURN_X(OID_GEN_RCV_CRC_ERROR); + RETURN_X(OID_GEN_TRANSMIT_QUEUE_LENGTH); + RETURN_X(OID_GEN_GET_TIME_CAPS); + RETURN_X(OID_GEN_GET_NETCARD_TIME); + RETURN_X(OID_GEN_NETCARD_LOAD); + RETURN_X(OID_GEN_DEVICE_PROFILE); + RETURN_X(OID_GEN_INIT_TIME_MS); + RETURN_X(OID_GEN_RESET_COUNTS); + RETURN_X(OID_GEN_MEDIA_SENSE_COUNTS); + RETURN_X(OID_GEN_FRIENDLY_NAME); + RETURN_X(OID_GEN_MINIPORT_INFO); + RETURN_X(OID_GEN_RESET_VERIFY_PARAMETERS); + + /* IEEE 802.3 (Ethernet) OIDs */ + //RETURN_X(NDIS_802_3_MAC_OPTION_PRIORITY); /*Duplicate ID */ + + RETURN_X(OID_802_3_PERMANENT_ADDRESS); + RETURN_X(OID_802_3_CURRENT_ADDRESS); + RETURN_X(OID_802_3_MULTICAST_LIST); + RETURN_X(OID_802_3_MAXIMUM_LIST_SIZE); + RETURN_X(OID_802_3_MAC_OPTIONS); + RETURN_X(OID_802_3_RCV_ERROR_ALIGNMENT); + RETURN_X(OID_802_3_XMIT_ONE_COLLISION); + RETURN_X(OID_802_3_XMIT_MORE_COLLISIONS); + RETURN_X(OID_802_3_XMIT_DEFERRED); + RETURN_X(OID_802_3_XMIT_MAX_COLLISIONS); + RETURN_X(OID_802_3_RCV_OVERRUN); + RETURN_X(OID_802_3_XMIT_UNDERRUN); + RETURN_X(OID_802_3_XMIT_HEARTBEAT_FAILURE); + RETURN_X(OID_802_3_XMIT_TIMES_CRS_LOST); + RETURN_X(OID_802_3_XMIT_LATE_COLLISIONS); + + /* IEEE 802.11 (WLAN) OIDs */ + RETURN_X(OID_802_11_BSSID); + RETURN_X(OID_802_11_SSID); + RETURN_X(OID_802_11_NETWORK_TYPES_SUPPORTED); + RETURN_X(OID_802_11_NETWORK_TYPE_IN_USE); + RETURN_X(OID_802_11_TX_POWER_LEVEL); + RETURN_X(OID_802_11_RSSI); + RETURN_X(OID_802_11_RSSI_TRIGGER); + RETURN_X(OID_802_11_INFRASTRUCTURE_MODE); + RETURN_X(OID_802_11_FRAGMENTATION_THRESHOLD); + RETURN_X(OID_802_11_RTS_THRESHOLD); + RETURN_X(OID_802_11_NUMBER_OF_ANTENNAS); + RETURN_X(OID_802_11_RX_ANTENNA_SELECTED); + RETURN_X(OID_802_11_TX_ANTENNA_SELECTED); + RETURN_X(OID_802_11_SUPPORTED_RATES); + RETURN_X(OID_802_11_DESIRED_RATES); + RETURN_X(OID_802_11_CONFIGURATION); + RETURN_X(OID_802_11_STATISTICS); + RETURN_X(OID_802_11_ADD_WEP); + RETURN_X(OID_802_11_REMOVE_WEP); + RETURN_X(OID_802_11_DISASSOCIATE); + RETURN_X(OID_802_11_POWER_MODE); + RETURN_X(OID_802_11_BSSID_LIST); + RETURN_X(OID_802_11_AUTHENTICATION_MODE); + RETURN_X(OID_802_11_PRIVACY_FILTER); + RETURN_X(OID_802_11_BSSID_LIST_SCAN); + RETURN_X(OID_802_11_WEP_STATUS); + RETURN_X(OID_802_11_RELOAD_DEFAULTS); + + /* OID_GEN_MINIPORT_INFO constants */ + RETURN_X(NDIS_MINIPORT_BUS_MASTER); + RETURN_X(NDIS_MINIPORT_WDM_DRIVER); + RETURN_X(NDIS_MINIPORT_SG_LIST); + RETURN_X(NDIS_MINIPORT_SUPPORTS_MEDIA_QUERY); + RETURN_X(NDIS_MINIPORT_INDICATES_PACKETS); + RETURN_X(NDIS_MINIPORT_IGNORE_PACKET_QUEUE); + RETURN_X(NDIS_MINIPORT_IGNORE_REQUEST_QUEUE); + RETURN_X(NDIS_MINIPORT_IGNORE_TOKEN_RING_ERRORS); + RETURN_X(NDIS_MINIPORT_INTERMEDIATE_DRIVER); + RETURN_X(NDIS_MINIPORT_IS_NDIS_5); + RETURN_X(NDIS_MINIPORT_IS_CO); + RETURN_X(NDIS_MINIPORT_DESERIALIZE); + RETURN_X(NDIS_MINIPORT_REQUIRES_MEDIA_POLLING); + RETURN_X(NDIS_MINIPORT_SUPPORTS_MEDIA_SENSE); + RETURN_X(NDIS_MINIPORT_NETBOOT_CARD); + RETURN_X(NDIS_MINIPORT_PM_SUPPORTED); + RETURN_X(NDIS_MINIPORT_SUPPORTS_MAC_ADDRESS_OVERWRITE); + RETURN_X(NDIS_MINIPORT_USES_SAFE_BUFFER_APIS); + RETURN_X(NDIS_MINIPORT_HIDDEN); + RETURN_X(NDIS_MINIPORT_SWENUM); + RETURN_X(NDIS_MINIPORT_SURPRISE_REMOVE_OK); + RETURN_X(NDIS_MINIPORT_NO_HALT_ON_SUSPEND); + RETURN_X(NDIS_MINIPORT_HARDWARE_DEVICE); + RETURN_X(NDIS_MINIPORT_SUPPORTS_CANCEL_SEND_PACKETS); + RETURN_X(NDIS_MINIPORT_64BITS_DMA); + default: + return "<UNKNOWN>"; + } +#else + return "!DBG"; +#endif +} + + diff --git a/drivers/network/dd/e1000/debug.h b/drivers/network/dd/e1000/debug.h index b6ff2cf92e..481f60429c 100644 --- a/drivers/network/dd/e1000/debug.h +++ b/drivers/network/dd/e1000/debug.h @@ -62,3 +62,5 @@ extern ULONG DebugTraceLevel; } while (0)
+const char* Oid2Str(IN NDIS_OID Oid); + diff --git a/drivers/network/dd/e1000/e1000hw.h b/drivers/network/dd/e1000/e1000hw.h index 57ac8fc2e8..9932974281 100644 --- a/drivers/network/dd/e1000/e1000hw.h +++ b/drivers/network/dd/e1000/e1000hw.h @@ -9,6 +9,18 @@
#define IEEE_802_ADDR_LENGTH 6
+#define HW_VENDOR_INTEL 0x8086 + +#define MAX_RESET_ATTEMPTS 10 + +#define MAX_PHY_REG_ADDRESS 0x1F +#define MAX_PHY_READ_ATTEMPTS 1800 + +#define MAX_EEPROM_READ_ATTEMPTS 10000 + + +#define MAXIMUM_MULTICAST_ADDRESSES 16 +
/* Ethernet frame header */ typedef struct _ETH_HEADER { @@ -17,3 +29,91 @@ typedef struct _ETH_HEADER { USHORT PayloadType; } ETH_HEADER, *PETH_HEADER;
+ + + + +/* Registers */ +#define E1000_REG_CTRL 0x0000 /* Device Control Register, R/W */ +#define E1000_REG_STATUS 0x0008 /* Device Status Register, R */ +#define E1000_REG_EERD 0x0014 /* EEPROM Read Register, R/W */ +#define E1000_REG_MDIC 0x0020 /* MDI Control Register, R/W */ +#define E1000_REG_VET 0x0038 /* VLAN Ether Type, R/W */ +#define E1000_REG_ICR 0x00C0 /* Interrupt Cause Read, R/clr */ + +#define E1000_REG_IMS 0x00D0 /* Interrupt Mask Set/Read Register, R/W */ +#define E1000_REG_IMC 0x00D8 /* Interrupt Mask Clear, W */ +#define E1000_REG_RCTL 0x0100 /* Receive Control, R/W */ + +#define E1000_REG_RAL 0x5400 /* Receive Address Low, R/W */ +#define E1000_REG_RAH 0x5404 /* Receive Address High, R/W */ + + +/* E1000_REG_CTRL */ +#define E1000_CTRL_RST (1 << 26) /* Device Reset, Self clearing */ + + +/* E1000_REG_STATUS */ +#define E1000_STATUS_LU (1 << 0) /* Link Up Indication */ +#define E1000_STATUS_SPEEDSHIFT 6 /* Link speed setting */ +#define E1000_STATUS_SPEEDMASK (3 << E1000_STATUS_SPEEDSHIFT) + + +/* E1000_REG_EERD */ +#define E1000_EERD_START (1 << 0) /* Start Read*/ +#define E1000_EERD_DONE (1 << 4) /* Read Done */ +#define E1000_EERD_ADDR_SHIFT 8 +#define E1000_EERD_DATA_SHIFT 16 + + +/* E1000_REG_MDIC */ +#define E1000_MDIC_REGADD_SHIFT 16 /* PHY Register Address */ +#define E1000_MDIC_PHYADD_SHIFT 21 /* PHY Address (1=Gigabit, 2=PCIe) */ +#define E1000_MDIC_PHYADD_GIGABIT 1 +#define E1000_MDIC_OP_READ (2 << 26) /* Opcode */ +#define E1000_MDIC_R (1 << 28) /* Ready Bit */ +#define E1000_MDIC_E (1 << 30) /* Error */ + + +/* E1000_REG_IMS */ +#define E1000_IMS_LSC (1 << 2) /* Sets mask for Link Status Change */ + + +/* E1000_REG_RCTL */ +#define E1000_RCTL_EN (1 << 1) /* Receiver Enable */ +#define E1000_RCTL_SBP (1 << 2) /* Store Bad Packets */ +#define E1000_RCTL_UPE (1 << 3) /* Unicast Promiscuous Enabled */ +#define E1000_RCTL_MPE (1 << 4) /* Multicast Promiscuous Enabled */ +#define E1000_RCTL_BAM (1 << 15) /* Broadcast Accept Mode */ +#define E1000_RCTL_PMCF (1 << 23) /* Pass MAC Control Frames */ + +#define E1000_RCTL_FILTER_BITS (E1000_RCTL_SBP | E1000_RCTL_UPE | E1000_RCTL_MPE | E1000_RCTL_BAM | E1000_RCTL_PMCF) + +/* E1000_REG_RAH */ +#define E1000_RAH_AV (1 << 31) /* Address Valid */ + + + + +/* NVM */ +#define E1000_NVM_REG_CHECKSUM 0x03f +#define NVM_MAGIC_SUM 0xBABA + + + +/* PHY (Read with MDIC) */ + +#define E1000_PHY_STATUS 0x01 +#define E1000_PHY_SPECIFIC_STATUS 0x11 + + +/* E1000_PHY_STATUS */ +#define E1000_PS_LINK_STATUS (1 << 2) + + + +/* E1000_PHY_SPECIFIC_STATUS */ +#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 b238be0997..5308afadd5 100644 --- a/drivers/network/dd/e1000/hardware.c +++ b/drivers/network/dd/e1000/hardware.c @@ -9,13 +9,162 @@
#include <debug.h>
+ +static USHORT SupportedDevices[] = +{ + 0x100f, // Intel 82545EM (VMWare E1000) +}; + + +static ULONG E1000WriteFlush(IN PE1000_ADAPTER Adapter) +{ + volatile ULONG Value; + + NdisReadRegisterUlong(Adapter->IoBase + E1000_REG_STATUS, &Value); + return Value; +} + +static VOID E1000WriteUlong(IN PE1000_ADAPTER Adapter, IN ULONG Address, IN ULONG Value) +{ + NdisWriteRegisterUlong((PULONG)(Adapter->IoBase + Address), Value); +} + +static VOID 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 BOOLEAN E1000ReadMdic(IN PE1000_ADAPTER Adapter, IN ULONG Address, USHORT *Result) +{ + ULONG ResultAddress; + ULONG Mdic; + UINT n; + + if (Address > MAX_PHY_REG_ADDRESS) + { + NDIS_DbgPrint(MIN_TRACE, ("PHY Address %d is invalid\n", Address)); + return 1; + } + + 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++) + { + NdisStallExecution(50); + E1000ReadUlong(Adapter, E1000_REG_MDIC, &Mdic); + if (Mdic & E1000_MDIC_R) + break; + } + if (!(Mdic & E1000_MDIC_R)) + { + NDIS_DbgPrint(MIN_TRACE, ("MDI Read incomplete\n")); + return FALSE; + } + if (Mdic & E1000_MDIC_E) + { + NDIS_DbgPrint(MIN_TRACE, ("MDI Read error\n")); + return FALSE; + } + + ResultAddress = (Mdic >> E1000_MDIC_REGADD_SHIFT) & MAX_PHY_REG_ADDRESS; + + if (ResultAddress!= Address) + { + /* Add locking? */ + NDIS_DbgPrint(MIN_TRACE, ("MDI Read got wrong address (%d instead of %d)\n", + ResultAddress, Address)); + return FALSE; + } + *Result = (USHORT) Mdic; + return TRUE; +} + + +static BOOLEAN E1000ReadEeprom(IN PE1000_ADAPTER Adapter, IN UCHAR Address, USHORT *Result) +{ + UINT Value; + UINT n; + + E1000WriteUlong(Adapter, E1000_REG_EERD, E1000_EERD_START | ((UINT)Address << E1000_EERD_ADDR_SHIFT)); + + for (n = 0; n < MAX_EEPROM_READ_ATTEMPTS; ++n) + { + NdisStallExecution(5); + + E1000ReadUlong(Adapter, E1000_REG_EERD, &Value); + + if (Value & E1000_EERD_DONE) + break; + } + if (!(Value & E1000_EERD_DONE)) + { + NDIS_DbgPrint(MIN_TRACE, ("EEPROM Read incomplete\n")); + return FALSE; + } + *Result = (USHORT)(Value >> E1000_EERD_DATA_SHIFT); + return TRUE; +} + +BOOLEAN E1000ValidateNvmChecksum(IN PE1000_ADAPTER Adapter) +{ + USHORT Checksum = 0, Data; + UINT n; + + /* 5.6.35 Checksum Word Calculation (Word 3Fh) */ + for (n = 0; n <= E1000_NVM_REG_CHECKSUM; n++) + { + if (!E1000ReadEeprom(Adapter, n, &Data)) + { + return FALSE; + } + Checksum += Data; + } + + if (Checksum != NVM_MAGIC_SUM) + { + NDIS_DbgPrint(MIN_TRACE, ("EEPROM has an invalid checksum of 0x%x\n", (ULONG)Checksum)); + return FALSE; + } + + return TRUE; +} + + BOOLEAN NTAPI NICRecognizeHardware( IN PE1000_ADAPTER Adapter) { + UINT n; NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+ if (Adapter->VendorID != HW_VENDOR_INTEL) + { + NDIS_DbgPrint(MIN_TRACE, ("Unknown vendor: 0x%x\n", Adapter->VendorID)); + return FALSE; + } + + for (n = 0; n < ARRAYSIZE(SupportedDevices); ++n) + { + if (SupportedDevices[n] == Adapter->DeviceID) + { + return TRUE; + } + } + + NDIS_DbgPrint(MIN_TRACE, ("Unknown device: 0x%x\n", Adapter->DeviceID)); + return FALSE; }
@@ -25,19 +174,92 @@ NICInitializeAdapterResources( IN PE1000_ADAPTER Adapter, IN PNDIS_RESOURCE_LIST ResourceList) { + UINT n; NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
- return NDIS_STATUS_FAILURE; + for (n = 0; n < ResourceList->Count; n++) + { + PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor = ResourceList->PartialDescriptors + n; + + switch (ResourceDescriptor->Type) + { + case CmResourceTypePort: + ASSERT(Adapter->IoPortAddress == 0); + ASSERT(ResourceDescriptor->u.Port.Start.HighPart == 0); + + Adapter->IoPortAddress = ResourceDescriptor->u.Port.Start.LowPart; + Adapter->IoPortLength = ResourceDescriptor->u.Port.Length; + + NDIS_DbgPrint(MID_TRACE, ("I/O port range is %p to %p\n", + Adapter->IoPortAddress, + Adapter->IoPortAddress + Adapter->IoPortLength)); + break; + case CmResourceTypeInterrupt: + ASSERT(Adapter->InterruptVector == 0); + ASSERT(Adapter->InterruptLevel == 0); + + Adapter->InterruptVector = ResourceDescriptor->u.Interrupt.Vector; + Adapter->InterruptLevel = ResourceDescriptor->u.Interrupt.Level; + Adapter->InterruptShared = (ResourceDescriptor->ShareDisposition == CmResourceShareShared); + Adapter->InterruptFlags = ResourceDescriptor->Flags; + + NDIS_DbgPrint(MID_TRACE, ("IRQ vector is %d\n", Adapter->InterruptVector)); + break; + case CmResourceTypeMemory: + /* Internal registers and memories (including PHY) */ + if (ResourceDescriptor->u.Memory.Length == (128 * 1024)) + { + ASSERT(Adapter->IoAddress.LowPart == 0); + ASSERT(ResourceDescriptor->u.Port.Start.HighPart == 0); + + + Adapter->IoAddress.QuadPart = ResourceDescriptor->u.Memory.Start.QuadPart; + Adapter->IoLength = ResourceDescriptor->u.Memory.Length; + NDIS_DbgPrint(MID_TRACE, ("Memory range is %I64x to %I64x\n", + Adapter->IoAddress.QuadPart, + Adapter->IoAddress.QuadPart + Adapter->IoLength)); + } + break; + + default: + NDIS_DbgPrint(MIN_TRACE, ("Unrecognized resource type: 0x%x\n", ResourceDescriptor->Type)); + break; + } + } + + if (Adapter->IoAddress.QuadPart == 0 || Adapter->IoPortAddress == 0 || Adapter->InterruptVector == 0) + { + NDIS_DbgPrint(MIN_TRACE, ("Adapter didn't receive enough resources\n")); + return NDIS_STATUS_RESOURCES; + } + + return NDIS_STATUS_SUCCESS; }
NDIS_STATUS NTAPI -NICAllocateResources( +NICAllocateIoResources( IN PE1000_ADAPTER Adapter) { + NDIS_STATUS Status; NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
- return NDIS_STATUS_FAILURE; + Status = NdisMRegisterIoPortRange((PVOID*)&Adapter->IoPort, + Adapter->AdapterHandle, + Adapter->IoPortAddress, + Adapter->IoPortLength); + if (Status != NDIS_STATUS_SUCCESS) + { + NDIS_DbgPrint(MIN_TRACE, ("Unable to register IO port range (0x%x)\n", Status)); + return NDIS_STATUS_RESOURCES; + } + + Status = NdisMMapIoSpace((PVOID*)&Adapter->IoBase, + Adapter->AdapterHandle, + Adapter->IoAddress, + Adapter->IoLength); + + return NDIS_STATUS_SUCCESS; }
NDIS_STATUS @@ -45,9 +267,24 @@ NTAPI NICRegisterInterrupts( IN PE1000_ADAPTER Adapter) { + NDIS_STATUS Status; NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
- return NDIS_STATUS_FAILURE; + Status = NdisMRegisterInterrupt(&Adapter->Interrupt, + Adapter->AdapterHandle, + Adapter->InterruptVector, + Adapter->InterruptLevel, + TRUE, // We always want ISR calls + Adapter->InterruptShared, + (Adapter->InterruptFlags & CM_RESOURCE_INTERRUPT_LATCHED) ? + NdisInterruptLatched : NdisInterruptLevelSensitive); + + if (Status == NDIS_STATUS_SUCCESS) + { + Adapter->InterruptRegistered = TRUE; + } + + return Status; }
NDIS_STATUS @@ -57,7 +294,13 @@ NICUnregisterInterrupts( { NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
- return NDIS_STATUS_FAILURE; + if (Adapter->InterruptRegistered) + { + NdisMDeregisterInterrupt(&Adapter->Interrupt); + Adapter->InterruptRegistered = FALSE; + } + + return NDIS_STATUS_SUCCESS; }
NDIS_STATUS @@ -67,7 +310,21 @@ NICReleaseIoResources( { NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
- return NDIS_STATUS_FAILURE; + if (Adapter->IoPort) + { + NdisMDeregisterIoPortRange(Adapter->AdapterHandle, + Adapter->IoPortAddress, + Adapter->IoPortLength, + Adapter->IoPort); + } + + if (Adapter->IoBase) + { + NdisMUnmapIoSpace(Adapter->AdapterHandle, Adapter->IoBase, Adapter->IoLength); + } + + + return NDIS_STATUS_SUCCESS; }
@@ -76,18 +333,61 @@ NTAPI NICPowerOn( IN PE1000_ADAPTER Adapter) { + NDIS_STATUS Status; NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
- return NDIS_STATUS_FAILURE; + Status = NICSoftReset(Adapter); + if (Status != NDIS_STATUS_SUCCESS) + { + return Status; + } + + if (!E1000ValidateNvmChecksum(Adapter)) + { + return NDIS_STATUS_INVALID_DATA; + } + + return NDIS_STATUS_SUCCESS; }
NDIS_STATUS NTAPI NICSoftReset( - IN PE1000_ADAPTER adapter) + IN PE1000_ADAPTER Adapter) { + ULONG Value, ResetAttempts; NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+ //em_get_hw_control(adapter); + + NICDisableInterrupts(Adapter); + E1000WriteUlong(Adapter, E1000_REG_RCTL, 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); + + + for (ResetAttempts = 0; ResetAttempts < MAX_RESET_ATTEMPTS; ResetAttempts++) + { + NdisStallExecution(100); + E1000ReadUlong(Adapter, E1000_REG_CTRL, &Value); + + if (!(Value & E1000_CTRL_RST)) + { + NDIS_DbgPrint(MAX_TRACE, ("Device is back (%u)\n", ResetAttempts)); + + NICDisableInterrupts(Adapter); + /* Clear out interrupts */ + E1000ReadUlong(Adapter, E1000_REG_ICR, &Value); + + //NdisWriteRegisterUlong(Adapter->IoBase + E1000_REG_WUFC, 0); + //NdisWriteRegisterUlong(Adapter->IoBase + E1000_REG_VET, E1000_VET_VLAN); + + return NDIS_STATUS_SUCCESS; + } + } + + NDIS_DbgPrint(MIN_TRACE, ("Device did not recover\n")); return NDIS_STATUS_FAILURE; }
@@ -98,7 +398,7 @@ NICEnableTxRx( { NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
- return NDIS_STATUS_FAILURE; + return NDIS_STATUS_SUCCESS; }
NDIS_STATUS @@ -108,7 +408,7 @@ NICDisableTxRx( { NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
- return NDIS_STATUS_FAILURE; + return NDIS_STATUS_SUCCESS; }
NDIS_STATUS @@ -117,9 +417,97 @@ NICGetPermanentMacAddress( IN PE1000_ADAPTER Adapter, OUT PUCHAR MacAddress) { + USHORT AddrWord; + UINT n; + NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
- return NDIS_STATUS_FAILURE; + /* Should we read from RAL/RAH first? */ + for (n = 0; n < (IEEE_802_ADDR_LENGTH / 2); ++n) + { + if (!E1000ReadEeprom(Adapter, (UCHAR)n, &AddrWord)) + return NDIS_STATUS_FAILURE; + Adapter->PermanentMacAddress[n * 2 + 0] = AddrWord & 0xff; + Adapter->PermanentMacAddress[n * 2 + 1] = (AddrWord >> 8) & 0xff; + } + + NDIS_DbgPrint(MIN_TRACE, ("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", + Adapter->PermanentMacAddress[0], + Adapter->PermanentMacAddress[1], + Adapter->PermanentMacAddress[2], + Adapter->PermanentMacAddress[3], + Adapter->PermanentMacAddress[4], + Adapter->PermanentMacAddress[5])); + return NDIS_STATUS_SUCCESS; +} + +NDIS_STATUS +NTAPI +NICUpdateMulticastList( + IN PE1000_ADAPTER Adapter) +{ + UINT n; + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + for (n = 0; n < MAXIMUM_MULTICAST_ADDRESSES; ++n) + { + ULONG Ral = *(ULONG *)Adapter->MulticastList[n].MacAddress; + ULONG Rah = *(USHORT *)&Adapter->MulticastList[n].MacAddress[4]; + + if (Rah || Ral) + { + Rah |= E1000_RAH_AV; + + E1000WriteUlong(Adapter, E1000_REG_RAL + (8*n), Ral); + E1000WriteUlong(Adapter, E1000_REG_RAH + (8*n), Rah); + } + else + { + E1000WriteUlong(Adapter, E1000_REG_RAH + (8*n), 0); + E1000WriteUlong(Adapter, E1000_REG_RAL + (8*n), 0); + } + } + + return NDIS_STATUS_SUCCESS; +} + +NDIS_STATUS +NTAPI +NICApplyPacketFilter( + IN PE1000_ADAPTER Adapter) +{ + ULONG FilterMask = 0; + + E1000ReadUlong(Adapter, E1000_REG_RCTL, &FilterMask); + + FilterMask &= ~E1000_RCTL_FILTER_BITS; + + if (Adapter->PacketFilter & NDIS_PACKET_TYPE_ALL_MULTICAST) + { + /* Multicast Promiscuous Enabled */ + FilterMask |= E1000_RCTL_MPE; + } + if (Adapter->PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS) + { + /* Unicast Promiscuous Enabled */ + FilterMask |= E1000_RCTL_UPE; + /* Multicast Promiscuous Enabled */ + FilterMask |= E1000_RCTL_MPE; + } + if (Adapter->PacketFilter & NDIS_PACKET_TYPE_MAC_FRAME) + { + /* Pass MAC Control Frames */ + FilterMask |= E1000_RCTL_PMCF; + } + if (Adapter->PacketFilter & NDIS_PACKET_TYPE_BROADCAST) + { + /* Broadcast Accept Mode */ + FilterMask |= E1000_RCTL_BAM; + } + + E1000WriteUlong(Adapter, E1000_REG_RCTL, FilterMask); + + return NDIS_STATUS_SUCCESS; }
NDIS_STATUS @@ -129,7 +517,8 @@ NICApplyInterruptMask( { NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
- return NDIS_STATUS_FAILURE; + E1000WriteUlong(Adapter, E1000_REG_IMS, Adapter->InterruptMask); + return NDIS_STATUS_SUCCESS; }
NDIS_STATUS @@ -139,7 +528,8 @@ NICDisableInterrupts( { NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
- return NDIS_STATUS_FAILURE; + E1000WriteUlong(Adapter, E1000_REG_IMC, ~0); + return NDIS_STATUS_SUCCESS; }
USHORT @@ -166,17 +556,48 @@ NTAPI NICUpdateLinkStatus( IN PE1000_ADAPTER Adapter) { - NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); -} + ULONG SpeedIndex; + USHORT PhyStatus; + static ULONG SpeedValues[] = { 10, 100, 1000, 1000 };
-NDIS_STATUS -NTAPI -NICApplyPacketFilter( - IN PE1000_ADAPTER Adapter) -{ NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
- return NDIS_STATUS_FAILURE; +#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 diff --git a/drivers/network/dd/e1000/info.c b/drivers/network/dd/e1000/info.c index 84817956e4..2c98034fe6 100644 --- a/drivers/network/dd/e1000/info.c +++ b/drivers/network/dd/e1000/info.c @@ -13,11 +13,13 @@ static ULONG SupportedOidList[] = { OID_GEN_SUPPORTED_LIST, + OID_GEN_CURRENT_PACKET_FILTER, OID_GEN_HARDWARE_STATUS, OID_GEN_MEDIA_SUPPORTED, OID_GEN_MEDIA_IN_USE, OID_GEN_MAXIMUM_LOOKAHEAD, OID_GEN_MAXIMUM_FRAME_SIZE, + OID_GEN_MAXIMUM_SEND_PACKETS, OID_GEN_LINK_SPEED, OID_GEN_TRANSMIT_BUFFER_SPACE, OID_GEN_RECEIVE_BUFFER_SPACE, @@ -27,14 +29,23 @@ static ULONG SupportedOidList[] = OID_GEN_VENDOR_DESCRIPTION, OID_GEN_VENDOR_DRIVER_VERSION, OID_GEN_CURRENT_LOOKAHEAD, + OID_802_3_MULTICAST_LIST, OID_GEN_DRIVER_VERSION, OID_GEN_MAXIMUM_TOTAL_SIZE, OID_GEN_MAC_OPTIONS, OID_GEN_MEDIA_CONNECT_STATUS, 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, };
+ NDIS_STATUS NTAPI MiniportQueryInformation( @@ -64,6 +75,10 @@ MiniportQueryInformation( copyLength = sizeof(SupportedOidList); break;
+ case OID_GEN_CURRENT_PACKET_FILTER: + genericUlong = Adapter->PacketFilter; + break; + case OID_GEN_HARDWARE_STATUS: UNIMPLEMENTED_DBGBREAK(); genericUlong = (ULONG)NdisHardwareStatusReady; //FIXME @@ -86,8 +101,12 @@ MiniportQueryInformation( genericUlong = MAXIMUM_FRAME_SIZE - sizeof(ETH_HEADER); break;
+ case OID_802_3_MAXIMUM_LIST_SIZE: + genericUlong = MAXIMUM_MULTICAST_ADDRESSES; + break; + case OID_GEN_LINK_SPEED: - genericUlong = Adapter->LinkSpeedMbps * 1000; + genericUlong = Adapter->LinkSpeedMbps * 10000; break;
case OID_GEN_TRANSMIT_BUFFER_SPACE: @@ -131,6 +150,10 @@ MiniportQueryInformation( genericUlong = MAXIMUM_FRAME_SIZE; break;
+ case OID_GEN_MAXIMUM_SEND_PACKETS: + genericUlong = 1; + break; + case OID_GEN_MAC_OPTIONS: genericUlong = NDIS_MAC_OPTION_RECEIVE_SERIALIZED | NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | @@ -144,7 +167,7 @@ MiniportQueryInformation(
case OID_802_3_CURRENT_ADDRESS: - copySource = Adapter->CurrentMacAddress; + copySource = Adapter->MulticastList[0].MacAddress; copyLength = IEEE_802_ADDR_LENGTH; break;
@@ -153,8 +176,24 @@ MiniportQueryInformation( copyLength = IEEE_802_ADDR_LENGTH; 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; + break; + default: - NDIS_DbgPrint(MIN_TRACE, ("Unknown OID 0x%x\n", Oid)); + NDIS_DbgPrint(MIN_TRACE, ("Unknown OID 0x%x(%s)\n", Oid, Oid2Str(Oid))); status = NDIS_STATUS_NOT_SUPPORTED; break; } @@ -181,9 +220,12 @@ MiniportQueryInformation( }
NdisReleaseSpinLock(&Adapter->Lock); - - NDIS_DbgPrint(MAX_TRACE, ("Query OID 0x%x: Completed with status 0x%x (%d, %d)\n", - Oid, status, *BytesWritten, *BytesNeeded)); + /* 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)); + }
return status; } @@ -208,6 +250,42 @@ MiniportSetInformation(
switch (Oid) { + case OID_GEN_CURRENT_PACKET_FILTER: + if (InformationBufferLength < sizeof(ULONG)) + { + *BytesRead = 0; + *BytesNeeded = sizeof(ULONG); + status = NDIS_STATUS_INVALID_LENGTH; + break; + } + + 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)) + { + *BytesRead = sizeof(ULONG); + *BytesNeeded = sizeof(ULONG); + status = NDIS_STATUS_NOT_SUPPORTED; + break; + } + + Adapter->PacketFilter = genericUlong; + + status = NICApplyPacketFilter(Adapter); + if (status != NDIS_STATUS_SUCCESS) + { + NDIS_DbgPrint(MIN_TRACE, ("Failed to apply new packet filter (0x%x)\n", status)); + break; + } + + break; + case OID_GEN_CURRENT_LOOKAHEAD: if (InformationBufferLength < sizeof(ULONG)) { @@ -230,8 +308,29 @@ MiniportSetInformation(
break;
+ case OID_802_3_MULTICAST_LIST: + if (InformationBufferLength % IEEE_802_ADDR_LENGTH) + { + *BytesRead = 0; + *BytesNeeded = InformationBufferLength + (InformationBufferLength % IEEE_802_ADDR_LENGTH); + status = NDIS_STATUS_INVALID_LENGTH; + break; + } + + if (InformationBufferLength / 6 > MAXIMUM_MULTICAST_ADDRESSES) + { + *BytesNeeded = MAXIMUM_MULTICAST_ADDRESSES * IEEE_802_ADDR_LENGTH; + *BytesRead = 0; + status = NDIS_STATUS_INVALID_LENGTH; + break; + } + + NdisMoveMemory(Adapter->MulticastList, InformationBuffer, InformationBufferLength); + NICUpdateMulticastList(Adapter); + break; + default: - NDIS_DbgPrint(MIN_TRACE, ("Unknown OID 0x%x\n", Oid)); + NDIS_DbgPrint(MIN_TRACE, ("Unknown OID 0x%x(%s)\n", Oid, Oid2Str(Oid))); status = NDIS_STATUS_NOT_SUPPORTED; *BytesRead = 0; *BytesNeeded = 0; @@ -248,3 +347,4 @@ MiniportSetInformation(
return status; } + diff --git a/drivers/network/dd/e1000/ndis.c b/drivers/network/dd/e1000/ndis.c index b02f397bd9..50b5c44e93 100644 --- a/drivers/network/dd/e1000/ndis.c +++ b/drivers/network/dd/e1000/ndis.c @@ -224,7 +224,9 @@ MiniportInitialize( goto Cleanup; }
- RtlCopyMemory(Adapter->CurrentMacAddress, Adapter->PermanentMacAddress, IEEE_802_ADDR_LENGTH); + RtlCopyMemory(Adapter->MulticastList[0].MacAddress, Adapter->PermanentMacAddress, IEEE_802_ADDR_LENGTH); + + NICUpdateMulticastList(Adapter);
/* Update link state and speed */ NICUpdateLinkStatus(Adapter); @@ -238,7 +240,7 @@ MiniportInitialize( }
/* Enable interrupts on the NIC */ - //Adapter->InterruptMask = DEFAULT_INTERRUPT_MASK; + Adapter->InterruptMask = DEFAULT_INTERRUPT_MASK; Status = NICApplyInterruptMask(Adapter); if (Status != NDIS_STATUS_SUCCESS) { diff --git a/drivers/network/dd/e1000/nic.h b/drivers/network/dd/e1000/nic.h index ea6922ed17..9586b615f6 100644 --- a/drivers/network/dd/e1000/nic.h +++ b/drivers/network/dd/e1000/nic.h @@ -21,6 +21,8 @@ #define DRIVER_VERSION 1
+#define DEFAULT_INTERRUPT_MASK (E1000_IMS_LSC) + typedef struct _E1000_ADAPTER { NDIS_SPIN_LOCK Lock; @@ -31,10 +33,34 @@ typedef struct _E1000_ADAPTER USHORT SubsystemVendorID;
UCHAR PermanentMacAddress[IEEE_802_ADDR_LENGTH]; - UCHAR CurrentMacAddress[IEEE_802_ADDR_LENGTH]; + struct { + UCHAR MacAddress[IEEE_802_ADDR_LENGTH]; + } MulticastList[MAXIMUM_MULTICAST_ADDRESSES];
ULONG LinkSpeedMbps; ULONG MediaState; + ULONG PacketFilter; + + /* Io Port */ + ULONG IoPortAddress; + ULONG IoPortLength; + volatile PUCHAR IoPort; + + /* NIC Memory */ + NDIS_PHYSICAL_ADDRESS IoAddress; + ULONG IoLength; + volatile PUCHAR IoBase; + + /* Interrupt */ + ULONG InterruptVector; + ULONG InterruptLevel; + BOOLEAN InterruptShared; + ULONG InterruptFlags; + + NDIS_MINIPORT_INTERRUPT Interrupt; + BOOLEAN InterruptRegistered; + + ULONG InterruptMask; ULONG InterruptPending;
} E1000_ADAPTER, *PE1000_ADAPTER; @@ -53,7 +79,7 @@ NICInitializeAdapterResources(
NDIS_STATUS NTAPI -NICAllocateResources( +NICAllocateIoResources( IN PE1000_ADAPTER Adapter);
NDIS_STATUS @@ -97,6 +123,11 @@ NICGetPermanentMacAddress( IN PE1000_ADAPTER Adapter, OUT PUCHAR MacAddress);
+NDIS_STATUS +NTAPI +NICUpdateMulticastList( + IN PE1000_ADAPTER Adapter); + NDIS_STATUS NTAPI NICApplyPacketFilter(