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 BOOLEAN 697 NvEqualMemory( 698 _In_reads_bytes_(Length) PVOID Destination, 699 _In_reads_bytes_(Length) PVOID Source, 700 _In_ ULONG Length) 701 { 702 ULONG i; 703 PUCHAR Src, Dest; 704 705 Src = Source; 706 Dest = Destination; 707 for (i = 0; i < Length; ++i) 708 { 709 if (Src[i] != Dest[i]) 710 return FALSE; 711 } 712 713 return TRUE; 714 } 715 /* 'memcmp' is unavailable for some reason */ 716 #undef NdisEqualMemory 717 #define NdisEqualMemory NvEqualMemory 718 719 static 720 NDIS_STATUS 721 NvNetRemoveWakeUpPattern( 722 _In_ PNVNET_ADAPTER Adapter, 723 _In_ PNDIS_PM_PACKET_PATTERN Pattern) 724 { 725 ULONG i; 726 727 for (i = 0; i < RTL_NUMBER_OF(Adapter->WakeFrames); ++i) 728 { 729 PNVNET_WAKE_FRAME WakeFrame = Adapter->WakeFrames[i]; 730 731 if (!WakeFrame) 732 continue; 733 734 if (!NdisEqualMemory(&WakeFrame->PatternMask, 735 (PUCHAR)Pattern + sizeof(NDIS_PM_PACKET_PATTERN), 736 min(Pattern->MaskSize, 16))) 737 { 738 continue; 739 } 740 741 if (!NdisEqualMemory(&WakeFrame->WakeUpPattern, 742 (PUCHAR)Pattern + Pattern->PatternOffset, 743 min(Pattern->PatternSize, 128))) 744 { 745 continue; 746 } 747 748 NdisFreeMemory(WakeFrame, sizeof(*WakeFrame), 0); 749 750 Adapter->WakeFrameBitmap |= (1 << i); 751 Adapter->WakeFrames[i] = NULL; 752 753 return NDIS_STATUS_SUCCESS; 754 } 755 756 return NDIS_STATUS_INVALID_DATA; 757 } 758 759 static 760 ULONG 761 NvNetGetWakeUp( 762 _In_ PNVNET_ADAPTER Adapter) 763 { 764 return Adapter->WakeFlags & (NDIS_PNP_WAKE_UP_MAGIC_PACKET | 765 NDIS_PNP_WAKE_UP_PATTERN_MATCH | 766 NDIS_PNP_WAKE_UP_LINK_CHANGE); 767 } 768 769 static 770 VOID 771 NvNetEnableWakeUp( 772 _In_ PNVNET_ADAPTER Adapter, 773 _In_ ULONG Flags) 774 { 775 Adapter->WakeFlags = Flags; 776 } 777 778 static 779 NDIS_STATUS 780 NvNetGetTcpTaskOffload( 781 _In_ PNVNET_ADAPTER Adapter, 782 _In_ PNDIS_TASK_OFFLOAD_HEADER TaskOffloadHeader, 783 _In_ ULONG InformationBufferLength, 784 _Out_ PULONG BytesWritten, 785 _Out_ PULONG BytesNeeded) 786 { 787 ULONG InfoLength; 788 PNDIS_TASK_OFFLOAD TaskOffload; 789 790 if (!(Adapter->Flags & (NV_SEND_CHECKSUM | NV_SEND_LARGE_SEND))) 791 { 792 *BytesWritten = 0; 793 *BytesNeeded = 0; 794 return NDIS_STATUS_NOT_SUPPORTED; 795 } 796 797 InfoLength = sizeof(NDIS_TASK_OFFLOAD_HEADER); 798 if (Adapter->Flags & NV_SEND_CHECKSUM) 799 { 800 InfoLength += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) + 801 sizeof(NDIS_TASK_TCP_IP_CHECKSUM); 802 } 803 if (Adapter->Flags & NV_SEND_LARGE_SEND) 804 { 805 InfoLength += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) + 806 sizeof(NDIS_TASK_TCP_LARGE_SEND); 807 } 808 809 if (InformationBufferLength < InfoLength) 810 { 811 *BytesWritten = 0; 812 *BytesNeeded = InfoLength; 813 return NDIS_STATUS_BUFFER_TOO_SHORT; 814 } 815 816 if ((TaskOffloadHeader->EncapsulationFormat.Encapsulation != IEEE_802_3_Encapsulation) && 817 (TaskOffloadHeader->EncapsulationFormat.Encapsulation != UNSPECIFIED_Encapsulation || 818 TaskOffloadHeader->EncapsulationFormat.EncapsulationHeaderSize != sizeof(ETH_HEADER))) 819 { 820 *BytesWritten = 0; 821 *BytesNeeded = 0; 822 return NDIS_STATUS_NOT_SUPPORTED; 823 } 824 if (TaskOffloadHeader->Version != NDIS_TASK_OFFLOAD_VERSION) 825 { 826 *BytesWritten = 0; 827 *BytesNeeded = 0; 828 return NDIS_STATUS_NOT_SUPPORTED; 829 } 830 831 TaskOffloadHeader->OffsetFirstTask = sizeof(NDIS_TASK_OFFLOAD_HEADER); 832 TaskOffload = (PNDIS_TASK_OFFLOAD)(TaskOffloadHeader + 1); 833 if (Adapter->Flags & NV_SEND_CHECKSUM) 834 { 835 PNDIS_TASK_TCP_IP_CHECKSUM ChecksumTask; 836 837 TaskOffload->Size = sizeof(NDIS_TASK_OFFLOAD); 838 TaskOffload->Version = NDIS_TASK_OFFLOAD_VERSION; 839 TaskOffload->Task = TcpIpChecksumNdisTask; 840 TaskOffload->TaskBufferLength = sizeof(NDIS_TASK_TCP_IP_CHECKSUM); 841 TaskOffload->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) + 842 sizeof(NDIS_TASK_TCP_IP_CHECKSUM); 843 844 ChecksumTask = (PNDIS_TASK_TCP_IP_CHECKSUM)TaskOffload->TaskBuffer; 845 NdisZeroMemory(ChecksumTask, sizeof(*ChecksumTask)); 846 847 ChecksumTask->V4Transmit.IpOptionsSupported = 1; 848 ChecksumTask->V4Transmit.TcpOptionsSupported = 1; 849 ChecksumTask->V4Transmit.TcpChecksum = 1; 850 ChecksumTask->V4Transmit.UdpChecksum = 1; 851 ChecksumTask->V4Transmit.IpChecksum = 1; 852 853 ChecksumTask->V4Receive.IpOptionsSupported = 1; 854 ChecksumTask->V4Receive.TcpOptionsSupported = 1; 855 ChecksumTask->V4Receive.TcpChecksum = 1; 856 ChecksumTask->V4Receive.UdpChecksum = 1; 857 ChecksumTask->V4Receive.IpChecksum = 1; 858 859 TaskOffload = (PNDIS_TASK_OFFLOAD)(ChecksumTask + 1); 860 } 861 if (Adapter->Flags & NV_SEND_LARGE_SEND) 862 { 863 PNDIS_TASK_TCP_LARGE_SEND LargeSendTask; 864 865 TaskOffload->Size = sizeof(NDIS_TASK_OFFLOAD); 866 TaskOffload->Version = NDIS_TASK_OFFLOAD_VERSION; 867 TaskOffload->Task = TcpLargeSendNdisTask; 868 TaskOffload->TaskBufferLength = sizeof(NDIS_TASK_TCP_LARGE_SEND); 869 TaskOffload->OffsetNextTask = 0; 870 871 LargeSendTask = (PNDIS_TASK_TCP_LARGE_SEND)TaskOffload->TaskBuffer; 872 LargeSendTask->Version = NDIS_TASK_TCP_LARGE_SEND_V0; 873 LargeSendTask->MinSegmentCount = NVNET_MINIMUM_LSO_SEGMENT_COUNT; 874 LargeSendTask->MaxOffLoadSize = NVNET_MAXIMUM_LSO_FRAME_SIZE; 875 LargeSendTask->IpOptions = TRUE; 876 LargeSendTask->TcpOptions = TRUE; 877 } 878 TaskOffload->OffsetNextTask = 0; 879 880 *BytesWritten = InfoLength; 881 *BytesNeeded = 0; 882 883 return NDIS_STATUS_SUCCESS; 884 } 885 886 static 887 NDIS_STATUS 888 NvNetSetTcpTaskOffload( 889 _Inout_ PNVNET_ADAPTER Adapter, 890 _In_ PNDIS_TASK_OFFLOAD_HEADER TaskOffloadHeader, 891 _In_ PULONG BytesRead) 892 { 893 ULONG Offset; 894 PNDIS_TASK_OFFLOAD TaskOffload; 895 896 if (TaskOffloadHeader->Version != NDIS_TASK_OFFLOAD_VERSION) 897 { 898 return NDIS_STATUS_NOT_SUPPORTED; 899 } 900 901 Adapter->IpHeaderOffset = TaskOffloadHeader->EncapsulationFormat.EncapsulationHeaderSize; 902 903 TaskOffload = (PNDIS_TASK_OFFLOAD)TaskOffloadHeader; 904 Offset = TaskOffloadHeader->OffsetFirstTask; 905 906 while (Offset) 907 { 908 *BytesRead += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer); 909 910 TaskOffload = (PNDIS_TASK_OFFLOAD)((PUCHAR)TaskOffload + Offset); 911 switch (TaskOffload->Task) 912 { 913 case TcpIpChecksumNdisTask: 914 { 915 PNDIS_TASK_TCP_IP_CHECKSUM Task; 916 917 *BytesRead += sizeof(NDIS_TASK_TCP_IP_CHECKSUM); 918 919 if (!(Adapter->Flags & NV_SEND_CHECKSUM)) 920 { 921 return NDIS_STATUS_NOT_SUPPORTED; 922 } 923 924 Task = (PNDIS_TASK_TCP_IP_CHECKSUM)TaskOffload->TaskBuffer; 925 926 Adapter->Offload.SendTcpChecksum = Task->V4Transmit.TcpChecksum; 927 Adapter->Offload.SendUdpChecksum = Task->V4Transmit.UdpChecksum; 928 Adapter->Offload.SendIpChecksum = Task->V4Transmit.IpChecksum; 929 930 Adapter->Offload.ReceiveTcpChecksum = Task->V4Receive.TcpChecksum; 931 Adapter->Offload.ReceiveUdpChecksum = Task->V4Receive.UdpChecksum; 932 Adapter->Offload.ReceiveIpChecksum = Task->V4Receive.IpChecksum; 933 break; 934 } 935 936 case TcpLargeSendNdisTask: 937 { 938 PNDIS_TASK_TCP_LARGE_SEND Task; 939 940 if (!(Adapter->Flags & NV_SEND_LARGE_SEND)) 941 { 942 return NDIS_STATUS_NOT_SUPPORTED; 943 } 944 945 if ((TaskOffloadHeader-> 946 EncapsulationFormat.Encapsulation != IEEE_802_3_Encapsulation) && 947 (TaskOffloadHeader-> 948 EncapsulationFormat.Encapsulation != UNSPECIFIED_Encapsulation || 949 TaskOffloadHeader-> 950 EncapsulationFormat.EncapsulationHeaderSize != sizeof(ETH_HEADER))) 951 { 952 return NDIS_STATUS_NOT_SUPPORTED; 953 } 954 955 *BytesRead += sizeof(NDIS_TASK_TCP_LARGE_SEND); 956 957 Task = (PNDIS_TASK_TCP_LARGE_SEND)TaskOffload->TaskBuffer; 958 959 if (Task->MinSegmentCount != NVNET_MINIMUM_LSO_SEGMENT_COUNT) 960 return NDIS_STATUS_NOT_SUPPORTED; 961 962 if (Task->MaxOffLoadSize > NVNET_MAXIMUM_LSO_FRAME_SIZE) 963 return NDIS_STATUS_NOT_SUPPORTED; 964 965 /* Nothing to do */ 966 break; 967 } 968 969 default: 970 break; 971 } 972 973 Offset = TaskOffload->OffsetNextTask; 974 } 975 976 NdisAcquireSpinLock(&Adapter->Send.Lock); 977 978 if (Adapter->Offload.ReceiveTcpChecksum || 979 Adapter->Offload.ReceiveUdpChecksum || 980 Adapter->Offload.ReceiveIpChecksum) 981 { 982 Adapter->TxRxControl |= NVREG_TXRXCTL_RXCHECK; 983 } 984 else 985 { 986 Adapter->TxRxControl &= ~NVREG_TXRXCTL_RXCHECK; 987 } 988 NV_WRITE(Adapter, NvRegTxRxControl, Adapter->TxRxControl); 989 990 NdisReleaseSpinLock(&Adapter->Send.Lock); 991 992 return NDIS_STATUS_SUCCESS; 993 } 994 995 NDIS_STATUS 996 NTAPI 997 MiniportQueryInformation( 998 _In_ NDIS_HANDLE MiniportAdapterContext, 999 _In_ NDIS_OID Oid, 1000 _In_ PVOID InformationBuffer, 1001 _In_ ULONG InformationBufferLength, 1002 _Out_ PULONG BytesWritten, 1003 _Out_ PULONG BytesNeeded) 1004 { 1005 PNVNET_ADAPTER Adapter = (PNVNET_ADAPTER)MiniportAdapterContext; 1006 NDIS_STATUS Status = NDIS_STATUS_SUCCESS; 1007 ULONG InfoLength; 1008 PVOID InfoPtr; 1009 union _GENERIC_INFORMATION 1010 { 1011 USHORT Ushort; 1012 ULONG Ulong; 1013 ULONG64 Ulong64; 1014 NDIS_MEDIUM Medium; 1015 NDIS_HARDWARE_STATUS Status; 1016 NDIS_DEVICE_POWER_STATE PowerState; 1017 } GenericInfo; 1018 1019 InfoLength = sizeof(ULONG); 1020 InfoPtr = &GenericInfo; 1021 1022 switch (Oid) 1023 { 1024 case OID_GEN_SUPPORTED_LIST: 1025 InfoPtr = (PVOID)&NvpSupportedOidList; 1026 InfoLength = sizeof(NvpSupportedOidList); 1027 break; 1028 1029 case OID_GEN_HARDWARE_STATUS: 1030 InfoLength = sizeof(NDIS_HARDWARE_STATUS); 1031 GenericInfo.Status = NdisHardwareStatusReady; 1032 break; 1033 1034 case OID_GEN_MEDIA_SUPPORTED: 1035 case OID_GEN_MEDIA_IN_USE: 1036 { 1037 InfoLength = sizeof(NDIS_MEDIUM); 1038 GenericInfo.Medium = NdisMedium802_3; 1039 break; 1040 } 1041 1042 case OID_GEN_CURRENT_LOOKAHEAD: 1043 case OID_GEN_MAXIMUM_LOOKAHEAD: 1044 { 1045 GenericInfo.Ulong = Adapter->MaximumFrameSize - sizeof(ETH_HEADER); 1046 break; 1047 } 1048 1049 case OID_GEN_MAXIMUM_FRAME_SIZE: 1050 { 1051 GenericInfo.Ulong = Adapter->MaximumFrameSize; 1052 break; 1053 } 1054 1055 case OID_GEN_LINK_SPEED: 1056 { 1057 GenericInfo.Ulong = NvNetGetLinkSpeed(Adapter) * 10000; 1058 break; 1059 } 1060 1061 case OID_GEN_TRANSMIT_BUFFER_SPACE: 1062 { 1063 /* TODO: Change this later, once the driver can handle multipacket sends */ 1064 GenericInfo.Ulong = Adapter->MaximumFrameSize; 1065 break; 1066 } 1067 1068 case OID_GEN_RECEIVE_BUFFER_SPACE: 1069 { 1070 GenericInfo.Ulong = Adapter->MaximumFrameSize * NVNET_RECEIVE_DESCRIPTORS; 1071 } 1072 1073 case OID_GEN_MAXIMUM_TOTAL_SIZE: 1074 case OID_GEN_TRANSMIT_BLOCK_SIZE: 1075 case OID_GEN_RECEIVE_BLOCK_SIZE: 1076 { 1077 GenericInfo.Ulong = Adapter->MaximumFrameSize; 1078 break; 1079 } 1080 1081 case OID_GEN_VENDOR_ID: 1082 { 1083 GenericInfo.Ulong = 0; 1084 GenericInfo.Ulong |= (Adapter->PermanentMacAddress[0] << 16); 1085 GenericInfo.Ulong |= (Adapter->PermanentMacAddress[1] << 8); 1086 GenericInfo.Ulong |= (Adapter->PermanentMacAddress[2] & 0xFF); 1087 break; 1088 } 1089 1090 case OID_GEN_DRIVER_VERSION: 1091 { 1092 InfoLength = sizeof(USHORT); 1093 GenericInfo.Ushort = (NDIS_MINIPORT_MAJOR_VERSION << 8) | NDIS_MINIPORT_MINOR_VERSION; 1094 break; 1095 } 1096 1097 case OID_GEN_VENDOR_DESCRIPTION: 1098 { 1099 static const CHAR VendorDesc[] = "nVidia nForce Ethernet Controller"; 1100 InfoPtr = (PVOID)&VendorDesc; 1101 InfoLength = sizeof(VendorDesc); 1102 break; 1103 } 1104 1105 case OID_GEN_CURRENT_PACKET_FILTER: 1106 { 1107 GenericInfo.Ulong = Adapter->PacketFilter; 1108 break; 1109 } 1110 1111 case OID_GEN_MAC_OPTIONS: 1112 { 1113 GenericInfo.Ulong = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | 1114 NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | 1115 NDIS_MAC_OPTION_NO_LOOPBACK; 1116 1117 if (Adapter->Flags & NV_PACKET_PRIORITY) 1118 GenericInfo.Ulong |= NDIS_MAC_OPTION_8021P_PRIORITY; 1119 if (Adapter->Flags & NV_VLAN_TAGGING) 1120 GenericInfo.Ulong |= NDIS_MAC_OPTION_8021Q_VLAN; 1121 break; 1122 } 1123 1124 case OID_GEN_MEDIA_CONNECT_STATUS: 1125 { 1126 GenericInfo.Ulong = Adapter->Connected ? NdisMediaStateConnected 1127 : NdisMediaStateDisconnected; 1128 break; 1129 } 1130 1131 case OID_GEN_MAXIMUM_SEND_PACKETS: 1132 { 1133 /* TODO: Multipacket sends */ 1134 GenericInfo.Ulong = 1; 1135 break; 1136 } 1137 1138 case OID_GEN_VENDOR_DRIVER_VERSION: 1139 { 1140 /* 1.0.0 */ 1141 GenericInfo.Ulong = 0x100; 1142 break; 1143 } 1144 1145 case OID_GEN_XMIT_OK: 1146 case OID_GEN_RCV_OK: 1147 case OID_GEN_XMIT_ERROR: 1148 case OID_GEN_RCV_ERROR: 1149 case OID_GEN_RCV_NO_BUFFER: 1150 case OID_GEN_DIRECTED_FRAMES_RCV: 1151 case OID_GEN_RCV_CRC_ERROR: 1152 case OID_802_3_RCV_ERROR_ALIGNMENT: 1153 case OID_802_3_XMIT_ONE_COLLISION: 1154 case OID_802_3_XMIT_MORE_COLLISIONS: 1155 case OID_802_3_XMIT_DEFERRED: 1156 case OID_802_3_XMIT_MAX_COLLISIONS: 1157 case OID_802_3_RCV_OVERRUN: 1158 case OID_802_3_XMIT_UNDERRUN: 1159 case OID_802_3_XMIT_HEARTBEAT_FAILURE: 1160 case OID_802_3_XMIT_TIMES_CRS_LOST: 1161 case OID_802_3_XMIT_LATE_COLLISIONS: 1162 { 1163 if (Adapter->Features & DEV_HAS_STATISTICS_COUNTERS) 1164 { 1165 NvNetReadStatistics(Adapter); 1166 NvNetQueryHwCounter(Adapter, Oid, &GenericInfo.Ulong64); 1167 } 1168 else 1169 { 1170 NvNetQuerySoftwareCounter(Adapter, Oid, &GenericInfo.Ulong64); 1171 } 1172 1173 *BytesNeeded = sizeof(ULONG64); 1174 if (InformationBufferLength < sizeof(ULONG)) 1175 { 1176 *BytesWritten = 0; 1177 return NDIS_STATUS_BUFFER_TOO_SHORT; 1178 } 1179 if (InformationBufferLength >= sizeof(ULONG64)) 1180 { 1181 *BytesWritten = sizeof(ULONG64); 1182 NdisMoveMemory(InformationBuffer, InfoPtr, sizeof(ULONG64)); 1183 } 1184 else 1185 { 1186 *BytesWritten = sizeof(ULONG); 1187 NdisMoveMemory(InformationBuffer, InfoPtr, sizeof(ULONG)); 1188 } 1189 1190 return NDIS_STATUS_SUCCESS; 1191 } 1192 1193 case OID_GEN_TRANSMIT_QUEUE_LENGTH: 1194 { 1195 GenericInfo.Ulong = NVNET_TRANSMIT_BLOCKS - Adapter->Send.TcbSlots; 1196 break; 1197 } 1198 1199 case OID_802_3_PERMANENT_ADDRESS: 1200 { 1201 InfoPtr = Adapter->PermanentMacAddress; 1202 InfoLength = ETH_LENGTH_OF_ADDRESS; 1203 break; 1204 } 1205 1206 case OID_802_3_CURRENT_ADDRESS: 1207 { 1208 InfoPtr = Adapter->CurrentMacAddress; 1209 InfoLength = ETH_LENGTH_OF_ADDRESS; 1210 break; 1211 } 1212 1213 case OID_802_3_MULTICAST_LIST: 1214 { 1215 InfoPtr = Adapter->MulticastList; 1216 InfoLength = Adapter->MulticastListSize * ETH_LENGTH_OF_ADDRESS; 1217 break; 1218 } 1219 1220 case OID_802_3_MAXIMUM_LIST_SIZE: 1221 { 1222 GenericInfo.Ulong = NVNET_MULTICAST_LIST_SIZE; 1223 break; 1224 } 1225 1226 case OID_TCP_TASK_OFFLOAD: 1227 { 1228 return NvNetGetTcpTaskOffload(Adapter, 1229 InformationBuffer, 1230 InformationBufferLength, 1231 BytesWritten, 1232 BytesWritten); 1233 } 1234 1235 case OID_PNP_ENABLE_WAKE_UP: 1236 { 1237 GenericInfo.Ulong = NvNetGetWakeUp(Adapter); 1238 break; 1239 } 1240 1241 case OID_PNP_CAPABILITIES: 1242 { 1243 InfoLength = sizeof(NDIS_PNP_CAPABILITIES); 1244 1245 if (InformationBufferLength < InfoLength) 1246 { 1247 *BytesWritten = 0; 1248 *BytesNeeded = InfoLength; 1249 return NDIS_STATUS_BUFFER_TOO_SHORT; 1250 } 1251 1252 *BytesWritten = InfoLength; 1253 *BytesNeeded = 0; 1254 return NvNetFillPowerManagementCapabilities(Adapter, InformationBuffer); 1255 } 1256 1257 case OID_PNP_QUERY_POWER: 1258 { 1259 return NDIS_STATUS_SUCCESS; 1260 } 1261 1262 case OID_GEN_VLAN_ID: 1263 { 1264 /* TODO: Implement software VLAN support */ 1265 if (!(Adapter->Flags & NV_VLAN_TAGGING)) 1266 { 1267 Status = NDIS_STATUS_NOT_SUPPORTED; 1268 break; 1269 } 1270 1271 GenericInfo.Ulong = Adapter->VlanId; 1272 break; 1273 } 1274 1275 default: 1276 Status = NDIS_STATUS_INVALID_OID; 1277 break; 1278 } 1279 1280 if (Status == NDIS_STATUS_SUCCESS) 1281 { 1282 if (InfoLength > InformationBufferLength) 1283 { 1284 *BytesWritten = 0; 1285 *BytesNeeded = InfoLength; 1286 Status = NDIS_STATUS_BUFFER_TOO_SHORT; 1287 } 1288 else 1289 { 1290 NdisMoveMemory(InformationBuffer, InfoPtr, InfoLength); 1291 *BytesWritten = InfoLength; 1292 *BytesNeeded = 0; 1293 } 1294 } 1295 else 1296 { 1297 *BytesWritten = 0; 1298 *BytesNeeded = 0; 1299 } 1300 1301 return Status; 1302 } 1303 1304 NDIS_STATUS 1305 NTAPI 1306 MiniportSetInformation( 1307 _In_ NDIS_HANDLE MiniportAdapterContext, 1308 _In_ NDIS_OID Oid, 1309 _In_ PVOID InformationBuffer, 1310 _In_ ULONG InformationBufferLength, 1311 _Out_ PULONG BytesRead, 1312 _Out_ PULONG BytesNeeded) 1313 { 1314 PNVNET_ADAPTER Adapter = (PNVNET_ADAPTER)MiniportAdapterContext; 1315 NDIS_STATUS Status = NDIS_STATUS_SUCCESS; 1316 ULONG GenericUlong; 1317 1318 *BytesRead = 0; 1319 *BytesNeeded = 0; 1320 1321 switch (Oid) 1322 { 1323 case OID_802_3_MULTICAST_LIST: 1324 { 1325 if (InformationBufferLength % ETH_LENGTH_OF_ADDRESS) 1326 { 1327 *BytesNeeded = (InformationBufferLength / ETH_LENGTH_OF_ADDRESS) * 1328 ETH_LENGTH_OF_ADDRESS; 1329 Status = NDIS_STATUS_INVALID_LENGTH; 1330 break; 1331 } 1332 1333 if (InformationBufferLength > sizeof(Adapter->MulticastList)) 1334 { 1335 *BytesNeeded = sizeof(Adapter->MulticastList); 1336 Status = NDIS_STATUS_MULTICAST_FULL; 1337 break; 1338 } 1339 1340 *BytesRead = InformationBufferLength; 1341 NdisMoveMemory(Adapter->MulticastList, InformationBuffer, InformationBufferLength); 1342 1343 Adapter->MulticastListSize = InformationBufferLength / ETH_LENGTH_OF_ADDRESS; 1344 1345 NvNetApplyPacketFilter(Adapter); 1346 break; 1347 } 1348 1349 case OID_GEN_CURRENT_PACKET_FILTER: 1350 { 1351 if (InformationBufferLength < sizeof(ULONG)) 1352 { 1353 *BytesNeeded = sizeof(ULONG); 1354 Status = NDIS_STATUS_INVALID_LENGTH; 1355 break; 1356 } 1357 1358 *BytesRead = sizeof(ULONG); 1359 NdisMoveMemory(&GenericUlong, InformationBuffer, sizeof(ULONG)); 1360 1361 if (GenericUlong & ~NVNET_PACKET_FILTERS) 1362 { 1363 Status = NDIS_STATUS_NOT_SUPPORTED; 1364 break; 1365 } 1366 1367 /* Do not check to see if the filter is the same filter */ 1368 Adapter->PacketFilter = GenericUlong; 1369 1370 NvNetApplyPacketFilter(Adapter); 1371 break; 1372 } 1373 1374 case OID_GEN_CURRENT_LOOKAHEAD: 1375 { 1376 if (InformationBufferLength < sizeof(ULONG)) 1377 { 1378 *BytesNeeded = sizeof(ULONG); 1379 Status = NDIS_STATUS_INVALID_LENGTH; 1380 break; 1381 } 1382 1383 /* Nothing to do */ 1384 *BytesRead = sizeof(ULONG); 1385 break; 1386 } 1387 1388 case OID_GEN_VLAN_ID: 1389 { 1390 if (InformationBufferLength < sizeof(ULONG)) 1391 { 1392 *BytesNeeded = sizeof(ULONG); 1393 Status = NDIS_STATUS_INVALID_LENGTH; 1394 break; 1395 } 1396 1397 if (!(Adapter->Flags & NV_VLAN_TAGGING)) 1398 { 1399 Status = NDIS_STATUS_NOT_SUPPORTED; 1400 break; 1401 } 1402 1403 *BytesRead = sizeof(ULONG); 1404 NdisMoveMemory(&GenericUlong, InformationBuffer, sizeof(ULONG)); 1405 1406 if (GenericUlong > NVNET_MAXIMUM_VLAN_ID) 1407 { 1408 Status = NDIS_STATUS_FAILURE; 1409 break; 1410 } 1411 1412 Adapter->VlanId = GenericUlong; 1413 break; 1414 } 1415 1416 case OID_TCP_TASK_OFFLOAD: 1417 { 1418 if (InformationBufferLength < sizeof(NDIS_TASK_OFFLOAD_HEADER)) 1419 { 1420 *BytesNeeded = sizeof(NDIS_TASK_OFFLOAD_HEADER); 1421 Status = NDIS_STATUS_INVALID_LENGTH; 1422 break; 1423 } 1424 1425 *BytesRead = InformationBufferLength; 1426 1427 Status = NvNetSetTcpTaskOffload(Adapter, InformationBuffer, BytesRead); 1428 break; 1429 } 1430 1431 case OID_PNP_ADD_WAKE_UP_PATTERN: 1432 { 1433 if (InformationBufferLength < sizeof(NDIS_PM_PACKET_PATTERN)) 1434 { 1435 *BytesNeeded = sizeof(NDIS_PM_PACKET_PATTERN); 1436 Status = NDIS_STATUS_INVALID_LENGTH; 1437 break; 1438 } 1439 1440 *BytesRead = sizeof(NDIS_PM_PACKET_PATTERN); 1441 1442 Status = NvNetAddWakeUpPattern(Adapter, InformationBuffer); 1443 break; 1444 } 1445 1446 case OID_PNP_REMOVE_WAKE_UP_PATTERN: 1447 { 1448 if (InformationBufferLength < sizeof(NDIS_PM_PACKET_PATTERN)) 1449 { 1450 *BytesNeeded = sizeof(NDIS_PM_PACKET_PATTERN); 1451 Status = NDIS_STATUS_INVALID_LENGTH; 1452 break; 1453 } 1454 1455 *BytesRead = sizeof(NDIS_PM_PACKET_PATTERN); 1456 1457 Status = NvNetRemoveWakeUpPattern(Adapter, InformationBuffer); 1458 break; 1459 } 1460 1461 case OID_PNP_ENABLE_WAKE_UP: 1462 { 1463 if (InformationBufferLength < sizeof(ULONG)) 1464 { 1465 *BytesNeeded = sizeof(ULONG); 1466 Status = NDIS_STATUS_INVALID_LENGTH; 1467 break; 1468 } 1469 1470 *BytesRead = sizeof(ULONG); 1471 NdisMoveMemory(&GenericUlong, InformationBuffer, sizeof(ULONG)); 1472 1473 NvNetEnableWakeUp(Adapter, GenericUlong); 1474 break; 1475 } 1476 1477 case OID_PNP_SET_POWER: 1478 { 1479 if (InformationBufferLength < sizeof(NDIS_DEVICE_POWER_STATE)) 1480 { 1481 *BytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE); 1482 Status = NDIS_STATUS_INVALID_LENGTH; 1483 break; 1484 } 1485 1486 *BytesRead = sizeof(ULONG); 1487 NdisMoveMemory(&GenericUlong, InformationBuffer, sizeof(ULONG)); 1488 1489 if (GenericUlong < NdisDeviceStateD0 || GenericUlong > NdisDeviceStateD3) 1490 { 1491 Status = NDIS_STATUS_INVALID_DATA; 1492 break; 1493 } 1494 1495 Status = NvNetSetPower(Adapter, GenericUlong); 1496 break; 1497 } 1498 1499 default: 1500 Status = NDIS_STATUS_NOT_SUPPORTED; 1501 break; 1502 } 1503 1504 return Status; 1505 } 1506