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