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 initialization helper routines 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 /* FUNCTIONS ******************************************************************/ 16 17 static 18 CODE_SEG("PAGE") 19 VOID 20 QueryInteger( 21 _In_ NDIS_HANDLE ConfigurationHandle, 22 _In_ PCWSTR EntryName, 23 _Out_ PULONG EntryContext, 24 _In_ ULONG DefaultValue, 25 _In_ ULONG Minimum, 26 _In_ ULONG Maximum) 27 { 28 NDIS_STATUS Status; 29 UNICODE_STRING Keyword; 30 PNDIS_CONFIGURATION_PARAMETER ConfigurationParameter; 31 32 PAGED_CODE(); 33 34 NdisInitUnicodeString(&Keyword, EntryName); 35 NdisReadConfiguration(&Status, 36 &ConfigurationParameter, 37 ConfigurationHandle, 38 &Keyword, 39 NdisParameterInteger); 40 if (Status != NDIS_STATUS_SUCCESS) 41 { 42 NDIS_DbgPrint(MIN_TRACE, ("'%S' request failed\n", EntryName)); 43 44 *EntryContext = DefaultValue; 45 } 46 else 47 { 48 if (ConfigurationParameter->ParameterData.IntegerData >= Minimum && 49 ConfigurationParameter->ParameterData.IntegerData <= Maximum) 50 { 51 *EntryContext = ConfigurationParameter->ParameterData.IntegerData; 52 } 53 else 54 { 55 NDIS_DbgPrint(MAX_TRACE, ("'%S' value out of range\n", EntryName)); 56 57 *EntryContext = DefaultValue; 58 } 59 } 60 61 NDIS_DbgPrint(MIN_TRACE, ("Set '%S' to %d\n", EntryName, *EntryContext)); 62 } 63 64 static 65 CODE_SEG("PAGE") 66 NDIS_STATUS 67 NvNetReadConfiguration( 68 _Inout_ PNVNET_ADAPTER Adapter) 69 { 70 NDIS_STATUS Status; 71 NDIS_HANDLE ConfigurationHandle; 72 PUCHAR NetworkAddress; 73 UINT Length; 74 ULONG GenericUlong; 75 76 PAGED_CODE(); 77 78 NDIS_DbgPrint(MIN_TRACE, ("()\n")); 79 80 NdisOpenConfiguration(&Status, 81 &ConfigurationHandle, 82 Adapter->WrapperConfigurationHandle); 83 if (Status != NDIS_STATUS_SUCCESS) 84 return Status; 85 86 QueryInteger(ConfigurationHandle, 87 L"OptimizationMode", 88 &GenericUlong, 89 NV_OPTIMIZATION_MODE_DYNAMIC, 90 NV_OPTIMIZATION_MODE_THROUGHPUT, 91 NV_OPTIMIZATION_MODE_DYNAMIC); 92 Adapter->OptimizationMode = GenericUlong; 93 94 QueryInteger(ConfigurationHandle, 95 L"FlowControl", 96 &GenericUlong, 97 NV_FLOW_CONTROL_AUTO, 98 NV_FLOW_CONTROL_DISABLE, 99 NV_FLOW_CONTROL_RX_TX); 100 Adapter->FlowControlMode = GenericUlong; 101 102 QueryInteger(ConfigurationHandle, 103 L"SpeedDuplex", 104 &GenericUlong, 105 0, 106 0, 107 4); 108 switch (GenericUlong) 109 { 110 case 1: 111 Adapter->Flags |= NV_FORCE_SPEED_AND_DUPLEX; 112 break; 113 case 2: 114 Adapter->Flags |= (NV_FORCE_SPEED_AND_DUPLEX | NV_FORCE_FULL_DUPLEX); 115 break; 116 case 3: 117 Adapter->Flags |= (NV_FORCE_SPEED_AND_DUPLEX | NV_USER_SPEED_100); 118 break; 119 case 4: 120 Adapter->Flags |= (NV_FORCE_SPEED_AND_DUPLEX | NV_FORCE_FULL_DUPLEX | 121 NV_USER_SPEED_100); 122 break; 123 124 default: 125 break; 126 } 127 128 QueryInteger(ConfigurationHandle, 129 L"ChecksumOffload", 130 &GenericUlong, 131 0, 132 0, 133 1); 134 if (GenericUlong) 135 Adapter->Flags |= NV_SEND_CHECKSUM; 136 137 QueryInteger(ConfigurationHandle, 138 L"LargeSendOffload", 139 &GenericUlong, 140 0, 141 0, 142 1); 143 if (GenericUlong) 144 Adapter->Flags |= NV_SEND_LARGE_SEND; 145 146 QueryInteger(ConfigurationHandle, 147 L"JumboSize", 148 &GenericUlong, 149 NVNET_MAXIMUM_FRAME_SIZE, 150 NVNET_MAXIMUM_FRAME_SIZE, 151 NVNET_MAXIMUM_FRAME_SIZE_JUMBO); 152 Adapter->MaximumFrameSize = GenericUlong; 153 154 QueryInteger(ConfigurationHandle, 155 L"Priority", 156 &GenericUlong, 157 0, 158 0, 159 1); 160 if (GenericUlong) 161 Adapter->Flags |= NV_PACKET_PRIORITY; 162 163 QueryInteger(ConfigurationHandle, 164 L"VlanTag", 165 &GenericUlong, 166 0, 167 0, 168 1); 169 if (GenericUlong) 170 Adapter->Flags |= NV_VLAN_TAGGING; 171 172 QueryInteger(ConfigurationHandle, 173 L"VlanID", 174 &GenericUlong, 175 0, 176 0, 177 NVNET_MAXIMUM_VLAN_ID); 178 179 NdisReadNetworkAddress(&Status, 180 (PVOID*)&NetworkAddress, 181 &Length, 182 ConfigurationHandle); 183 if ((Status == NDIS_STATUS_SUCCESS) && (Length == ETH_LENGTH_OF_ADDRESS)) 184 { 185 if ((ETH_IS_MULTICAST(NetworkAddress) || ETH_IS_BROADCAST(NetworkAddress)) || 186 !ETH_IS_LOCALLY_ADMINISTERED(NetworkAddress)) 187 { 188 NDIS_DbgPrint(MAX_TRACE, ("Invalid software MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", 189 NetworkAddress[0], 190 NetworkAddress[1], 191 NetworkAddress[2], 192 NetworkAddress[3], 193 NetworkAddress[4], 194 NetworkAddress[5])); 195 } 196 else 197 { 198 NDIS_DbgPrint(MIN_TRACE, ("Using software MAC\n")); 199 200 ETH_COPY_NETWORK_ADDRESS(Adapter->CurrentMacAddress, NetworkAddress); 201 202 Adapter->Flags |= NV_USE_SOFT_MAC_ADDRESS; 203 } 204 } 205 Status = NDIS_STATUS_SUCCESS; 206 207 NdisCloseConfiguration(ConfigurationHandle); 208 209 return Status; 210 } 211 212 static 213 CODE_SEG("PAGE") 214 NDIS_STATUS 215 NvNetInitializeAdapterResources( 216 _Inout_ PNVNET_ADAPTER Adapter) 217 { 218 NDIS_STATUS Status; 219 PNDIS_RESOURCE_LIST AssignedResources = NULL; 220 UINT i, ResourceListSize = 0; 221 222 PAGED_CODE(); 223 224 NDIS_DbgPrint(MIN_TRACE, ("()\n")); 225 226 NdisMQueryAdapterResources(&Status, 227 Adapter->WrapperConfigurationHandle, 228 AssignedResources, 229 &ResourceListSize); 230 if (Status != NDIS_STATUS_RESOURCES) 231 { 232 NvNetLogError(Adapter, NDIS_ERROR_CODE_RESOURCE_CONFLICT); 233 return NDIS_STATUS_FAILURE; 234 } 235 236 Status = NdisAllocateMemoryWithTag((PVOID*)&AssignedResources, 237 ResourceListSize, 238 NVNET_TAG); 239 if (Status != NDIS_STATUS_SUCCESS) 240 { 241 NvNetLogError(Adapter, NDIS_ERROR_CODE_OUT_OF_RESOURCES); 242 return Status; 243 } 244 245 NdisMQueryAdapterResources(&Status, 246 Adapter->WrapperConfigurationHandle, 247 AssignedResources, 248 &ResourceListSize); 249 if (Status != NDIS_STATUS_SUCCESS) 250 { 251 NvNetLogError(Adapter, NDIS_ERROR_CODE_RESOURCE_CONFLICT); 252 goto Cleanup; 253 } 254 255 for (i = 0; i < AssignedResources->Count; ++i) 256 { 257 PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &AssignedResources->PartialDescriptors[i]; 258 259 switch (Descriptor->Type) 260 { 261 case CmResourceTypeMemory: 262 { 263 Adapter->IoAddress = Descriptor->u.Memory.Start; 264 Adapter->IoLength = Descriptor->u.Memory.Length; 265 break; 266 } 267 268 case CmResourceTypeInterrupt: 269 { 270 Adapter->InterruptVector = Descriptor->u.Interrupt.Vector; 271 Adapter->InterruptLevel = Descriptor->u.Interrupt.Level; 272 Adapter->InterruptShared = (Descriptor->ShareDisposition == CmResourceShareShared); 273 Adapter->InterruptFlags = Descriptor->Flags; 274 break; 275 } 276 277 default: 278 break; 279 } 280 } 281 282 if (!Adapter->IoAddress.QuadPart || !Adapter->InterruptVector) 283 { 284 Status = NDIS_STATUS_RESOURCES; 285 NvNetLogError(Adapter, NDIS_ERROR_CODE_RESOURCE_CONFLICT); 286 goto Cleanup; 287 } 288 289 NDIS_DbgPrint(MIN_TRACE, ("MEM at [%I64X-%I64X]\n", 290 Adapter->IoAddress.QuadPart, 291 Adapter->IoAddress.QuadPart + Adapter->IoLength)); 292 NDIS_DbgPrint(MIN_TRACE, ("IRQ Vector %d Level %d\n", 293 Adapter->InterruptVector, 294 Adapter->InterruptLevel)); 295 296 Status = NdisMMapIoSpace((PVOID*)&Adapter->IoBase, 297 Adapter->AdapterHandle, 298 Adapter->IoAddress, 299 Adapter->IoLength); 300 if (Status != NDIS_STATUS_SUCCESS) 301 { 302 NvNetLogError(Adapter, NDIS_ERROR_CODE_RESOURCE_CONFLICT); 303 goto Cleanup; 304 } 305 306 Cleanup: 307 NdisFreeMemory(AssignedResources, ResourceListSize, 0); 308 309 return Status; 310 } 311 312 static 313 CODE_SEG("PAGE") 314 NDIS_STATUS 315 AllocateTransmitBuffers( 316 _In_ PNVNET_ADAPTER Adapter) 317 { 318 ULONG i; 319 BOOLEAN HasBuffer = FALSE; 320 PNVNET_TX_BUFFER CoalesceBuffer; 321 NDIS_STATUS Status; 322 323 PAGED_CODE(); 324 325 Status = NdisAllocateMemoryWithTag((PVOID*)&CoalesceBuffer, 326 NVNET_TRANSMIT_BUFFERS * sizeof(NVNET_TX_BUFFER), 327 NVNET_TAG); 328 if (Status != NDIS_STATUS_SUCCESS) 329 return Status; 330 331 NdisZeroMemory(CoalesceBuffer, NVNET_TRANSMIT_BUFFERS * sizeof(NVNET_TX_BUFFER)); 332 333 Adapter->SendBuffer = CoalesceBuffer; 334 335 for (i = 0; i < NVNET_TRANSMIT_BUFFERS; ++i) 336 { 337 PVOID VirtualAddress; 338 NDIS_PHYSICAL_ADDRESS PhysicalAddress; 339 340 NdisMAllocateSharedMemory(Adapter->AdapterHandle, 341 Adapter->MaximumFrameSize + NVNET_ALIGNMENT, 342 TRUE, /* Cached */ 343 &VirtualAddress, 344 &PhysicalAddress); 345 if (!VirtualAddress) 346 continue; 347 348 CoalesceBuffer->VirtualAddress = ALIGN_UP_POINTER_BY(VirtualAddress, NVNET_ALIGNMENT); 349 CoalesceBuffer->PhysicalAddress.QuadPart = 350 ALIGN_UP_BY(PhysicalAddress.QuadPart, NVNET_ALIGNMENT); 351 352 Adapter->SendBufferAllocationData[i].PhysicalAddress.QuadPart = PhysicalAddress.QuadPart; 353 Adapter->SendBufferAllocationData[i].VirtualAddress = VirtualAddress; 354 355 PushEntryList(&Adapter->Send.BufferList, &CoalesceBuffer->Link); 356 ++CoalesceBuffer; 357 358 HasBuffer = TRUE; 359 } 360 if (!HasBuffer) 361 { 362 return NDIS_STATUS_RESOURCES; 363 } 364 365 return NDIS_STATUS_SUCCESS; 366 } 367 368 static 369 CODE_SEG("PAGE") 370 NDIS_STATUS 371 AllocateTransmitBlocks( 372 _In_ PNVNET_ADAPTER Adapter) 373 { 374 PNVNET_TCB Tcb; 375 NDIS_STATUS Status; 376 377 PAGED_CODE(); 378 379 Status = NdisAllocateMemoryWithTag((PVOID*)&Tcb, 380 NVNET_TRANSMIT_BLOCKS * sizeof(NVNET_TCB), 381 NVNET_TAG); 382 if (Status != NDIS_STATUS_SUCCESS) 383 return Status; 384 385 NdisZeroMemory(Tcb, NVNET_TRANSMIT_BLOCKS * sizeof(NVNET_TCB)); 386 387 Adapter->Send.TailTcb = Tcb + (NVNET_TRANSMIT_BLOCKS - 1); 388 Adapter->Send.HeadTcb = Tcb; 389 Adapter->Send.CurrentTcb = Tcb; 390 Adapter->Send.LastTcb = Tcb; 391 392 return NDIS_STATUS_SUCCESS; 393 } 394 395 static 396 CODE_SEG("PAGE") 397 NDIS_STATUS 398 AllocateTransmitDescriptors( 399 _In_ PNVNET_ADAPTER Adapter) 400 { 401 NVNET_TBD Tbd; 402 ULONG Size; 403 404 PAGED_CODE(); 405 406 if (Adapter->Features & DEV_HAS_HIGH_DMA) 407 { 408 Size = sizeof(NVNET_DESCRIPTOR_64); 409 } 410 else 411 { 412 Size = sizeof(NVNET_DESCRIPTOR_32); 413 } 414 NdisMAllocateSharedMemory(Adapter->AdapterHandle, 415 Size * NVNET_TRANSMIT_DESCRIPTORS + NVNET_ALIGNMENT, 416 TRUE, /* Cached */ 417 &Adapter->TbdOriginal, 418 &Adapter->TbdPhysOriginal); 419 if (!Adapter->TbdOriginal) 420 return NDIS_STATUS_RESOURCES; 421 422 Tbd.Memory = ALIGN_UP_POINTER_BY(Adapter->TbdOriginal, NVNET_ALIGNMENT); 423 Adapter->TbdPhys.QuadPart = ALIGN_UP_BY(Adapter->TbdPhysOriginal.QuadPart, NVNET_ALIGNMENT); 424 425 Adapter->Send.HeadTbd = Tbd; 426 Adapter->Send.CurrentTbd = Tbd; 427 428 if (Adapter->Features & DEV_HAS_HIGH_DMA) 429 { 430 Adapter->Send.TailTbd.x64 = Tbd.x64 + (NVNET_TRANSMIT_DESCRIPTORS - 1); 431 } 432 else 433 { 434 Adapter->Send.TailTbd.x32 = Tbd.x32 + (NVNET_TRANSMIT_DESCRIPTORS - 1); 435 } 436 437 return NDIS_STATUS_SUCCESS; 438 } 439 440 static 441 CODE_SEG("PAGE") 442 NDIS_STATUS 443 AllocateReceiveDescriptors( 444 _In_ PNVNET_ADAPTER Adapter) 445 { 446 ULONG Size; 447 448 PAGED_CODE(); 449 450 if (Adapter->Features & DEV_HAS_HIGH_DMA) 451 { 452 Size = sizeof(NVNET_DESCRIPTOR_64); 453 } 454 else 455 { 456 Size = sizeof(NVNET_DESCRIPTOR_32); 457 } 458 NdisMAllocateSharedMemory(Adapter->AdapterHandle, 459 Size * NVNET_RECEIVE_DESCRIPTORS + NVNET_ALIGNMENT, 460 TRUE, /* Cached */ 461 &Adapter->RbdOriginal, 462 &Adapter->RbdPhysOriginal); 463 if (!Adapter->RbdOriginal) 464 return NDIS_STATUS_RESOURCES; 465 466 Adapter->Receive.NvRbd.Memory = ALIGN_UP_POINTER_BY(Adapter->RbdOriginal, NVNET_ALIGNMENT); 467 Adapter->RbdPhys.QuadPart = ALIGN_UP_BY(Adapter->RbdPhysOriginal.QuadPart, NVNET_ALIGNMENT); 468 469 return NDIS_STATUS_SUCCESS; 470 } 471 472 static 473 CODE_SEG("PAGE") 474 NDIS_STATUS 475 AllocateReceiveBuffers( 476 _In_ PNVNET_ADAPTER Adapter) 477 { 478 PAGED_CODE(); 479 480 NdisMAllocateSharedMemory(Adapter->AdapterHandle, 481 NVNET_RECEIVE_BUFFER_SIZE * NVNET_RECEIVE_DESCRIPTORS, 482 TRUE, /* Cached */ 483 (PVOID*)&Adapter->ReceiveBuffer, 484 &Adapter->ReceiveBufferPhys); 485 if (!Adapter->ReceiveBuffer) 486 { 487 return NDIS_STATUS_RESOURCES; 488 } 489 490 return NDIS_STATUS_SUCCESS; 491 } 492 493 static 494 CODE_SEG("PAGE") 495 NDIS_STATUS 496 AllocateAdapterMemory( 497 _In_ PNVNET_ADAPTER Adapter) 498 { 499 NDIS_STATUS Status; 500 501 PAGED_CODE(); 502 503 Status = AllocateTransmitBuffers(Adapter); 504 if (Status != NDIS_STATUS_SUCCESS) 505 return Status; 506 507 Status = AllocateTransmitBlocks(Adapter); 508 if (Status != NDIS_STATUS_SUCCESS) 509 return Status; 510 511 Status = AllocateTransmitDescriptors(Adapter); 512 if (Status != NDIS_STATUS_SUCCESS) 513 return Status; 514 515 Status = AllocateReceiveDescriptors(Adapter); 516 if (Status != NDIS_STATUS_SUCCESS) 517 return Status; 518 519 Status = AllocateReceiveBuffers(Adapter); 520 if (Status != NDIS_STATUS_SUCCESS) 521 return Status; 522 523 NdisAllocateSpinLock(&Adapter->Send.Lock); 524 NdisAllocateSpinLock(&Adapter->Receive.Lock); 525 NdisAllocateSpinLock(&Adapter->Lock); 526 527 return NDIS_STATUS_SUCCESS; 528 } 529 530 CODE_SEG("PAGE") 531 VOID 532 NvNetInitTransmitMemory( 533 _In_ PNVNET_ADAPTER Adapter) 534 { 535 PAGED_CODE(); 536 537 Adapter->Send.TcbSlots = NVNET_TRANSMIT_BLOCKS; 538 Adapter->Send.TbdSlots = NVNET_TRANSMIT_DESCRIPTORS; 539 540 if (Adapter->Features & DEV_HAS_HIGH_DMA) 541 { 542 NdisZeroMemory(Adapter->Send.HeadTbd.x64, 543 sizeof(NVNET_DESCRIPTOR_64) * NVNET_TRANSMIT_DESCRIPTORS); 544 } 545 else 546 { 547 NdisZeroMemory(Adapter->Send.HeadTbd.x32, 548 sizeof(NVNET_DESCRIPTOR_32) * NVNET_TRANSMIT_DESCRIPTORS); 549 } 550 } 551 552 static 553 CODE_SEG("PAGE") 554 VOID 555 NvNetInitReceiveMemory( 556 _In_ PNVNET_ADAPTER Adapter) 557 { 558 NV_RBD NvRbd; 559 ULONG i; 560 561 PAGED_CODE(); 562 563 Adapter->CurrentRx = 0; 564 565 if (Adapter->Features & DEV_HAS_HIGH_DMA) 566 { 567 for (i = 0; i < NVNET_RECEIVE_DESCRIPTORS; ++i) 568 { 569 NvRbd.x64 = &Adapter->Receive.NvRbd.x64[i]; 570 571 NvRbd.x64->AddressHigh = NdisGetPhysicalAddressHigh(Adapter->ReceiveBufferPhys) 572 + i * NVNET_RECEIVE_BUFFER_SIZE; 573 NvRbd.x64->AddressLow = NdisGetPhysicalAddressLow(Adapter->ReceiveBufferPhys) 574 + i * NVNET_RECEIVE_BUFFER_SIZE; 575 NvRbd.x64->VlanTag = 0; 576 NvRbd.x64->FlagsLength = NV_RX2_AVAIL | NVNET_RECEIVE_BUFFER_SIZE; 577 } 578 } 579 else 580 { 581 for (i = 0; i < NVNET_RECEIVE_DESCRIPTORS; ++i) 582 { 583 NvRbd.x32 = &Adapter->Receive.NvRbd.x32[i]; 584 585 NvRbd.x32->Address = NdisGetPhysicalAddressLow(Adapter->ReceiveBufferPhys) 586 + i * NVNET_RECEIVE_BUFFER_SIZE; 587 NvRbd.x32->FlagsLength = NV_RX_AVAIL | NVNET_RECEIVE_BUFFER_SIZE; 588 } 589 } 590 } 591 592 593 CODE_SEG("PAGE") 594 VOID 595 NvNetFreeAdapter( 596 _In_ PNVNET_ADAPTER Adapter) 597 { 598 ULONG i; 599 ULONG DescriptorSize; 600 601 PAGED_CODE(); 602 603 NDIS_DbgPrint(MIN_TRACE, ("()\n")); 604 605 for (i = 0; i < RTL_NUMBER_OF(Adapter->WakeFrames); ++i) 606 { 607 PNVNET_WAKE_FRAME WakeFrame = Adapter->WakeFrames[i]; 608 609 if (!WakeFrame) 610 continue; 611 612 NdisFreeMemory(WakeFrame, sizeof(*WakeFrame), 0); 613 } 614 615 if (Adapter->Interrupt.InterruptObject) 616 { 617 NdisMDeregisterInterrupt(&Adapter->Interrupt); 618 Adapter->Interrupt.InterruptObject = NULL; 619 } 620 621 if (Adapter->Features & DEV_HAS_HIGH_DMA) 622 { 623 DescriptorSize = sizeof(NVNET_DESCRIPTOR_64); 624 } 625 else 626 { 627 DescriptorSize = sizeof(NVNET_DESCRIPTOR_32); 628 } 629 if (Adapter->TbdOriginal) 630 { 631 NdisMFreeSharedMemory(Adapter->AdapterHandle, 632 DescriptorSize * NVNET_TRANSMIT_DESCRIPTORS, 633 FALSE, 634 Adapter->TbdOriginal, 635 Adapter->TbdPhysOriginal); 636 Adapter->TbdOriginal = NULL; 637 } 638 if (Adapter->RbdOriginal) 639 { 640 NdisMFreeSharedMemory(Adapter->AdapterHandle, 641 DescriptorSize * NVNET_RECEIVE_DESCRIPTORS, 642 FALSE, 643 Adapter->RbdOriginal, 644 Adapter->RbdPhysOriginal); 645 Adapter->RbdOriginal = NULL; 646 } 647 if (Adapter->SendBuffer) 648 { 649 ULONG Length = ALIGN_UP_BY(Adapter->MaximumFrameSize, NVNET_ALIGNMENT); 650 651 for (i = 0; i < NVNET_TRANSMIT_BUFFERS; ++i) 652 { 653 PNVNET_TX_BUFFER_DATA SendBufferData = &Adapter->SendBufferAllocationData[i]; 654 655 if (!SendBufferData->VirtualAddress) 656 continue; 657 658 NdisMFreeSharedMemory(Adapter->AdapterHandle, 659 Length, 660 TRUE, 661 SendBufferData->VirtualAddress, 662 SendBufferData->PhysicalAddress); 663 } 664 665 NdisFreeMemory(Adapter->SendBuffer, NVNET_TRANSMIT_BUFFERS * sizeof(NVNET_TX_BUFFER), 0); 666 Adapter->SendBuffer = NULL; 667 } 668 669 if (Adapter->ReceiveBuffer) 670 { 671 NdisMFreeSharedMemory(Adapter->AdapterHandle, 672 NVNET_RECEIVE_BUFFER_SIZE * NVNET_RECEIVE_DESCRIPTORS, 673 FALSE, 674 Adapter->ReceiveBuffer, 675 Adapter->ReceiveBufferPhys); 676 Adapter->ReceiveBuffer = NULL; 677 } 678 679 if (Adapter->IoBase) 680 { 681 NdisMUnmapIoSpace(Adapter->AdapterHandle, 682 Adapter->IoBase, 683 Adapter->IoLength); 684 Adapter->IoBase = NULL; 685 } 686 687 if (Adapter->Lock.SpinLock) 688 NdisFreeSpinLock(&Adapter->Lock); 689 if (Adapter->Send.Lock.SpinLock) 690 NdisFreeSpinLock(&Adapter->Send.Lock); 691 if (Adapter->Receive.Lock.SpinLock) 692 NdisFreeSpinLock(&Adapter->Receive.Lock); 693 694 NdisFreeMemory(Adapter->AdapterOriginal, sizeof(NVNET_ADAPTER), 0); 695 } 696 697 CODE_SEG("PAGE") 698 NDIS_STATUS 699 NTAPI 700 MiniportInitialize( 701 _Out_ PNDIS_STATUS OpenErrorStatus, 702 _Out_ PUINT SelectedMediumIndex, 703 _In_ PNDIS_MEDIUM MediumArray, 704 _In_ UINT MediumArraySize, 705 _In_ NDIS_HANDLE MiniportAdapterHandle, 706 _In_ NDIS_HANDLE WrapperConfigurationContext) 707 { 708 UINT i; 709 ULONG Size; 710 PVOID UnalignedAdapter; 711 PNVNET_ADAPTER Adapter; 712 NDIS_STATUS Status; 713 714 PAGED_CODE(); 715 716 NDIS_DbgPrint(MIN_TRACE, ("()\n")); 717 718 for (i = 0; i < MediumArraySize; ++i) 719 { 720 if (MediumArray[i] == NdisMedium802_3) 721 { 722 *SelectedMediumIndex = i; 723 break; 724 } 725 } 726 if (i == MediumArraySize) 727 { 728 NDIS_DbgPrint(MAX_TRACE, ("No supported media\n")); 729 return NDIS_STATUS_UNSUPPORTED_MEDIA; 730 } 731 732 Size = sizeof(NVNET_ADAPTER) + NdisGetSharedDataAlignment(); 733 734 Status = NdisAllocateMemoryWithTag((PVOID*)&UnalignedAdapter, 735 Size, 736 NVNET_TAG); 737 if (Status != NDIS_STATUS_SUCCESS) 738 { 739 NDIS_DbgPrint(MAX_TRACE, ("Failed to allocate adapter\n")); 740 return NDIS_STATUS_RESOURCES; 741 } 742 743 NdisZeroMemory(UnalignedAdapter, Size); 744 Adapter = ALIGN_UP_POINTER_BY(UnalignedAdapter, NdisGetSharedDataAlignment()); 745 Adapter->AdapterOriginal = UnalignedAdapter; 746 Adapter->AdapterHandle = MiniportAdapterHandle; 747 Adapter->WrapperConfigurationHandle = WrapperConfigurationContext; 748 749 Status = NvNetReadConfiguration(Adapter); 750 if (Status != NDIS_STATUS_SUCCESS) 751 { 752 goto Failure; 753 } 754 755 NdisMSetAttributesEx(MiniportAdapterHandle, 756 Adapter, 757 0, 758 NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS | 759 // NDIS_ATTRIBUTE_DESERIALIZE | TODO 760 NDIS_ATTRIBUTE_BUS_MASTER, 761 NdisInterfacePci); 762 763 Status = NvNetRecognizeHardware(Adapter); 764 if (Status != NDIS_STATUS_SUCCESS) 765 { 766 if (Status == NDIS_STATUS_ADAPTER_NOT_FOUND) 767 { 768 NvNetLogError(Adapter, NDIS_ERROR_CODE_ADAPTER_NOT_FOUND); 769 } 770 else if (Status == NDIS_STATUS_NOT_RECOGNIZED) 771 { 772 NvNetLogError(Adapter, NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION); 773 } 774 775 goto Failure; 776 } 777 778 Status = NvNetInitializeAdapterResources(Adapter); 779 if (Status != NDIS_STATUS_SUCCESS) 780 { 781 goto Failure; 782 } 783 784 Status = NdisMInitializeScatterGatherDma(Adapter->AdapterHandle, 785 !!(Adapter->Features & DEV_HAS_HIGH_DMA), 786 NVNET_MAXIMUM_FRAME_SIZE); 787 // ^TODO: NVNET_MAX_DMA_TRANSFER); 788 if (Status != NDIS_STATUS_SUCCESS) 789 { 790 NvNetLogError(Adapter, NDIS_ERROR_CODE_OUT_OF_RESOURCES); 791 goto Failure; 792 } 793 794 Status = AllocateAdapterMemory(Adapter); 795 if (Status != NDIS_STATUS_SUCCESS) 796 { 797 NDIS_DbgPrint(MAX_TRACE, ("Failed to allocate adapter memory\n")); 798 799 NvNetLogError(Adapter, NDIS_ERROR_CODE_OUT_OF_RESOURCES); 800 goto Failure; 801 } 802 803 NvNetInitTransmitMemory(Adapter); 804 NvNetInitReceiveMemory(Adapter); 805 806 if (Adapter->Features & DEV_HAS_HIGH_DMA) 807 { 808 Adapter->TransmitPacket = NvNetTransmitPacket64; 809 Adapter->ProcessTransmit = ProcessTransmitDescriptors64; 810 } 811 else 812 { 813 Adapter->TransmitPacket = NvNetTransmitPacket32; 814 815 if (Adapter->Features & DEV_HAS_LARGEDESC) 816 { 817 Adapter->ProcessTransmit = ProcessTransmitDescriptors32; 818 } 819 else 820 { 821 Adapter->ProcessTransmit = ProcessTransmitDescriptorsLegacy; 822 } 823 } 824 825 Status = NvNetGetPermanentMacAddress(Adapter, Adapter->PermanentMacAddress); 826 if (Status != NDIS_STATUS_SUCCESS) 827 { 828 NvNetLogError(Adapter, NDIS_ERROR_CODE_NETWORK_ADDRESS); 829 goto Failure; 830 } 831 832 if (!(Adapter->Flags & NV_USE_SOFT_MAC_ADDRESS)) 833 { 834 ETH_COPY_NETWORK_ADDRESS(Adapter->CurrentMacAddress, 835 Adapter->PermanentMacAddress); 836 } 837 838 NvNetSetupMacAddress(Adapter, Adapter->CurrentMacAddress); 839 840 Status = NvNetInitNIC(Adapter, TRUE); 841 if (Status != NDIS_STATUS_SUCCESS) 842 { 843 NDIS_DbgPrint(MAX_TRACE, ("Failed to initialize the NIC\n")); 844 845 NvNetLogError(Adapter, NDIS_ERROR_CODE_HARDWARE_FAILURE); 846 goto Failure; 847 } 848 849 NvNetDisableInterrupts(Adapter); 850 NV_WRITE(Adapter, NvRegMIIStatus, NVREG_MIISTAT_MASK_ALL); 851 NV_WRITE(Adapter, NvRegIrqStatus, NVREG_IRQSTAT_MASK); 852 853 /* FIXME: Bug in the PIC HAL? */ 854 #if defined(SARCH_XBOX) 855 Status = NdisMRegisterInterrupt(&Adapter->Interrupt, 856 Adapter->AdapterHandle, 857 Adapter->InterruptVector, 858 Adapter->InterruptLevel, 859 TRUE, /* Request ISR calls */ 860 FALSE, 861 NdisInterruptLatched); 862 #else 863 Status = NdisMRegisterInterrupt(&Adapter->Interrupt, 864 Adapter->AdapterHandle, 865 Adapter->InterruptVector, 866 Adapter->InterruptLevel, 867 TRUE, /* Request ISR calls */ 868 TRUE, /* Shared */ 869 NdisInterruptLevelSensitive); 870 #endif 871 if (Status != NDIS_STATUS_SUCCESS) 872 { 873 NvNetLogError(Adapter, NDIS_ERROR_CODE_INTERRUPT_CONNECT); 874 goto Failure; 875 } 876 877 NvNetStartAdapter(Adapter); 878 879 return NDIS_STATUS_SUCCESS; 880 881 Failure: 882 NvNetFreeAdapter(Adapter); 883 884 return Status; 885 } 886