1 /* 2 * PROJECT: ReactOS DC21x4 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 2023 Dmitry Borisov <di.sean@protonmail.com> 6 */ 7 8 /* INCLUDES *******************************************************************/ 9 10 #include "dc21x4.h" 11 12 #include <debug.h> 13 14 /* GLOBALS ********************************************************************/ 15 16 /* 17 * The driver must align the buffers on a 4 byte boundary to meet the hardware requirement. 18 * We stick with cache alignment to get better performance. 19 */ 20 C_ASSERT((SYSTEM_CACHE_ALIGNMENT_SIZE % DC_RECEIVE_BUFFER_ALIGNMENT) == 0); 21 C_ASSERT((SYSTEM_CACHE_ALIGNMENT_SIZE % DC_DESCRIPTOR_ALIGNMENT) == 0); 22 C_ASSERT((SYSTEM_CACHE_ALIGNMENT_SIZE % DC_SETUP_FRAME_ALIGNMENT) == 0); 23 24 /* Errata: The end of receive buffer must not fall on a cache boundary */ 25 #define DC_RECEIVE_BUFFER_SIZE (DC_RECEIVE_BLOCK_SIZE - 4) 26 C_ASSERT((DC_RECEIVE_BUFFER_SIZE % 32) != 0); 27 28 #define DC_MEM_BLOCK_SIZE_RCB \ 29 (DC_RECEIVE_BLOCK_SIZE + SYSTEM_CACHE_ALIGNMENT_SIZE - 1) 30 31 #define DC_MEM_BLOCK_SIZE_RBD \ 32 (sizeof(DC_RBD) * DC_RECEIVE_BUFFERS_DEFAULT + SYSTEM_CACHE_ALIGNMENT_SIZE - 1) 33 34 #define DC_MEM_BLOCK_SIZE_TBD_AUX \ 35 (sizeof(DC_TBD) * DC_TRANSMIT_DESCRIPTORS + SYSTEM_CACHE_ALIGNMENT_SIZE - 1 + \ 36 DC_SETUP_FRAME_SIZE + SYSTEM_CACHE_ALIGNMENT_SIZE - 1 + \ 37 DC_LOOPBACK_FRAME_SIZE * DC_LOOPBACK_FRAMES + SYSTEM_CACHE_ALIGNMENT_SIZE - 1) 38 39 #define DC_MEM_BLOCK_SIZE_TX_BUFFER \ 40 (DC_TRANSMIT_BLOCK_SIZE + SYSTEM_CACHE_ALIGNMENT_SIZE - 1) 41 42 /* FUNCTIONS ******************************************************************/ 43 44 static 45 CODE_SEG("PAGE") 46 VOID 47 DcConfigQueryInteger( 48 _In_ NDIS_HANDLE ConfigurationHandle, 49 _In_ PCWSTR EntryName, 50 _Out_ PULONG EntryContext, 51 _In_ ULONG DefaultValue, 52 _In_ ULONG Minimum, 53 _In_ ULONG Maximum) 54 { 55 NDIS_STATUS Status; 56 UNICODE_STRING Keyword; 57 PNDIS_CONFIGURATION_PARAMETER ConfigurationParameter; 58 59 PAGED_CODE(); 60 61 NdisInitUnicodeString(&Keyword, EntryName); 62 NdisReadConfiguration(&Status, 63 &ConfigurationParameter, 64 ConfigurationHandle, 65 &Keyword, 66 NdisParameterInteger); 67 if (Status != NDIS_STATUS_SUCCESS) 68 { 69 TRACE("'%S' request failed, default value %u\n", EntryName, DefaultValue); 70 71 *EntryContext = DefaultValue; 72 return; 73 } 74 75 if (ConfigurationParameter->ParameterData.IntegerData >= Minimum && 76 ConfigurationParameter->ParameterData.IntegerData <= Maximum) 77 { 78 *EntryContext = ConfigurationParameter->ParameterData.IntegerData; 79 } 80 else 81 { 82 WARN("'%S' value out of range\n", EntryName); 83 84 *EntryContext = DefaultValue; 85 } 86 87 TRACE("Set '%S' to %u\n", EntryName, *EntryContext); 88 } 89 90 static 91 CODE_SEG("PAGE") 92 NDIS_STATUS 93 DcReadConfiguration( 94 _In_ PDC21X4_ADAPTER Adapter) 95 { 96 NDIS_STATUS Status; 97 NDIS_HANDLE ConfigurationHandle; 98 PUCHAR NetworkAddress; 99 UINT Length; 100 ULONG GenericUlong; 101 102 PAGED_CODE(); 103 104 NdisOpenConfiguration(&Status, 105 &ConfigurationHandle, 106 Adapter->WrapperConfigurationHandle); 107 if (Status != NDIS_STATUS_SUCCESS) 108 return Status; 109 110 DcConfigQueryInteger(ConfigurationHandle, 111 L"SpeedDuplex", 112 &GenericUlong, 113 MEDIA_AUTO, 114 MEDIA_10T, 115 MEDIA_HMR); 116 Adapter->DefaultMedia = GenericUlong; 117 118 NdisReadNetworkAddress(&Status, 119 (PVOID*)&NetworkAddress, 120 &Length, 121 ConfigurationHandle); 122 if ((Status == NDIS_STATUS_SUCCESS) && (Length == ETH_LENGTH_OF_ADDRESS)) 123 { 124 if (ETH_IS_MULTICAST(NetworkAddress) || 125 ETH_IS_EMPTY(NetworkAddress) || 126 ETH_IS_BROADCAST(NetworkAddress) || 127 !ETH_IS_LOCALLY_ADMINISTERED(NetworkAddress)) 128 { 129 ERR("Invalid software MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n", 130 NetworkAddress[0], 131 NetworkAddress[1], 132 NetworkAddress[2], 133 NetworkAddress[3], 134 NetworkAddress[4], 135 NetworkAddress[5]); 136 } 137 else 138 { 139 INFO("Using software MAC address\n"); 140 141 /* Override the MAC address */ 142 NdisMoveMemory(Adapter->CurrentMacAddress, NetworkAddress, ETH_LENGTH_OF_ADDRESS); 143 } 144 } 145 146 NdisCloseConfiguration(ConfigurationHandle); 147 148 return NDIS_STATUS_SUCCESS; 149 } 150 151 static 152 CODE_SEG("PAGE") 153 VOID 154 DcFreeRcb( 155 _In_ PDC21X4_ADAPTER Adapter, 156 _In_ __drv_freesMem(Mem) PDC_RCB Rcb) 157 { 158 PAGED_CODE(); 159 160 if (Rcb->VirtualAddressOriginal) 161 { 162 NdisMFreeSharedMemory(Adapter->AdapterHandle, 163 DC_MEM_BLOCK_SIZE_RCB, 164 TRUE, /* Cached */ 165 Rcb->VirtualAddressOriginal, 166 Rcb->PhysicalAddressOriginal); 167 } 168 169 if (Rcb->NdisBuffer) 170 NdisFreeBuffer(Rcb->NdisBuffer); 171 if (Rcb->Packet) 172 NdisFreePacket(Rcb->Packet); 173 174 NdisFreeMemory(Rcb, sizeof(*Rcb), 0); 175 } 176 177 static 178 CODE_SEG("PAGE") 179 PDC_RCB 180 DcAllocateRcb( 181 _In_ PDC21X4_ADAPTER Adapter) 182 { 183 NDIS_STATUS Status; 184 PDC_RCB Rcb; 185 PVOID VirtualAddress; 186 NDIS_PHYSICAL_ADDRESS PhysicalAddress; 187 188 PAGED_CODE(); 189 190 Status = NdisAllocateMemoryWithTag((PVOID*)&Rcb, sizeof(*Rcb), DC21X4_TAG); 191 if (Status != NDIS_STATUS_SUCCESS) 192 return NULL; 193 NdisZeroMemory(Rcb, sizeof(*Rcb)); 194 195 NdisMAllocateSharedMemory(Adapter->AdapterHandle, 196 DC_MEM_BLOCK_SIZE_RCB, 197 TRUE, /* Cached */ 198 &VirtualAddress, 199 &PhysicalAddress); 200 if (!VirtualAddress) 201 goto Failure; 202 203 /* 32-bit DMA */ 204 ASSERT(PhysicalAddress.HighPart == 0); 205 206 Rcb->VirtualAddress = ALIGN_UP_POINTER_BY(VirtualAddress, SYSTEM_CACHE_ALIGNMENT_SIZE); 207 Rcb->PhysicalAddress = ALIGN_UP_BY(PhysicalAddress.LowPart, SYSTEM_CACHE_ALIGNMENT_SIZE); 208 209 ASSERT((Rcb->PhysicalAddress % DC_RECEIVE_BUFFER_ALIGNMENT) == 0); 210 211 Rcb->VirtualAddressOriginal = VirtualAddress; 212 Rcb->PhysicalAddressOriginal.QuadPart = PhysicalAddress.QuadPart; 213 214 NdisAllocatePacket(&Status, &Rcb->Packet, Adapter->PacketPool); 215 if (Status != NDIS_STATUS_SUCCESS) 216 goto Failure; 217 218 *DC_RCB_FROM_PACKET(Rcb->Packet) = Rcb; 219 220 NdisAllocateBuffer(&Status, 221 &Rcb->NdisBuffer, 222 Adapter->BufferPool, 223 Rcb->VirtualAddress, 224 DC_RECEIVE_BLOCK_SIZE); 225 if (Status != NDIS_STATUS_SUCCESS) 226 goto Failure; 227 228 NDIS_SET_PACKET_HEADER_SIZE(Rcb->Packet, DC_ETHERNET_HEADER_SIZE); 229 NdisChainBufferAtFront(Rcb->Packet, Rcb->NdisBuffer); 230 231 PushEntryList(&Adapter->AllocRcbList, &Rcb->AllocListEntry); 232 233 return Rcb; 234 235 Failure: 236 DcFreeRcb(Adapter, Rcb); 237 238 return NULL; 239 } 240 241 static 242 CODE_SEG("PAGE") 243 NDIS_STATUS 244 DcAllocateReceiveBuffers( 245 _In_ PDC21X4_ADAPTER Adapter) 246 { 247 ULONG i; 248 NDIS_STATUS Status; 249 PDC_RCB Rcb; 250 251 PAGED_CODE(); 252 253 NdisAllocatePacketPool(&Status, 254 &Adapter->PacketPool, 255 DC_RECEIVE_BUFFERS_DEFAULT + DC_RECEIVE_BUFFERS_EXTRA, 256 PROTOCOL_RESERVED_SIZE_IN_PACKET); 257 if (Status != NDIS_STATUS_SUCCESS) 258 return Status; 259 260 NdisAllocateBufferPool(&Status, 261 &Adapter->BufferPool, 262 DC_RECEIVE_BUFFERS_DEFAULT + DC_RECEIVE_BUFFERS_EXTRA); 263 if (Status != NDIS_STATUS_SUCCESS) 264 return Status; 265 266 /* Allocate RCBs */ 267 for (i = 0; i < DC_RECEIVE_BUFFERS_DEFAULT; ++i) 268 { 269 Rcb = DcAllocateRcb(Adapter); 270 if (!Rcb) 271 { 272 WARN("RCB allocation failed, total buffers %u\n", Adapter->RcbCount); 273 break; 274 } 275 276 PushEntryList(&Adapter->UsedRcbList, &Rcb->ListEntry); 277 278 ++Adapter->RcbCount; 279 } 280 281 if (Adapter->RcbCount < DC_RECEIVE_BUFFERS_MIN) 282 return NDIS_STATUS_RESOURCES; 283 284 Adapter->RcbFree = Adapter->RcbCount; 285 286 /* Fix up the ring size */ 287 Adapter->TailRbd = Adapter->HeadRbd + Adapter->RcbCount - 1; 288 289 /* Allocate extra RCBs for receive indication */ 290 for (i = 0; i < DC_RECEIVE_BUFFERS_EXTRA; ++i) 291 { 292 Rcb = DcAllocateRcb(Adapter); 293 if (!Rcb) 294 { 295 WARN("Extra RCB allocation failed\n"); 296 break; 297 } 298 299 PushEntryList(&Adapter->FreeRcbList, &Rcb->ListEntry); 300 } 301 302 Status = NdisAllocateMemoryWithTag((PVOID*)&Adapter->RcbArray, 303 sizeof(PVOID) * Adapter->RcbCount, 304 DC21X4_TAG); 305 if (Status != NDIS_STATUS_SUCCESS) 306 return Status; 307 308 return NDIS_STATUS_SUCCESS; 309 } 310 311 static 312 CODE_SEG("PAGE") 313 NDIS_STATUS 314 DcAllocateReceiveDescriptors( 315 _In_ PDC21X4_ADAPTER Adapter) 316 { 317 PDC_RBD Rbd; 318 319 PAGED_CODE(); 320 321 NdisMAllocateSharedMemory(Adapter->AdapterHandle, 322 DC_MEM_BLOCK_SIZE_RBD, 323 FALSE, /* Non-cached */ 324 &Adapter->RbdOriginal, 325 &Adapter->RbdPhysOriginal); 326 if (!Adapter->RbdOriginal) 327 return NDIS_STATUS_RESOURCES; 328 329 /* 32-bit DMA */ 330 ASSERT(Adapter->RbdPhysOriginal.HighPart == 0); 331 332 Adapter->RbdPhys = ALIGN_UP_BY(Adapter->RbdPhysOriginal.LowPart, SYSTEM_CACHE_ALIGNMENT_SIZE); 333 334 ASSERT((Adapter->RbdPhys % DC_DESCRIPTOR_ALIGNMENT) == 0); 335 336 Rbd = ALIGN_UP_POINTER_BY(Adapter->RbdOriginal, SYSTEM_CACHE_ALIGNMENT_SIZE); 337 338 Adapter->HeadRbd = Rbd; 339 340 return NDIS_STATUS_SUCCESS; 341 } 342 343 static 344 CODE_SEG("PAGE") 345 NDIS_STATUS 346 DcAllocateTransmitBlocks( 347 _In_ PDC21X4_ADAPTER Adapter) 348 { 349 PDC_TCB Tcb; 350 NDIS_STATUS Status; 351 352 PAGED_CODE(); 353 354 Status = NdisAllocateMemoryWithTag((PVOID*)&Tcb, 355 DC_TRANSMIT_BLOCKS * sizeof(*Tcb), 356 DC21X4_TAG); 357 if (Status != NDIS_STATUS_SUCCESS) 358 return Status; 359 360 NdisZeroMemory(Tcb, DC_TRANSMIT_BLOCKS * sizeof(*Tcb)); 361 362 Adapter->HeadTcb = Tcb; 363 Adapter->TailTcb = Tcb + (DC_TRANSMIT_BLOCKS - 1); 364 365 return NDIS_STATUS_SUCCESS; 366 } 367 368 static 369 CODE_SEG("PAGE") 370 NDIS_STATUS 371 DcAllocateTransmitDescriptorsAndBuffers( 372 _In_ PDC21X4_ADAPTER Adapter) 373 { 374 ULONG_PTR BufferVa, BufferPa; 375 NDIS_STATUS Status; 376 ULONG i; 377 378 PAGED_CODE(); 379 380 NdisMAllocateSharedMemory(Adapter->AdapterHandle, 381 DC_MEM_BLOCK_SIZE_TBD_AUX, 382 FALSE, /* Non-cached */ 383 &Adapter->TbdOriginal, 384 &Adapter->TbdPhysOriginal); 385 if (!Adapter->TbdOriginal) 386 return NDIS_STATUS_RESOURCES; 387 388 /* 32-bit DMA */ 389 ASSERT(Adapter->TbdPhysOriginal.HighPart == 0); 390 391 BufferVa = (ULONG_PTR)Adapter->TbdOriginal; 392 BufferPa = Adapter->TbdPhysOriginal.LowPart; 393 394 BufferVa = ALIGN_UP_BY(BufferVa, SYSTEM_CACHE_ALIGNMENT_SIZE); 395 BufferPa = ALIGN_UP_BY(BufferPa, SYSTEM_CACHE_ALIGNMENT_SIZE); 396 397 ASSERT((BufferPa % DC_DESCRIPTOR_ALIGNMENT) == 0); 398 399 Adapter->TbdPhys = (ULONG)BufferPa; 400 Adapter->HeadTbd = (PDC_TBD)BufferVa; 401 Adapter->TailTbd = (PDC_TBD)BufferVa + DC_TRANSMIT_DESCRIPTORS - 1; 402 403 BufferVa += sizeof(DC_TBD) * DC_TRANSMIT_DESCRIPTORS; 404 BufferPa += sizeof(DC_TBD) * DC_TRANSMIT_DESCRIPTORS; 405 406 BufferVa = ALIGN_UP_BY(BufferVa, SYSTEM_CACHE_ALIGNMENT_SIZE); 407 BufferPa = ALIGN_UP_BY(BufferPa, SYSTEM_CACHE_ALIGNMENT_SIZE); 408 409 ASSERT((BufferPa % DC_SETUP_FRAME_ALIGNMENT) == 0); 410 411 Adapter->SetupFrame = (PVOID)BufferVa; 412 Adapter->SetupFramePhys = BufferPa; 413 414 BufferVa += DC_SETUP_FRAME_SIZE; 415 BufferPa += DC_SETUP_FRAME_SIZE; 416 417 BufferVa = ALIGN_UP_BY(BufferVa, SYSTEM_CACHE_ALIGNMENT_SIZE); 418 BufferPa = ALIGN_UP_BY(BufferPa, SYSTEM_CACHE_ALIGNMENT_SIZE); 419 420 for (i = 0; i < DC_LOOPBACK_FRAMES; ++i) 421 { 422 Adapter->LoopbackFrame[i] = (PVOID)BufferVa; 423 Adapter->LoopbackFramePhys[i] = BufferPa; 424 425 BufferVa += DC_LOOPBACK_FRAME_SIZE; 426 BufferPa += DC_LOOPBACK_FRAME_SIZE; 427 } 428 429 if (Adapter->Features & DC_HAS_POWER_MANAGEMENT) 430 { 431 Status = NdisAllocateMemoryWithTag((PVOID*)&Adapter->SetupFrameSaved, 432 DC_SETUP_FRAME_SIZE, 433 DC21X4_TAG); 434 if (Status != NDIS_STATUS_SUCCESS) 435 return Status; 436 } 437 438 return NDIS_STATUS_SUCCESS; 439 } 440 441 static 442 CODE_SEG("PAGE") 443 NDIS_STATUS 444 DcAllocateTransmitBuffers( 445 _In_ PDC21X4_ADAPTER Adapter) 446 { 447 PDC_COALESCE_BUFFER CoalesceBuffer; 448 NDIS_STATUS Status; 449 ULONG i; 450 451 PAGED_CODE(); 452 453 Status = NdisAllocateMemoryWithTag((PVOID*)&CoalesceBuffer, 454 DC_TRANSMIT_BUFFERS * sizeof(*CoalesceBuffer), 455 DC21X4_TAG); 456 if (Status != NDIS_STATUS_SUCCESS) 457 return Status; 458 459 NdisZeroMemory(CoalesceBuffer, DC_TRANSMIT_BUFFERS * sizeof(*CoalesceBuffer)); 460 461 Adapter->CoalesceBuffer = CoalesceBuffer; 462 463 for (i = 0; i < DC_TRANSMIT_BUFFERS; ++i) 464 { 465 PVOID VirtualAddress; 466 NDIS_PHYSICAL_ADDRESS PhysicalAddress; 467 468 NdisMAllocateSharedMemory(Adapter->AdapterHandle, 469 DC_MEM_BLOCK_SIZE_TX_BUFFER, 470 FALSE, /* Non-cached */ 471 &VirtualAddress, 472 &PhysicalAddress); 473 if (!VirtualAddress) 474 continue; 475 476 ASSERT(PhysicalAddress.HighPart == 0); 477 478 CoalesceBuffer->VirtualAddress = 479 ALIGN_UP_POINTER_BY(VirtualAddress, SYSTEM_CACHE_ALIGNMENT_SIZE); 480 CoalesceBuffer->PhysicalAddress = 481 ALIGN_UP_BY(PhysicalAddress.LowPart, SYSTEM_CACHE_ALIGNMENT_SIZE); 482 483 Adapter->SendBufferData[i].PhysicalAddress.QuadPart = PhysicalAddress.QuadPart; 484 Adapter->SendBufferData[i].VirtualAddress = VirtualAddress; 485 486 PushEntryList(&Adapter->SendBufferList, &CoalesceBuffer->ListEntry); 487 488 ++CoalesceBuffer; 489 } 490 491 if (!Adapter->SendBufferList.Next) 492 return NDIS_STATUS_RESOURCES; 493 494 return NDIS_STATUS_SUCCESS; 495 } 496 497 CODE_SEG("PAGE") 498 VOID 499 DcInitTxRing( 500 _In_ PDC21X4_ADAPTER Adapter) 501 { 502 PDC_TCB Tcb; 503 PDC_TBD Tbd; 504 505 PAGED_CODE(); 506 507 InitializeListHead(&Adapter->SendQueueList); 508 509 Tcb = Adapter->HeadTcb; 510 511 Adapter->CurrentTcb = Tcb; 512 Adapter->LastTcb = Tcb; 513 514 Adapter->TcbSlots = DC_TRANSMIT_BLOCKS - DC_TCB_RESERVE; 515 Adapter->TbdSlots = DC_TRANSMIT_DESCRIPTORS - DC_TBD_RESERVE; 516 Adapter->LoopbackFrameSlots = DC_LOOPBACK_FRAMES; 517 Adapter->TcbCompleted = 0; 518 519 Tbd = Adapter->HeadTbd; 520 Adapter->CurrentTbd = Tbd; 521 522 NdisZeroMemory(Tbd, sizeof(*Tbd) * DC_TRANSMIT_DESCRIPTORS); 523 524 Adapter->TailTbd->Control |= DC_TBD_CONTROL_END_OF_RING; 525 } 526 527 static 528 CODE_SEG("PAGE") 529 VOID 530 DcCreateRxRing( 531 _In_ PDC21X4_ADAPTER Adapter) 532 { 533 PDC_RCB* RcbSlot; 534 PDC_RCB Rcb; 535 PDC_RBD Rbd; 536 PSINGLE_LIST_ENTRY Entry; 537 538 PAGED_CODE(); 539 540 Rbd = Adapter->HeadRbd; 541 Adapter->CurrentRbd = Rbd; 542 543 RcbSlot = DC_GET_RCB_SLOT(Adapter, Rbd); 544 Rcb = (PDC_RCB)Adapter->UsedRcbList.Next; 545 546 for (Entry = Adapter->UsedRcbList.Next; 547 Entry != NULL; 548 Entry = Entry->Next) 549 { 550 Rcb = (PDC_RCB)Entry; 551 552 C_ASSERT((DC_RECEIVE_BUFFER_SIZE % DC_RECEIVE_BUFFER_SIZE_MULTIPLE) == 0); 553 554 Rbd->Address1 = Rcb->PhysicalAddress; 555 Rbd->Address2 = 0; 556 Rbd->Control = DC_RECEIVE_BUFFER_SIZE; 557 Rbd->Status = DC_RBD_STATUS_OWNED; 558 559 *RcbSlot = Rcb; 560 561 ++RcbSlot; 562 ++Rbd; 563 Rcb = (PDC_RCB)Rcb->ListEntry.Next; 564 } 565 Rbd = Rbd - 1; 566 Rbd->Control |= DC_RBD_CONTROL_CHAINED; 567 Rbd->Address2 = Adapter->RbdPhys; 568 569 ASSERT(Rbd == Adapter->TailRbd); 570 } 571 572 CODE_SEG("PAGE") 573 VOID 574 DcInitRxRing( 575 _In_ PDC21X4_ADAPTER Adapter) 576 { 577 PDC_RBD Rbd; 578 ULONG i; 579 580 PAGED_CODE(); 581 582 Rbd = Adapter->HeadRbd; 583 Adapter->CurrentRbd = Rbd; 584 585 for (i = 0; i < Adapter->RcbCount; ++i) 586 { 587 Rbd->Control = DC_RECEIVE_BUFFER_SIZE; 588 Rbd->Status = DC_RBD_STATUS_OWNED; 589 590 ++Rbd; 591 } 592 Rbd = Rbd - 1; 593 Rbd->Control |= DC_RBD_CONTROL_CHAINED; 594 595 ASSERT(Rbd == Adapter->TailRbd); 596 } 597 598 static 599 CODE_SEG("PAGE") 600 NDIS_STATUS 601 DcAllocateMemory( 602 _In_ PDC21X4_ADAPTER Adapter) 603 { 604 NDIS_STATUS Status; 605 606 PAGED_CODE(); 607 608 Status = NdisMInitializeScatterGatherDma(Adapter->AdapterHandle, 609 FALSE, /* 32-bit DMA */ 610 DC_TRANSMIT_BLOCK_SIZE); 611 if (Status != NDIS_STATUS_SUCCESS) 612 return Status; 613 614 Status = DcAllocateReceiveDescriptors(Adapter); 615 if (Status != NDIS_STATUS_SUCCESS) 616 return Status; 617 618 Status = DcAllocateTransmitBlocks(Adapter); 619 if (Status != NDIS_STATUS_SUCCESS) 620 return Status; 621 622 Status = DcAllocateTransmitBuffers(Adapter); 623 if (Status != NDIS_STATUS_SUCCESS) 624 return Status; 625 626 Status = DcAllocateTransmitDescriptorsAndBuffers(Adapter); 627 if (Status != NDIS_STATUS_SUCCESS) 628 return Status; 629 630 Status = DcAllocateReceiveBuffers(Adapter); 631 if (Status != NDIS_STATUS_SUCCESS) 632 return Status; 633 634 NdisAllocateSpinLock(&Adapter->SendLock); 635 NdisAllocateSpinLock(&Adapter->ReceiveLock); 636 NdisAllocateSpinLock(&Adapter->ModeLock); 637 638 return NDIS_STATUS_SUCCESS; 639 } 640 641 static 642 CODE_SEG("PAGE") 643 VOID 644 DcInitTestPacket( 645 _In_ PDC21X4_ADAPTER Adapter) 646 { 647 ULONG i; 648 649 PAGED_CODE(); 650 651 for (i = 0; i < DC_LOOPBACK_FRAMES; ++i) 652 { 653 PETH_HEADER PacketBuffer = Adapter->LoopbackFrame[i]; 654 655 NdisZeroMemory(PacketBuffer, DC_LOOPBACK_FRAME_SIZE); 656 657 /* Destination MAC address */ 658 NdisMoveMemory(PacketBuffer->Destination, 659 Adapter->CurrentMacAddress, 660 ETH_LENGTH_OF_ADDRESS); 661 662 /* Source MAC address */ 663 NdisMoveMemory(PacketBuffer->Source, 664 Adapter->CurrentMacAddress, 665 ETH_LENGTH_OF_ADDRESS); 666 667 ++PacketBuffer; 668 } 669 } 670 671 static 672 CODE_SEG("PAGE") 673 NDIS_STATUS 674 DcInitializeAdapterResources( 675 _In_ PDC21X4_ADAPTER Adapter) 676 { 677 NDIS_STATUS Status; 678 PNDIS_RESOURCE_LIST AssignedResources = NULL; 679 PCM_PARTIAL_RESOURCE_DESCRIPTOR IoDescriptor = NULL; 680 PCM_PARTIAL_RESOURCE_DESCRIPTOR InterruptDescriptor = NULL; 681 UINT i, ResourceListSize = 0; 682 683 PAGED_CODE(); 684 685 NdisMQueryAdapterResources(&Status, 686 Adapter->WrapperConfigurationHandle, 687 AssignedResources, 688 &ResourceListSize); 689 if (Status != NDIS_STATUS_RESOURCES) 690 return NDIS_STATUS_FAILURE; 691 692 Status = NdisAllocateMemoryWithTag((PVOID*)&AssignedResources, 693 ResourceListSize, 694 DC21X4_TAG); 695 if (Status != NDIS_STATUS_SUCCESS) 696 return Status; 697 698 NdisMQueryAdapterResources(&Status, 699 Adapter->WrapperConfigurationHandle, 700 AssignedResources, 701 &ResourceListSize); 702 if (Status != NDIS_STATUS_SUCCESS) 703 goto Cleanup; 704 705 for (i = 0; i < AssignedResources->Count; ++i) 706 { 707 PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor; 708 709 Descriptor = &AssignedResources->PartialDescriptors[i]; 710 switch (Descriptor->Type) 711 { 712 case CmResourceTypePort: 713 case CmResourceTypeMemory: 714 { 715 if (!IoDescriptor && (Descriptor->u.Port.Length == DC_IO_LENGTH)) 716 IoDescriptor = Descriptor; 717 break; 718 } 719 720 case CmResourceTypeInterrupt: 721 { 722 if (!InterruptDescriptor) 723 InterruptDescriptor = Descriptor; 724 break; 725 } 726 727 default: 728 break; 729 } 730 } 731 732 if (!IoDescriptor || !InterruptDescriptor) 733 { 734 Status = NDIS_STATUS_RESOURCES; 735 goto Cleanup; 736 } 737 738 Adapter->InterruptVector = InterruptDescriptor->u.Interrupt.Vector; 739 Adapter->InterruptLevel = InterruptDescriptor->u.Interrupt.Level; 740 Adapter->InterruptFlags = InterruptDescriptor->Flags; 741 if (InterruptDescriptor->ShareDisposition == CmResourceShareShared) 742 Adapter->Flags |= DC_IRQ_SHARED; 743 744 Adapter->IoBaseAddress = IoDescriptor->u.Port.Start; 745 746 if ((IoDescriptor->Type == CmResourceTypePort) && 747 (IoDescriptor->Flags & CM_RESOURCE_PORT_IO)) 748 { 749 Status = NdisMRegisterIoPortRange((PVOID*)&Adapter->IoBase, 750 Adapter->AdapterHandle, 751 Adapter->IoBaseAddress.LowPart, 752 DC_IO_LENGTH); 753 } 754 else 755 { 756 Status = NdisMMapIoSpace((PVOID*)&Adapter->IoBase, 757 Adapter->AdapterHandle, 758 Adapter->IoBaseAddress, 759 DC_IO_LENGTH); 760 761 Adapter->Flags |= DC_IO_MAPPED; 762 } 763 if (Status != NDIS_STATUS_SUCCESS) 764 goto Cleanup; 765 766 INFO("IO Base %p\n", Adapter->IoBase); 767 INFO("IRQ Level %u, Vector %u\n", 768 Adapter->InterruptLevel, 769 Adapter->InterruptVector); 770 INFO("IRQ ShareDisposition %u, InterruptFlags %lx\n", 771 InterruptDescriptor->ShareDisposition, 772 InterruptDescriptor->Flags); 773 774 Cleanup: 775 NdisFreeMemory(AssignedResources, ResourceListSize, 0); 776 777 return Status; 778 } 779 780 static 781 CODE_SEG("PAGE") 782 NDIS_STATUS 783 DcInitializeAdapterLocation( 784 _In_ PDC21X4_ADAPTER Adapter) 785 { 786 PDEVICE_OBJECT Pdo; 787 NTSTATUS Status; 788 ULONG PropertyValue, Length; 789 790 PAGED_CODE(); 791 792 NdisMGetDeviceProperty(Adapter->AdapterHandle, 793 &Pdo, 794 NULL, 795 NULL, 796 NULL, 797 NULL); 798 799 Status = IoGetDeviceProperty(Pdo, 800 DevicePropertyAddress, 801 sizeof(PropertyValue), 802 &PropertyValue, 803 &Length); 804 if (!NT_SUCCESS(Status)) 805 return NDIS_STATUS_FAILURE; 806 807 /* We need this for PCI devices only ((DeviceNumber << 16) | Function) */ 808 Adapter->DeviceNumber = (PropertyValue >> 16) & 0x000000FF; 809 810 Status = IoGetDeviceProperty(Pdo, 811 DevicePropertyBusNumber, 812 sizeof(PropertyValue), 813 &Adapter->BusNumber, 814 &Length); 815 if (!NT_SUCCESS(Status)) 816 return NDIS_STATUS_FAILURE; 817 818 return NDIS_STATUS_SUCCESS; 819 } 820 821 static 822 CODE_SEG("PAGE") 823 ULONG 824 DcGetBusModeParameters( 825 _In_ PDC21X4_ADAPTER Adapter, 826 _In_ PPCI_COMMON_CONFIG PciData) 827 { 828 ULONG DefaultMode, NewMode; 829 830 PAGED_CODE(); 831 832 /* TODO: Other architectures than x86 */ 833 DefaultMode = DC_BUS_MODE_CACHE_ALIGNMENT_16 | DC_BUS_MODE_BURST_LENGTH_NO_LIMIT; 834 835 if (!(Adapter->Features & DC_ENABLE_PCI_COMMANDS)) 836 return DefaultMode; 837 838 INFO("PCI Cache Line Size %u\n", PciData->CacheLineSize * 4); 839 INFO("PCI Command %04lx\n", PciData->Command); 840 841 /* Use the cache line size if it was set up by firmware */ 842 switch (PciData->CacheLineSize) 843 { 844 case 8: 845 NewMode = DC_BUS_MODE_CACHE_ALIGNMENT_8 | DC_BUS_MODE_BURST_LENGTH_8; 846 break; 847 case 16: 848 NewMode = DC_BUS_MODE_CACHE_ALIGNMENT_16 | DC_BUS_MODE_BURST_LENGTH_16; 849 break; 850 case 32: 851 NewMode = DC_BUS_MODE_CACHE_ALIGNMENT_32 | DC_BUS_MODE_BURST_LENGTH_32; 852 break; 853 854 default: 855 return DefaultMode; 856 } 857 858 /* Enable one of those commands */ 859 if (PciData->Command & PCI_ENABLE_WRITE_AND_INVALIDATE) 860 { 861 NewMode |= DC_BUS_MODE_WRITE_INVALIDATE; 862 } 863 else 864 { 865 NewMode |= DC_BUS_MODE_READ_LINE; 866 } 867 868 return NewMode; 869 } 870 871 static 872 CODE_SEG("PAGE") 873 NDIS_STATUS 874 DcRecognizeHardware( 875 _In_ PDC21X4_ADAPTER Adapter) 876 { 877 UCHAR Buffer[RTL_SIZEOF_THROUGH_FIELD(PCI_COMMON_CONFIG, CacheLineSize)]; 878 PPCI_COMMON_CONFIG PciConfig = (PPCI_COMMON_CONFIG)Buffer; // Partial PCI header 879 PNDIS_TIMER_FUNCTION MediaMonitorRoutine; 880 ULONG Bytes; 881 882 PAGED_CODE(); 883 884 Bytes = NdisReadPciSlotInformation(Adapter->AdapterHandle, 885 0, 886 FIELD_OFFSET(PCI_COMMON_CONFIG, VendorID), 887 Buffer, 888 sizeof(Buffer)); 889 if (Bytes != sizeof(Buffer)) 890 return NDIS_STATUS_FAILURE; 891 892 Adapter->DeviceId = PciConfig->DeviceID; 893 Adapter->RevisionId = PciConfig->RevisionID; 894 895 switch ((PciConfig->DeviceID << 16) | PciConfig->VendorID) 896 { 897 case DC_DEV_DECCHIP_21040: 898 { 899 Adapter->ChipType = DC21040; 900 Adapter->InterruptMask = DC_GENERIC_IRQ_MASK | DC_IRQ_LINK_FAIL; 901 Adapter->LinkStateChangeMask = DC_IRQ_LINK_FAIL; 902 Adapter->HandleLinkStateChange = MediaLinkStateChange21040; 903 MediaMonitorRoutine = MediaMonitor21040Dpc; 904 break; 905 } 906 907 case DC_DEV_DECCHIP_21041: 908 { 909 Adapter->ChipType = DC21041; 910 Adapter->Features |= DC_HAS_POWER_SAVING | DC_HAS_TIMER; 911 Adapter->InterruptMask = DC_GENERIC_IRQ_MASK | DC_IRQ_LINK_PASS | DC_IRQ_LINK_FAIL; 912 Adapter->LinkStateChangeMask = DC_IRQ_LINK_PASS | DC_IRQ_LINK_FAIL; 913 Adapter->HandleLinkStateChange = MediaLinkStateChange21041; 914 MediaMonitorRoutine = MediaMonitor21041Dpc; 915 break; 916 } 917 918 case DC_DEV_DECCHIP_21140: 919 { 920 Adapter->ChipType = DC21140; 921 Adapter->Features |= DC_HAS_TIMER; 922 923 if ((PciConfig->RevisionID & 0xF0) < 0x20) 924 { 925 /* 21140 */ 926 Adapter->Features |= DC_PERFECT_FILTERING_ONLY; 927 } 928 else 929 { 930 /* 21140A */ 931 Adapter->Features |= DC_NEED_RX_OVERFLOW_WORKAROUND | DC_ENABLE_PCI_COMMANDS | 932 DC_HAS_POWER_SAVING; 933 } 934 935 Adapter->OpMode |= DC_OPMODE_PORT_ALWAYS; 936 Adapter->InterruptMask = DC_GENERIC_IRQ_MASK; 937 MediaMonitorRoutine = MediaMonitor21140Dpc; 938 break; 939 } 940 941 case DC_DEV_INTEL_21143: 942 { 943 Adapter->Features |= DC_NEED_RX_OVERFLOW_WORKAROUND | DC_SIA_GPIO | 944 DC_HAS_POWER_SAVING | DC_MII_AUTOSENSE | DC_HAS_TIMER; 945 946 Adapter->InterruptMask = DC_GENERIC_IRQ_MASK | DC_IRQ_LINK_PASS | DC_IRQ_LINK_FAIL; 947 Adapter->LinkStateChangeMask = DC_IRQ_LINK_PASS | DC_IRQ_LINK_FAIL; 948 949 Adapter->ChipType = DC21143; 950 951 if ((PciConfig->RevisionID & 0xF0) < 0x20) 952 { 953 /* 21142 */ 954 } 955 else 956 { 957 /* 21143 */ 958 Adapter->Features |= DC_ENABLE_PCI_COMMANDS; 959 Adapter->OpMode |= DC_OPMODE_PORT_ALWAYS; 960 Adapter->InterruptMask |= DC_IRQ_LINK_CHANGED; 961 Adapter->LinkStateChangeMask |= DC_IRQ_LINK_CHANGED; 962 } 963 964 /* 21143 -PD and -TD */ 965 if ((PciConfig->RevisionID & 0xF0) > 0x30) 966 Adapter->Features |= DC_HAS_POWER_MANAGEMENT; 967 968 Adapter->HandleLinkStateChange = MediaLinkStateChange21143; 969 MediaMonitorRoutine = MediaMonitor21143Dpc; 970 break; 971 } 972 973 case DC_DEV_INTEL_21145: 974 { 975 Adapter->ChipType = DC21145; 976 977 Adapter->Features |= DC_NEED_RX_OVERFLOW_WORKAROUND | DC_SIA_GPIO | 978 DC_HAS_POWER_MANAGEMENT | DC_HAS_POWER_SAVING | 979 DC_SIA_ANALOG_CONTROL | DC_ENABLE_PCI_COMMANDS | 980 DC_MII_AUTOSENSE | DC_HAS_TIMER; 981 982 Adapter->OpMode |= DC_OPMODE_PORT_ALWAYS; 983 Adapter->InterruptMask = DC_GENERIC_IRQ_MASK | DC_IRQ_LINK_CHANGED | 984 DC_IRQ_LINK_PASS | DC_IRQ_LINK_FAIL; 985 Adapter->LinkStateChangeMask = DC_IRQ_LINK_CHANGED | 986 DC_IRQ_LINK_PASS | DC_IRQ_LINK_FAIL; 987 Adapter->HandleLinkStateChange = MediaLinkStateChange21143; 988 MediaMonitorRoutine = MediaMonitor21143Dpc; 989 990 Adapter->AnalogControl = DC_HPNA_ANALOG_CTRL; 991 992 /* Workaround for internal RX errata */ 993 Adapter->HpnaRegister[HPNA_NOISE_FLOOR] = 0x10; 994 Adapter->HpnaInitBitmap = (1 << HPNA_NOISE_FLOOR); 995 break; 996 } 997 998 default: 999 return NDIS_STATUS_NOT_RECOGNIZED; 1000 } 1001 1002 Adapter->BusMode = DcGetBusModeParameters(Adapter, PciConfig); 1003 1004 INFO("Bus Mode %08lx\n", Adapter->BusMode); 1005 1006 /* Errata: hash filtering is broken on some chips */ 1007 if (Adapter->Features & DC_PERFECT_FILTERING_ONLY) 1008 Adapter->MulticastMaxEntries = DC_SETUP_FRAME_ADDRESSES; 1009 else 1010 Adapter->MulticastMaxEntries = DC_MULTICAST_LIST_SIZE; 1011 1012 NdisMInitializeTimer(&Adapter->MediaMonitorTimer, 1013 Adapter->AdapterHandle, 1014 MediaMonitorRoutine, 1015 Adapter); 1016 1017 return NDIS_STATUS_SUCCESS; 1018 } 1019 1020 CODE_SEG("PAGE") 1021 VOID 1022 DcFreeAdapter( 1023 _In_ __drv_freesMem(Mem) PDC21X4_ADAPTER Adapter) 1024 { 1025 ULONG i; 1026 1027 PAGED_CODE(); 1028 1029 DcFreeEeprom(Adapter); 1030 1031 if (Adapter->Interrupt.InterruptObject) 1032 { 1033 NdisMDeregisterInterrupt(&Adapter->Interrupt); 1034 } 1035 1036 if (Adapter->IoBase) 1037 { 1038 if (Adapter->Flags & DC_IO_MAPPED) 1039 { 1040 NdisMUnmapIoSpace(Adapter->AdapterHandle, 1041 Adapter->IoBase, 1042 DC_IO_LENGTH); 1043 } 1044 else 1045 { 1046 NdisMDeregisterIoPortRange(Adapter->AdapterHandle, 1047 Adapter->IoBaseAddress.LowPart, 1048 DC_IO_LENGTH, 1049 Adapter->IoBase); 1050 } 1051 } 1052 1053 if (Adapter->HeadTcb) 1054 { 1055 NdisFreeMemory(Adapter->HeadTcb, sizeof(DC_TCB) * DC_TRANSMIT_BLOCKS, 0); 1056 } 1057 if (Adapter->RcbArray) 1058 { 1059 NdisFreeMemory(Adapter->RcbArray, sizeof(PVOID) * Adapter->RcbCount, 0); 1060 } 1061 if (Adapter->SetupFrameSaved) 1062 { 1063 NdisFreeMemory(Adapter->SetupFrameSaved, DC_SETUP_FRAME_SIZE, 0); 1064 } 1065 1066 while (Adapter->AllocRcbList.Next) 1067 { 1068 PSINGLE_LIST_ENTRY Entry = PopEntryList(&Adapter->AllocRcbList); 1069 PDC_RCB Rcb = CONTAINING_RECORD(Entry, DC_RCB, AllocListEntry); 1070 1071 DcFreeRcb(Adapter, Rcb); 1072 } 1073 1074 if (Adapter->RbdOriginal) 1075 { 1076 NdisMFreeSharedMemory(Adapter->AdapterHandle, 1077 DC_MEM_BLOCK_SIZE_RBD, 1078 FALSE, /* Non-cached */ 1079 Adapter->RbdOriginal, 1080 Adapter->RbdPhysOriginal); 1081 } 1082 if (Adapter->TbdOriginal) 1083 { 1084 NdisMFreeSharedMemory(Adapter->AdapterHandle, 1085 DC_MEM_BLOCK_SIZE_TBD_AUX, 1086 FALSE, /* Non-cached */ 1087 Adapter->TbdOriginal, 1088 Adapter->TbdPhysOriginal); 1089 } 1090 if (Adapter->CoalesceBuffer) 1091 { 1092 for (i = 0; i < DC_TRANSMIT_BUFFERS; ++i) 1093 { 1094 PDC_TX_BUFFER_DATA SendBufferData = &Adapter->SendBufferData[i]; 1095 1096 if (!SendBufferData->VirtualAddress) 1097 continue; 1098 1099 NdisMFreeSharedMemory(Adapter->AdapterHandle, 1100 DC_MEM_BLOCK_SIZE_TX_BUFFER, 1101 FALSE, /* Non-cached */ 1102 SendBufferData->VirtualAddress, 1103 SendBufferData->PhysicalAddress); 1104 } 1105 } 1106 1107 if (Adapter->PacketPool) 1108 NdisFreePacketPool(Adapter->PacketPool); 1109 if (Adapter->BufferPool) 1110 NdisFreeBufferPool(Adapter->BufferPool); 1111 1112 if (Adapter->SendLock.SpinLock) 1113 NdisFreeSpinLock(&Adapter->SendLock); 1114 if (Adapter->ReceiveLock.SpinLock) 1115 NdisFreeSpinLock(&Adapter->ReceiveLock); 1116 if (Adapter->ModeLock.SpinLock) 1117 NdisFreeSpinLock(&Adapter->ModeLock); 1118 1119 NdisFreeMemory(Adapter->AdapterOriginal, sizeof(*Adapter), 0); 1120 } 1121 1122 CODE_SEG("PAGE") 1123 NDIS_STATUS 1124 NTAPI 1125 DcInitialize( 1126 _Out_ PNDIS_STATUS OpenErrorStatus, 1127 _Out_ PUINT SelectedMediumIndex, 1128 _In_ PNDIS_MEDIUM MediumArray, 1129 _In_ UINT MediumArraySize, 1130 _In_ NDIS_HANDLE MiniportAdapterHandle, 1131 _In_ NDIS_HANDLE WrapperConfigurationContext) 1132 { 1133 PDC21X4_ADAPTER Adapter; 1134 PVOID UnalignedAdapter; 1135 NDIS_STATUS Status; 1136 ULONG Alignment, AdapterSize, OpMode; 1137 BOOLEAN Success; 1138 UINT i; 1139 1140 INFO("Called\n"); 1141 1142 PAGED_CODE(); 1143 1144 for (i = 0; i < MediumArraySize; ++i) 1145 { 1146 if (MediumArray[i] == NdisMedium802_3) 1147 { 1148 *SelectedMediumIndex = i; 1149 break; 1150 } 1151 } 1152 if (i == MediumArraySize) 1153 { 1154 ERR("No supported media\n"); 1155 return NDIS_STATUS_UNSUPPORTED_MEDIA; 1156 } 1157 1158 Alignment = NdisGetSharedDataAlignment(); 1159 AdapterSize = sizeof(*Adapter) + Alignment; 1160 1161 Status = NdisAllocateMemoryWithTag((PVOID*)&UnalignedAdapter, AdapterSize, DC21X4_TAG); 1162 if (Status != NDIS_STATUS_SUCCESS) 1163 { 1164 ERR("Failed to allocate adapter context\n"); 1165 return NDIS_STATUS_RESOURCES; 1166 } 1167 NdisZeroMemory(UnalignedAdapter, AdapterSize); 1168 1169 Adapter = ALIGN_UP_POINTER_BY(UnalignedAdapter, Alignment); 1170 Adapter->AdapterOriginal = UnalignedAdapter; 1171 Adapter->AdapterSize = AdapterSize; 1172 Adapter->AdapterHandle = MiniportAdapterHandle; 1173 Adapter->WrapperConfigurationHandle = WrapperConfigurationContext; 1174 1175 NdisInitializeWorkItem(&Adapter->ResetWorkItem, DcResetWorker, Adapter); 1176 NdisInitializeWorkItem(&Adapter->PowerWorkItem, DcPowerWorker, Adapter); 1177 NdisInitializeWorkItem(&Adapter->TxRecoveryWorkItem, DcTransmitTimeoutRecoveryWorker, Adapter); 1178 1179 NdisMSetAttributesEx(MiniportAdapterHandle, 1180 Adapter, 1181 2, /* CheckForHangTimeInSeconds */ 1182 NDIS_ATTRIBUTE_BUS_MASTER | 1183 NDIS_ATTRIBUTE_DESERIALIZE | 1184 NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS, 1185 NdisInterfacePci); 1186 1187 Status = DcRecognizeHardware(Adapter); 1188 if (Status != NDIS_STATUS_SUCCESS) 1189 { 1190 return Status; 1191 } 1192 1193 Status = DcInitializeAdapterResources(Adapter); 1194 if (Status != NDIS_STATUS_SUCCESS) 1195 { 1196 goto Failure; 1197 } 1198 1199 Status = DcInitializeAdapterLocation(Adapter); 1200 if (Status != NDIS_STATUS_SUCCESS) 1201 { 1202 goto Failure; 1203 } 1204 1205 /* Bring the chip out of sleep mode */ 1206 DcPowerSave(Adapter, FALSE); 1207 1208 OpMode = DC_READ(Adapter, DcCsr6_OpMode); 1209 OpMode &= ~(DC_OPMODE_RX_ENABLE | DC_OPMODE_TX_ENABLE); 1210 DC_WRITE(Adapter, DcCsr6_OpMode, OpMode); 1211 1212 MediaInitMediaList(Adapter); 1213 1214 Status = DcReadEeprom(Adapter); 1215 if (Status != NDIS_STATUS_SUCCESS) 1216 { 1217 goto Failure; 1218 } 1219 1220 NdisMoveMemory(Adapter->CurrentMacAddress, Adapter->PermanentMacAddress, ETH_LENGTH_OF_ADDRESS); 1221 1222 Status = DcReadConfiguration(Adapter); 1223 if (Status != NDIS_STATUS_SUCCESS) 1224 { 1225 goto Failure; 1226 } 1227 1228 Status = DcAllocateMemory(Adapter); 1229 if (Status != NDIS_STATUS_SUCCESS) 1230 { 1231 goto Failure; 1232 } 1233 1234 DcInitTestPacket(Adapter); 1235 1236 DcCreateRxRing(Adapter); 1237 1238 /* Execute the reset sequence */ 1239 if (Adapter->ResetStreamLength) 1240 { 1241 for (i = 0; i < Adapter->ResetStreamLength; ++i) 1242 { 1243 DcWriteGpio(Adapter, Adapter->ResetStream[i]); 1244 NdisMSleep(100); 1245 } 1246 1247 /* Give the PHY some time to reset */ 1248 NdisMSleep(5000); 1249 } 1250 1251 /* Perform a software reset */ 1252 DC_WRITE(Adapter, DcCsr0_BusMode, DC_BUS_MODE_SOFT_RESET); 1253 NdisMSleep(100); 1254 DC_WRITE(Adapter, DcCsr0_BusMode, Adapter->BusMode); 1255 1256 /* Try to detect a MII PHY */ 1257 if (Adapter->Features & DC_HAS_MII) 1258 { 1259 MediaSelectMiiPort(Adapter, TRUE); 1260 1261 Success = DcFindMiiPhy(Adapter); 1262 if (Success) 1263 { 1264 /* Disable all link interrupts when the MII PHY media is found */ 1265 Adapter->InterruptMask &= ~(DC_IRQ_LINK_CHANGED | DC_IRQ_LINK_FAIL | DC_IRQ_LINK_PASS); 1266 Adapter->LinkStateChangeMask = 0; 1267 } 1268 else 1269 { 1270 /* Incorrect EEPROM table or PHY is not connected, switch to a serial transceiver */ 1271 WARN("No PHY devices found\n"); 1272 Adapter->Features &= ~DC_HAS_MII; 1273 } 1274 } 1275 1276 MediaInitDefaultMedia(Adapter, Adapter->DefaultMedia); 1277 1278 /* Set the MAC address */ 1279 DcSetupFrameInitialize(Adapter); 1280 1281 /* Clear statistics */ 1282 DC_READ(Adapter, DcCsr8_RxCounters); 1283 1284 Adapter->Flags |= DC_FIRST_SETUP; 1285 1286 Status = DcSetupAdapter(Adapter); 1287 if (Status != NDIS_STATUS_SUCCESS) 1288 { 1289 ERR("Failed to initialize the NIC\n"); 1290 goto Disable; 1291 } 1292 1293 Adapter->Flags &= ~DC_FIRST_SETUP; 1294 1295 Status = NdisMRegisterInterrupt(&Adapter->Interrupt, 1296 Adapter->AdapterHandle, 1297 Adapter->InterruptVector, 1298 Adapter->InterruptLevel, 1299 TRUE, /* Request ISR calls */ 1300 !!(Adapter->Flags & DC_IRQ_SHARED), 1301 (Adapter->InterruptFlags & CM_RESOURCE_INTERRUPT_LATCHED) ? 1302 NdisInterruptLatched : NdisInterruptLevelSensitive); 1303 if (Status != NDIS_STATUS_SUCCESS) 1304 { 1305 ERR("Unable to register interrupt\n"); 1306 goto Disable; 1307 } 1308 1309 DcStartAdapter(Adapter); 1310 1311 return NDIS_STATUS_SUCCESS; 1312 1313 Disable: 1314 DcDisableHw(Adapter); 1315 Failure: 1316 ERR("Initialization failed with status %08lx\n", Status); 1317 1318 DcFreeAdapter(Adapter); 1319 1320 return Status; 1321 } 1322