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: Miniport information callbacks 5 * COPYRIGHT: Copyright 2021-2022 Dmitry Borisov <di.sean@protonmail.com> 6 */ 7 8 /* INCLUDES *******************************************************************/ 9 10 #include "nvnet.h" 11 12 #define NDEBUG 13 #include "debug.h" 14 15 /* GLOBALS ********************************************************************/ 16 17 static const NDIS_OID NvpSupportedOidList[] = 18 { 19 OID_GEN_SUPPORTED_LIST, 20 OID_GEN_CURRENT_PACKET_FILTER, 21 OID_GEN_HARDWARE_STATUS, 22 OID_GEN_MEDIA_SUPPORTED, 23 OID_GEN_MEDIA_IN_USE, 24 OID_GEN_MAXIMUM_LOOKAHEAD, 25 OID_GEN_MAXIMUM_FRAME_SIZE, 26 OID_GEN_MAXIMUM_SEND_PACKETS, 27 OID_GEN_LINK_SPEED, 28 OID_GEN_TRANSMIT_BUFFER_SPACE, 29 OID_GEN_RECEIVE_BUFFER_SPACE, 30 OID_GEN_RECEIVE_BLOCK_SIZE, 31 OID_GEN_TRANSMIT_BLOCK_SIZE, 32 OID_GEN_VENDOR_ID, 33 OID_GEN_VENDOR_DESCRIPTION, 34 OID_GEN_VENDOR_DRIVER_VERSION, 35 OID_GEN_CURRENT_LOOKAHEAD, 36 OID_GEN_DRIVER_VERSION, 37 OID_GEN_MAXIMUM_TOTAL_SIZE, 38 OID_GEN_MAC_OPTIONS, 39 OID_GEN_MEDIA_CONNECT_STATUS, 40 OID_GEN_VLAN_ID, 41 OID_802_3_PERMANENT_ADDRESS, 42 OID_802_3_CURRENT_ADDRESS, 43 OID_802_3_MULTICAST_LIST, 44 OID_802_3_MAXIMUM_LIST_SIZE, 45 46 /* Statistics */ 47 OID_GEN_XMIT_OK, 48 OID_GEN_RCV_OK, 49 OID_GEN_XMIT_ERROR, 50 OID_GEN_RCV_ERROR, 51 OID_GEN_RCV_NO_BUFFER, 52 OID_GEN_DIRECTED_FRAMES_RCV, 53 OID_GEN_RCV_CRC_ERROR, 54 OID_GEN_TRANSMIT_QUEUE_LENGTH, 55 OID_802_3_RCV_ERROR_ALIGNMENT, 56 OID_802_3_XMIT_ONE_COLLISION, 57 OID_802_3_XMIT_MORE_COLLISIONS, 58 OID_802_3_XMIT_DEFERRED, 59 OID_802_3_XMIT_MAX_COLLISIONS, 60 OID_802_3_RCV_OVERRUN, 61 OID_802_3_XMIT_UNDERRUN, 62 OID_802_3_XMIT_HEARTBEAT_FAILURE, 63 OID_802_3_XMIT_TIMES_CRS_LOST, 64 OID_802_3_XMIT_LATE_COLLISIONS, 65 66 /* Offload */ 67 OID_TCP_TASK_OFFLOAD, 68 69 /* Power management */ 70 OID_PNP_CAPABILITIES, 71 OID_PNP_SET_POWER, 72 OID_PNP_QUERY_POWER, 73 OID_PNP_ADD_WAKE_UP_PATTERN, 74 OID_PNP_REMOVE_WAKE_UP_PATTERN, 75 OID_PNP_ENABLE_WAKE_UP 76 }; 77 78 /* FUNCTIONS ******************************************************************/ 79 80 static 81 ULONG 82 NvNetGetLinkSpeed( 83 _In_ PNVNET_ADAPTER Adapter) 84 { 85 ULONG LinkSpeedMbps; 86 87 switch (Adapter->LinkSpeed) 88 { 89 case NVREG_LINKSPEED_10: 90 LinkSpeedMbps = 10; 91 break; 92 case NVREG_LINKSPEED_100: 93 LinkSpeedMbps = 100; 94 break; 95 case NVREG_LINKSPEED_1000: 96 LinkSpeedMbps = 1000; 97 break; 98 99 default: 100 UNREACHABLE; 101 break; 102 } 103 104 return LinkSpeedMbps; 105 } 106 107 static 108 ULONG 109 PacketFilterToMask( 110 _In_ ULONG PacketFilter) 111 { 112 ULONG FilterMask = NVREG_PFF_ALWAYS | NVREG_PFF_MYADDR | NVREG_PFF_PROMISC; 113 114 if (PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS) 115 { 116 FilterMask &= ~NVREG_PFF_MYADDR; 117 } 118 119 if (PacketFilter & NDIS_PACKET_TYPE_BROADCAST) 120 { 121 FilterMask &= ~NVREG_PFF_PROMISC; 122 } 123 124 return FilterMask; 125 } 126 127 static 128 DECLSPEC_NOINLINE /* Called from pageable code */ 129 VOID 130 NvNetApplyPacketFilter( 131 _In_ PNVNET_ADAPTER Adapter) 132 { 133 UCHAR Address[ETH_LENGTH_OF_ADDRESS]; 134 UCHAR Mask[ETH_LENGTH_OF_ADDRESS]; 135 ULONG FilterMask; 136 BOOLEAN RestartReceiver; 137 138 if (Adapter->PacketFilter & NDIS_PACKET_TYPE_ALL_MULTICAST) 139 { 140 NdisZeroMemory(Address, sizeof(Address)); 141 NdisZeroMemory(Mask, sizeof(Mask)); 142 143 Address[0] |= NVREG_MCASTADDRA_FORCE; 144 Mask[0] |= NVREG_MCASTADDRA_FORCE; 145 } 146 else if (Adapter->PacketFilter & NDIS_PACKET_TYPE_MULTICAST) 147 { 148 if (Adapter->MulticastListSize > 0) 149 { 150 ULONG i, j; 151 152 NdisFillMemory(Address, sizeof(Address), 0xFF); 153 NdisFillMemory(Mask, sizeof(Mask), 0xFF); 154 155 for (i = 0; i < Adapter->MulticastListSize; ++i) 156 { 157 PUCHAR MacAddress = Adapter->MulticastList[i].MacAddress; 158 159 for (j = 0; j < ETH_LENGTH_OF_ADDRESS; ++j) 160 { 161 Address[j] &= MacAddress[j]; 162 Mask[j] &= ~MacAddress[j]; 163 } 164 } 165 166 for (j = 0; j < ETH_LENGTH_OF_ADDRESS; ++j) 167 { 168 Mask[j] |= Address[j]; 169 } 170 } 171 else 172 { 173 NdisZeroMemory(Address, sizeof(Address)); 174 NdisZeroMemory(Mask, sizeof(Mask)); 175 } 176 } 177 else 178 { 179 NdisZeroMemory(Address, sizeof(Address)); 180 NdisFillMemory(Mask, sizeof(Mask), 0xFF); 181 } 182 183 FilterMask = NV_READ(Adapter, NvRegPacketFilterFlags) & NVREG_PFF_PAUSE_RX; 184 FilterMask |= PacketFilterToMask(Adapter->PacketFilter); 185 186 NdisAcquireSpinLock(&Adapter->Receive.Lock); 187 188 RestartReceiver = !!(NV_READ(Adapter, NvRegReceiverControl) & NVREG_RCVCTL_START); 189 if (RestartReceiver) 190 { 191 NvNetStopReceiver(Adapter); 192 } 193 194 NV_WRITE(Adapter, NvRegMulticastAddrA, 195 Address[3] << 24 | Address[2] << 16 | Address[1] << 8 | Address[0]); 196 NV_WRITE(Adapter, NvRegMulticastAddrB, Address[5] << 8 | Address[4]); 197 NV_WRITE(Adapter, NvRegMulticastMaskA, 198 Mask[3] << 24 | Mask[2] << 16 | Mask[1] << 8 | Mask[0]); 199 NV_WRITE(Adapter, NvRegMulticastMaskB, Mask[5] << 8 | Mask[4]); 200 201 NV_WRITE(Adapter, NvRegPacketFilterFlags, FilterMask); 202 203 if (RestartReceiver) 204 { 205 NvNetStartReceiver(Adapter); 206 } 207 208 NdisReleaseSpinLock(&Adapter->Receive.Lock); 209 } 210 211 static 212 VOID 213 NvNetReadStatistics( 214 _In_ PNVNET_ADAPTER Adapter) 215 { 216 Adapter->Statistics.HwTxCnt += NV_READ(Adapter, NvRegTxCnt); 217 Adapter->Statistics.HwTxZeroReXmt += NV_READ(Adapter, NvRegTxZeroReXmt); 218 Adapter->Statistics.HwTxOneReXmt += NV_READ(Adapter, NvRegTxOneReXmt); 219 Adapter->Statistics.HwTxManyReXmt += NV_READ(Adapter, NvRegTxManyReXmt); 220 Adapter->Statistics.HwTxLateCol += NV_READ(Adapter, NvRegTxLateCol); 221 Adapter->Statistics.HwTxUnderflow += NV_READ(Adapter, NvRegTxUnderflow); 222 Adapter->Statistics.HwTxLossCarrier += NV_READ(Adapter, NvRegTxLossCarrier); 223 Adapter->Statistics.HwTxExcessDef += NV_READ(Adapter, NvRegTxExcessDef); 224 Adapter->Statistics.HwTxRetryErr += NV_READ(Adapter, NvRegTxRetryErr); 225 Adapter->Statistics.HwRxFrameErr += NV_READ(Adapter, NvRegRxFrameErr); 226 Adapter->Statistics.HwRxExtraByte += NV_READ(Adapter, NvRegRxExtraByte); 227 Adapter->Statistics.HwRxLateCol += NV_READ(Adapter, NvRegRxLateCol); 228 Adapter->Statistics.HwRxRunt += NV_READ(Adapter, NvRegRxRunt); 229 Adapter->Statistics.HwRxFrameTooLong += NV_READ(Adapter, NvRegRxFrameTooLong); 230 Adapter->Statistics.HwRxOverflow += NV_READ(Adapter, NvRegRxOverflow); 231 Adapter->Statistics.HwRxFCSErr += NV_READ(Adapter, NvRegRxFCSErr); 232 Adapter->Statistics.HwRxFrameAlignErr += NV_READ(Adapter, NvRegRxFrameAlignErr); 233 Adapter->Statistics.HwRxLenErr += NV_READ(Adapter, NvRegRxLenErr); 234 Adapter->Statistics.HwRxUnicast += NV_READ(Adapter, NvRegRxUnicast); 235 Adapter->Statistics.HwRxMulticast += NV_READ(Adapter, NvRegRxMulticast); 236 Adapter->Statistics.HwRxBroadcast += NV_READ(Adapter, NvRegRxBroadcast); 237 238 if (Adapter->Features & DEV_HAS_STATISTICS_V2) 239 { 240 Adapter->Statistics.HwTxDef += NV_READ(Adapter, NvRegTxDef); 241 Adapter->Statistics.HwTxFrame += NV_READ(Adapter, NvRegTxFrame); 242 Adapter->Statistics.HwRxCnt += NV_READ(Adapter, NvRegRxCnt); 243 Adapter->Statistics.HwTxPause += NV_READ(Adapter, NvRegTxPause); 244 Adapter->Statistics.HwRxPause += NV_READ(Adapter, NvRegRxPause); 245 Adapter->Statistics.HwRxDropFrame += NV_READ(Adapter, NvRegRxDropFrame); 246 } 247 248 if (Adapter->Features & DEV_HAS_STATISTICS_V3) 249 { 250 Adapter->Statistics.HwTxUnicast += NV_READ(Adapter, NvRegTxUnicast); 251 Adapter->Statistics.HwTxMulticast += NV_READ(Adapter, NvRegTxMulticast); 252 Adapter->Statistics.HwTxBroadcast += NV_READ(Adapter, NvRegTxBroadcast); 253 } 254 } 255 256 static 257 VOID 258 NvNetQueryHwCounter( 259 _In_ PNVNET_ADAPTER Adapter, 260 _In_ NDIS_OID Oid, 261 _Out_ PULONG64 Counter) 262 { 263 switch (Oid) 264 { 265 case OID_GEN_XMIT_OK: 266 *Counter = (Adapter->Features & DEV_HAS_STATISTICS_V2) 267 ? Adapter->Statistics.HwTxFrame 268 : (Adapter->Statistics.HwTxZeroReXmt + 269 Adapter->Statistics.HwTxOneReXmt + 270 Adapter->Statistics.HwTxManyReXmt); 271 break; 272 case OID_GEN_RCV_OK: 273 *Counter = (Adapter->Statistics.HwRxUnicast + 274 Adapter->Statistics.HwRxMulticast + 275 Adapter->Statistics.HwRxBroadcast); 276 break; 277 case OID_GEN_XMIT_ERROR: 278 *Counter = (Adapter->Statistics.HwTxRetryErr + 279 Adapter->Statistics.HwTxLateCol + 280 Adapter->Statistics.HwTxUnderflow + 281 Adapter->Statistics.HwTxLossCarrier + 282 Adapter->Statistics.HwTxExcessDef); 283 break; 284 case OID_GEN_RCV_ERROR: 285 *Counter = (Adapter->Statistics.HwRxFrameAlignErr + 286 Adapter->Statistics.HwRxLenErr + 287 Adapter->Statistics.HwRxRunt + 288 Adapter->Statistics.HwRxFrameTooLong + 289 Adapter->Statistics.HwRxFCSErr + 290 Adapter->Statistics.HwRxFrameErr + 291 Adapter->Statistics.HwRxExtraByte + 292 Adapter->Statistics.HwRxLateCol); 293 break; 294 case OID_GEN_RCV_NO_BUFFER: 295 *Counter = (Adapter->Statistics.HwRxDropFrame + 296 Adapter->Statistics.HwRxOverflow + 297 Adapter->Statistics.ReceiveIrqNoBuffers); 298 break; 299 case OID_GEN_DIRECTED_FRAMES_RCV: 300 *Counter = Adapter->Statistics.HwRxUnicast; 301 break; 302 case OID_GEN_RCV_CRC_ERROR: 303 *Counter = Adapter->Statistics.HwRxFCSErr; 304 break; 305 case OID_802_3_RCV_ERROR_ALIGNMENT: 306 *Counter = Adapter->Statistics.HwRxFrameErr; 307 break; 308 case OID_802_3_XMIT_ONE_COLLISION: 309 *Counter = Adapter->Statistics.HwTxOneReXmt; 310 break; 311 case OID_802_3_XMIT_MORE_COLLISIONS: 312 *Counter = Adapter->Statistics.HwTxManyReXmt; 313 break; 314 case OID_802_3_XMIT_DEFERRED: 315 *Counter = Adapter->Statistics.HwTxDef; 316 break; 317 case OID_802_3_XMIT_MAX_COLLISIONS: 318 *Counter = Adapter->Statistics.HwTxRetryErr; 319 break; 320 case OID_802_3_RCV_OVERRUN: 321 *Counter = Adapter->Statistics.HwRxOverflow; 322 break; 323 case OID_802_3_XMIT_UNDERRUN: 324 *Counter = Adapter->Statistics.HwTxUnderflow; 325 break; 326 case OID_802_3_XMIT_HEARTBEAT_FAILURE: 327 *Counter = Adapter->Statistics.HwTxZeroReXmt; 328 break; 329 case OID_802_3_XMIT_TIMES_CRS_LOST: 330 *Counter = Adapter->Statistics.HwTxLossCarrier; 331 break; 332 case OID_802_3_XMIT_LATE_COLLISIONS: 333 *Counter = Adapter->Statistics.HwTxLateCol; 334 break; 335 336 default: 337 UNREACHABLE; 338 break; 339 } 340 } 341 342 static 343 VOID 344 NvNetQuerySoftwareCounter( 345 _In_ PNVNET_ADAPTER Adapter, 346 _In_ NDIS_OID Oid, 347 _Out_ PULONG64 Counter) 348 { 349 switch (Oid) 350 { 351 case OID_GEN_XMIT_OK: 352 *Counter = Adapter->Statistics.TransmitOk; 353 break; 354 case OID_GEN_RCV_OK: 355 *Counter = Adapter->Statistics.ReceiveOk; 356 break; 357 case OID_GEN_XMIT_ERROR: 358 *Counter = Adapter->Statistics.TransmitErrors; 359 break; 360 case OID_GEN_RCV_ERROR: 361 *Counter = Adapter->Statistics.ReceiveErrors; 362 break; 363 case OID_GEN_RCV_NO_BUFFER: 364 *Counter = Adapter->Statistics.ReceiveNoBuffers; 365 break; 366 case OID_GEN_DIRECTED_FRAMES_RCV: 367 *Counter = 0; 368 break; 369 case OID_GEN_RCV_CRC_ERROR: 370 *Counter = Adapter->Statistics.ReceiveCrcErrors; 371 break; 372 case OID_802_3_RCV_ERROR_ALIGNMENT: 373 *Counter = Adapter->Statistics.ReceiveAlignmentErrors; 374 break; 375 case OID_802_3_XMIT_ONE_COLLISION: 376 *Counter = Adapter->Statistics.TransmitOneRetry; 377 break; 378 case OID_802_3_XMIT_MORE_COLLISIONS: 379 *Counter = (Adapter->Statistics.TransmitOk - 380 Adapter->Statistics.TransmitOneRetry - 381 Adapter->Statistics.TransmitZeroRetry); 382 break; 383 case OID_802_3_XMIT_DEFERRED: 384 *Counter = Adapter->Statistics.TransmitDeferred; 385 break; 386 case OID_802_3_XMIT_MAX_COLLISIONS: 387 *Counter = Adapter->Statistics.TransmitExcessiveCollisions; 388 break; 389 case OID_802_3_RCV_OVERRUN: 390 *Counter = Adapter->Statistics.ReceiveOverrunErrors; 391 break; 392 case OID_802_3_XMIT_UNDERRUN: 393 *Counter = Adapter->Statistics.TransmitUnderrunErrors; 394 break; 395 case OID_802_3_XMIT_HEARTBEAT_FAILURE: 396 *Counter = Adapter->Statistics.TransmitZeroRetry; 397 break; 398 case OID_802_3_XMIT_TIMES_CRS_LOST: 399 *Counter = Adapter->Statistics.TransmitLostCarrierSense; 400 break; 401 case OID_802_3_XMIT_LATE_COLLISIONS: 402 *Counter = Adapter->Statistics.TransmitLateCollisions; 403 break; 404 405 default: 406 UNREACHABLE; 407 break; 408 } 409 } 410 411 static 412 NDIS_STATUS 413 NvNetFillPowerManagementCapabilities( 414 _In_ PNVNET_ADAPTER Adapter, 415 _Out_ PNDIS_PNP_CAPABILITIES Capabilities) 416 { 417 Capabilities->WakeUpCapabilities.MinMagicPacketWakeUp = 418 Capabilities->WakeUpCapabilities.MinPatternWakeUp = 419 Capabilities->WakeUpCapabilities.MinLinkChangeWakeUp = NdisDeviceStateD3; 420 421 /* All hardware is PM-aware */ 422 return NDIS_STATUS_SUCCESS; 423 } 424 425 static 426 ULONG 427 BuildFrameSignature( 428 _In_ PNVNET_WAKE_FRAME WakeFrame) 429 { 430 ULONG i, j, Crc; 431 432 Crc = 0xFFFFFFFF; 433 for (i = 0; i < sizeof(WakeFrame->WakeUpPattern); ++i) 434 { 435 if (WakeFrame->PatternMask.AsUCHAR[i / 8] & (1 << (i % 8))) 436 { 437 Crc ^= WakeFrame->WakeUpPattern[i]; 438 for (j = 8; j > 0; --j) 439 { 440 Crc = (Crc >> 1) ^ (-(LONG)(Crc & 1) & 0xEDB88320); 441 } 442 } 443 } 444 445 return ~Crc; 446 } 447 448 static 449 VOID 450 WriteWakeFrame( 451 _In_ PNVNET_ADAPTER Adapter, 452 _In_ PNVNET_WAKE_FRAME WakeFrame, 453 _In_ ULONG FrameNumber) 454 { 455 ULONG Offset = FrameNumber * 5 * sizeof(ULONG); 456 457 if (FrameNumber >= NV_WAKEUPPATTERNS) 458 { 459 Offset += NV_PATTERN_V2_OFFSET; 460 } 461 462 NV_WRITE(Adapter, NvRegPatternCrc + Offset, BuildFrameSignature(WakeFrame)); 463 NV_WRITE(Adapter, NvRegPatternMask0 + Offset, WakeFrame->PatternMask.AsULONG[0]); 464 NV_WRITE(Adapter, NvRegPatternMask1 + Offset, WakeFrame->PatternMask.AsULONG[1]); 465 NV_WRITE(Adapter, NvRegPatternMask2 + Offset, WakeFrame->PatternMask.AsULONG[2]); 466 NV_WRITE(Adapter, NvRegPatternMask3 + Offset, WakeFrame->PatternMask.AsULONG[3]); 467 } 468 469 static 470 ULONG 471 FrameNumberToWakeUpMask( 472 _In_ ULONG FrameNumber) 473 { 474 if (FrameNumber < 5) 475 return 0x10000 << FrameNumber; 476 else 477 return 0; 478 } 479 480 static 481 ULONG 482 FrameNumberToPowerMask( 483 _In_ ULONG FrameNumber) 484 { 485 switch (FrameNumber) 486 { 487 case 5: 488 return NVREG_POWERSTATE2_WAKEUPPAT_5; 489 case 6: 490 return NVREG_POWERSTATE2_WAKEUPPAT_6; 491 case 7: 492 return NVREG_POWERSTATE2_WAKEUPPAT_7; 493 494 default: 495 return 0; 496 } 497 } 498 499 VOID 500 NvNetSetPowerState( 501 _In_ PNVNET_ADAPTER Adapter, 502 _In_ NDIS_DEVICE_POWER_STATE NewPowerState, 503 _In_ ULONG WakeFlags) 504 { 505 ULONG i, PowerState, PowerState2, WakeUpFlags; 506 507 NV_READ(Adapter, NvRegPowerCap); 508 509 WakeUpFlags = 0; 510 PowerState2 = 0; 511 if (Adapter->Features & DEV_HAS_POWER_CNTRL) 512 { 513 PowerState2 = NV_READ(Adapter, NvRegPowerState2); 514 PowerState2 &= ~(NVREG_POWERSTATE2_WAKEUPPAT_5 | 515 NVREG_POWERSTATE2_WAKEUPPAT_6 | 516 NVREG_POWERSTATE2_WAKEUPPAT_7); 517 } 518 519 if (NewPowerState != NdisDeviceStateD0) 520 { 521 ULONG FramesEnabled = 0; 522 523 if (WakeFlags & NDIS_PNP_WAKE_UP_PATTERN_MATCH) 524 WakeUpFlags |= NVREG_WAKEUPFLAGS_ENABLE_MAGPAT; 525 if (WakeFlags & NDIS_PNP_WAKE_UP_LINK_CHANGE) 526 WakeUpFlags |= NVREG_WAKEUPFLAGS_ENABLE_LINKCHANGE; 527 if (WakeFlags & NDIS_PNP_WAKE_UP_MAGIC_PACKET) 528 { 529 WakeUpFlags |= NVREG_WAKEUPFLAGS_ENABLE_WAKEUPPAT; 530 531 for (i = 0; i < RTL_NUMBER_OF(Adapter->WakeFrames); ++i) 532 { 533 PNVNET_WAKE_FRAME WakeFrame = Adapter->WakeFrames[i]; 534 535 if (!WakeFrame) 536 continue; 537 538 WriteWakeFrame(Adapter, WakeFrame, i); 539 540 PowerState2 |= FrameNumberToPowerMask(i); 541 WakeUpFlags |= FrameNumberToWakeUpMask(i); 542 543 ++FramesEnabled; 544 } 545 } 546 547 if (WakeUpFlags) 548 { 549 if (!(Adapter->Flags & NV_MAC_IN_USE)) 550 { 551 PowerState2 &= ~NVREG_POWERSTATE2_GATE_CLOCKS; 552 PowerState2 |= NVREG_POWERSTATE2_GATE_CLOCK_3; 553 554 if (!FramesEnabled && (WakeUpFlags & NVREG_WAKEUPFLAGS_ENABLE_LINKCHANGE)) 555 PowerState2 |= NVREG_POWERSTATE2_GATE_CLOCK_1; 556 if (FramesEnabled < NV_WAKEUPMASKENTRIES) 557 PowerState2 |= NVREG_POWERSTATE2_GATE_CLOCK_2; 558 } 559 560 NvNetStartReceiver(Adapter); 561 } 562 else 563 { 564 if (!(Adapter->Flags & NV_MAC_IN_USE)) 565 PowerState2 |= NVREG_POWERSTATE2_GATE_CLOCKS; 566 } 567 } 568 569 NdisStallExecution(NV_POWER_STALL); 570 571 NV_WRITE(Adapter, NvRegWakeUpFlags, WakeUpFlags); 572 if (Adapter->Features & DEV_HAS_POWER_CNTRL) 573 { 574 NV_WRITE(Adapter, NvRegPowerState2, PowerState2); 575 } 576 577 NV_WRITE(Adapter, NvRegPowerState, 578 NV_READ(Adapter, NvRegPowerState) | NVREG_POWERSTATE_POWEREDUP); 579 for (i = 0; i < NV_POWER_ATTEMPTS; ++i) 580 { 581 ULONG State = NV_READ(Adapter, NvRegPowerState); 582 583 if (!(State & NVREG_POWERSTATE_POWEREDUP)) 584 break; 585 586 NV_WRITE(Adapter, NvRegPowerState, State | NVREG_POWERSTATE_POWEREDUP); 587 588 NdisStallExecution(NV_POWER_DELAY); 589 } 590 591 PowerState = NewPowerState - 1; 592 if (WakeUpFlags) 593 { 594 PowerState |= NVREG_POWERSTATE_VALID; 595 } 596 NV_WRITE(Adapter, NvRegPowerState, PowerState); 597 } 598 599 static 600 CODE_SEG("PAGE") 601 VOID 602 NTAPI 603 NvNetPowerWorker( 604 _In_ PNDIS_WORK_ITEM WorkItem, 605 _In_opt_ PVOID Context) 606 { 607 PNVNET_ADAPTER Adapter = Context; 608 609 UNREFERENCED_PARAMETER(WorkItem); 610 611 PAGED_CODE(); 612 613 if (Adapter->PowerStatePending == NdisDeviceStateD0) 614 { 615 NvNetSetPowerState(Adapter, NdisDeviceStateD0, 0); 616 617 NT_VERIFY(NvNetInitNIC(Adapter, TRUE) == NDIS_STATUS_SUCCESS); 618 619 NvNetStartAdapter(Adapter); 620 621 NvNetApplyPacketFilter(Adapter); 622 } 623 else 624 { 625 NvNetPauseProcessing(Adapter); 626 627 NvNetStopAdapter(Adapter); 628 629 NvNetIdleTransmitter(Adapter, FALSE); 630 NvNetStopTransmitter(Adapter); 631 NvNetStopReceiver(Adapter); 632 NV_WRITE(Adapter, NvRegTxRxControl, 633 Adapter->TxRxControl | NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET); 634 NdisStallExecution(NV_TXRX_RESET_DELAY); 635 636 NvNetFlushTransmitQueue(Adapter, NDIS_STATUS_FAILURE); 637 638 NvNetSetPowerState(Adapter, Adapter->PowerStatePending, Adapter->WakeFlags); 639 } 640 641 NdisMSetInformationComplete(Adapter->AdapterHandle, NDIS_STATUS_SUCCESS); 642 } 643 644 static 645 NDIS_STATUS 646 NvNetSetPower( 647 _In_ PNVNET_ADAPTER Adapter, 648 _In_ NDIS_DEVICE_POWER_STATE NewPowerState) 649 { 650 Adapter->PowerStatePending = NewPowerState; 651 652 NdisInitializeWorkItem(&Adapter->PowerWorkItem, NvNetPowerWorker, Adapter); 653 NdisScheduleWorkItem(&Adapter->PowerWorkItem); 654 655 return NDIS_STATUS_PENDING; 656 } 657 658 static 659 NDIS_STATUS 660 NvNetAddWakeUpPattern( 661 _In_ PNVNET_ADAPTER Adapter, 662 _In_ PNDIS_PM_PACKET_PATTERN Pattern) 663 { 664 ULONG FrameNumber; 665 NDIS_STATUS Status; 666 PNVNET_WAKE_FRAME WakeFrame; 667 668 if (!_BitScanForward(&FrameNumber, Adapter->WakeFrameBitmap)) 669 { 670 return NDIS_STATUS_RESOURCES; 671 } 672 673 Status = NdisAllocateMemoryWithTag((PVOID*)&WakeFrame, sizeof(*WakeFrame), NVNET_TAG); 674 if (Status != NDIS_STATUS_SUCCESS) 675 { 676 return NDIS_STATUS_RESOURCES; 677 } 678 679 Adapter->WakeFrameBitmap &= ~(1 << FrameNumber); 680 681 NdisZeroMemory(WakeFrame, sizeof(*WakeFrame)); 682 NdisMoveMemory(&WakeFrame->PatternMask, 683 (PUCHAR)Pattern + sizeof(NDIS_PM_PACKET_PATTERN), 684 min(Pattern->MaskSize, 16)); 685 NdisMoveMemory(&WakeFrame->WakeUpPattern, 686 (PUCHAR)Pattern + Pattern->PatternOffset, 687 min(Pattern->PatternSize, 128)); 688 Adapter->WakeFrames[FrameNumber] = WakeFrame; 689 690 /* TODO: VLAN frame translation */ 691 692 return NDIS_STATUS_SUCCESS; 693 } 694 695 static 696 NDIS_STATUS 697 NvNetRemoveWakeUpPattern( 698 _In_ PNVNET_ADAPTER Adapter, 699 _In_ PNDIS_PM_PACKET_PATTERN Pattern) 700 { 701 ULONG i; 702 703 for (i = 0; i < RTL_NUMBER_OF(Adapter->WakeFrames); ++i) 704 { 705 PNVNET_WAKE_FRAME WakeFrame = Adapter->WakeFrames[i]; 706 707 if (!WakeFrame) 708 continue; 709 710 if (!NdisEqualMemory(&WakeFrame->PatternMask, 711 (PUCHAR)Pattern + sizeof(NDIS_PM_PACKET_PATTERN), 712 min(Pattern->MaskSize, 16))) 713 { 714 continue; 715 } 716 717 if (!NdisEqualMemory(&WakeFrame->WakeUpPattern, 718 (PUCHAR)Pattern + Pattern->PatternOffset, 719 min(Pattern->PatternSize, 128))) 720 { 721 continue; 722 } 723 724 NdisFreeMemory(WakeFrame, sizeof(*WakeFrame), 0); 725 726 Adapter->WakeFrameBitmap |= (1 << i); 727 Adapter->WakeFrames[i] = NULL; 728 729 return NDIS_STATUS_SUCCESS; 730 } 731 732 return NDIS_STATUS_INVALID_DATA; 733 } 734 735 static 736 ULONG 737 NvNetGetWakeUp( 738 _In_ PNVNET_ADAPTER Adapter) 739 { 740 return Adapter->WakeFlags & (NDIS_PNP_WAKE_UP_MAGIC_PACKET | 741 NDIS_PNP_WAKE_UP_PATTERN_MATCH | 742 NDIS_PNP_WAKE_UP_LINK_CHANGE); 743 } 744 745 static 746 VOID 747 NvNetEnableWakeUp( 748 _In_ PNVNET_ADAPTER Adapter, 749 _In_ ULONG Flags) 750 { 751 Adapter->WakeFlags = Flags; 752 } 753 754 static 755 NDIS_STATUS 756 NvNetGetTcpTaskOffload( 757 _In_ PNVNET_ADAPTER Adapter, 758 _In_ PNDIS_TASK_OFFLOAD_HEADER TaskOffloadHeader, 759 _In_ ULONG InformationBufferLength, 760 _Out_ PULONG BytesWritten, 761 _Out_ PULONG BytesNeeded) 762 { 763 ULONG InfoLength; 764 PNDIS_TASK_OFFLOAD TaskOffload; 765 766 if (!(Adapter->Flags & (NV_SEND_CHECKSUM | NV_SEND_LARGE_SEND))) 767 { 768 *BytesWritten = 0; 769 *BytesNeeded = 0; 770 return NDIS_STATUS_NOT_SUPPORTED; 771 } 772 773 InfoLength = sizeof(NDIS_TASK_OFFLOAD_HEADER); 774 if (Adapter->Flags & NV_SEND_CHECKSUM) 775 { 776 InfoLength += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) + 777 sizeof(NDIS_TASK_TCP_IP_CHECKSUM); 778 } 779 if (Adapter->Flags & NV_SEND_LARGE_SEND) 780 { 781 InfoLength += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) + 782 sizeof(NDIS_TASK_TCP_LARGE_SEND); 783 } 784 785 if (InformationBufferLength < InfoLength) 786 { 787 *BytesWritten = 0; 788 *BytesNeeded = InfoLength; 789 return NDIS_STATUS_BUFFER_TOO_SHORT; 790 } 791 792 if ((TaskOffloadHeader->EncapsulationFormat.Encapsulation != IEEE_802_3_Encapsulation) && 793 (TaskOffloadHeader->EncapsulationFormat.Encapsulation != UNSPECIFIED_Encapsulation || 794 TaskOffloadHeader->EncapsulationFormat.EncapsulationHeaderSize != sizeof(ETH_HEADER))) 795 { 796 *BytesWritten = 0; 797 *BytesNeeded = 0; 798 return NDIS_STATUS_NOT_SUPPORTED; 799 } 800 if (TaskOffloadHeader->Version != NDIS_TASK_OFFLOAD_VERSION) 801 { 802 *BytesWritten = 0; 803 *BytesNeeded = 0; 804 return NDIS_STATUS_NOT_SUPPORTED; 805 } 806 807 TaskOffloadHeader->OffsetFirstTask = sizeof(NDIS_TASK_OFFLOAD_HEADER); 808 TaskOffload = (PNDIS_TASK_OFFLOAD)(TaskOffloadHeader + 1); 809 if (Adapter->Flags & NV_SEND_CHECKSUM) 810 { 811 PNDIS_TASK_TCP_IP_CHECKSUM ChecksumTask; 812 813 TaskOffload->Size = sizeof(NDIS_TASK_OFFLOAD); 814 TaskOffload->Version = NDIS_TASK_OFFLOAD_VERSION; 815 TaskOffload->Task = TcpIpChecksumNdisTask; 816 TaskOffload->TaskBufferLength = sizeof(NDIS_TASK_TCP_IP_CHECKSUM); 817 TaskOffload->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) + 818 sizeof(NDIS_TASK_TCP_IP_CHECKSUM); 819 820 ChecksumTask = (PNDIS_TASK_TCP_IP_CHECKSUM)TaskOffload->TaskBuffer; 821 NdisZeroMemory(ChecksumTask, sizeof(*ChecksumTask)); 822 823 ChecksumTask->V4Transmit.IpOptionsSupported = 1; 824 ChecksumTask->V4Transmit.TcpOptionsSupported = 1; 825 ChecksumTask->V4Transmit.TcpChecksum = 1; 826 ChecksumTask->V4Transmit.UdpChecksum = 1; 827 ChecksumTask->V4Transmit.IpChecksum = 1; 828 829 ChecksumTask->V4Receive.IpOptionsSupported = 1; 830 ChecksumTask->V4Receive.TcpOptionsSupported = 1; 831 ChecksumTask->V4Receive.TcpChecksum = 1; 832 ChecksumTask->V4Receive.UdpChecksum = 1; 833 ChecksumTask->V4Receive.IpChecksum = 1; 834 835 TaskOffload = (PNDIS_TASK_OFFLOAD)(ChecksumTask + 1); 836 } 837 if (Adapter->Flags & NV_SEND_LARGE_SEND) 838 { 839 PNDIS_TASK_TCP_LARGE_SEND LargeSendTask; 840 841 TaskOffload->Size = sizeof(NDIS_TASK_OFFLOAD); 842 TaskOffload->Version = NDIS_TASK_OFFLOAD_VERSION; 843 TaskOffload->Task = TcpLargeSendNdisTask; 844 TaskOffload->TaskBufferLength = sizeof(NDIS_TASK_TCP_LARGE_SEND); 845 TaskOffload->OffsetNextTask = 0; 846 847 LargeSendTask = (PNDIS_TASK_TCP_LARGE_SEND)TaskOffload->TaskBuffer; 848 LargeSendTask->Version = NDIS_TASK_TCP_LARGE_SEND_V0; 849 LargeSendTask->MinSegmentCount = NVNET_MINIMUM_LSO_SEGMENT_COUNT; 850 LargeSendTask->MaxOffLoadSize = NVNET_MAXIMUM_LSO_FRAME_SIZE; 851 LargeSendTask->IpOptions = TRUE; 852 LargeSendTask->TcpOptions = TRUE; 853 } 854 TaskOffload->OffsetNextTask = 0; 855 856 *BytesWritten = InfoLength; 857 *BytesNeeded = 0; 858 859 return NDIS_STATUS_SUCCESS; 860 } 861 862 static 863 NDIS_STATUS 864 NvNetSetTcpTaskOffload( 865 _Inout_ PNVNET_ADAPTER Adapter, 866 _In_ PNDIS_TASK_OFFLOAD_HEADER TaskOffloadHeader, 867 _In_ PULONG BytesRead) 868 { 869 ULONG Offset; 870 PNDIS_TASK_OFFLOAD TaskOffload; 871 872 if (TaskOffloadHeader->Version != NDIS_TASK_OFFLOAD_VERSION) 873 { 874 return NDIS_STATUS_NOT_SUPPORTED; 875 } 876 877 Adapter->IpHeaderOffset = TaskOffloadHeader->EncapsulationFormat.EncapsulationHeaderSize; 878 879 TaskOffload = (PNDIS_TASK_OFFLOAD)TaskOffloadHeader; 880 Offset = TaskOffloadHeader->OffsetFirstTask; 881 882 while (Offset) 883 { 884 *BytesRead += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer); 885 886 TaskOffload = (PNDIS_TASK_OFFLOAD)((PUCHAR)TaskOffload + Offset); 887 switch (TaskOffload->Task) 888 { 889 case TcpIpChecksumNdisTask: 890 { 891 PNDIS_TASK_TCP_IP_CHECKSUM Task; 892 893 *BytesRead += sizeof(NDIS_TASK_TCP_IP_CHECKSUM); 894 895 if (!(Adapter->Flags & NV_SEND_CHECKSUM)) 896 { 897 return NDIS_STATUS_NOT_SUPPORTED; 898 } 899 900 Task = (PNDIS_TASK_TCP_IP_CHECKSUM)TaskOffload->TaskBuffer; 901 902 Adapter->Offload.SendTcpChecksum = Task->V4Transmit.TcpChecksum; 903 Adapter->Offload.SendUdpChecksum = Task->V4Transmit.UdpChecksum; 904 Adapter->Offload.SendIpChecksum = Task->V4Transmit.IpChecksum; 905 906 Adapter->Offload.ReceiveTcpChecksum = Task->V4Receive.TcpChecksum; 907 Adapter->Offload.ReceiveUdpChecksum = Task->V4Receive.UdpChecksum; 908 Adapter->Offload.ReceiveIpChecksum = Task->V4Receive.IpChecksum; 909 break; 910 } 911 912 case TcpLargeSendNdisTask: 913 { 914 PNDIS_TASK_TCP_LARGE_SEND Task; 915 916 if (!(Adapter->Flags & NV_SEND_LARGE_SEND)) 917 { 918 return NDIS_STATUS_NOT_SUPPORTED; 919 } 920 921 if ((TaskOffloadHeader-> 922 EncapsulationFormat.Encapsulation != IEEE_802_3_Encapsulation) && 923 (TaskOffloadHeader-> 924 EncapsulationFormat.Encapsulation != UNSPECIFIED_Encapsulation || 925 TaskOffloadHeader-> 926 EncapsulationFormat.EncapsulationHeaderSize != sizeof(ETH_HEADER))) 927 { 928 return NDIS_STATUS_NOT_SUPPORTED; 929 } 930 931 *BytesRead += sizeof(NDIS_TASK_TCP_LARGE_SEND); 932 933 Task = (PNDIS_TASK_TCP_LARGE_SEND)TaskOffload->TaskBuffer; 934 935 if (Task->MinSegmentCount != NVNET_MINIMUM_LSO_SEGMENT_COUNT) 936 return NDIS_STATUS_NOT_SUPPORTED; 937 938 if (Task->MaxOffLoadSize > NVNET_MAXIMUM_LSO_FRAME_SIZE) 939 return NDIS_STATUS_NOT_SUPPORTED; 940 941 /* Nothing to do */ 942 break; 943 } 944 945 default: 946 break; 947 } 948 949 Offset = TaskOffload->OffsetNextTask; 950 } 951 952 NdisAcquireSpinLock(&Adapter->Send.Lock); 953 954 if (Adapter->Offload.ReceiveTcpChecksum || 955 Adapter->Offload.ReceiveUdpChecksum || 956 Adapter->Offload.ReceiveIpChecksum) 957 { 958 Adapter->TxRxControl |= NVREG_TXRXCTL_RXCHECK; 959 } 960 else 961 { 962 Adapter->TxRxControl &= ~NVREG_TXRXCTL_RXCHECK; 963 } 964 NV_WRITE(Adapter, NvRegTxRxControl, Adapter->TxRxControl); 965 966 NdisReleaseSpinLock(&Adapter->Send.Lock); 967 968 return NDIS_STATUS_SUCCESS; 969 } 970 971 NDIS_STATUS 972 NTAPI 973 MiniportQueryInformation( 974 _In_ NDIS_HANDLE MiniportAdapterContext, 975 _In_ NDIS_OID Oid, 976 _In_ PVOID InformationBuffer, 977 _In_ ULONG InformationBufferLength, 978 _Out_ PULONG BytesWritten, 979 _Out_ PULONG BytesNeeded) 980 { 981 PNVNET_ADAPTER Adapter = (PNVNET_ADAPTER)MiniportAdapterContext; 982 NDIS_STATUS Status = NDIS_STATUS_SUCCESS; 983 ULONG InfoLength; 984 PVOID InfoPtr; 985 union _GENERIC_INFORMATION 986 { 987 USHORT Ushort; 988 ULONG Ulong; 989 ULONG64 Ulong64; 990 NDIS_MEDIUM Medium; 991 NDIS_HARDWARE_STATUS Status; 992 NDIS_DEVICE_POWER_STATE PowerState; 993 } GenericInfo; 994 995 InfoLength = sizeof(ULONG); 996 InfoPtr = &GenericInfo; 997 998 switch (Oid) 999 { 1000 case OID_GEN_SUPPORTED_LIST: 1001 InfoPtr = (PVOID)&NvpSupportedOidList; 1002 InfoLength = sizeof(NvpSupportedOidList); 1003 break; 1004 1005 case OID_GEN_HARDWARE_STATUS: 1006 InfoLength = sizeof(NDIS_HARDWARE_STATUS); 1007 GenericInfo.Status = NdisHardwareStatusReady; 1008 break; 1009 1010 case OID_GEN_MEDIA_SUPPORTED: 1011 case OID_GEN_MEDIA_IN_USE: 1012 { 1013 InfoLength = sizeof(NDIS_MEDIUM); 1014 GenericInfo.Medium = NdisMedium802_3; 1015 break; 1016 } 1017 1018 case OID_GEN_CURRENT_LOOKAHEAD: 1019 case OID_GEN_MAXIMUM_LOOKAHEAD: 1020 { 1021 GenericInfo.Ulong = Adapter->MaximumFrameSize - sizeof(ETH_HEADER); 1022 break; 1023 } 1024 1025 case OID_GEN_MAXIMUM_FRAME_SIZE: 1026 { 1027 GenericInfo.Ulong = Adapter->MaximumFrameSize; 1028 break; 1029 } 1030 1031 case OID_GEN_LINK_SPEED: 1032 { 1033 GenericInfo.Ulong = NvNetGetLinkSpeed(Adapter) * 10000; 1034 break; 1035 } 1036 1037 case OID_GEN_TRANSMIT_BUFFER_SPACE: 1038 { 1039 /* TODO: Change this later, once the driver can handle multipacket sends */ 1040 GenericInfo.Ulong = Adapter->MaximumFrameSize; 1041 break; 1042 } 1043 1044 case OID_GEN_RECEIVE_BUFFER_SPACE: 1045 { 1046 GenericInfo.Ulong = Adapter->MaximumFrameSize * NVNET_RECEIVE_DESCRIPTORS; 1047 } 1048 1049 case OID_GEN_MAXIMUM_TOTAL_SIZE: 1050 case OID_GEN_TRANSMIT_BLOCK_SIZE: 1051 case OID_GEN_RECEIVE_BLOCK_SIZE: 1052 { 1053 GenericInfo.Ulong = Adapter->MaximumFrameSize; 1054 break; 1055 } 1056 1057 case OID_GEN_VENDOR_ID: 1058 { 1059 GenericInfo.Ulong = 0; 1060 GenericInfo.Ulong |= (Adapter->PermanentMacAddress[0] << 16); 1061 GenericInfo.Ulong |= (Adapter->PermanentMacAddress[1] << 8); 1062 GenericInfo.Ulong |= (Adapter->PermanentMacAddress[2] & 0xFF); 1063 break; 1064 } 1065 1066 case OID_GEN_DRIVER_VERSION: 1067 { 1068 InfoLength = sizeof(USHORT); 1069 GenericInfo.Ushort = (NDIS_MINIPORT_MAJOR_VERSION << 8) | NDIS_MINIPORT_MINOR_VERSION; 1070 break; 1071 } 1072 1073 case OID_GEN_VENDOR_DESCRIPTION: 1074 { 1075 static const CHAR VendorDesc[] = "nVidia nForce Ethernet Controller"; 1076 InfoPtr = (PVOID)&VendorDesc; 1077 InfoLength = sizeof(VendorDesc); 1078 break; 1079 } 1080 1081 case OID_GEN_CURRENT_PACKET_FILTER: 1082 { 1083 GenericInfo.Ulong = Adapter->PacketFilter; 1084 break; 1085 } 1086 1087 case OID_GEN_MAC_OPTIONS: 1088 { 1089 GenericInfo.Ulong = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | 1090 NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | 1091 NDIS_MAC_OPTION_NO_LOOPBACK; 1092 1093 if (Adapter->Flags & NV_PACKET_PRIORITY) 1094 GenericInfo.Ulong |= NDIS_MAC_OPTION_8021P_PRIORITY; 1095 if (Adapter->Flags & NV_VLAN_TAGGING) 1096 GenericInfo.Ulong |= NDIS_MAC_OPTION_8021Q_VLAN; 1097 break; 1098 } 1099 1100 case OID_GEN_MEDIA_CONNECT_STATUS: 1101 { 1102 GenericInfo.Ulong = Adapter->Connected ? NdisMediaStateConnected 1103 : NdisMediaStateDisconnected; 1104 break; 1105 } 1106 1107 case OID_GEN_MAXIMUM_SEND_PACKETS: 1108 { 1109 /* TODO: Multipacket sends */ 1110 GenericInfo.Ulong = 1; 1111 break; 1112 } 1113 1114 case OID_GEN_VENDOR_DRIVER_VERSION: 1115 { 1116 /* 1.0.0 */ 1117 GenericInfo.Ulong = 0x100; 1118 break; 1119 } 1120 1121 case OID_GEN_XMIT_OK: 1122 case OID_GEN_RCV_OK: 1123 case OID_GEN_XMIT_ERROR: 1124 case OID_GEN_RCV_ERROR: 1125 case OID_GEN_RCV_NO_BUFFER: 1126 case OID_GEN_DIRECTED_FRAMES_RCV: 1127 case OID_GEN_RCV_CRC_ERROR: 1128 case OID_802_3_RCV_ERROR_ALIGNMENT: 1129 case OID_802_3_XMIT_ONE_COLLISION: 1130 case OID_802_3_XMIT_MORE_COLLISIONS: 1131 case OID_802_3_XMIT_DEFERRED: 1132 case OID_802_3_XMIT_MAX_COLLISIONS: 1133 case OID_802_3_RCV_OVERRUN: 1134 case OID_802_3_XMIT_UNDERRUN: 1135 case OID_802_3_XMIT_HEARTBEAT_FAILURE: 1136 case OID_802_3_XMIT_TIMES_CRS_LOST: 1137 case OID_802_3_XMIT_LATE_COLLISIONS: 1138 { 1139 if (Adapter->Features & DEV_HAS_STATISTICS_COUNTERS) 1140 { 1141 NvNetReadStatistics(Adapter); 1142 NvNetQueryHwCounter(Adapter, Oid, &GenericInfo.Ulong64); 1143 } 1144 else 1145 { 1146 NvNetQuerySoftwareCounter(Adapter, Oid, &GenericInfo.Ulong64); 1147 } 1148 1149 *BytesNeeded = sizeof(ULONG64); 1150 if (InformationBufferLength < sizeof(ULONG)) 1151 { 1152 *BytesWritten = 0; 1153 return NDIS_STATUS_BUFFER_TOO_SHORT; 1154 } 1155 if (InformationBufferLength >= sizeof(ULONG64)) 1156 { 1157 *BytesWritten = sizeof(ULONG64); 1158 NdisMoveMemory(InformationBuffer, InfoPtr, sizeof(ULONG64)); 1159 } 1160 else 1161 { 1162 *BytesWritten = sizeof(ULONG); 1163 NdisMoveMemory(InformationBuffer, InfoPtr, sizeof(ULONG)); 1164 } 1165 1166 return NDIS_STATUS_SUCCESS; 1167 } 1168 1169 case OID_GEN_TRANSMIT_QUEUE_LENGTH: 1170 { 1171 GenericInfo.Ulong = NVNET_TRANSMIT_BLOCKS - Adapter->Send.TcbSlots; 1172 break; 1173 } 1174 1175 case OID_802_3_PERMANENT_ADDRESS: 1176 { 1177 InfoPtr = Adapter->PermanentMacAddress; 1178 InfoLength = ETH_LENGTH_OF_ADDRESS; 1179 break; 1180 } 1181 1182 case OID_802_3_CURRENT_ADDRESS: 1183 { 1184 InfoPtr = Adapter->CurrentMacAddress; 1185 InfoLength = ETH_LENGTH_OF_ADDRESS; 1186 break; 1187 } 1188 1189 case OID_802_3_MULTICAST_LIST: 1190 { 1191 InfoPtr = Adapter->MulticastList; 1192 InfoLength = Adapter->MulticastListSize * ETH_LENGTH_OF_ADDRESS; 1193 break; 1194 } 1195 1196 case OID_802_3_MAXIMUM_LIST_SIZE: 1197 { 1198 GenericInfo.Ulong = NVNET_MULTICAST_LIST_SIZE; 1199 break; 1200 } 1201 1202 case OID_TCP_TASK_OFFLOAD: 1203 { 1204 return NvNetGetTcpTaskOffload(Adapter, 1205 InformationBuffer, 1206 InformationBufferLength, 1207 BytesWritten, 1208 BytesWritten); 1209 } 1210 1211 case OID_PNP_ENABLE_WAKE_UP: 1212 { 1213 GenericInfo.Ulong = NvNetGetWakeUp(Adapter); 1214 break; 1215 } 1216 1217 case OID_PNP_CAPABILITIES: 1218 { 1219 InfoLength = sizeof(NDIS_PNP_CAPABILITIES); 1220 1221 if (InformationBufferLength < InfoLength) 1222 { 1223 *BytesWritten = 0; 1224 *BytesNeeded = InfoLength; 1225 return NDIS_STATUS_BUFFER_TOO_SHORT; 1226 } 1227 1228 *BytesWritten = InfoLength; 1229 *BytesNeeded = 0; 1230 return NvNetFillPowerManagementCapabilities(Adapter, InformationBuffer); 1231 } 1232 1233 case OID_PNP_QUERY_POWER: 1234 { 1235 return NDIS_STATUS_SUCCESS; 1236 } 1237 1238 case OID_GEN_VLAN_ID: 1239 { 1240 /* TODO: Implement software VLAN support */ 1241 if (!(Adapter->Flags & NV_VLAN_TAGGING)) 1242 { 1243 Status = NDIS_STATUS_NOT_SUPPORTED; 1244 break; 1245 } 1246 1247 GenericInfo.Ulong = Adapter->VlanId; 1248 break; 1249 } 1250 1251 default: 1252 Status = NDIS_STATUS_INVALID_OID; 1253 break; 1254 } 1255 1256 if (Status == NDIS_STATUS_SUCCESS) 1257 { 1258 if (InfoLength > InformationBufferLength) 1259 { 1260 *BytesWritten = 0; 1261 *BytesNeeded = InfoLength; 1262 Status = NDIS_STATUS_BUFFER_TOO_SHORT; 1263 } 1264 else 1265 { 1266 NdisMoveMemory(InformationBuffer, InfoPtr, InfoLength); 1267 *BytesWritten = InfoLength; 1268 *BytesNeeded = 0; 1269 } 1270 } 1271 else 1272 { 1273 *BytesWritten = 0; 1274 *BytesNeeded = 0; 1275 } 1276 1277 return Status; 1278 } 1279 1280 NDIS_STATUS 1281 NTAPI 1282 MiniportSetInformation( 1283 _In_ NDIS_HANDLE MiniportAdapterContext, 1284 _In_ NDIS_OID Oid, 1285 _In_ PVOID InformationBuffer, 1286 _In_ ULONG InformationBufferLength, 1287 _Out_ PULONG BytesRead, 1288 _Out_ PULONG BytesNeeded) 1289 { 1290 PNVNET_ADAPTER Adapter = (PNVNET_ADAPTER)MiniportAdapterContext; 1291 NDIS_STATUS Status = NDIS_STATUS_SUCCESS; 1292 ULONG GenericUlong; 1293 1294 *BytesRead = 0; 1295 *BytesNeeded = 0; 1296 1297 switch (Oid) 1298 { 1299 case OID_802_3_MULTICAST_LIST: 1300 { 1301 if (InformationBufferLength % ETH_LENGTH_OF_ADDRESS) 1302 { 1303 *BytesNeeded = (InformationBufferLength / ETH_LENGTH_OF_ADDRESS) * 1304 ETH_LENGTH_OF_ADDRESS; 1305 Status = NDIS_STATUS_INVALID_LENGTH; 1306 break; 1307 } 1308 1309 if (InformationBufferLength > sizeof(Adapter->MulticastList)) 1310 { 1311 *BytesNeeded = sizeof(Adapter->MulticastList); 1312 Status = NDIS_STATUS_MULTICAST_FULL; 1313 break; 1314 } 1315 1316 *BytesRead = InformationBufferLength; 1317 NdisMoveMemory(Adapter->MulticastList, InformationBuffer, InformationBufferLength); 1318 1319 Adapter->MulticastListSize = InformationBufferLength / ETH_LENGTH_OF_ADDRESS; 1320 1321 NvNetApplyPacketFilter(Adapter); 1322 break; 1323 } 1324 1325 case OID_GEN_CURRENT_PACKET_FILTER: 1326 { 1327 if (InformationBufferLength < sizeof(ULONG)) 1328 { 1329 *BytesNeeded = sizeof(ULONG); 1330 Status = NDIS_STATUS_INVALID_LENGTH; 1331 break; 1332 } 1333 1334 *BytesRead = sizeof(ULONG); 1335 NdisMoveMemory(&GenericUlong, InformationBuffer, sizeof(ULONG)); 1336 1337 if (GenericUlong & ~NVNET_PACKET_FILTERS) 1338 { 1339 Status = NDIS_STATUS_NOT_SUPPORTED; 1340 break; 1341 } 1342 1343 /* Do not check to see if the filter is the same filter */ 1344 Adapter->PacketFilter = GenericUlong; 1345 1346 NvNetApplyPacketFilter(Adapter); 1347 break; 1348 } 1349 1350 case OID_GEN_CURRENT_LOOKAHEAD: 1351 { 1352 if (InformationBufferLength < sizeof(ULONG)) 1353 { 1354 *BytesNeeded = sizeof(ULONG); 1355 Status = NDIS_STATUS_INVALID_LENGTH; 1356 break; 1357 } 1358 1359 /* Nothing to do */ 1360 *BytesRead = sizeof(ULONG); 1361 break; 1362 } 1363 1364 case OID_GEN_VLAN_ID: 1365 { 1366 if (InformationBufferLength < sizeof(ULONG)) 1367 { 1368 *BytesNeeded = sizeof(ULONG); 1369 Status = NDIS_STATUS_INVALID_LENGTH; 1370 break; 1371 } 1372 1373 if (!(Adapter->Flags & NV_VLAN_TAGGING)) 1374 { 1375 Status = NDIS_STATUS_NOT_SUPPORTED; 1376 break; 1377 } 1378 1379 *BytesRead = sizeof(ULONG); 1380 NdisMoveMemory(&GenericUlong, InformationBuffer, sizeof(ULONG)); 1381 1382 if (GenericUlong > NVNET_MAXIMUM_VLAN_ID) 1383 { 1384 Status = NDIS_STATUS_FAILURE; 1385 break; 1386 } 1387 1388 Adapter->VlanId = GenericUlong; 1389 break; 1390 } 1391 1392 case OID_TCP_TASK_OFFLOAD: 1393 { 1394 if (InformationBufferLength < sizeof(NDIS_TASK_OFFLOAD_HEADER)) 1395 { 1396 *BytesNeeded = sizeof(NDIS_TASK_OFFLOAD_HEADER); 1397 Status = NDIS_STATUS_INVALID_LENGTH; 1398 break; 1399 } 1400 1401 *BytesRead = InformationBufferLength; 1402 1403 Status = NvNetSetTcpTaskOffload(Adapter, InformationBuffer, BytesRead); 1404 break; 1405 } 1406 1407 case OID_PNP_ADD_WAKE_UP_PATTERN: 1408 { 1409 if (InformationBufferLength < sizeof(NDIS_PM_PACKET_PATTERN)) 1410 { 1411 *BytesNeeded = sizeof(NDIS_PM_PACKET_PATTERN); 1412 Status = NDIS_STATUS_INVALID_LENGTH; 1413 break; 1414 } 1415 1416 *BytesRead = sizeof(NDIS_PM_PACKET_PATTERN); 1417 1418 Status = NvNetAddWakeUpPattern(Adapter, InformationBuffer); 1419 break; 1420 } 1421 1422 case OID_PNP_REMOVE_WAKE_UP_PATTERN: 1423 { 1424 if (InformationBufferLength < sizeof(NDIS_PM_PACKET_PATTERN)) 1425 { 1426 *BytesNeeded = sizeof(NDIS_PM_PACKET_PATTERN); 1427 Status = NDIS_STATUS_INVALID_LENGTH; 1428 break; 1429 } 1430 1431 *BytesRead = sizeof(NDIS_PM_PACKET_PATTERN); 1432 1433 Status = NvNetRemoveWakeUpPattern(Adapter, InformationBuffer); 1434 break; 1435 } 1436 1437 case OID_PNP_ENABLE_WAKE_UP: 1438 { 1439 if (InformationBufferLength < sizeof(ULONG)) 1440 { 1441 *BytesNeeded = sizeof(ULONG); 1442 Status = NDIS_STATUS_INVALID_LENGTH; 1443 break; 1444 } 1445 1446 *BytesRead = sizeof(ULONG); 1447 NdisMoveMemory(&GenericUlong, InformationBuffer, sizeof(ULONG)); 1448 1449 NvNetEnableWakeUp(Adapter, GenericUlong); 1450 break; 1451 } 1452 1453 case OID_PNP_SET_POWER: 1454 { 1455 if (InformationBufferLength < sizeof(NDIS_DEVICE_POWER_STATE)) 1456 { 1457 *BytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE); 1458 Status = NDIS_STATUS_INVALID_LENGTH; 1459 break; 1460 } 1461 1462 *BytesRead = sizeof(ULONG); 1463 NdisMoveMemory(&GenericUlong, InformationBuffer, sizeof(ULONG)); 1464 1465 if (GenericUlong < NdisDeviceStateD0 || GenericUlong > NdisDeviceStateD3) 1466 { 1467 Status = NDIS_STATUS_INVALID_DATA; 1468 break; 1469 } 1470 1471 Status = NvNetSetPower(Adapter, GenericUlong); 1472 break; 1473 } 1474 1475 default: 1476 Status = NDIS_STATUS_NOT_SUPPORTED; 1477 break; 1478 } 1479 1480 return Status; 1481 } 1482