1 /* 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) 7 */ 8 9 #include "nic.h" 10 11 #include <debug.h> 12 13 14 static USHORT SupportedDevices[] = 15 { 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 54 }; 55 56 static ULONG PacketFilterToMask(ULONG PacketFilter) 57 { 58 ULONG FilterMask = 0; 59 60 if (PacketFilter & NDIS_PACKET_TYPE_ALL_MULTICAST) 61 { 62 /* Multicast Promiscuous Enabled */ 63 FilterMask |= E1000_RCTL_MPE; 64 } 65 if (PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS) 66 { 67 /* Unicast Promiscuous Enabled */ 68 FilterMask |= E1000_RCTL_UPE; 69 /* Multicast Promiscuous Enabled */ 70 FilterMask |= E1000_RCTL_MPE; 71 } 72 if (PacketFilter & NDIS_PACKET_TYPE_MAC_FRAME) 73 { 74 /* Pass MAC Control Frames */ 75 FilterMask |= E1000_RCTL_PMCF; 76 } 77 if (PacketFilter & NDIS_PACKET_TYPE_BROADCAST) 78 { 79 /* Broadcast Accept Mode */ 80 FilterMask |= E1000_RCTL_BAM; 81 } 82 83 return FilterMask; 84 } 85 86 static ULONG RcvBufAllocationSize(E1000_RCVBUF_SIZE BufSize) 87 { 88 static ULONG PredefSizes[4] = { 89 2048, 1024, 512, 256, 90 }; 91 ULONG Size; 92 93 Size = PredefSizes[BufSize & E1000_RCVBUF_INDEXMASK]; 94 if (BufSize & E1000_RCVBUF_RESERVED) 95 { 96 ASSERT(BufSize != 2048); 97 Size *= 16; 98 } 99 return Size; 100 } 101 102 static ULONG RcvBufRegisterMask(E1000_RCVBUF_SIZE BufSize) 103 { 104 ULONG Mask = 0; 105 106 Mask |= BufSize & E1000_RCVBUF_INDEXMASK; 107 Mask <<= E1000_RCTL_BSIZE_SHIFT; 108 if (BufSize & E1000_RCVBUF_RESERVED) 109 Mask |= E1000_RCTL_BSEX; 110 111 return Mask; 112 } 113 114 #if 0 115 /* This function works, but the driver does not use PHY register access right now */ 116 static BOOLEAN E1000ReadMdic(IN PE1000_ADAPTER Adapter, IN ULONG Address, USHORT *Result) 117 { 118 ULONG ResultAddress; 119 ULONG Mdic; 120 UINT n; 121 122 ASSERT(Address <= MAX_PHY_REG_ADDRESS) 123 124 Mdic = (Address << E1000_MDIC_REGADD_SHIFT); 125 Mdic |= (E1000_MDIC_PHYADD_GIGABIT << E1000_MDIC_PHYADD_SHIFT); 126 Mdic |= E1000_MDIC_OP_READ; 127 E1000WriteUlong(Adapter, E1000_REG_MDIC, Mdic); 128 129 for (n = 0; n < MAX_PHY_READ_ATTEMPTS; n++) 130 { 131 NdisStallExecution(50); 132 E1000ReadUlong(Adapter, E1000_REG_MDIC, &Mdic); 133 if (Mdic & E1000_MDIC_R) 134 break; 135 } 136 if (!(Mdic & E1000_MDIC_R)) 137 { 138 NDIS_DbgPrint(MIN_TRACE, ("MDI Read incomplete\n")); 139 return FALSE; 140 } 141 if (Mdic & E1000_MDIC_E) 142 { 143 NDIS_DbgPrint(MIN_TRACE, ("MDI Read error\n")); 144 return FALSE; 145 } 146 147 ResultAddress = (Mdic >> E1000_MDIC_REGADD_SHIFT) & MAX_PHY_REG_ADDRESS; 148 149 if (ResultAddress!= Address) 150 { 151 /* Add locking? */ 152 NDIS_DbgPrint(MIN_TRACE, ("MDI Read got wrong address (%d instead of %d)\n", 153 ResultAddress, Address)); 154 return FALSE; 155 } 156 *Result = (USHORT) Mdic; 157 return TRUE; 158 } 159 #endif 160 161 162 static BOOLEAN E1000ReadEeprom(IN PE1000_ADAPTER Adapter, IN UCHAR Address, USHORT *Result) 163 { 164 ULONG Value; 165 UINT n; 166 167 E1000WriteUlong(Adapter, E1000_REG_EERD, E1000_EERD_START | ((UINT)Address << E1000_EERD_ADDR_SHIFT)); 168 169 for (n = 0; n < MAX_EEPROM_READ_ATTEMPTS; ++n) 170 { 171 NdisStallExecution(5); 172 173 E1000ReadUlong(Adapter, E1000_REG_EERD, &Value); 174 175 if (Value & E1000_EERD_DONE) 176 break; 177 } 178 if (!(Value & E1000_EERD_DONE)) 179 { 180 NDIS_DbgPrint(MIN_TRACE, ("EEPROM Read incomplete\n")); 181 return FALSE; 182 } 183 *Result = (USHORT)(Value >> E1000_EERD_DATA_SHIFT); 184 return TRUE; 185 } 186 187 BOOLEAN E1000ValidateNvmChecksum(IN PE1000_ADAPTER Adapter) 188 { 189 USHORT Checksum = 0, Data; 190 UINT n; 191 192 /* 5.6.35 Checksum Word Calculation (Word 3Fh) */ 193 for (n = 0; n <= E1000_NVM_REG_CHECKSUM; n++) 194 { 195 if (!E1000ReadEeprom(Adapter, n, &Data)) 196 { 197 return FALSE; 198 } 199 Checksum += Data; 200 } 201 202 if (Checksum != NVM_MAGIC_SUM) 203 { 204 NDIS_DbgPrint(MIN_TRACE, ("EEPROM has an invalid checksum of 0x%x\n", (ULONG)Checksum)); 205 return FALSE; 206 } 207 208 return TRUE; 209 } 210 211 212 BOOLEAN 213 NTAPI 214 NICRecognizeHardware( 215 IN PE1000_ADAPTER Adapter) 216 { 217 UINT n; 218 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 219 220 if (Adapter->VendorID != HW_VENDOR_INTEL) 221 { 222 NDIS_DbgPrint(MIN_TRACE, ("Unknown vendor: 0x%x\n", Adapter->VendorID)); 223 return FALSE; 224 } 225 226 for (n = 0; n < ARRAYSIZE(SupportedDevices); ++n) 227 { 228 if (SupportedDevices[n] == Adapter->DeviceID) 229 { 230 return TRUE; 231 } 232 } 233 234 NDIS_DbgPrint(MIN_TRACE, ("Unknown device: 0x%x\n", Adapter->DeviceID)); 235 236 return FALSE; 237 } 238 239 NDIS_STATUS 240 NTAPI 241 NICInitializeAdapterResources( 242 IN PE1000_ADAPTER Adapter, 243 IN PNDIS_RESOURCE_LIST ResourceList) 244 { 245 UINT n; 246 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 247 248 for (n = 0; n < ResourceList->Count; n++) 249 { 250 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor = ResourceList->PartialDescriptors + n; 251 252 switch (ResourceDescriptor->Type) 253 { 254 case CmResourceTypePort: 255 ASSERT(Adapter->IoPortAddress == 0); 256 ASSERT(ResourceDescriptor->u.Port.Start.HighPart == 0); 257 258 Adapter->IoPortAddress = ResourceDescriptor->u.Port.Start.LowPart; 259 Adapter->IoPortLength = ResourceDescriptor->u.Port.Length; 260 261 NDIS_DbgPrint(MID_TRACE, ("I/O port range is %p to %p\n", 262 Adapter->IoPortAddress, 263 Adapter->IoPortAddress + Adapter->IoPortLength)); 264 break; 265 case CmResourceTypeInterrupt: 266 ASSERT(Adapter->InterruptVector == 0); 267 ASSERT(Adapter->InterruptLevel == 0); 268 269 Adapter->InterruptVector = ResourceDescriptor->u.Interrupt.Vector; 270 Adapter->InterruptLevel = ResourceDescriptor->u.Interrupt.Level; 271 Adapter->InterruptShared = (ResourceDescriptor->ShareDisposition == CmResourceShareShared); 272 Adapter->InterruptFlags = ResourceDescriptor->Flags; 273 274 NDIS_DbgPrint(MID_TRACE, ("IRQ vector is %d\n", Adapter->InterruptVector)); 275 break; 276 case CmResourceTypeMemory: 277 /* Internal registers and memories (including PHY) */ 278 if (ResourceDescriptor->u.Memory.Length == (128 * 1024)) 279 { 280 ASSERT(Adapter->IoAddress.LowPart == 0); 281 ASSERT(ResourceDescriptor->u.Port.Start.HighPart == 0); 282 283 284 Adapter->IoAddress.QuadPart = ResourceDescriptor->u.Memory.Start.QuadPart; 285 Adapter->IoLength = ResourceDescriptor->u.Memory.Length; 286 NDIS_DbgPrint(MID_TRACE, ("Memory range is %I64x to %I64x\n", 287 Adapter->IoAddress.QuadPart, 288 Adapter->IoAddress.QuadPart + Adapter->IoLength)); 289 } 290 break; 291 292 default: 293 NDIS_DbgPrint(MIN_TRACE, ("Unrecognized resource type: 0x%x\n", ResourceDescriptor->Type)); 294 break; 295 } 296 } 297 298 if (Adapter->IoAddress.QuadPart == 0 || Adapter->IoPortAddress == 0 || Adapter->InterruptVector == 0) 299 { 300 NDIS_DbgPrint(MIN_TRACE, ("Adapter didn't receive enough resources\n")); 301 return NDIS_STATUS_RESOURCES; 302 } 303 304 return NDIS_STATUS_SUCCESS; 305 } 306 307 NDIS_STATUS 308 NTAPI 309 NICAllocateIoResources( 310 IN PE1000_ADAPTER Adapter) 311 { 312 NDIS_STATUS Status; 313 ULONG AllocationSize; 314 UINT n; 315 316 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 317 318 Status = NdisMRegisterIoPortRange((PVOID*)&Adapter->IoPort, 319 Adapter->AdapterHandle, 320 Adapter->IoPortAddress, 321 Adapter->IoPortLength); 322 if (Status != NDIS_STATUS_SUCCESS) 323 { 324 NDIS_DbgPrint(MIN_TRACE, ("Unable to register IO port range (0x%x)\n", Status)); 325 return NDIS_STATUS_RESOURCES; 326 } 327 328 Status = NdisMMapIoSpace((PVOID*)&Adapter->IoBase, 329 Adapter->AdapterHandle, 330 Adapter->IoAddress, 331 Adapter->IoLength); 332 333 334 NdisMAllocateSharedMemory(Adapter->AdapterHandle, 335 sizeof(E1000_TRANSMIT_DESCRIPTOR) * NUM_TRANSMIT_DESCRIPTORS, 336 FALSE, 337 (PVOID*)&Adapter->TransmitDescriptors, 338 &Adapter->TransmitDescriptorsPa); 339 if (Adapter->TransmitDescriptors == NULL) 340 { 341 NDIS_DbgPrint(MIN_TRACE, ("Unable to allocate transmit descriptors\n")); 342 return NDIS_STATUS_RESOURCES; 343 } 344 345 for (n = 0; n < NUM_TRANSMIT_DESCRIPTORS; ++n) 346 { 347 PE1000_TRANSMIT_DESCRIPTOR Descriptor = Adapter->TransmitDescriptors + n; 348 Descriptor->Address = 0; 349 Descriptor->Length = 0; 350 } 351 352 NdisMAllocateSharedMemory(Adapter->AdapterHandle, 353 sizeof(E1000_RECEIVE_DESCRIPTOR) * NUM_RECEIVE_DESCRIPTORS, 354 FALSE, 355 (PVOID*)&Adapter->ReceiveDescriptors, 356 &Adapter->ReceiveDescriptorsPa); 357 if (Adapter->ReceiveDescriptors == NULL) 358 { 359 NDIS_DbgPrint(MIN_TRACE, ("Unable to allocate receive descriptors\n")); 360 return NDIS_STATUS_RESOURCES; 361 } 362 363 AllocationSize = RcvBufAllocationSize(Adapter->ReceiveBufferType); 364 ASSERT(Adapter->ReceiveBufferEntrySize == 0 || Adapter->ReceiveBufferEntrySize == AllocationSize); 365 Adapter->ReceiveBufferEntrySize = AllocationSize; 366 367 NdisMAllocateSharedMemory(Adapter->AdapterHandle, 368 Adapter->ReceiveBufferEntrySize * NUM_RECEIVE_DESCRIPTORS, 369 FALSE, 370 (PVOID*)&Adapter->ReceiveBuffer, 371 &Adapter->ReceiveBufferPa); 372 373 if (Adapter->ReceiveBuffer == NULL) 374 { 375 NDIS_DbgPrint(MIN_TRACE, ("Unable to allocate receive buffer\n")); 376 return NDIS_STATUS_RESOURCES; 377 } 378 379 for (n = 0; n < NUM_RECEIVE_DESCRIPTORS; ++n) 380 { 381 PE1000_RECEIVE_DESCRIPTOR Descriptor = Adapter->ReceiveDescriptors + n; 382 383 RtlZeroMemory(Descriptor, sizeof(*Descriptor)); 384 Descriptor->Address = Adapter->ReceiveBufferPa.QuadPart + n * Adapter->ReceiveBufferEntrySize; 385 } 386 387 return NDIS_STATUS_SUCCESS; 388 } 389 390 NDIS_STATUS 391 NTAPI 392 NICRegisterInterrupts( 393 IN PE1000_ADAPTER Adapter) 394 { 395 NDIS_STATUS Status; 396 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 397 398 Status = NdisMRegisterInterrupt(&Adapter->Interrupt, 399 Adapter->AdapterHandle, 400 Adapter->InterruptVector, 401 Adapter->InterruptLevel, 402 TRUE, // We always want ISR calls 403 Adapter->InterruptShared, 404 (Adapter->InterruptFlags & CM_RESOURCE_INTERRUPT_LATCHED) ? 405 NdisInterruptLatched : NdisInterruptLevelSensitive); 406 407 if (Status == NDIS_STATUS_SUCCESS) 408 { 409 Adapter->InterruptRegistered = TRUE; 410 } 411 412 return Status; 413 } 414 415 NDIS_STATUS 416 NTAPI 417 NICUnregisterInterrupts( 418 IN PE1000_ADAPTER Adapter) 419 { 420 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 421 422 if (Adapter->InterruptRegistered) 423 { 424 NdisMDeregisterInterrupt(&Adapter->Interrupt); 425 Adapter->InterruptRegistered = FALSE; 426 } 427 428 return NDIS_STATUS_SUCCESS; 429 } 430 431 NDIS_STATUS 432 NTAPI 433 NICReleaseIoResources( 434 IN PE1000_ADAPTER Adapter) 435 { 436 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 437 438 if (Adapter->ReceiveDescriptors != NULL) 439 { 440 /* Disassociate our shared buffer before freeing it to avoid NIC-induced memory corruption */ 441 if (Adapter->IoBase) 442 { 443 E1000WriteUlong(Adapter, E1000_REG_RDH, 0); 444 E1000WriteUlong(Adapter, E1000_REG_RDT, 0); 445 } 446 447 NdisMFreeSharedMemory(Adapter->AdapterHandle, 448 sizeof(E1000_RECEIVE_DESCRIPTOR) * NUM_RECEIVE_DESCRIPTORS, 449 FALSE, 450 Adapter->ReceiveDescriptors, 451 Adapter->ReceiveDescriptorsPa); 452 453 Adapter->ReceiveDescriptors = NULL; 454 } 455 456 if (Adapter->ReceiveBuffer != NULL) 457 { 458 NdisMFreeSharedMemory(Adapter->AdapterHandle, 459 Adapter->ReceiveBufferEntrySize * NUM_RECEIVE_DESCRIPTORS, 460 FALSE, 461 Adapter->ReceiveBuffer, 462 Adapter->ReceiveBufferPa); 463 464 Adapter->ReceiveBuffer = NULL; 465 Adapter->ReceiveBufferEntrySize = 0; 466 } 467 468 469 if (Adapter->TransmitDescriptors != NULL) 470 { 471 /* Disassociate our shared buffer before freeing it to avoid NIC-induced memory corruption */ 472 if (Adapter->IoBase) 473 { 474 E1000WriteUlong(Adapter, E1000_REG_TDH, 0); 475 E1000WriteUlong(Adapter, E1000_REG_TDT, 0); 476 } 477 478 NdisMFreeSharedMemory(Adapter->AdapterHandle, 479 sizeof(E1000_TRANSMIT_DESCRIPTOR) * NUM_TRANSMIT_DESCRIPTORS, 480 FALSE, 481 Adapter->TransmitDescriptors, 482 Adapter->TransmitDescriptorsPa); 483 484 Adapter->TransmitDescriptors = NULL; 485 } 486 487 488 489 if (Adapter->IoPort) 490 { 491 NdisMDeregisterIoPortRange(Adapter->AdapterHandle, 492 Adapter->IoPortAddress, 493 Adapter->IoPortLength, 494 Adapter->IoPort); 495 } 496 497 if (Adapter->IoBase) 498 { 499 NdisMUnmapIoSpace(Adapter->AdapterHandle, Adapter->IoBase, Adapter->IoLength); 500 } 501 502 503 return NDIS_STATUS_SUCCESS; 504 } 505 506 507 NDIS_STATUS 508 NTAPI 509 NICPowerOn( 510 IN PE1000_ADAPTER Adapter) 511 { 512 NDIS_STATUS Status; 513 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 514 515 Status = NICSoftReset(Adapter); 516 if (Status != NDIS_STATUS_SUCCESS) 517 { 518 return Status; 519 } 520 521 if (!E1000ValidateNvmChecksum(Adapter)) 522 { 523 return NDIS_STATUS_INVALID_DATA; 524 } 525 526 return NDIS_STATUS_SUCCESS; 527 } 528 529 NDIS_STATUS 530 NTAPI 531 NICSoftReset( 532 IN PE1000_ADAPTER Adapter) 533 { 534 ULONG Value, ResetAttempts; 535 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 536 537 NICDisableInterrupts(Adapter); 538 E1000WriteUlong(Adapter, E1000_REG_RCTL, 0); 539 E1000WriteUlong(Adapter, E1000_REG_TCTL, 0); 540 E1000ReadUlong(Adapter, E1000_REG_CTRL, &Value); 541 /* Write this using IO port, some devices cannot ack this otherwise */ 542 E1000WriteIoUlong(Adapter, E1000_REG_CTRL, Value | E1000_CTRL_RST); 543 544 545 for (ResetAttempts = 0; ResetAttempts < MAX_RESET_ATTEMPTS; ResetAttempts++) 546 { 547 /* Wait 1us after reset (according to manual) */ 548 NdisStallExecution(1); 549 E1000ReadUlong(Adapter, E1000_REG_CTRL, &Value); 550 551 if (!(Value & E1000_CTRL_RST)) 552 { 553 NDIS_DbgPrint(MAX_TRACE, ("Device is back (%u)\n", ResetAttempts)); 554 555 NICDisableInterrupts(Adapter); 556 /* Clear out interrupts (the register is cleared upon read) */ 557 E1000ReadUlong(Adapter, E1000_REG_ICR, &Value); 558 559 E1000ReadUlong(Adapter, E1000_REG_CTRL, &Value); 560 Value &= ~(E1000_CTRL_LRST|E1000_CTRL_VME); 561 Value |= (E1000_CTRL_ASDE|E1000_CTRL_SLU); 562 E1000WriteUlong(Adapter, E1000_REG_CTRL, Value); 563 564 return NDIS_STATUS_SUCCESS; 565 } 566 } 567 568 NDIS_DbgPrint(MIN_TRACE, ("Device did not recover\n")); 569 return NDIS_STATUS_FAILURE; 570 } 571 572 NDIS_STATUS 573 NTAPI 574 NICEnableTxRx( 575 IN PE1000_ADAPTER Adapter) 576 { 577 ULONG Value; 578 579 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 580 NDIS_DbgPrint(MID_TRACE, ("Setting up transmit.\n")); 581 582 /* Make sure the thing is disabled first. */ 583 E1000WriteUlong(Adapter, E1000_REG_TCTL, 0); 584 585 /* Transmit descriptor ring buffer */ 586 E1000WriteUlong(Adapter, E1000_REG_TDBAH, Adapter->TransmitDescriptorsPa.HighPart); 587 E1000WriteUlong(Adapter, E1000_REG_TDBAL, Adapter->TransmitDescriptorsPa.LowPart); 588 589 /* Transmit descriptor buffer size */ 590 E1000WriteUlong(Adapter, E1000_REG_TDLEN, sizeof(E1000_TRANSMIT_DESCRIPTOR) * NUM_TRANSMIT_DESCRIPTORS); 591 592 /* Transmit descriptor tail / head */ 593 E1000WriteUlong(Adapter, E1000_REG_TDH, 0); 594 E1000WriteUlong(Adapter, E1000_REG_TDT, 0); 595 Adapter->CurrentTxDesc = 0; 596 597 /* Set up interrupt timers */ 598 E1000WriteUlong(Adapter, E1000_REG_TADV, 96); // value is in 1.024 of usec 599 E1000WriteUlong(Adapter, E1000_REG_TIDV, 16); 600 601 E1000WriteUlong(Adapter, E1000_REG_TCTL, E1000_TCTL_EN | E1000_TCTL_PSP); 602 603 E1000WriteUlong(Adapter, E1000_REG_TIPG, E1000_TIPG_IPGT_DEF | E1000_TIPG_IPGR1_DEF | E1000_TIPG_IPGR2_DEF); 604 605 NDIS_DbgPrint(MID_TRACE, ("Setting up receive.\n")); 606 607 /* Make sure the thing is disabled first. */ 608 E1000WriteUlong(Adapter, E1000_REG_RCTL, 0); 609 610 /* Receive descriptor ring buffer */ 611 E1000WriteUlong(Adapter, E1000_REG_RDBAH, Adapter->ReceiveDescriptorsPa.HighPart); 612 E1000WriteUlong(Adapter, E1000_REG_RDBAL, Adapter->ReceiveDescriptorsPa.LowPart); 613 614 /* Receive descriptor buffer size */ 615 E1000WriteUlong(Adapter, E1000_REG_RDLEN, sizeof(E1000_RECEIVE_DESCRIPTOR) * NUM_RECEIVE_DESCRIPTORS); 616 617 /* Receive descriptor tail / head */ 618 E1000WriteUlong(Adapter, E1000_REG_RDH, 0); 619 E1000WriteUlong(Adapter, E1000_REG_RDT, NUM_RECEIVE_DESCRIPTORS - 1); 620 621 /* Set up interrupt timers */ 622 E1000WriteUlong(Adapter, E1000_REG_RADV, 96); 623 E1000WriteUlong(Adapter, E1000_REG_RDTR, 16); 624 625 /* Some defaults */ 626 Value = E1000_RCTL_SECRC | E1000_RCTL_EN; 627 628 /* Receive buffer size */ 629 Value |= RcvBufRegisterMask(Adapter->ReceiveBufferType); 630 631 /* Add our current packet filter */ 632 Value |= PacketFilterToMask(Adapter->PacketFilter); 633 634 E1000WriteUlong(Adapter, E1000_REG_RCTL, Value); 635 636 return NDIS_STATUS_SUCCESS; 637 } 638 639 NDIS_STATUS 640 NTAPI 641 NICDisableTxRx( 642 IN PE1000_ADAPTER Adapter) 643 { 644 ULONG Value; 645 646 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 647 648 E1000ReadUlong(Adapter, E1000_REG_TCTL, &Value); 649 Value &= ~E1000_TCTL_EN; 650 E1000WriteUlong(Adapter, E1000_REG_TCTL, Value); 651 652 E1000ReadUlong(Adapter, E1000_REG_RCTL, &Value); 653 Value &= ~E1000_RCTL_EN; 654 E1000WriteUlong(Adapter, E1000_REG_RCTL, Value); 655 656 return NDIS_STATUS_SUCCESS; 657 } 658 659 NDIS_STATUS 660 NTAPI 661 NICGetPermanentMacAddress( 662 IN PE1000_ADAPTER Adapter, 663 OUT PUCHAR MacAddress) 664 { 665 USHORT AddrWord; 666 UINT n; 667 668 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 669 670 /* Should we read from RAL/RAH first? */ 671 for (n = 0; n < (IEEE_802_ADDR_LENGTH / 2); ++n) 672 { 673 if (!E1000ReadEeprom(Adapter, (UCHAR)n, &AddrWord)) 674 return NDIS_STATUS_FAILURE; 675 Adapter->PermanentMacAddress[n * 2 + 0] = AddrWord & 0xff; 676 Adapter->PermanentMacAddress[n * 2 + 1] = (AddrWord >> 8) & 0xff; 677 } 678 679 #if 0 680 NDIS_DbgPrint(MIN_TRACE, ("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", 681 Adapter->PermanentMacAddress[0], 682 Adapter->PermanentMacAddress[1], 683 Adapter->PermanentMacAddress[2], 684 Adapter->PermanentMacAddress[3], 685 Adapter->PermanentMacAddress[4], 686 Adapter->PermanentMacAddress[5])); 687 #endif 688 return NDIS_STATUS_SUCCESS; 689 } 690 691 NDIS_STATUS 692 NTAPI 693 NICUpdateMulticastList( 694 IN PE1000_ADAPTER Adapter) 695 { 696 UINT n; 697 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 698 699 // FIXME: Use 'Adapter->MulticastListSize'? Check the datasheet 700 for (n = 0; n < MAXIMUM_MULTICAST_ADDRESSES; ++n) 701 { 702 ULONG Ral = *(ULONG *)Adapter->MulticastList[n].MacAddress; 703 ULONG Rah = *(USHORT *)&Adapter->MulticastList[n].MacAddress[4]; 704 705 if (Rah || Ral) 706 { 707 Rah |= E1000_RAH_AV; 708 709 E1000WriteUlong(Adapter, E1000_REG_RAL + (8*n), Ral); 710 E1000WriteUlong(Adapter, E1000_REG_RAH + (8*n), Rah); 711 } 712 else 713 { 714 E1000WriteUlong(Adapter, E1000_REG_RAH + (8*n), 0); 715 E1000WriteUlong(Adapter, E1000_REG_RAL + (8*n), 0); 716 } 717 } 718 719 return NDIS_STATUS_SUCCESS; 720 } 721 722 NDIS_STATUS 723 NTAPI 724 NICApplyPacketFilter( 725 IN PE1000_ADAPTER Adapter) 726 { 727 ULONG FilterMask; 728 729 E1000ReadUlong(Adapter, E1000_REG_RCTL, &FilterMask); 730 731 FilterMask &= ~E1000_RCTL_FILTER_BITS; 732 FilterMask |= PacketFilterToMask(Adapter->PacketFilter); 733 E1000WriteUlong(Adapter, E1000_REG_RCTL, FilterMask); 734 735 return NDIS_STATUS_SUCCESS; 736 } 737 738 VOID 739 NTAPI 740 NICUpdateLinkStatus( 741 IN PE1000_ADAPTER Adapter) 742 { 743 ULONG DeviceStatus; 744 SIZE_T SpeedIndex; 745 static ULONG SpeedValues[] = { 10, 100, 1000, 1000 }; 746 747 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 748 749 E1000ReadUlong(Adapter, E1000_REG_STATUS, &DeviceStatus); 750 Adapter->MediaState = (DeviceStatus & E1000_STATUS_LU) ? NdisMediaStateConnected : NdisMediaStateDisconnected; 751 SpeedIndex = (DeviceStatus & E1000_STATUS_SPEEDMASK) >> E1000_STATUS_SPEEDSHIFT; 752 Adapter->LinkSpeedMbps = SpeedValues[SpeedIndex]; 753 } 754