[E1000] Basic initialization of the card

Initialize some registers, allocate basic resources

CORE-14675
This commit is contained in:
Mark Jansen 2018-05-28 00:09:10 +02:00
parent 4561998a45
commit d9b0601ceb
8 changed files with 856 additions and 32 deletions

View file

@ -11,6 +11,7 @@ list(APPEND SOURCE
interrupt.c
nic.h
e1000hw.h
debug.c
debug.h)
add_library(e1000 SHARED ${SOURCE} e1000.rc)

View file

@ -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
}

View file

@ -62,3 +62,5 @@ extern ULONG DebugTraceLevel;
} while (0)
const char* Oid2Str(IN NDIS_OID Oid);

View file

@ -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)

View file

@ -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

View file

@ -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;
}

View file

@ -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)
{

View file

@ -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(