1 /* 2 * PROJECT: ReactOS nVidia nForce Ethernet Controller Driver 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: NIC support code 5 * COPYRIGHT: Copyright 2021-2022 Dmitry Borisov <di.sean@protonmail.com> 6 */ 7 8 /* 9 * HW access code was taken from the Linux forcedeth driver 10 * Copyright (C) 2003,4,5 Manfred Spraul 11 * Copyright (C) 2004 Andrew de Quincey 12 * Copyright (C) 2004 Carl-Daniel Hailfinger 13 * Copyright (c) 2004,2005,2006,2007,2008,2009 NVIDIA Corporation 14 */ 15 16 /* INCLUDES *******************************************************************/ 17 18 #include "nvnet.h" 19 20 #define NDEBUG 21 #include "debug.h" 22 23 /* FUNCTIONS ******************************************************************/ 24 25 static 26 CODE_SEG("PAGE") 27 VOID 28 NvNetClearStatisticsCounters( 29 _In_ PNVNET_ADAPTER Adapter) 30 { 31 NVNET_REGISTER Counter, CounterEnd; 32 33 PAGED_CODE(); 34 35 NDIS_DbgPrint(MIN_TRACE, ("()\n")); 36 37 if (Adapter->Features & DEV_HAS_STATISTICS_V2) 38 CounterEnd = NvRegRxDropFrame; 39 else 40 CounterEnd = NvRegRxBroadcast; 41 42 for (Counter = NvRegTxCnt; Counter <= CounterEnd; Counter += sizeof(ULONG)) 43 { 44 NV_READ(Adapter, Counter); 45 } 46 47 if (Adapter->Features & DEV_HAS_STATISTICS_V3) 48 { 49 NV_READ(Adapter, NvRegTxUnicast); 50 NV_READ(Adapter, NvRegTxMulticast); 51 NV_READ(Adapter, NvRegTxBroadcast); 52 } 53 } 54 55 static 56 CODE_SEG("PAGE") 57 VOID 58 NvNetResetMac( 59 _In_ PNVNET_ADAPTER Adapter) 60 { 61 ULONG Temp[3]; 62 63 NDIS_DbgPrint(MIN_TRACE, ("()\n")); 64 65 if (!(Adapter->Features & DEV_HAS_POWER_CNTRL)) 66 return; 67 68 NV_WRITE(Adapter, NvRegTxRxControl, 69 Adapter->TxRxControl | NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET); 70 71 /* Save registers since they will be cleared on reset */ 72 Temp[0] = NV_READ(Adapter, NvRegMacAddrA); 73 Temp[1] = NV_READ(Adapter, NvRegMacAddrB); 74 Temp[2] = NV_READ(Adapter, NvRegTransmitPoll); 75 76 NV_WRITE(Adapter, NvRegMacReset, NVREG_MAC_RESET_ASSERT); 77 NdisStallExecution(NV_MAC_RESET_DELAY); 78 NV_WRITE(Adapter, NvRegMacReset, 0); 79 NdisStallExecution(NV_MAC_RESET_DELAY); 80 81 /* Restore saved registers */ 82 NV_WRITE(Adapter, NvRegMacAddrA, Temp[0]); 83 NV_WRITE(Adapter, NvRegMacAddrB, Temp[1]); 84 NV_WRITE(Adapter, NvRegTransmitPoll, Temp[2]); 85 86 NV_WRITE(Adapter, NvRegTxRxControl, 87 Adapter->TxRxControl | NVREG_TXRXCTL_BIT2); 88 } 89 90 VOID 91 NvNetResetReceiverAndTransmitter( 92 _In_ PNVNET_ADAPTER Adapter) 93 { 94 NV_WRITE(Adapter, NvRegTxRxControl, 95 Adapter->TxRxControl | NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET); 96 97 NdisStallExecution(NV_TXRX_RESET_DELAY); 98 99 NV_WRITE(Adapter, NvRegTxRxControl, 100 Adapter->TxRxControl | NVREG_TXRXCTL_BIT2); 101 } 102 103 VOID 104 NvNetStartReceiver( 105 _In_ PNVNET_ADAPTER Adapter) 106 { 107 ULONG RxControl; 108 109 NDIS_DbgPrint(MIN_TRACE, ("()\n")); 110 111 RxControl = NV_READ(Adapter, NvRegReceiverControl); 112 if ((NV_READ(Adapter, NvRegReceiverControl) & NVREG_RCVCTL_START) && 113 !(Adapter->Flags & NV_MAC_IN_USE)) 114 { 115 /* Already running? Stop it */ 116 RxControl &= ~NVREG_RCVCTL_START; 117 NV_WRITE(Adapter, NvRegReceiverControl, RxControl); 118 } 119 NV_WRITE(Adapter, NvRegLinkSpeed, Adapter->LinkSpeed | NVREG_LINKSPEED_FORCE); 120 121 RxControl |= NVREG_RCVCTL_START; 122 if (Adapter->Flags & NV_MAC_IN_USE) 123 { 124 RxControl &= ~NVREG_RCVCTL_RX_PATH_EN; 125 } 126 NV_WRITE(Adapter, NvRegReceiverControl, RxControl); 127 } 128 129 VOID 130 NvNetStartTransmitter( 131 _In_ PNVNET_ADAPTER Adapter) 132 { 133 ULONG TxControl; 134 135 NDIS_DbgPrint(MIN_TRACE, ("()\n")); 136 137 TxControl = NV_READ(Adapter, NvRegTransmitterControl); 138 TxControl |= NVREG_XMITCTL_START; 139 if (Adapter->Flags & NV_MAC_IN_USE) 140 { 141 TxControl &= ~NVREG_XMITCTL_TX_PATH_EN; 142 } 143 NV_WRITE(Adapter, NvRegTransmitterControl, TxControl); 144 } 145 146 VOID 147 NvNetStopReceiver( 148 _In_ PNVNET_ADAPTER Adapter) 149 { 150 ULONG RxControl, i; 151 152 NDIS_DbgPrint(MIN_TRACE, ("()\n")); 153 154 RxControl = NV_READ(Adapter, NvRegReceiverControl); 155 if (!(Adapter->Flags & NV_MAC_IN_USE)) 156 RxControl &= ~NVREG_RCVCTL_START; 157 else 158 RxControl |= NVREG_RCVCTL_RX_PATH_EN; 159 NV_WRITE(Adapter, NvRegReceiverControl, RxControl); 160 161 for (i = 0; i < NV_RXSTOP_DELAY1MAX; ++i) 162 { 163 if (!(NV_READ(Adapter, NvRegReceiverStatus) & NVREG_RCVSTAT_BUSY)) 164 break; 165 166 NdisStallExecution(NV_RXSTOP_DELAY1); 167 } 168 169 NdisStallExecution(NV_RXSTOP_DELAY2); 170 171 if (!(Adapter->Flags & NV_MAC_IN_USE)) 172 { 173 NV_WRITE(Adapter, NvRegLinkSpeed, 0); 174 } 175 } 176 177 VOID 178 NvNetStopTransmitter( 179 _In_ PNVNET_ADAPTER Adapter) 180 { 181 ULONG TxControl, i; 182 183 NDIS_DbgPrint(MIN_TRACE, ("()\n")); 184 185 TxControl = NV_READ(Adapter, NvRegTransmitterControl); 186 if (!(Adapter->Flags & NV_MAC_IN_USE)) 187 TxControl &= ~NVREG_XMITCTL_START; 188 else 189 TxControl |= NVREG_XMITCTL_TX_PATH_EN; 190 NV_WRITE(Adapter, NvRegTransmitterControl, TxControl); 191 192 for (i = 0; i < NV_TXSTOP_DELAY1MAX; ++i) 193 { 194 if (!(NV_READ(Adapter, NvRegTransmitterStatus) & NVREG_XMITSTAT_BUSY)) 195 break; 196 197 NdisStallExecution(NV_TXSTOP_DELAY1); 198 } 199 200 NdisStallExecution(NV_TXSTOP_DELAY2); 201 202 if (!(Adapter->Flags & NV_MAC_IN_USE)) 203 { 204 NV_WRITE(Adapter, NvRegTransmitPoll, 205 NV_READ(Adapter, NvRegTransmitPoll) & NVREG_TRANSMITPOLL_MAC_ADDR_REV); 206 } 207 } 208 209 CODE_SEG("PAGE") 210 VOID 211 NvNetIdleTransmitter( 212 _In_ PNVNET_ADAPTER Adapter, 213 _In_ BOOLEAN ClearPhyControl) 214 { 215 ULONG i; 216 217 PAGED_CODE(); 218 219 if (ClearPhyControl) 220 { 221 NV_WRITE(Adapter, NvRegAdapterControl, 222 NV_READ(Adapter, NvRegAdapterControl) & ~NVREG_ADAPTCTL_RUNNING); 223 } 224 else 225 { 226 NV_WRITE(Adapter, NvRegAdapterControl, 227 (Adapter->PhyAddress << NVREG_ADAPTCTL_PHYSHIFT) | 228 NVREG_ADAPTCTL_PHYVALID | NVREG_ADAPTCTL_RUNNING); 229 } 230 231 NV_WRITE(Adapter, NvRegTxRxControl, Adapter->TxRxControl | NVREG_TXRXCTL_BIT2); 232 for (i = 0; i < NV_TXIDLE_ATTEMPTS; ++i) 233 { 234 if (NV_READ(Adapter, NvRegTxRxControl) & NVREG_TXRXCTL_IDLE) 235 break; 236 237 NdisStallExecution(NV_TXIDLE_DELAY); 238 } 239 } 240 241 VOID 242 NvNetUpdatePauseFrame( 243 _Inout_ PNVNET_ADAPTER Adapter, 244 _In_ ULONG PauseFlags) 245 { 246 NDIS_DbgPrint(MIN_TRACE, ("()\n")); 247 248 Adapter->PauseFlags &= ~(NV_PAUSEFRAME_TX_ENABLE | NV_PAUSEFRAME_RX_ENABLE); 249 250 if (Adapter->PauseFlags & NV_PAUSEFRAME_RX_CAPABLE) 251 { 252 ULONG PacketFilter = NV_READ(Adapter, NvRegPacketFilterFlags) & ~NVREG_PFF_PAUSE_RX; 253 254 if (PauseFlags & NV_PAUSEFRAME_RX_ENABLE) 255 { 256 PacketFilter |= NVREG_PFF_PAUSE_RX; 257 Adapter->PauseFlags |= NV_PAUSEFRAME_RX_ENABLE; 258 } 259 NV_WRITE(Adapter, NvRegPacketFilterFlags, PacketFilter); 260 } 261 262 if (Adapter->PauseFlags & NV_PAUSEFRAME_TX_CAPABLE) 263 { 264 ULONG Mics = NV_READ(Adapter, NvRegMisc1) & ~NVREG_MISC1_PAUSE_TX; 265 266 if (PauseFlags & NV_PAUSEFRAME_TX_ENABLE) 267 { 268 ULONG PauseEnable = NVREG_TX_PAUSEFRAME_ENABLE_V1; 269 270 if (Adapter->Features & DEV_HAS_PAUSEFRAME_TX_V2) 271 PauseEnable = NVREG_TX_PAUSEFRAME_ENABLE_V2; 272 if (Adapter->Features & DEV_HAS_PAUSEFRAME_TX_V3) 273 { 274 PauseEnable = NVREG_TX_PAUSEFRAME_ENABLE_V3; 275 /* Limit the number of TX pause frames to a default of 8 */ 276 NV_WRITE(Adapter, 277 NvRegTxPauseFrameLimit, 278 NV_READ(Adapter, NvRegTxPauseFrameLimit) | 279 NVREG_TX_PAUSEFRAMELIMIT_ENABLE); 280 } 281 NV_WRITE(Adapter, NvRegTxPauseFrame, PauseEnable); 282 NV_WRITE(Adapter, NvRegMisc1, Mics | NVREG_MISC1_PAUSE_TX); 283 Adapter->PauseFlags |= NV_PAUSEFRAME_TX_ENABLE; 284 } 285 else 286 { 287 NV_WRITE(Adapter, NvRegTxPauseFrame, NVREG_TX_PAUSEFRAME_DISABLE); 288 NV_WRITE(Adapter, NvRegMisc1, Mics); 289 } 290 } 291 } 292 293 VOID 294 NvNetToggleClockPowerGating( 295 _In_ PNVNET_ADAPTER Adapter, 296 _In_ BOOLEAN Gate) 297 { 298 NDIS_DbgPrint(MIN_TRACE, ("()\n")); 299 300 if (!(Adapter->Flags & NV_MAC_IN_USE) && (Adapter->Features & DEV_HAS_POWER_CNTRL)) 301 { 302 ULONG PowerState = NV_READ(Adapter, NvRegPowerState2); 303 304 if (Gate) 305 PowerState |= NVREG_POWERSTATE2_GATE_CLOCKS; 306 else 307 PowerState &= ~NVREG_POWERSTATE2_GATE_CLOCKS; 308 NV_WRITE(Adapter, NvRegPowerState2, PowerState); 309 } 310 } 311 312 VOID 313 NTAPI 314 NvNetMediaDetectionDpc( 315 _In_ PVOID SystemSpecific1, 316 _In_ PVOID FunctionContext, 317 _In_ PVOID SystemSpecific2, 318 _In_ PVOID SystemSpecific3) 319 { 320 PNVNET_ADAPTER Adapter = FunctionContext; 321 BOOLEAN Connected, Report = FALSE; 322 323 UNREFERENCED_PARAMETER(SystemSpecific1); 324 UNREFERENCED_PARAMETER(SystemSpecific2); 325 UNREFERENCED_PARAMETER(SystemSpecific3); 326 327 NDIS_DbgPrint(MIN_TRACE, ("()\n")); 328 329 NdisDprAcquireSpinLock(&Adapter->Lock); 330 331 Connected = NvNetUpdateLinkSpeed(Adapter); 332 if (Adapter->Connected != Connected) 333 { 334 Adapter->Connected = Connected; 335 Report = TRUE; 336 337 if (Connected) 338 { 339 /* Link up */ 340 NvNetToggleClockPowerGating(Adapter, FALSE); 341 NdisDprAcquireSpinLock(&Adapter->Receive.Lock); 342 NvNetStartReceiver(Adapter); 343 } 344 else 345 { 346 /* Link down */ 347 NvNetToggleClockPowerGating(Adapter, TRUE); 348 NdisDprAcquireSpinLock(&Adapter->Receive.Lock); 349 NvNetStopReceiver(Adapter); 350 } 351 352 NdisDprReleaseSpinLock(&Adapter->Receive.Lock); 353 } 354 355 NdisDprReleaseSpinLock(&Adapter->Lock); 356 357 if (Report) 358 { 359 NdisMIndicateStatus(Adapter->AdapterHandle, 360 Connected ? NDIS_STATUS_MEDIA_CONNECT : NDIS_STATUS_MEDIA_DISCONNECT, 361 NULL, 362 0); 363 NdisMIndicateStatusComplete(Adapter->AdapterHandle); 364 } 365 } 366 367 BOOLEAN 368 NTAPI 369 NvNetInitPhaseSynchronized( 370 _In_ PVOID SynchronizeContext) 371 { 372 PNVNET_ADAPTER Adapter = SynchronizeContext; 373 374 NDIS_DbgPrint(MIN_TRACE, ("()\n")); 375 376 /* Enable interrupts on the NIC */ 377 NvNetApplyInterruptMask(Adapter); 378 379 /* 380 * One manual link speed update: Interrupts are enabled, 381 * future link speed changes cause interrupts. 382 */ 383 NV_READ(Adapter, NvRegMIIStatus); 384 NV_WRITE(Adapter, NvRegMIIStatus, NVREG_MIISTAT_MASK_ALL); 385 386 /* Set link speed to invalid value, thus force NvNetUpdateLinkSpeed() to init HW */ 387 Adapter->LinkSpeed = 0xFFFFFFFF; 388 389 Adapter->Connected = NvNetUpdateLinkSpeed(Adapter); 390 391 NvNetStartReceiver(Adapter); 392 NvNetStartTransmitter(Adapter); 393 394 Adapter->Flags |= NV_ACTIVE; 395 396 return TRUE; 397 } 398 399 CODE_SEG("PAGE") 400 NDIS_STATUS 401 NvNetInitNIC( 402 _In_ PNVNET_ADAPTER Adapter, 403 _In_ BOOLEAN InitPhy) 404 { 405 ULONG MiiControl, i; 406 NDIS_STATUS Status; 407 408 PAGED_CODE(); 409 410 NDIS_DbgPrint(MIN_TRACE, ("()\n")); 411 412 /* Disable WOL */ 413 NV_WRITE(Adapter, NvRegWakeUpFlags, 0); 414 415 if (InitPhy) 416 { 417 Status = NvNetPhyInit(Adapter); 418 if (Status != NDIS_STATUS_SUCCESS) 419 { 420 return Status; 421 } 422 } 423 424 if (Adapter->PauseFlags & NV_PAUSEFRAME_TX_CAPABLE) 425 { 426 NV_WRITE(Adapter, NvRegTxPauseFrame, NVREG_TX_PAUSEFRAME_DISABLE); 427 } 428 429 /* Power up PHY */ 430 MiiRead(Adapter, Adapter->PhyAddress, MII_CONTROL, &MiiControl); 431 MiiControl &= ~MII_CR_POWER_DOWN; 432 MiiWrite(Adapter, Adapter->PhyAddress, MII_CONTROL, MiiControl); 433 434 NvNetToggleClockPowerGating(Adapter, FALSE); 435 436 NvNetResetMac(Adapter); 437 438 /* Clear multicast masks and addresses */ 439 NV_WRITE(Adapter, NvRegMulticastAddrA, 0); 440 NV_WRITE(Adapter, NvRegMulticastAddrB, 0); 441 NV_WRITE(Adapter, NvRegMulticastMaskA, NVREG_MCASTMASKA_NONE); 442 NV_WRITE(Adapter, NvRegMulticastMaskB, NVREG_MCASTMASKB_NONE); 443 444 NV_WRITE(Adapter, NvRegTransmitterControl, 0); 445 NV_WRITE(Adapter, NvRegReceiverControl, 0); 446 447 NV_WRITE(Adapter, NvRegAdapterControl, 0); 448 449 NV_WRITE(Adapter, NvRegLinkSpeed, 0); 450 NV_WRITE(Adapter, NvRegTransmitPoll, 451 NV_READ(Adapter, NvRegTransmitPoll) & NVREG_TRANSMITPOLL_MAC_ADDR_REV); 452 NvNetResetReceiverAndTransmitter(Adapter); 453 NV_WRITE(Adapter, NvRegUnknownSetupReg6, 0); 454 455 /* Receive descriptor ring buffer */ 456 NV_WRITE(Adapter, NvRegRxRingPhysAddr, 457 NdisGetPhysicalAddressLow(Adapter->RbdPhys)); 458 if (Adapter->Features & DEV_HAS_HIGH_DMA) 459 { 460 NV_WRITE(Adapter, NvRegRxRingPhysAddrHigh, 461 NdisGetPhysicalAddressHigh(Adapter->RbdPhys)); 462 } 463 464 /* Transmit descriptor ring buffer */ 465 NV_WRITE(Adapter, NvRegTxRingPhysAddr, 466 NdisGetPhysicalAddressLow(Adapter->TbdPhys)); 467 if (Adapter->Features & DEV_HAS_HIGH_DMA) 468 { 469 NV_WRITE(Adapter, NvRegTxRingPhysAddrHigh, 470 NdisGetPhysicalAddressHigh(Adapter->TbdPhys)); 471 } 472 473 /* Ring sizes */ 474 NV_WRITE(Adapter, NvRegRingSizes, 475 (NVNET_RECEIVE_DESCRIPTORS - 1) << NVREG_RINGSZ_RXSHIFT | 476 (NVNET_TRANSMIT_DESCRIPTORS - 1) << NVREG_RINGSZ_TXSHIFT); 477 478 /* Set default link speed settings */ 479 NV_WRITE(Adapter, NvRegLinkSpeed, NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10); 480 481 if (Adapter->Features & (DEV_HAS_HIGH_DMA | DEV_HAS_LARGEDESC)) 482 NV_WRITE(Adapter, NvRegTxWatermark, NVREG_TX_WM_DESC2_3_DEFAULT); 483 else 484 NV_WRITE(Adapter, NvRegTxWatermark, NVREG_TX_WM_DESC1_DEFAULT); 485 486 NV_WRITE(Adapter, NvRegTxRxControl, Adapter->TxRxControl); 487 NV_WRITE(Adapter, NvRegVlanControl, Adapter->VlanControl); 488 NV_WRITE(Adapter, NvRegTxRxControl, Adapter->TxRxControl | NVREG_TXRXCTL_BIT1); 489 490 for (i = 0; i < NV_SETUP5_DELAYMAX; ++i) 491 { 492 if (NV_READ(Adapter, NvRegUnknownSetupReg5) & NVREG_UNKSETUP5_BIT31) 493 break; 494 495 NdisStallExecution(NV_SETUP5_DELAY); 496 } 497 498 NV_WRITE(Adapter, NvRegMIIMask, 0); 499 NV_WRITE(Adapter, NvRegIrqStatus, NVREG_IRQSTAT_MASK); 500 NV_WRITE(Adapter, NvRegMIIStatus, NVREG_MIISTAT_MASK_ALL); 501 502 NV_WRITE(Adapter, NvRegMisc1, NVREG_MISC1_FORCE | NVREG_MISC1_HD); 503 NV_WRITE(Adapter, NvRegTransmitterStatus, NV_READ(Adapter, NvRegTransmitterStatus)); 504 NV_WRITE(Adapter, NvRegPacketFilterFlags, NVREG_PFF_ALWAYS | NVREG_PFF_MYADDR); 505 NV_WRITE(Adapter, NvRegOffloadConfig, (NVNET_MAXIMUM_FRAME_SIZE - sizeof(ETH_HEADER)) 506 + NV_RX_HEADERS); 507 508 NV_WRITE(Adapter, NvRegReceiverStatus, NV_READ(Adapter, NvRegReceiverStatus)); 509 510 NvNetBackoffSetSlotTime(Adapter); 511 512 NV_WRITE(Adapter, NvRegTxDeferral, NVREG_TX_DEFERRAL_DEFAULT); 513 NV_WRITE(Adapter, NvRegRxDeferral, NVREG_RX_DEFERRAL_DEFAULT); 514 515 if (Adapter->OptimizationMode == NV_OPTIMIZATION_MODE_THROUGHPUT) 516 NV_WRITE(Adapter, NvRegPollingInterval, NVREG_POLL_DEFAULT_THROUGHPUT); 517 else 518 NV_WRITE(Adapter, NvRegPollingInterval, NVREG_POLL_DEFAULT_CPU); 519 NV_WRITE(Adapter, NvRegUnknownSetupReg6, NVREG_UNKSETUP6_VAL); 520 521 NV_WRITE(Adapter, NvRegAdapterControl, 522 (Adapter->PhyAddress << NVREG_ADAPTCTL_PHYSHIFT) | 523 NVREG_ADAPTCTL_PHYVALID | NVREG_ADAPTCTL_RUNNING); 524 NV_WRITE(Adapter, NvRegMIISpeed, NVREG_MIISPEED_BIT8 | NVREG_MIIDELAY); 525 NV_WRITE(Adapter, NvRegMIIMask, NVREG_MII_LINKCHANGE); 526 527 NdisStallExecution(10); 528 NV_WRITE(Adapter, NvRegPowerState, 529 NV_READ(Adapter, NvRegPowerState) & ~NVREG_POWERSTATE_VALID); 530 531 if (Adapter->Features & DEV_HAS_STATISTICS_COUNTERS) 532 { 533 NvNetClearStatisticsCounters(Adapter); 534 } 535 536 return NDIS_STATUS_SUCCESS; 537 } 538 539 CODE_SEG("PAGE") 540 NDIS_STATUS 541 NvNetGetPermanentMacAddress( 542 _Inout_ PNVNET_ADAPTER Adapter, 543 _Out_writes_bytes_all_(ETH_LENGTH_OF_ADDRESS) PUCHAR MacAddress) 544 { 545 ULONG Temp[2], TxPoll; 546 547 PAGED_CODE(); 548 549 NDIS_DbgPrint(MIN_TRACE, ("()\n")); 550 551 Temp[0] = NV_READ(Adapter, NvRegMacAddrA); 552 Temp[1] = NV_READ(Adapter, NvRegMacAddrB); 553 554 TxPoll = NV_READ(Adapter, NvRegTransmitPoll); 555 556 if (Adapter->Features & DEV_HAS_CORRECT_MACADDR) 557 { 558 /* MAC address is already in the correct order */ 559 MacAddress[0] = (Temp[0] >> 0) & 0xFF; 560 MacAddress[1] = (Temp[0] >> 8) & 0xFF; 561 MacAddress[2] = (Temp[0] >> 16) & 0xFF; 562 MacAddress[3] = (Temp[0] >> 24) & 0xFF; 563 MacAddress[4] = (Temp[1] >> 0) & 0xFF; 564 MacAddress[5] = (Temp[1] >> 8) & 0xFF; 565 } 566 /* Handle the special flag for the correct MAC address order */ 567 else if (TxPoll & NVREG_TRANSMITPOLL_MAC_ADDR_REV) 568 { 569 /* MAC address is already in the correct order */ 570 MacAddress[0] = (Temp[0] >> 0) & 0xFF; 571 MacAddress[1] = (Temp[0] >> 8) & 0xFF; 572 MacAddress[2] = (Temp[0] >> 16) & 0xFF; 573 MacAddress[3] = (Temp[0] >> 24) & 0xFF; 574 MacAddress[4] = (Temp[1] >> 0) & 0xFF; 575 MacAddress[5] = (Temp[1] >> 8) & 0xFF; 576 577 /* 578 * Set original MAC address back to the reversed version. 579 * This flag will be cleared during low power transition. 580 * Therefore, we should always put back the reversed address. 581 */ 582 Temp[0] = (MacAddress[5] << 0) | (MacAddress[4] << 8) | 583 (MacAddress[3] << 16) | (MacAddress[2] << 24); 584 Temp[1] = (MacAddress[1] << 0) | (MacAddress[0] << 8); 585 } 586 else 587 { 588 /* Need to reverse MAC address to the correct order */ 589 MacAddress[0] = (Temp[1] >> 8) & 0xFF; 590 MacAddress[1] = (Temp[1] >> 0) & 0xFF; 591 MacAddress[2] = (Temp[0] >> 24) & 0xFF; 592 MacAddress[3] = (Temp[0] >> 16) & 0xFF; 593 MacAddress[4] = (Temp[0] >> 8) & 0xFF; 594 MacAddress[5] = (Temp[0] >> 0) & 0xFF; 595 596 /* 597 * Use a flag to signal the driver whether the MAC address was already corrected, 598 * so that it is not reversed again on a subsequent initialize. 599 */ 600 NV_WRITE(Adapter, NvRegTransmitPoll, TxPoll | NVREG_TRANSMITPOLL_MAC_ADDR_REV); 601 } 602 603 Adapter->OriginalMacAddress[0] = Temp[0]; 604 Adapter->OriginalMacAddress[1] = Temp[1]; 605 606 NDIS_DbgPrint(MIN_TRACE, ("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", 607 MacAddress[0], 608 MacAddress[1], 609 MacAddress[2], 610 MacAddress[3], 611 MacAddress[4], 612 MacAddress[5])); 613 614 if (ETH_IS_MULTICAST(MacAddress) || ETH_IS_EMPTY(MacAddress)) 615 return NDIS_STATUS_INVALID_ADDRESS; 616 617 return NDIS_STATUS_SUCCESS; 618 } 619 620 CODE_SEG("PAGE") 621 VOID 622 NvNetSetupMacAddress( 623 _In_ PNVNET_ADAPTER Adapter, 624 _In_reads_bytes_(ETH_LENGTH_OF_ADDRESS) PUCHAR MacAddress) 625 { 626 PAGED_CODE(); 627 628 NDIS_DbgPrint(MIN_TRACE, ("()\n")); 629 630 NV_WRITE(Adapter, NvRegMacAddrA, 631 MacAddress[3] << 24 | MacAddress[2] << 16 | MacAddress[1] << 8 | MacAddress[0]); 632 NV_WRITE(Adapter, NvRegMacAddrB, MacAddress[5] << 8 | MacAddress[4]); 633 } 634 635 static 636 VOID 637 CODE_SEG("PAGE") 638 NvNetValidateConfiguration( 639 _Inout_ PNVNET_ADAPTER Adapter) 640 { 641 PAGED_CODE(); 642 643 if (!(Adapter->Features & DEV_HAS_LARGEDESC)) 644 { 645 Adapter->MaximumFrameSize = NVNET_MAXIMUM_FRAME_SIZE; 646 } 647 if (!(Adapter->Features & DEV_HAS_CHECKSUM)) 648 { 649 Adapter->Flags &= ~(NV_SEND_CHECKSUM | NV_SEND_LARGE_SEND); 650 } 651 if (!(Adapter->Features & DEV_HAS_VLAN)) 652 { 653 Adapter->Flags &= ~(NV_PACKET_PRIORITY | NV_VLAN_TAGGING); 654 } 655 if ((Adapter->Features & DEV_NEED_TIMERIRQ) && 656 (Adapter->OptimizationMode == NV_OPTIMIZATION_MODE_DYNAMIC)) 657 { 658 Adapter->OptimizationMode = NV_OPTIMIZATION_MODE_THROUGHPUT; 659 } 660 if (!(Adapter->Features & DEV_HAS_TX_PAUSEFRAME)) 661 { 662 if (Adapter->FlowControlMode == NV_FLOW_CONTROL_TX) 663 { 664 Adapter->FlowControlMode = NV_FLOW_CONTROL_AUTO; 665 } 666 else if (Adapter->FlowControlMode == NV_FLOW_CONTROL_RX_TX) 667 { 668 Adapter->FlowControlMode = NV_FLOW_CONTROL_RX; 669 } 670 } 671 } 672 673 CODE_SEG("PAGE") 674 NDIS_STATUS 675 NvNetRecognizeHardware( 676 _Inout_ PNVNET_ADAPTER Adapter) 677 { 678 ULONG Bytes; 679 PCI_COMMON_CONFIG PciConfig; 680 681 PAGED_CODE(); 682 683 NDIS_DbgPrint(MIN_TRACE, ("()\n")); 684 685 Bytes = NdisReadPciSlotInformation(Adapter->AdapterHandle, 686 0, 687 FIELD_OFFSET(PCI_COMMON_CONFIG, VendorID), 688 &PciConfig, 689 PCI_COMMON_HDR_LENGTH); 690 if (Bytes != PCI_COMMON_HDR_LENGTH) 691 return NDIS_STATUS_ADAPTER_NOT_FOUND; 692 693 if (PciConfig.VendorID != 0x10DE) 694 return NDIS_STATUS_ADAPTER_NOT_FOUND; 695 696 Adapter->DeviceId = PciConfig.DeviceID; 697 Adapter->RevisionId = PciConfig.RevisionID; 698 699 switch (PciConfig.DeviceID) 700 { 701 case 0x01C3: /* nForce */ 702 case 0x0066: /* nForce2 */ 703 case 0x00D6: /* nForce2 */ 704 Adapter->Features = DEV_NEED_TIMERIRQ | DEV_NEED_LINKTIMER; 705 break; 706 707 case 0x0086: /* nForce3 */ 708 case 0x008C: /* nForce3 */ 709 case 0x00E6: /* nForce3 */ 710 case 0x00DF: /* nForce3 */ 711 Adapter->Features = DEV_NEED_TIMERIRQ | DEV_NEED_LINKTIMER | 712 DEV_HAS_LARGEDESC | DEV_HAS_CHECKSUM; 713 break; 714 715 case 0x0056: /* CK804 */ 716 case 0x0057: /* CK804 */ 717 case 0x0037: /* MCP04 */ 718 case 0x0038: /* MCP04 */ 719 Adapter->Features = DEV_NEED_LINKTIMER | DEV_HAS_LARGEDESC | DEV_HAS_CHECKSUM | 720 DEV_HAS_HIGH_DMA | DEV_HAS_STATISTICS_V1 | DEV_NEED_TX_LIMIT; 721 break; 722 723 case 0x0268: /* MCP51 */ 724 case 0x0269: /* MCP51 */ 725 Adapter->Features = DEV_NEED_LINKTIMER | DEV_HAS_HIGH_DMA | DEV_HAS_POWER_CNTRL | 726 DEV_HAS_STATISTICS_V1 | DEV_NEED_LOW_POWER_FIX; 727 break; 728 729 case 0x0372: /* MCP55 */ 730 case 0x0373: /* MCP55 */ 731 Adapter->Features = DEV_NEED_LINKTIMER | DEV_HAS_LARGEDESC | DEV_HAS_CHECKSUM | 732 DEV_HAS_HIGH_DMA | DEV_HAS_VLAN | DEV_HAS_MSI | DEV_HAS_MSI_X | 733 DEV_HAS_POWER_CNTRL | DEV_HAS_PAUSEFRAME_TX_V1 | 734 DEV_HAS_STATISTICS_V1 | DEV_HAS_STATISTICS_V2 | 735 DEV_HAS_TEST_EXTENDED | DEV_HAS_MGMT_UNIT | 736 DEV_NEED_TX_LIMIT | DEV_NEED_MSI_FIX; 737 break; 738 739 case 0x03E5: /* MCP61 */ 740 case 0x03E6: /* MCP61 */ 741 case 0x03EE: /* MCP61 */ 742 case 0x03EF: /* MCP61 */ 743 Adapter->Features = DEV_NEED_LINKTIMER | DEV_HAS_HIGH_DMA | DEV_HAS_POWER_CNTRL | 744 DEV_HAS_MSI | DEV_HAS_PAUSEFRAME_TX_V1 | DEV_HAS_STATISTICS_V1 | 745 DEV_HAS_STATISTICS_V2 | DEV_HAS_TEST_EXTENDED | DEV_HAS_MGMT_UNIT | 746 DEV_HAS_CORRECT_MACADDR | DEV_NEED_MSI_FIX; 747 break; 748 749 case 0x0450: /* MCP65 */ 750 case 0x0451: /* MCP65 */ 751 case 0x0452: /* MCP65 */ 752 case 0x0453: /* MCP65 */ 753 Adapter->Features = DEV_NEED_LINKTIMER | DEV_HAS_LARGEDESC | DEV_HAS_HIGH_DMA | 754 DEV_HAS_POWER_CNTRL | DEV_HAS_MSI | DEV_HAS_PAUSEFRAME_TX_V1 | 755 DEV_HAS_STATISTICS_V1 | DEV_HAS_STATISTICS_V2 | 756 DEV_HAS_TEST_EXTENDED | DEV_HAS_MGMT_UNIT | 757 DEV_HAS_CORRECT_MACADDR | DEV_NEED_TX_LIMIT | 758 DEV_HAS_GEAR_MODE | DEV_NEED_MSI_FIX; 759 break; 760 761 case 0x054C: /* MCP67 */ 762 case 0x054D: /* MCP67 */ 763 case 0x054E: /* MCP67 */ 764 case 0x054F: /* MCP67 */ 765 Adapter->Features = DEV_NEED_LINKTIMER | DEV_HAS_HIGH_DMA | DEV_HAS_POWER_CNTRL | 766 DEV_HAS_MSI | DEV_HAS_PAUSEFRAME_TX_V1 | DEV_HAS_STATISTICS_V1 | 767 DEV_HAS_STATISTICS_V2 | DEV_HAS_TEST_EXTENDED | DEV_HAS_MGMT_UNIT | 768 DEV_HAS_CORRECT_MACADDR | DEV_HAS_GEAR_MODE | DEV_NEED_MSI_FIX; 769 break; 770 771 case 0x07DC: /* MCP73 */ 772 case 0x07DD: /* MCP73 */ 773 case 0x07DE: /* MCP73 */ 774 case 0x07DF: /* MCP73 */ 775 Adapter->Features = DEV_NEED_LINKTIMER | DEV_HAS_HIGH_DMA | DEV_HAS_POWER_CNTRL | 776 DEV_HAS_MSI | DEV_HAS_PAUSEFRAME_TX_V1 | DEV_HAS_STATISTICS_V1 | 777 DEV_HAS_STATISTICS_V2 | DEV_HAS_TEST_EXTENDED | DEV_HAS_MGMT_UNIT | 778 DEV_HAS_CORRECT_MACADDR | DEV_HAS_COLLISION_FIX | 779 DEV_HAS_GEAR_MODE | DEV_NEED_MSI_FIX; 780 break; 781 782 case 0x0760: /* MCP77 */ 783 case 0x0761: /* MCP77 */ 784 case 0x0762: /* MCP77 */ 785 case 0x0763: /* MCP77 */ 786 Adapter->Features = DEV_NEED_LINKTIMER | DEV_HAS_CHECKSUM | DEV_HAS_HIGH_DMA | 787 DEV_HAS_MSI | DEV_HAS_POWER_CNTRL | DEV_HAS_PAUSEFRAME_TX_V2 | 788 DEV_HAS_STATISTICS_V1 | DEV_HAS_STATISTICS_V2 | 789 DEV_HAS_STATISTICS_V3 | DEV_HAS_TEST_EXTENDED | DEV_HAS_MGMT_UNIT | 790 DEV_HAS_CORRECT_MACADDR | DEV_HAS_COLLISION_FIX | 791 DEV_NEED_TX_LIMIT2 | DEV_HAS_GEAR_MODE | 792 DEV_NEED_PHY_INIT_FIX | DEV_NEED_MSI_FIX; 793 break; 794 795 case 0x0AB0: /* MCP79 */ 796 case 0x0AB1: /* MCP79 */ 797 case 0x0AB2: /* MCP79 */ 798 case 0x0AB3: /* MCP79 */ 799 Adapter->Features = DEV_NEED_LINKTIMER | DEV_HAS_LARGEDESC | DEV_HAS_CHECKSUM | 800 DEV_HAS_HIGH_DMA | DEV_HAS_MSI | DEV_HAS_POWER_CNTRL | 801 DEV_HAS_PAUSEFRAME_TX_V3 | DEV_HAS_STATISTICS_V1 | 802 DEV_HAS_STATISTICS_V2 | DEV_HAS_STATISTICS_V3 | 803 DEV_HAS_TEST_EXTENDED | DEV_HAS_CORRECT_MACADDR | 804 DEV_HAS_COLLISION_FIX | DEV_NEED_TX_LIMIT2 | 805 DEV_HAS_GEAR_MODE | DEV_NEED_PHY_INIT_FIX | DEV_NEED_MSI_FIX; 806 break; 807 808 case 0x0D7D: /* MCP89 */ 809 Adapter->Features = DEV_NEED_LINKTIMER | DEV_HAS_LARGEDESC | DEV_HAS_CHECKSUM | 810 DEV_HAS_HIGH_DMA | DEV_HAS_MSI | DEV_HAS_POWER_CNTRL | 811 DEV_HAS_PAUSEFRAME_TX_V3 | DEV_HAS_STATISTICS_V1 | 812 DEV_HAS_STATISTICS_V2 | DEV_HAS_STATISTICS_V3 | 813 DEV_HAS_TEST_EXTENDED | DEV_HAS_CORRECT_MACADDR | 814 DEV_HAS_COLLISION_FIX | DEV_HAS_GEAR_MODE | DEV_NEED_PHY_INIT_FIX; 815 break; 816 817 default: 818 return NDIS_STATUS_NOT_RECOGNIZED; 819 } 820 821 /* Normalize all .INF parameters */ 822 NvNetValidateConfiguration(Adapter); 823 824 /* FIXME: Disable some NIC features, we don't support these yet */ 825 #if 1 826 Adapter->VlanControl = 0; 827 Adapter->Flags &= ~(NV_SEND_CHECKSUM | NV_SEND_LARGE_SEND | 828 NV_PACKET_PRIORITY | NV_VLAN_TAGGING); 829 #endif 830 831 /* For code paths debugging (32-bit descriptors work on all hardware variants) */ 832 #if 0 833 Adapter->Features &= ~(DEV_HAS_HIGH_DMA | DEV_HAS_LARGEDESC); 834 #endif 835 836 if (Adapter->Features & DEV_HAS_POWER_CNTRL) 837 Adapter->WakeFrameBitmap = ~(0xFFFFFFFF << NV_WAKEUPPATTERNS_V2); 838 else 839 Adapter->WakeFrameBitmap = ~(0xFFFFFFFF << NV_WAKEUPPATTERNS); 840 841 /* 64-bit descriptors */ 842 if (Adapter->Features & DEV_HAS_HIGH_DMA) 843 { 844 /* Note: Some devices here also support Jumbo Frames */ 845 Adapter->TxRxControl = NVREG_TXRXCTL_DESC_3; 846 } 847 /* 32-bit descriptors */ 848 else 849 { 850 if (Adapter->Features & DEV_HAS_LARGEDESC) 851 { 852 /* Jumbo Frames */ 853 Adapter->TxRxControl = NVREG_TXRXCTL_DESC_2; 854 } 855 else 856 { 857 /* Original packet format */ 858 Adapter->TxRxControl = NVREG_TXRXCTL_DESC_1; 859 } 860 } 861 862 /* Flow control */ 863 Adapter->PauseFlags = NV_PAUSEFRAME_RX_CAPABLE | NV_PAUSEFRAME_RX_REQ | NV_PAUSEFRAME_AUTONEG; 864 if (Adapter->Features & DEV_HAS_TX_PAUSEFRAME) 865 { 866 Adapter->PauseFlags |= NV_PAUSEFRAME_TX_CAPABLE | NV_PAUSEFRAME_TX_REQ; 867 } 868 if (Adapter->FlowControlMode != NV_FLOW_CONTROL_AUTO) 869 { 870 Adapter->PauseFlags &= ~(NV_PAUSEFRAME_AUTONEG | NV_PAUSEFRAME_RX_REQ | 871 NV_PAUSEFRAME_TX_REQ); 872 switch (Adapter->FlowControlMode) 873 { 874 case NV_FLOW_CONTROL_RX: 875 Adapter->PauseFlags |= NV_PAUSEFRAME_RX_REQ; 876 break; 877 case NV_FLOW_CONTROL_TX: 878 Adapter->PauseFlags |= NV_PAUSEFRAME_TX_REQ; 879 break; 880 case NV_FLOW_CONTROL_RX_TX: 881 Adapter->PauseFlags |= NV_PAUSEFRAME_RX_REQ | NV_PAUSEFRAME_TX_REQ; 882 break; 883 884 default: 885 break; 886 } 887 } 888 889 /* Work around errata in some NICs */ 890 if (Adapter->Features & (DEV_NEED_TX_LIMIT | DEV_NEED_TX_LIMIT2)) 891 { 892 Adapter->Flags |= NV_SEND_ERRATA_PRESENT; 893 894 if ((Adapter->Features & DEV_NEED_TX_LIMIT2) && Adapter->RevisionId >= 0xA2) 895 { 896 Adapter->Flags &= ~NV_SEND_ERRATA_PRESENT; 897 } 898 } 899 if (Adapter->Flags & NV_SEND_ERRATA_PRESENT) 900 { 901 NDIS_DbgPrint(MIN_TRACE, ("Transmit workaround active\n")); 902 } 903 904 /* Initialize the interrupt mask */ 905 if (Adapter->OptimizationMode == NV_OPTIMIZATION_MODE_CPU) 906 { 907 Adapter->InterruptMask = NVREG_IRQMASK_CPU; 908 } 909 else 910 { 911 Adapter->InterruptMask = NVREG_IRQMASK_THROUGHPUT; 912 } 913 if (Adapter->Features & DEV_NEED_TIMERIRQ) 914 { 915 Adapter->InterruptMask |= NVREG_IRQ_TIMER; 916 } 917 918 if (Adapter->Features & DEV_NEED_LINKTIMER) 919 { 920 NdisMInitializeTimer(&Adapter->MediaDetectionTimer, 921 Adapter->AdapterHandle, 922 NvNetMediaDetectionDpc, 923 Adapter); 924 } 925 926 return NDIS_STATUS_SUCCESS; 927 } 928