2 * PROJECT: ReactOS Intel PRO/1000 Driver
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Hardware specific functions
5 * COPYRIGHT: 2018 Mark Jansen (mark.jansen@reactos.org)
6 * 2019 Victor Perevertkin (victor.perevertkin@reactos.org)
14 static USHORT SupportedDevices
[] =
16 /* 8254x Family adapters. Not all of them are tested */
17 0x1000, // Intel 82542
18 0x1001, // Intel 82543GC Fiber
19 0x1004, // Intel 82543GC Copper
20 0x1008, // Intel 82544EI Copper
21 0x1009, // Intel 82544EI Fiber
22 0x100A, // Intel 82540EM
23 0x100C, // Intel 82544GC Copper
24 0x100D, // Intel 82544GC LOM (LAN on Motherboard)
25 0x100E, // Intel 82540EM
26 0x100F, // Intel 82545EM Copper
27 0x1010, // Intel 82546EB Copper
28 0x1011, // Intel 82545EM Fiber
29 0x1012, // Intel 82546EB Fiber
30 0x1013, // Intel 82541EI
31 0x1014, // Intel 82541EI LOM
32 0x1015, // Intel 82540EM LOM
33 0x1016, // Intel 82540EP LOM
34 0x1017, // Intel 82540EP
35 0x1018, // Intel 82541EI Mobile
36 0x1019, // Intel 82547EI
37 0x101A, // Intel 82547EI Mobile
38 0x101D, // Intel 82546EB Quad Copper
39 0x101E, // Intel 82540EP LP (Low profile)
40 0x1026, // Intel 82545GM Copper
41 0x1027, // Intel 82545GM Fiber
42 0x1028, // Intel 82545GM SerDes
43 0x1075, // Intel 82547GI
44 0x1076, // Intel 82541GI
45 0x1077, // Intel 82541GI Mobile
46 0x1078, // Intel 82541ER
47 0x1079, // Intel 82546GB Copper
48 0x107A, // Intel 82546GB Fiber
49 0x107B, // Intel 82546GB SerDes
50 0x107C, // Intel 82541PI
51 0x108A, // Intel 82546GB PCI-E
52 0x1099, // Intel 82546GB Quad Copper
53 0x10B5, // Intel 82546GB Quad Copper KSP3
57 static ULONG
E1000WriteFlush(IN PE1000_ADAPTER Adapter
)
61 NdisReadRegisterUlong(Adapter
->IoBase
+ E1000_REG_STATUS
, &Value
);
65 VOID NTAPI
E1000WriteUlong(IN PE1000_ADAPTER Adapter
, IN ULONG Address
, IN ULONG Value
)
67 NdisWriteRegisterUlong((PULONG
)(Adapter
->IoBase
+ Address
), Value
);
70 VOID NTAPI
E1000ReadUlong(IN PE1000_ADAPTER Adapter
, IN ULONG Address
, OUT PULONG Value
)
72 NdisReadRegisterUlong((PULONG
)(Adapter
->IoBase
+ Address
), Value
);
75 static VOID
E1000WriteIoUlong(IN PE1000_ADAPTER Adapter
, IN ULONG Address
, IN ULONG Value
)
77 NdisRawWritePortUlong((PULONG
)(Adapter
->IoPort
), Address
);
78 E1000WriteFlush(Adapter
);
79 NdisRawWritePortUlong((PULONG
)(Adapter
->IoPort
+ 4), Value
);
82 static ULONG
PacketFilterToMask(ULONG PacketFilter
)
86 if (PacketFilter
& NDIS_PACKET_TYPE_ALL_MULTICAST
)
88 /* Multicast Promiscuous Enabled */
89 FilterMask
|= E1000_RCTL_MPE
;
91 if (PacketFilter
& NDIS_PACKET_TYPE_PROMISCUOUS
)
93 /* Unicast Promiscuous Enabled */
94 FilterMask
|= E1000_RCTL_UPE
;
95 /* Multicast Promiscuous Enabled */
96 FilterMask
|= E1000_RCTL_MPE
;
98 if (PacketFilter
& NDIS_PACKET_TYPE_MAC_FRAME
)
100 /* Pass MAC Control Frames */
101 FilterMask
|= E1000_RCTL_PMCF
;
103 if (PacketFilter
& NDIS_PACKET_TYPE_BROADCAST
)
105 /* Broadcast Accept Mode */
106 FilterMask
|= E1000_RCTL_BAM
;
112 static ULONG
RcvBufAllocationSize(E1000_RCVBUF_SIZE BufSize
)
114 static ULONG PredefSizes
[4] = {
115 2048, 1024, 512, 256,
119 Size
= PredefSizes
[BufSize
& E1000_RCVBUF_INDEXMASK
];
120 if (BufSize
& E1000_RCVBUF_RESERVED
)
122 ASSERT(BufSize
!= 2048);
128 static ULONG
RcvBufRegisterMask(E1000_RCVBUF_SIZE BufSize
)
132 Mask
|= BufSize
& E1000_RCVBUF_INDEXMASK
;
133 Mask
<<= E1000_RCTL_BSIZE_SHIFT
;
134 if (BufSize
& E1000_RCVBUF_RESERVED
)
135 Mask
|= E1000_RCTL_BSEX
;
141 /* This function works, but the driver does not use PHY register access right now */
142 static BOOLEAN
E1000ReadMdic(IN PE1000_ADAPTER Adapter
, IN ULONG Address
, USHORT
*Result
)
148 if (Address
> MAX_PHY_REG_ADDRESS
)
150 NDIS_DbgPrint(MIN_TRACE
, ("PHY Address %d is invalid\n", Address
));
154 Mdic
= (Address
<< E1000_MDIC_REGADD_SHIFT
);
155 Mdic
|= (E1000_MDIC_PHYADD_GIGABIT
<< E1000_MDIC_PHYADD_SHIFT
);
156 Mdic
|= E1000_MDIC_OP_READ
;
158 E1000WriteUlong(Adapter
, E1000_REG_MDIC
, Mdic
);
160 for (n
= 0; n
< MAX_PHY_READ_ATTEMPTS
; n
++)
162 NdisStallExecution(50);
163 E1000ReadUlong(Adapter
, E1000_REG_MDIC
, &Mdic
);
164 if (Mdic
& E1000_MDIC_R
)
167 if (!(Mdic
& E1000_MDIC_R
))
169 NDIS_DbgPrint(MIN_TRACE
, ("MDI Read incomplete\n"));
172 if (Mdic
& E1000_MDIC_E
)
174 NDIS_DbgPrint(MIN_TRACE
, ("MDI Read error\n"));
178 ResultAddress
= (Mdic
>> E1000_MDIC_REGADD_SHIFT
) & MAX_PHY_REG_ADDRESS
;
180 if (ResultAddress
!= Address
)
183 NDIS_DbgPrint(MIN_TRACE
, ("MDI Read got wrong address (%d instead of %d)\n",
184 ResultAddress
, Address
));
187 *Result
= (USHORT
) Mdic
;
193 static BOOLEAN
E1000ReadEeprom(IN PE1000_ADAPTER Adapter
, IN UCHAR Address
, USHORT
*Result
)
198 E1000WriteUlong(Adapter
, E1000_REG_EERD
, E1000_EERD_START
| ((UINT
)Address
<< E1000_EERD_ADDR_SHIFT
));
200 for (n
= 0; n
< MAX_EEPROM_READ_ATTEMPTS
; ++n
)
202 NdisStallExecution(5);
204 E1000ReadUlong(Adapter
, E1000_REG_EERD
, &Value
);
206 if (Value
& E1000_EERD_DONE
)
209 if (!(Value
& E1000_EERD_DONE
))
211 NDIS_DbgPrint(MIN_TRACE
, ("EEPROM Read incomplete\n"));
214 *Result
= (USHORT
)(Value
>> E1000_EERD_DATA_SHIFT
);
218 BOOLEAN
E1000ValidateNvmChecksum(IN PE1000_ADAPTER Adapter
)
220 USHORT Checksum
= 0, Data
;
223 /* 5.6.35 Checksum Word Calculation (Word 3Fh) */
224 for (n
= 0; n
<= E1000_NVM_REG_CHECKSUM
; n
++)
226 if (!E1000ReadEeprom(Adapter
, n
, &Data
))
233 if (Checksum
!= NVM_MAGIC_SUM
)
235 NDIS_DbgPrint(MIN_TRACE
, ("EEPROM has an invalid checksum of 0x%x\n", (ULONG
)Checksum
));
245 NICRecognizeHardware(
246 IN PE1000_ADAPTER Adapter
)
249 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
251 if (Adapter
->VendorID
!= HW_VENDOR_INTEL
)
253 NDIS_DbgPrint(MIN_TRACE
, ("Unknown vendor: 0x%x\n", Adapter
->VendorID
));
257 for (n
= 0; n
< ARRAYSIZE(SupportedDevices
); ++n
)
259 if (SupportedDevices
[n
] == Adapter
->DeviceID
)
265 NDIS_DbgPrint(MIN_TRACE
, ("Unknown device: 0x%x\n", Adapter
->DeviceID
));
272 NICInitializeAdapterResources(
273 IN PE1000_ADAPTER Adapter
,
274 IN PNDIS_RESOURCE_LIST ResourceList
)
277 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
279 for (n
= 0; n
< ResourceList
->Count
; n
++)
281 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor
= ResourceList
->PartialDescriptors
+ n
;
283 switch (ResourceDescriptor
->Type
)
285 case CmResourceTypePort
:
286 ASSERT(Adapter
->IoPortAddress
== 0);
287 ASSERT(ResourceDescriptor
->u
.Port
.Start
.HighPart
== 0);
289 Adapter
->IoPortAddress
= ResourceDescriptor
->u
.Port
.Start
.LowPart
;
290 Adapter
->IoPortLength
= ResourceDescriptor
->u
.Port
.Length
;
292 NDIS_DbgPrint(MID_TRACE
, ("I/O port range is %p to %p\n",
293 Adapter
->IoPortAddress
,
294 Adapter
->IoPortAddress
+ Adapter
->IoPortLength
));
296 case CmResourceTypeInterrupt
:
297 ASSERT(Adapter
->InterruptVector
== 0);
298 ASSERT(Adapter
->InterruptLevel
== 0);
300 Adapter
->InterruptVector
= ResourceDescriptor
->u
.Interrupt
.Vector
;
301 Adapter
->InterruptLevel
= ResourceDescriptor
->u
.Interrupt
.Level
;
302 Adapter
->InterruptShared
= (ResourceDescriptor
->ShareDisposition
== CmResourceShareShared
);
303 Adapter
->InterruptFlags
= ResourceDescriptor
->Flags
;
305 NDIS_DbgPrint(MID_TRACE
, ("IRQ vector is %d\n", Adapter
->InterruptVector
));
307 case CmResourceTypeMemory
:
308 /* Internal registers and memories (including PHY) */
309 if (ResourceDescriptor
->u
.Memory
.Length
== (128 * 1024))
311 ASSERT(Adapter
->IoAddress
.LowPart
== 0);
312 ASSERT(ResourceDescriptor
->u
.Port
.Start
.HighPart
== 0);
315 Adapter
->IoAddress
.QuadPart
= ResourceDescriptor
->u
.Memory
.Start
.QuadPart
;
316 Adapter
->IoLength
= ResourceDescriptor
->u
.Memory
.Length
;
317 NDIS_DbgPrint(MID_TRACE
, ("Memory range is %I64x to %I64x\n",
318 Adapter
->IoAddress
.QuadPart
,
319 Adapter
->IoAddress
.QuadPart
+ Adapter
->IoLength
));
324 NDIS_DbgPrint(MIN_TRACE
, ("Unrecognized resource type: 0x%x\n", ResourceDescriptor
->Type
));
329 if (Adapter
->IoAddress
.QuadPart
== 0 || Adapter
->IoPortAddress
== 0 || Adapter
->InterruptVector
== 0)
331 NDIS_DbgPrint(MIN_TRACE
, ("Adapter didn't receive enough resources\n"));
332 return NDIS_STATUS_RESOURCES
;
335 return NDIS_STATUS_SUCCESS
;
340 NICAllocateIoResources(
341 IN PE1000_ADAPTER Adapter
)
344 ULONG AllocationSize
;
347 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
349 Status
= NdisMRegisterIoPortRange((PVOID
*)&Adapter
->IoPort
,
350 Adapter
->AdapterHandle
,
351 Adapter
->IoPortAddress
,
352 Adapter
->IoPortLength
);
353 if (Status
!= NDIS_STATUS_SUCCESS
)
355 NDIS_DbgPrint(MIN_TRACE
, ("Unable to register IO port range (0x%x)\n", Status
));
356 return NDIS_STATUS_RESOURCES
;
359 Status
= NdisMMapIoSpace((PVOID
*)&Adapter
->IoBase
,
360 Adapter
->AdapterHandle
,
365 NdisMAllocateSharedMemory(Adapter
->AdapterHandle
,
366 sizeof(E1000_TRANSMIT_DESCRIPTOR
) * NUM_TRANSMIT_DESCRIPTORS
,
368 (PVOID
*)&Adapter
->TransmitDescriptors
,
369 &Adapter
->TransmitDescriptorsPa
);
370 if (Adapter
->TransmitDescriptors
== NULL
)
372 NDIS_DbgPrint(MIN_TRACE
, ("Unable to allocate transmit descriptors\n"));
373 return NDIS_STATUS_RESOURCES
;
376 for (n
= 0; n
< NUM_TRANSMIT_DESCRIPTORS
; ++n
)
378 PE1000_TRANSMIT_DESCRIPTOR Descriptor
= Adapter
->TransmitDescriptors
+ n
;
379 Descriptor
->Address
= 0;
380 Descriptor
->Length
= 0;
383 NdisMAllocateSharedMemory(Adapter
->AdapterHandle
,
384 sizeof(E1000_RECEIVE_DESCRIPTOR
) * NUM_RECEIVE_DESCRIPTORS
,
386 (PVOID
*)&Adapter
->ReceiveDescriptors
,
387 &Adapter
->ReceiveDescriptorsPa
);
388 if (Adapter
->ReceiveDescriptors
== NULL
)
390 NDIS_DbgPrint(MIN_TRACE
, ("Unable to allocate receive descriptors\n"));
391 return NDIS_STATUS_RESOURCES
;
394 AllocationSize
= RcvBufAllocationSize(Adapter
->ReceiveBufferType
);
395 ASSERT(Adapter
->ReceiveBufferEntrySize
== 0 || Adapter
->ReceiveBufferEntrySize
== AllocationSize
);
396 Adapter
->ReceiveBufferEntrySize
= AllocationSize
;
398 NdisMAllocateSharedMemory(Adapter
->AdapterHandle
,
399 Adapter
->ReceiveBufferEntrySize
* NUM_RECEIVE_DESCRIPTORS
,
401 (PVOID
*)&Adapter
->ReceiveBuffer
,
402 &Adapter
->ReceiveBufferPa
);
404 if (Adapter
->ReceiveBuffer
== NULL
)
406 NDIS_DbgPrint(MIN_TRACE
, ("Unable to allocate receive buffer\n"));
407 return NDIS_STATUS_RESOURCES
;
410 for (n
= 0; n
< NUM_RECEIVE_DESCRIPTORS
; ++n
)
412 PE1000_RECEIVE_DESCRIPTOR Descriptor
= Adapter
->ReceiveDescriptors
+ n
;
414 RtlZeroMemory(Descriptor
, sizeof(*Descriptor
));
415 Descriptor
->Address
= Adapter
->ReceiveBufferPa
.QuadPart
+ n
* Adapter
->ReceiveBufferEntrySize
;
418 return NDIS_STATUS_SUCCESS
;
423 NICRegisterInterrupts(
424 IN PE1000_ADAPTER Adapter
)
427 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
429 Status
= NdisMRegisterInterrupt(&Adapter
->Interrupt
,
430 Adapter
->AdapterHandle
,
431 Adapter
->InterruptVector
,
432 Adapter
->InterruptLevel
,
433 TRUE
, // We always want ISR calls
434 Adapter
->InterruptShared
,
435 (Adapter
->InterruptFlags
& CM_RESOURCE_INTERRUPT_LATCHED
) ?
436 NdisInterruptLatched
: NdisInterruptLevelSensitive
);
438 if (Status
== NDIS_STATUS_SUCCESS
)
440 Adapter
->InterruptRegistered
= TRUE
;
448 NICUnregisterInterrupts(
449 IN PE1000_ADAPTER Adapter
)
451 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
453 if (Adapter
->InterruptRegistered
)
455 NdisMDeregisterInterrupt(&Adapter
->Interrupt
);
456 Adapter
->InterruptRegistered
= FALSE
;
459 return NDIS_STATUS_SUCCESS
;
464 NICReleaseIoResources(
465 IN PE1000_ADAPTER Adapter
)
467 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
469 if (Adapter
->ReceiveDescriptors
!= NULL
)
471 /* Disassociate our shared buffer before freeing it to avoid NIC-induced memory corruption */
474 E1000WriteUlong(Adapter
, E1000_REG_RDH
, 0);
475 E1000WriteUlong(Adapter
, E1000_REG_RDT
, 0);
478 NdisMFreeSharedMemory(Adapter
->AdapterHandle
,
479 sizeof(E1000_RECEIVE_DESCRIPTOR
) * NUM_RECEIVE_DESCRIPTORS
,
481 Adapter
->ReceiveDescriptors
,
482 Adapter
->ReceiveDescriptorsPa
);
484 Adapter
->ReceiveDescriptors
= NULL
;
487 if (Adapter
->ReceiveBuffer
!= NULL
)
489 NdisMFreeSharedMemory(Adapter
->AdapterHandle
,
490 Adapter
->ReceiveBufferEntrySize
* NUM_RECEIVE_DESCRIPTORS
,
492 Adapter
->ReceiveBuffer
,
493 Adapter
->ReceiveBufferPa
);
495 Adapter
->ReceiveBuffer
= NULL
;
496 Adapter
->ReceiveBufferEntrySize
= 0;
500 if (Adapter
->TransmitDescriptors
!= NULL
)
502 /* Disassociate our shared buffer before freeing it to avoid NIC-induced memory corruption */
505 E1000WriteUlong(Adapter
, E1000_REG_TDH
, 0);
506 E1000WriteUlong(Adapter
, E1000_REG_TDT
, 0);
509 NdisMFreeSharedMemory(Adapter
->AdapterHandle
,
510 sizeof(E1000_TRANSMIT_DESCRIPTOR
) * NUM_TRANSMIT_DESCRIPTORS
,
512 Adapter
->TransmitDescriptors
,
513 Adapter
->TransmitDescriptorsPa
);
515 Adapter
->TransmitDescriptors
= NULL
;
522 NdisMDeregisterIoPortRange(Adapter
->AdapterHandle
,
523 Adapter
->IoPortAddress
,
524 Adapter
->IoPortLength
,
530 NdisMUnmapIoSpace(Adapter
->AdapterHandle
, Adapter
->IoBase
, Adapter
->IoLength
);
534 return NDIS_STATUS_SUCCESS
;
541 IN PE1000_ADAPTER Adapter
)
544 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
546 Status
= NICSoftReset(Adapter
);
547 if (Status
!= NDIS_STATUS_SUCCESS
)
552 if (!E1000ValidateNvmChecksum(Adapter
))
554 return NDIS_STATUS_INVALID_DATA
;
557 return NDIS_STATUS_SUCCESS
;
563 IN PE1000_ADAPTER Adapter
)
565 ULONG Value
, ResetAttempts
;
566 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
568 NICDisableInterrupts(Adapter
);
569 E1000WriteUlong(Adapter
, E1000_REG_RCTL
, 0);
570 E1000WriteUlong(Adapter
, E1000_REG_TCTL
, 0);
571 E1000ReadUlong(Adapter
, E1000_REG_CTRL
, &Value
);
572 /* Write this using IO port, some devices cannot ack this otherwise */
573 E1000WriteIoUlong(Adapter
, E1000_REG_CTRL
, Value
| E1000_CTRL_RST
);
576 for (ResetAttempts
= 0; ResetAttempts
< MAX_RESET_ATTEMPTS
; ResetAttempts
++)
578 /* Wait 1us after reset (according to manual) */
579 NdisStallExecution(1);
580 E1000ReadUlong(Adapter
, E1000_REG_CTRL
, &Value
);
582 if (!(Value
& E1000_CTRL_RST
))
584 NDIS_DbgPrint(MAX_TRACE
, ("Device is back (%u)\n", ResetAttempts
));
586 NICDisableInterrupts(Adapter
);
587 /* Clear out interrupts (the register is cleared upon read) */
588 E1000ReadUlong(Adapter
, E1000_REG_ICR
, &Value
);
590 E1000ReadUlong(Adapter
, E1000_REG_CTRL
, &Value
);
591 Value
&= ~(E1000_CTRL_LRST
|E1000_CTRL_VME
);
592 Value
|= (E1000_CTRL_ASDE
|E1000_CTRL_SLU
);
593 E1000WriteUlong(Adapter
, E1000_REG_CTRL
, Value
);
595 return NDIS_STATUS_SUCCESS
;
599 NDIS_DbgPrint(MIN_TRACE
, ("Device did not recover\n"));
600 return NDIS_STATUS_FAILURE
;
606 IN PE1000_ADAPTER Adapter
)
610 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
611 NDIS_DbgPrint(MID_TRACE
, ("Setting up transmit.\n"));
613 /* Make sure the thing is disabled first. */
614 E1000WriteUlong(Adapter
, E1000_REG_TCTL
, 0);
616 /* Transmit descriptor ring buffer */
617 E1000WriteUlong(Adapter
, E1000_REG_TDBAH
, Adapter
->TransmitDescriptorsPa
.HighPart
);
618 E1000WriteUlong(Adapter
, E1000_REG_TDBAL
, Adapter
->TransmitDescriptorsPa
.LowPart
);
620 /* Transmit descriptor buffer size */
621 E1000WriteUlong(Adapter
, E1000_REG_TDLEN
, sizeof(E1000_TRANSMIT_DESCRIPTOR
) * NUM_TRANSMIT_DESCRIPTORS
);
623 /* Transmit descriptor tail / head */
624 E1000WriteUlong(Adapter
, E1000_REG_TDH
, 0);
625 E1000WriteUlong(Adapter
, E1000_REG_TDT
, 0);
626 Adapter
->CurrentTxDesc
= 0;
628 /* Set up interrupt timers */
629 E1000WriteUlong(Adapter
, E1000_REG_TADV
, 96); // value is in 1.024 of usec
630 E1000WriteUlong(Adapter
, E1000_REG_TIDV
, 16);
632 E1000WriteUlong(Adapter
, E1000_REG_TCTL
, E1000_TCTL_EN
| E1000_TCTL_PSP
);
634 E1000WriteUlong(Adapter
, E1000_REG_TIPG
, E1000_TIPG_IPGT_DEF
| E1000_TIPG_IPGR1_DEF
| E1000_TIPG_IPGR2_DEF
);
636 NDIS_DbgPrint(MID_TRACE
, ("Setting up receive.\n"));
638 /* Make sure the thing is disabled first. */
639 E1000WriteUlong(Adapter
, E1000_REG_RCTL
, 0);
641 /* Receive descriptor ring buffer */
642 E1000WriteUlong(Adapter
, E1000_REG_RDBAH
, Adapter
->ReceiveDescriptorsPa
.HighPart
);
643 E1000WriteUlong(Adapter
, E1000_REG_RDBAL
, Adapter
->ReceiveDescriptorsPa
.LowPart
);
645 /* Receive descriptor buffer size */
646 E1000WriteUlong(Adapter
, E1000_REG_RDLEN
, sizeof(E1000_RECEIVE_DESCRIPTOR
) * NUM_RECEIVE_DESCRIPTORS
);
648 /* Receive descriptor tail / head */
649 E1000WriteUlong(Adapter
, E1000_REG_RDH
, 0);
650 E1000WriteUlong(Adapter
, E1000_REG_RDT
, NUM_RECEIVE_DESCRIPTORS
- 1);
652 /* Set up interrupt timers */
653 E1000WriteUlong(Adapter
, E1000_REG_RADV
, 96);
654 E1000WriteUlong(Adapter
, E1000_REG_RDTR
, 16);
657 Value
= E1000_RCTL_SECRC
| E1000_RCTL_EN
;
659 /* Receive buffer size */
660 Value
|= RcvBufRegisterMask(Adapter
->ReceiveBufferType
);
662 /* Add our current packet filter */
663 Value
|= PacketFilterToMask(Adapter
->PacketFilter
);
665 E1000WriteUlong(Adapter
, E1000_REG_RCTL
, Value
);
667 return NDIS_STATUS_SUCCESS
;
673 IN PE1000_ADAPTER Adapter
)
677 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
679 E1000ReadUlong(Adapter
, E1000_REG_TCTL
, &Value
);
680 Value
&= ~E1000_TCTL_EN
;
681 E1000WriteUlong(Adapter
, E1000_REG_TCTL
, Value
);
683 E1000ReadUlong(Adapter
, E1000_REG_RCTL
, &Value
);
684 Value
&= ~E1000_RCTL_EN
;
685 E1000WriteUlong(Adapter
, E1000_REG_RCTL
, Value
);
687 return NDIS_STATUS_SUCCESS
;
692 NICGetPermanentMacAddress(
693 IN PE1000_ADAPTER Adapter
,
694 OUT PUCHAR MacAddress
)
699 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
701 /* Should we read from RAL/RAH first? */
702 for (n
= 0; n
< (IEEE_802_ADDR_LENGTH
/ 2); ++n
)
704 if (!E1000ReadEeprom(Adapter
, (UCHAR
)n
, &AddrWord
))
705 return NDIS_STATUS_FAILURE
;
706 Adapter
->PermanentMacAddress
[n
* 2 + 0] = AddrWord
& 0xff;
707 Adapter
->PermanentMacAddress
[n
* 2 + 1] = (AddrWord
>> 8) & 0xff;
710 NDIS_DbgPrint(MIN_TRACE
, ("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
711 Adapter
->PermanentMacAddress
[0],
712 Adapter
->PermanentMacAddress
[1],
713 Adapter
->PermanentMacAddress
[2],
714 Adapter
->PermanentMacAddress
[3],
715 Adapter
->PermanentMacAddress
[4],
716 Adapter
->PermanentMacAddress
[5]));
717 return NDIS_STATUS_SUCCESS
;
722 NICUpdateMulticastList(
723 IN PE1000_ADAPTER Adapter
)
726 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
728 for (n
= 0; n
< MAXIMUM_MULTICAST_ADDRESSES
; ++n
)
730 ULONG Ral
= *(ULONG
*)Adapter
->MulticastList
[n
].MacAddress
;
731 ULONG Rah
= *(USHORT
*)&Adapter
->MulticastList
[n
].MacAddress
[4];
737 E1000WriteUlong(Adapter
, E1000_REG_RAL
+ (8*n
), Ral
);
738 E1000WriteUlong(Adapter
, E1000_REG_RAH
+ (8*n
), Rah
);
742 E1000WriteUlong(Adapter
, E1000_REG_RAH
+ (8*n
), 0);
743 E1000WriteUlong(Adapter
, E1000_REG_RAL
+ (8*n
), 0);
747 return NDIS_STATUS_SUCCESS
;
752 NICApplyPacketFilter(
753 IN PE1000_ADAPTER Adapter
)
757 E1000ReadUlong(Adapter
, E1000_REG_RCTL
, &FilterMask
);
759 FilterMask
&= ~E1000_RCTL_FILTER_BITS
;
760 FilterMask
|= PacketFilterToMask(Adapter
->PacketFilter
);
761 E1000WriteUlong(Adapter
, E1000_REG_RCTL
, FilterMask
);
763 return NDIS_STATUS_SUCCESS
;
768 NICApplyInterruptMask(
769 IN PE1000_ADAPTER Adapter
)
771 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
773 E1000WriteUlong(Adapter
, E1000_REG_IMS
, Adapter
->InterruptMask
/*| 0x1F6DC*/);
774 return NDIS_STATUS_SUCCESS
;
779 NICDisableInterrupts(
780 IN PE1000_ADAPTER Adapter
)
782 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
784 E1000WriteUlong(Adapter
, E1000_REG_IMC
, ~0);
785 return NDIS_STATUS_SUCCESS
;
790 NICInterruptRecognized(
791 IN PE1000_ADAPTER Adapter
,
792 OUT PBOOLEAN InterruptRecognized
)
796 /* Reading the interrupt acknowledges them */
797 E1000ReadUlong(Adapter
, E1000_REG_ICR
, &Value
);
799 *InterruptRecognized
= (Value
& Adapter
->InterruptMask
) != 0;
801 NDIS_DbgPrint(MAX_TRACE
, ("NICInterruptRecognized(0x%x, 0x%x).\n", Value
, *InterruptRecognized
));
803 return (Value
& Adapter
->InterruptMask
);
809 IN PE1000_ADAPTER Adapter
)
813 static ULONG SpeedValues
[] = { 10, 100, 1000, 1000 };
815 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
817 E1000ReadUlong(Adapter
, E1000_REG_STATUS
, &DeviceStatus
);
818 Adapter
->MediaState
= (DeviceStatus
& E1000_STATUS_LU
) ? NdisMediaStateConnected
: NdisMediaStateDisconnected
;
819 SpeedIndex
= (DeviceStatus
& E1000_STATUS_SPEEDMASK
) >> E1000_STATUS_SPEEDSHIFT
;
820 Adapter
->LinkSpeedMbps
= SpeedValues
[SpeedIndex
];
826 IN PE1000_ADAPTER Adapter
,
827 IN PHYSICAL_ADDRESS PhysicalAddress
,
830 volatile PE1000_TRANSMIT_DESCRIPTOR TransmitDescriptor
;
832 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
834 TransmitDescriptor
= Adapter
->TransmitDescriptors
+ Adapter
->CurrentTxDesc
;
835 TransmitDescriptor
->Address
= PhysicalAddress
.QuadPart
;
836 TransmitDescriptor
->Length
= Length
;
837 TransmitDescriptor
->ChecksumOffset
= 0;
838 TransmitDescriptor
->Command
= E1000_TDESC_CMD_RS
| E1000_TDESC_CMD_IFCS
| E1000_TDESC_CMD_EOP
| E1000_TDESC_CMD_IDE
;
839 TransmitDescriptor
->Status
= 0;
840 TransmitDescriptor
->ChecksumStartField
= 0;
841 TransmitDescriptor
->Special
= 0;
843 Adapter
->CurrentTxDesc
= (Adapter
->CurrentTxDesc
+ 1) % NUM_TRANSMIT_DESCRIPTORS
;
845 E1000WriteUlong(Adapter
, E1000_REG_TDT
, Adapter
->CurrentTxDesc
);
847 if (Adapter
->CurrentTxDesc
== Adapter
->LastTxDesc
)
849 NDIS_DbgPrint(MID_TRACE
, ("All TX descriptors are full now\n"));
850 Adapter
->TxFull
= TRUE
;
853 return NDIS_STATUS_SUCCESS
;