1 /* 2 * PROJECT: ReactOS DC21x4 Driver 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: EEPROM manipulation and parsing 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 #define SROM_READ(Adapter, Data) \ 17 do { \ 18 *Data = DC_READ((Adapter), DcCsr9_SerialInterface); \ 19 NdisStallExecution(10); \ 20 } while (0) 21 22 #define SROM_WRITE(Adapter, Value) \ 23 do { \ 24 DC_WRITE((Adapter), DcCsr9_SerialInterface, Value); \ 25 NdisStallExecution(10); \ 26 } while (0) 27 28 extern DC_PG_DATA DC_SROM_REPAIR_ENTRY SRompRepairData[]; 29 30 LIST_ENTRY SRompAdapterList; 31 32 _Interlocked_ 33 static volatile LONG SRompAdapterLock = 0; 34 35 /* PRIVATE FUNCTIONS **********************************************************/ 36 37 static 38 CODE_SEG("PAGE") 39 VOID 40 SRomAcquireListMutex(VOID) 41 { 42 PAGED_CODE(); 43 44 while (_InterlockedCompareExchange(&SRompAdapterLock, 1, 0)) 45 { 46 NdisMSleep(10); 47 } 48 } 49 50 static inline 51 CODE_SEG("PAGE") 52 VOID 53 SRomReleaseListMutex(VOID) 54 { 55 PAGED_CODE(); 56 57 _InterlockedDecrement(&SRompAdapterLock); 58 } 59 60 static 61 CODE_SEG("PAGE") 62 BOOLEAN 63 SRomIsAdapterInList( 64 _In_ PDC21X4_ADAPTER Adapter, 65 _In_ BOOLEAN SearchForMaster, 66 _Out_opt_ PDC_SROM_ENTRY* FoundEntry) 67 { 68 PLIST_ENTRY PrevEntry; 69 PDC_SROM_ENTRY SRomEntry; 70 71 PAGED_CODE(); 72 73 /* Loop the adapter list backwards */ 74 for (PrevEntry = (&SRompAdapterList)->Blink; 75 PrevEntry != &SRompAdapterList; 76 PrevEntry = PrevEntry->Blink) 77 { 78 SRomEntry = CONTAINING_RECORD(PrevEntry, DC_SROM_ENTRY, ListEntry); 79 80 if ((SRomEntry->ChipType == Adapter->ChipType) && 81 (SRomEntry->BusNumber == Adapter->BusNumber) && 82 (!SearchForMaster || (SRomEntry->DeviceNumber == Adapter->DeviceNumber))) 83 { 84 if (FoundEntry) 85 *FoundEntry = SRomEntry; 86 87 return TRUE; 88 } 89 } 90 91 return FALSE; 92 } 93 94 static 95 CODE_SEG("PAGE") 96 BOOLEAN 97 SRomRegisterMasterAdapter( 98 _In_ PDC21X4_ADAPTER Adapter, 99 _In_ PDC_SROM_ENTRY SRomEntry) 100 { 101 BOOLEAN Success; 102 103 PAGED_CODE(); 104 105 SRomAcquireListMutex(); 106 107 /* Check if board is already registered */ 108 if (SRomIsAdapterInList(Adapter, TRUE, NULL)) 109 { 110 Success = FALSE; 111 goto Exit; 112 } 113 114 Adapter->SRomEntry = SRomEntry; 115 116 SRomEntry->ChipType = Adapter->ChipType; 117 SRomEntry->BusNumber = Adapter->BusNumber; 118 SRomEntry->DeviceNumber = Adapter->DeviceNumber; 119 SRomEntry->InterruptLevel = Adapter->InterruptLevel; 120 SRomEntry->InterruptVector = Adapter->InterruptVector; 121 122 /* Register the port */ 123 SRomEntry->DeviceBitmap |= 1 << Adapter->DeviceNumber; 124 125 /* 126 * On some multiport boards only the first port contains an EEPROM. 127 * We put their references to the global adapter list. 128 */ 129 InsertTailList(&SRompAdapterList, &SRomEntry->ListEntry); 130 Success = TRUE; 131 132 Exit: 133 SRomReleaseListMutex(); 134 135 return Success; 136 } 137 138 static 139 CODE_SEG("PAGE") 140 BOOLEAN 141 SRomFindMasterAdapter( 142 _In_ PDC21X4_ADAPTER Adapter, 143 _Out_ PDC_SROM_ENTRY* FoundEntry) 144 { 145 PDC_SROM_ENTRY SRomEntry; 146 ULONG i; 147 BOOLEAN Found; 148 149 PAGED_CODE(); 150 151 SRomAcquireListMutex(); 152 153 if (!SRomIsAdapterInList(Adapter, FALSE, &SRomEntry)) 154 { 155 Found = FALSE; 156 goto Exit; 157 } 158 159 Adapter->SRomEntry = SRomEntry; 160 161 /* Register the port */ 162 SRomEntry->DeviceBitmap |= 1 << Adapter->DeviceNumber; 163 164 /* 165 * Determine the port index that should be used in order to 166 * (possibly) update the base MAC address. 167 */ 168 for (i = 0; i < PCI_MAX_DEVICES; ++i) 169 { 170 if (i == Adapter->DeviceNumber) 171 break; 172 173 if (SRomEntry->DeviceBitmap & (1 << i)) 174 ++Adapter->ControllerIndex; 175 } 176 177 /* 178 * On a multiport board there can be up to 4 ports 179 * connected through a 21050 or 21152 PCI-to-PCI Bridge. 180 * These boards share a single IRQ line between all of the chips. 181 * Some BIOSes incorrectly assign different IRQs to the different ports. 182 */ 183 Adapter->InterruptLevel = SRomEntry->InterruptLevel; 184 Adapter->InterruptVector = SRomEntry->InterruptVector; 185 186 WARN("EEPROM is missing on controller %u, using image from the master at %u:%u\n", 187 Adapter->DeviceNumber, 188 SRomEntry->BusNumber, 189 SRomEntry->DeviceNumber); 190 191 *FoundEntry = SRomEntry; 192 Found = TRUE; 193 194 Exit: 195 SRomReleaseListMutex(); 196 197 return Found; 198 } 199 200 static 201 CODE_SEG("PAGE") 202 BOOLEAN 203 SRomIsEmpty( 204 _In_reads_bytes_(Length) const VOID* Buffer, 205 _In_ ULONG Length) 206 { 207 const UCHAR* Data = Buffer; 208 const UCHAR FirstByte = Data[0]; 209 ULONG i; 210 211 PAGED_CODE(); 212 213 for (i = 1; i < Length; ++i) 214 { 215 if (FirstByte != Data[i]) 216 return FALSE; 217 } 218 219 return TRUE; 220 } 221 222 static 223 CODE_SEG("PAGE") 224 VOID 225 SRomNWayAdvertise( 226 _In_ PDC21X4_ADAPTER Adapter, 227 _In_ ULONG MediaCode) 228 { 229 PAGED_CODE(); 230 231 switch (MediaCode) 232 { 233 case MEDIA_10T: 234 Adapter->SymAdvertising |= MII_ADV_10T_HD; 235 break; 236 case MEDIA_10T_FD: 237 Adapter->SymAdvertising |= MII_ADV_10T_FD; 238 break; 239 case MEDIA_100TX_HD: 240 Adapter->SymAdvertising |= MII_ADV_100T_HD; 241 break; 242 case MEDIA_100TX_FD: 243 Adapter->SymAdvertising |= MII_ADV_100T_FD; 244 break; 245 case MEDIA_100T4: 246 Adapter->SymAdvertising |= MII_ADV_100T4; 247 break; 248 249 default: 250 break; 251 } 252 } 253 254 static 255 CODE_SEG("PAGE") 256 NDIS_STATUS 257 SRomDecodeBlockGpr( 258 _In_ PDC21X4_ADAPTER Adapter, 259 _In_ PUCHAR SRomEnd, 260 _In_ PUCHAR BlockData) 261 { 262 PDC_MEDIA Media; 263 ULONG MediaCode, OpMode; 264 USHORT Command; 265 266 PAGED_CODE(); 267 268 if (BlockData > (SRomEnd - 4)) 269 return NDIS_STATUS_BUFFER_OVERFLOW; 270 271 MediaCode = SRomGetMediaCode(*BlockData++); 272 if (MediaCode > SROM_MEDIA_MAX) 273 { 274 WARN("Unknown media code %u\n", MediaCode); 275 return NDIS_STATUS_SUCCESS; 276 } 277 Adapter->MediaBitmap |= 1 << MediaCode; 278 279 Media = &Adapter->Media[MediaCode]; 280 281 Media->GpioData = *BlockData++; 282 283 Command = DcRetrieveWord(BlockData); 284 285 OpMode = Media->OpMode; 286 OpMode &= ~SROM_OPMODE_MASK; 287 OpMode |= SRomCommandToOpMode(Command); 288 Media->OpMode = OpMode; 289 290 if (SRomMediaHasActivityIndicator(Command)) 291 { 292 Media->LinkMask = SRomMediaGetSenseMask(Command); 293 } 294 if (SRomMediaActivityIsActiveLow(Command)) 295 { 296 Media->Polarity = 0xFFFFFFFF; 297 } 298 299 INFO("GPR #%u %s, Command %04lx, Data %02lx\n", 300 MediaCode, 301 MediaNumber2Str(Adapter, MediaCode), 302 Command, 303 Media->GpioData); 304 305 return NDIS_STATUS_SUCCESS; 306 } 307 308 static 309 CODE_SEG("PAGE") 310 NDIS_STATUS 311 SRomDecodeBlockMii( 312 _In_ PDC21X4_ADAPTER Adapter, 313 _In_ PUCHAR SRomEnd, 314 _In_ PUCHAR BlockData, 315 _In_ BOOLEAN IsOldVersion) 316 { 317 PDC_MII_MEDIA Media; 318 ULONG i, Bytes, Offset; 319 UCHAR PhyNumber, StreamLength, InterruptInfo; 320 USHORT Capabilities, Fdx, Ttm; 321 322 PAGED_CODE(); 323 324 if (BlockData > (SRomEnd - 2)) 325 return NDIS_STATUS_BUFFER_OVERFLOW; 326 327 PhyNumber = *BlockData++; 328 329 /* 330 * Even though the SROM specification allows several 331 * PHY devices to be connected to the same chip on a board, 332 * most if not all boards never use more than 1 MII PHY device. 333 */ 334 if (Adapter->Features & DC_HAS_MII) 335 { 336 WARN("Unsupported PHY %u\n", PhyNumber); 337 return NDIS_STATUS_SUCCESS; 338 } 339 340 Media = &Adapter->MiiMedia; 341 342 /* 343 * PHY selection sequence 344 */ 345 346 StreamLength = *BlockData++; 347 if (StreamLength > SROM_MAX_STREAM_REGS) 348 { 349 WARN("Too much registers %u\n", StreamLength); 350 return NDIS_STATUS_SUCCESS; 351 } 352 353 Bytes = StreamLength; 354 if (!IsOldVersion) 355 { 356 /* In words */ 357 Bytes *= 2; 358 } 359 if ((BlockData + Bytes) > (SRomEnd - 1)) 360 { 361 return NDIS_STATUS_BUFFER_OVERFLOW; 362 } 363 364 Media->SetupStreamLength = StreamLength; 365 366 /* Check if we already have the GPIO direction data */ 367 if (Media->SetupStream[0] != 0) 368 { 369 Offset = 1; 370 ++Media->SetupStreamLength; 371 } 372 else 373 { 374 Offset = 0; 375 } 376 377 for (i = 0; i < StreamLength; ++i) 378 { 379 if (IsOldVersion) 380 { 381 Media->SetupStream[i + Offset] = *BlockData++; 382 } 383 else 384 { 385 Media->SetupStream[i + Offset] = DcRetrieveWord(BlockData); 386 BlockData += sizeof(USHORT); 387 } 388 } 389 390 /* 391 * PHY reset sequence 392 */ 393 394 if (BlockData > (SRomEnd - 1)) 395 { 396 return NDIS_STATUS_BUFFER_OVERFLOW; 397 } 398 399 StreamLength = *BlockData++; 400 if (StreamLength > SROM_MAX_STREAM_REGS) 401 { 402 WARN("Too much registers %u\n", StreamLength); 403 return NDIS_STATUS_SUCCESS; 404 } 405 406 Bytes = StreamLength; 407 if (!IsOldVersion) 408 { 409 /* In words */ 410 Bytes *= 2; 411 } 412 if ((BlockData + Bytes) > (SRomEnd - 1)) 413 { 414 return NDIS_STATUS_BUFFER_OVERFLOW; 415 } 416 417 Media->ResetStreamLength = StreamLength; 418 419 for (i = 0; i < StreamLength; ++i) 420 { 421 if (IsOldVersion) 422 { 423 Media->ResetStream[i] = *BlockData++; 424 } 425 else 426 { 427 Media->ResetStream[i] = DcRetrieveWord(BlockData); 428 BlockData += sizeof(USHORT); 429 } 430 } 431 432 /* 433 * MII data 434 */ 435 436 Bytes = 4 * sizeof(USHORT); 437 if (!IsOldVersion) 438 { 439 Bytes += 1; 440 } 441 if (BlockData > (SRomEnd - Bytes)) 442 { 443 return NDIS_STATUS_BUFFER_OVERFLOW; 444 } 445 446 Capabilities = DcRetrieveWord(BlockData); 447 BlockData += sizeof(USHORT); 448 449 Media->Advertising = DcRetrieveWord(BlockData); 450 BlockData += sizeof(USHORT); 451 452 Fdx = DcRetrieveWord(BlockData); 453 BlockData += sizeof(USHORT); 454 455 Ttm = DcRetrieveWord(BlockData); 456 BlockData += sizeof(USHORT); 457 458 InterruptInfo = IsOldVersion ? 0 : *BlockData; 459 460 Adapter->Features |= DC_HAS_MII; 461 462 INFO("MII #%u, Caps %04lx, Adv %04lx, Fdx %04lx, Ttm %04lx, Int %02x\n", 463 PhyNumber, 464 Capabilities, 465 Media->Advertising, 466 Fdx, 467 Ttm, 468 InterruptInfo); 469 470 return NDIS_STATUS_SUCCESS; 471 } 472 473 static 474 CODE_SEG("PAGE") 475 NDIS_STATUS 476 SRomDecodeBlockSia( 477 _In_ PDC21X4_ADAPTER Adapter, 478 _In_ PUCHAR SRomEnd, 479 _In_ PUCHAR BlockData) 480 { 481 PDC_MEDIA Media; 482 UCHAR BlockStart; 483 ULONG MediaCode; 484 BOOLEAN HasExtendedData; 485 486 PAGED_CODE(); 487 488 if (BlockData > (SRomEnd - 1)) 489 return NDIS_STATUS_BUFFER_OVERFLOW; 490 491 BlockStart = *BlockData++; 492 493 HasExtendedData = SRomBlockHasExtendedData(BlockStart); 494 if (BlockData > (SRomEnd - (HasExtendedData ? 10 : 4))) 495 return NDIS_STATUS_BUFFER_OVERFLOW; 496 497 MediaCode = SRomGetMediaCode(BlockStart); 498 if (MediaCode > SROM_MEDIA_MAX && MediaCode != SROM_MEDIA_HMR) 499 { 500 WARN("Unknown media code %u\n", MediaCode); 501 return NDIS_STATUS_SUCCESS; 502 } 503 504 /* TODO: There were a few 21143-based boards with HMR media */ 505 if ((MediaCode == SROM_MEDIA_HMR) && (Adapter->ChipType != DC21145)) 506 { 507 ERR("FIXME: 21143 HMR is not supported yet\n"); 508 return NDIS_STATUS_SUCCESS; 509 } 510 511 /* Map the code to our internal value */ 512 if (MediaCode == SROM_MEDIA_HMR) 513 { 514 MediaCode = MEDIA_HMR; 515 } 516 517 Adapter->MediaBitmap |= 1 << MediaCode; 518 519 Media = &Adapter->Media[MediaCode]; 520 521 if (HasExtendedData) 522 { 523 Media->Csr13 = DcRetrieveWord(BlockData); 524 BlockData += sizeof(USHORT); 525 526 Media->Csr14 = DcRetrieveWord(BlockData); 527 BlockData += sizeof(USHORT); 528 529 Media->Csr15 = DcRetrieveWord(BlockData); 530 BlockData += sizeof(USHORT); 531 } 532 533 Media->GpioCtrl = DcRetrieveWord(BlockData); 534 BlockData += sizeof(USHORT); 535 536 Media->GpioData = DcRetrieveWord(BlockData); 537 BlockData += sizeof(USHORT); 538 539 SRomNWayAdvertise(Adapter, MediaCode); 540 541 INFO("SIA #%u %s, %sCSR13 %04lx CSR14 %04lx CSR15 %04lx, " 542 "Ctrl %04lx, Data %04lx\n", 543 MediaCode, 544 MediaNumber2Str(Adapter, MediaCode), 545 HasExtendedData ? "EXT " : "", 546 Media->Csr13, 547 Media->Csr14, 548 Media->Csr15, 549 Media->GpioCtrl, 550 Media->GpioData); 551 552 return NDIS_STATUS_SUCCESS; 553 } 554 555 static 556 CODE_SEG("PAGE") 557 NDIS_STATUS 558 SRomDecodeBlockSym( 559 _In_ PDC21X4_ADAPTER Adapter, 560 _In_ PUCHAR SRomEnd, 561 _In_ PUCHAR BlockData) 562 { 563 PDC_MEDIA Media; 564 ULONG MediaCode, OpMode; 565 USHORT Command; 566 567 PAGED_CODE(); 568 569 if (BlockData > (SRomEnd - 7)) 570 return NDIS_STATUS_BUFFER_OVERFLOW; 571 572 MediaCode = SRomGetMediaCode(*BlockData++); 573 if (MediaCode > SROM_MEDIA_MAX) 574 { 575 WARN("Unknown media code %u\n", MediaCode); 576 return NDIS_STATUS_SUCCESS; 577 } 578 Adapter->MediaBitmap |= 1 << MediaCode; 579 580 Media = &Adapter->Media[MediaCode]; 581 582 Media->GpioCtrl = DcRetrieveWord(BlockData); 583 BlockData += sizeof(USHORT); 584 585 Media->GpioData = DcRetrieveWord(BlockData); 586 BlockData += sizeof(USHORT); 587 588 Command = DcRetrieveWord(BlockData); 589 BlockData += sizeof(USHORT); 590 591 OpMode = Media->OpMode; 592 OpMode &= ~SROM_OPMODE_MASK; 593 OpMode |= SRomCommandToOpMode(Command); 594 Media->OpMode = OpMode; 595 596 SRomNWayAdvertise(Adapter, MediaCode); 597 598 INFO("SYM #%u %s, Command %04lx, Ctrl %04lx, Data %04lx\n", 599 MediaCode, 600 MediaNumber2Str(Adapter, MediaCode), 601 Command, 602 Media->GpioCtrl, 603 Media->GpioData); 604 605 return NDIS_STATUS_SUCCESS; 606 } 607 608 static 609 CODE_SEG("PAGE") 610 NDIS_STATUS 611 SRomDecodeBlockReset( 612 _In_ PDC21X4_ADAPTER Adapter, 613 _In_ PUCHAR SRomEnd, 614 _In_ PUCHAR BlockData) 615 { 616 UCHAR i, StreamLength; 617 618 PAGED_CODE(); 619 620 if (BlockData > (SRomEnd - 1)) 621 return NDIS_STATUS_BUFFER_OVERFLOW; 622 623 StreamLength = *BlockData++; 624 if (StreamLength > SROM_MAX_STREAM_REGS) 625 { 626 WARN("Too much registers %u\n", StreamLength); 627 return NDIS_STATUS_SUCCESS; 628 } 629 630 if ((BlockData + StreamLength * 2) > (SRomEnd - 1)) 631 return NDIS_STATUS_BUFFER_OVERFLOW; 632 633 Adapter->ResetStreamLength = StreamLength; 634 635 for (i = 0; i < StreamLength; ++i) 636 { 637 Adapter->ResetStream[i] = DcRetrieveWord(BlockData); 638 BlockData += sizeof(USHORT); 639 } 640 641 INFO("RESET, length %u\n", StreamLength); 642 643 return NDIS_STATUS_SUCCESS; 644 } 645 646 static 647 CODE_SEG("PAGE") 648 NDIS_STATUS 649 SRomDecodeBlockHmr( 650 _In_ PDC21X4_ADAPTER Adapter, 651 _In_ PUCHAR SRomEnd, 652 _In_ PUCHAR BlockData, 653 _In_ UCHAR BlockLength) 654 { 655 ULONG Offset, ExtraData, i; 656 657 PAGED_CODE(); 658 659 if (BlockData > (SRomEnd - (2 + 6))) 660 return NDIS_STATUS_BUFFER_OVERFLOW; 661 662 Adapter->AnalogControl = DcRetrieveWord(BlockData) << 16; 663 BlockData += sizeof(USHORT); 664 665 Adapter->HpnaRegister[HPNA_CONTROL_LOW] = *BlockData++; 666 Adapter->HpnaRegister[HPNA_CONTROL_HIGH] = *BlockData++; 667 Adapter->HpnaRegister[HPNA_NOISE] = *BlockData++; 668 Adapter->HpnaRegister[HPNA_NOISE_FLOOR] = *BlockData++; 669 Adapter->HpnaRegister[HPNA_NOISE_CEILING] = *BlockData++; 670 Adapter->HpnaRegister[HPNA_NOISE_ATTACK] = *BlockData++; 671 Adapter->HpnaInitBitmap |= ((1 << HPNA_CONTROL_LOW) | 672 (1 << HPNA_CONTROL_HIGH) | 673 (1 << HPNA_NOISE) | 674 (1 << HPNA_NOISE_FLOOR) | 675 (1 << HPNA_NOISE_CEILING) | 676 (1 << HPNA_NOISE_ATTACK)); 677 678 Offset = 2 /* Length and type fields */ + 2 /* Analog ctrl */ + 6; /* Regs */ 679 ExtraData = (BlockLength - Offset); 680 681 if ((BlockData + ExtraData) > (SRomEnd - 1)) 682 return NDIS_STATUS_BUFFER_OVERFLOW; 683 684 for (i = 0; i < ExtraData / sizeof(USHORT); ++i) 685 { 686 UCHAR RegAddress = SRomHmrRegAddress(*BlockData++); 687 UCHAR RegValue = *BlockData++; 688 689 Adapter->HpnaRegister[RegAddress] = RegValue; 690 Adapter->HpnaInitBitmap |= 1 << RegAddress; 691 } 692 693 #if DBG 694 INFO_VERB("Analog Ctrl %04lx\n", Adapter->AnalogControl); 695 696 for (i = 0; i < RTL_NUMBER_OF(Adapter->HpnaRegister); ++i) 697 { 698 if (Adapter->HpnaInitBitmap & (1 << i)) 699 { 700 INFO_VERB("HR Reg %02x = %02x\n", i, Adapter->HpnaRegister[i]); 701 } 702 } 703 704 if (ExtraData % sizeof(USHORT)) 705 { 706 INFO_VERB("HR Data = %02x\n", *BlockData); 707 } 708 #endif 709 710 return NDIS_STATUS_SUCCESS; 711 } 712 713 static 714 CODE_SEG("PAGE") 715 NDIS_STATUS 716 SRomParseExtendedBlock( 717 _In_ PDC21X4_ADAPTER Adapter, 718 _In_ PUCHAR SRomEnd, 719 _In_ PUCHAR BlockData, 720 _Out_ PULONG BlockSize) 721 { 722 NDIS_STATUS Status; 723 ULONG Length, Type; 724 725 PAGED_CODE(); 726 727 if (BlockData > (SRomEnd - 2)) 728 return NDIS_STATUS_BUFFER_OVERFLOW; 729 730 Length = SRomGetExtendedBlockLength(*BlockData++); 731 Type = *BlockData++; 732 733 *BlockSize = Length; 734 735 switch (Type) 736 { 737 case SROM_BLOCK_TYPE_GPR: 738 Status = SRomDecodeBlockGpr(Adapter, SRomEnd, BlockData); 739 break; 740 case SROM_BLOCK_TYPE_MII_1: 741 case SROM_BLOCK_TYPE_MII_2: 742 Status = SRomDecodeBlockMii(Adapter, 743 SRomEnd, 744 BlockData, 745 (Type == SROM_BLOCK_TYPE_MII_1)); 746 break; 747 case SROM_BLOCK_TYPE_SIA: 748 Status = SRomDecodeBlockSia(Adapter, SRomEnd, BlockData); 749 break; 750 case SROM_BLOCK_TYPE_SYM: 751 Status = SRomDecodeBlockSym(Adapter, SRomEnd, BlockData); 752 break; 753 case SROM_BLOCK_TYPE_RESET: 754 Status = SRomDecodeBlockReset(Adapter, SRomEnd, BlockData); 755 break; 756 case SROM_BLOCK_TYPE_HOMERUN: 757 Status = SRomDecodeBlockHmr(Adapter, SRomEnd, BlockData, Length); 758 break; 759 760 /* Skip over the unused or unknown blocks */ 761 default: 762 WARN("Unknown block type %u, length %u\n", Type, Length); 763 case SROM_BLOCK_TYPE_PHY_SHUTDOWN: 764 Status = NDIS_STATUS_SUCCESS; 765 break; 766 } 767 768 return Status; 769 } 770 771 static 772 CODE_SEG("PAGE") 773 NDIS_STATUS 774 SRomParse21041Block( 775 _In_ PDC21X4_ADAPTER Adapter, 776 _In_ PUCHAR SRomEnd, 777 _In_ PUCHAR BlockData, 778 _Out_ PULONG BlockSize) 779 { 780 PDC_MEDIA Media; 781 UCHAR BlockStart; 782 ULONG MediaCode; 783 BOOLEAN HasExtendedData; 784 785 PAGED_CODE(); 786 787 if (BlockData > (SRomEnd - 1)) 788 return NDIS_STATUS_BUFFER_OVERFLOW; 789 790 BlockStart = *BlockData++; 791 792 HasExtendedData = SRomBlockHasExtendedData(BlockStart); 793 if (BlockData > (SRomEnd - (HasExtendedData ? 7 : 1))) 794 return NDIS_STATUS_BUFFER_OVERFLOW; 795 796 *BlockSize = HasExtendedData ? 7 : 1; 797 798 MediaCode = SRomGetMediaCode(BlockStart); 799 if (MediaCode > SROM_MEDIA_MAX) 800 { 801 WARN("Unknown media code %u\n", MediaCode); 802 return NDIS_STATUS_SUCCESS; 803 } 804 Adapter->MediaBitmap |= 1 << MediaCode; 805 806 Media = &Adapter->Media[MediaCode]; 807 808 if (HasExtendedData) 809 { 810 Media->Csr13 = DcRetrieveWord(BlockData); 811 BlockData += sizeof(USHORT); 812 813 Media->Csr14 = DcRetrieveWord(BlockData); 814 BlockData += sizeof(USHORT); 815 816 Media->Csr15 = DcRetrieveWord(BlockData); 817 BlockData += sizeof(USHORT); 818 } 819 820 INFO("SIA #%u %s, %sCSR13 %04lx CSR14 %04lx CSR15 %04lx\n", 821 MediaCode, 822 MediaNumber2Str(Adapter, MediaCode), 823 HasExtendedData ? "EXT " : "", 824 Media->Csr13, 825 Media->Csr14, 826 Media->Csr15); 827 828 return NDIS_STATUS_SUCCESS; 829 } 830 831 static 832 CODE_SEG("PAGE") 833 BOOLEAN 834 SRomChecksumValid( 835 _In_ PUCHAR SRom) 836 { 837 USHORT Checksum; 838 839 PAGED_CODE(); 840 841 Checksum = ~DcEthernetCrc(SRom, SROM_CHECKSUM_V1); 842 if (Checksum == DcRetrieveWord(&SRom[SROM_CHECKSUM_V1])) 843 return TRUE; 844 845 Checksum = ~DcEthernetCrc(SRom, SROM_CHECKSUM_V2); 846 if (Checksum == DcRetrieveWord(&SRom[SROM_CHECKSUM_V2])) 847 return TRUE; 848 849 return FALSE; 850 } 851 852 static 853 CODE_SEG("PAGE") 854 BOOLEAN 855 AddressRomChecksumValid( 856 _In_reads_bytes_(EAR_SIZE) PVOID AddressRom) 857 { 858 const UCHAR* Octet = AddressRom; 859 ULONG64 TestPatterm; 860 ULONG Checksum, i; 861 862 PAGED_CODE(); 863 864 NdisMoveMemory(&TestPatterm, &Octet[24], 8); 865 if (TestPatterm != EAR_TEST_PATTERN) 866 return FALSE; 867 868 for (i = 0; i < 8; ++i) 869 { 870 if (Octet[i] != Octet[15 - i]) 871 return FALSE; 872 } 873 874 Checksum = (Octet[0] << 10) + (Octet[2] << 9) + (Octet[4] << 8) + 875 (Octet[1] << 2) + (Octet[3] << 1) + Octet[5]; 876 Checksum %= 0xFFFF; 877 878 return ((USHORT)Checksum == ((Octet[6] << 8) | Octet[7])); 879 } 880 881 static 882 CODE_SEG("PAGE") 883 BOOLEAN 884 SRomReadMacAddress( 885 _In_ PDC21X4_ADAPTER Adapter, 886 _In_ PUCHAR SRom, 887 _Out_opt_ PULONG AddressOffset) 888 { 889 ULONG MacOffset; 890 891 PAGED_CODE(); 892 893 /* Check if we have a board with an old EAR format */ 894 if (NdisEqualMemory(SRom, &SRom[16], 8)) 895 { 896 /* Validate the EAR checksum */ 897 if (!AddressRomChecksumValid(SRom)) 898 { 899 ERR("EAR has an invalid checksum\n"); 900 return FALSE; 901 } 902 903 MacOffset = 0; 904 goto ReadMac; 905 } 906 907 /* Check for a new SROM format */ 908 if (Adapter->ChipType != DC21040) 909 { 910 /* Validate the SROM checksum */ 911 if (SRomChecksumValid(SRom)) 912 { 913 MacOffset = SROM_MAC_ADDRESS; 914 goto ReadMac; 915 } 916 } 917 918 /* Sanity check */ 919 if (*(PULONG)SRom == 0xFFFFFFFF || *(PULONG)SRom == 0) 920 return FALSE; 921 922 WARN("Legacy/unknown board found\n"); 923 MacOffset = 0; 924 925 ReadMac: 926 if (AddressOffset) 927 *AddressOffset = MacOffset; 928 929 NdisMoveMemory(Adapter->PermanentMacAddress, 930 &SRom[MacOffset], 931 ETH_LENGTH_OF_ADDRESS); 932 933 return TRUE; 934 } 935 936 static 937 CODE_SEG("PAGE") 938 NDIS_STATUS 939 SRomParseHeader( 940 _In_ PDC21X4_ADAPTER Adapter, 941 _In_ PUCHAR SRom, 942 _Out_ PUCHAR* InfoLeaf, 943 _Out_ PUCHAR* SRomEnd) 944 { 945 ULONG i, MacOffset, LeafOffset; 946 947 PAGED_CODE(); 948 949 if (!SRomReadMacAddress(Adapter, SRom, &MacOffset)) 950 { 951 ERR("Unable to read the MAC address\n"); 952 return NDIS_STATUS_FAILURE; 953 } 954 955 /* Assign our own fake info leaf */ 956 if (MacOffset != SROM_MAC_ADDRESS) 957 { 958 for (i = 0; SRompRepairData[i].InfoLeaf; ++i) 959 { 960 /* Check for a MAC match */ 961 if (NdisEqualMemory(SRompRepairData[i].InfoLeaf, &Adapter->PermanentMacAddress, 3)) 962 { 963 /* This check is used to distinguish Accton EN1207 from Maxtech */ 964 if ((Adapter->PermanentMacAddress[0] == 0xE8) && (SRom[0x1A] == 0x55)) 965 ++i; 966 967 break; 968 } 969 } 970 if (!SRompRepairData[i].InfoLeaf) 971 { 972 ERR("Non-standard SROM format, OUI %02x:%02x:%02x\n", 973 Adapter->PermanentMacAddress[0], 974 Adapter->PermanentMacAddress[1], 975 Adapter->PermanentMacAddress[2]); 976 977 return NDIS_STATUS_ADAPTER_NOT_FOUND; 978 } 979 980 *InfoLeaf = &SRompRepairData[i].InfoLeaf[3]; 981 *SRomEnd = *InfoLeaf + SRompRepairData[i].Length; 982 983 /* Update the base address on multiport boards */ 984 Adapter->PermanentMacAddress[5] += Adapter->ControllerIndex; 985 986 #if DBG 987 WARN("Non-standard SROM format, using '%s' info leaf\n", SRompRepairData[i].Name); 988 #endif 989 return STATUS_SUCCESS; 990 } 991 992 /* Check if the SROM chip is shared between multiple controllers on a multiport board */ 993 if (SRom[SROM_CONTROLLER_COUNT] > 1) 994 { 995 INFO("Multiport board, controller number %u (%u/%u)\n", 996 Adapter->DeviceNumber, 997 Adapter->ControllerIndex + 1, 998 SRom[SROM_CONTROLLER_COUNT]); 999 1000 for (i = 0; i < SRom[SROM_CONTROLLER_COUNT]; ++i) 1001 { 1002 if (SROM_DEVICE_NUMBER(i) >= EE_SIZE) 1003 return NDIS_STATUS_BUFFER_OVERFLOW; 1004 1005 if (SRom[SROM_DEVICE_NUMBER(i)] == Adapter->DeviceNumber) 1006 break; 1007 } 1008 if (i == SRom[SROM_CONTROLLER_COUNT]) 1009 { 1010 ERR("Controller %u was not found in the SROM\n", Adapter->DeviceNumber); 1011 return NDIS_STATUS_ADAPTER_NOT_FOUND; 1012 } 1013 1014 if (SROM_LEAF_OFFSET(i) >= EE_SIZE) 1015 return NDIS_STATUS_BUFFER_OVERFLOW; 1016 1017 /* Update the base address */ 1018 Adapter->PermanentMacAddress[5] += i; 1019 } 1020 else 1021 { 1022 i = 0; 1023 } 1024 1025 /* Controller info block offset */ 1026 LeafOffset = DcRetrieveWord(SRom + SROM_LEAF_OFFSET(i)); 1027 if (LeafOffset > (EE_SIZE - sizeof(DC_SROM_COMPACT_BLOCK))) 1028 return NDIS_STATUS_BUFFER_OVERFLOW; 1029 1030 /* Controller info leaf */ 1031 *InfoLeaf = &SRom[LeafOffset]; 1032 1033 *SRomEnd = SRom + EE_SIZE; 1034 1035 return STATUS_SUCCESS; 1036 } 1037 1038 static 1039 CODE_SEG("PAGE") 1040 NDIS_STATUS 1041 SRomParse( 1042 _In_ PDC21X4_ADAPTER Adapter, 1043 _In_ PUCHAR SRom) 1044 { 1045 ULONG Index, BlockCount, BlockSize, DefaultMedia; 1046 NDIS_STATUS Status; 1047 USHORT GpioCtrl; 1048 PUCHAR Data, SRomEnd; 1049 1050 PAGED_CODE(); 1051 1052 INFO("SROM Version %u, Controller count %u\n", 1053 SRom[SROM_VERSION], 1054 SRom[SROM_CONTROLLER_COUNT]); 1055 1056 Status = SRomParseHeader(Adapter, SRom, &Data, &SRomEnd); 1057 if (Status != NDIS_STATUS_SUCCESS) 1058 return Status; 1059 1060 DefaultMedia = DcRetrieveWord(Data); 1061 Data += sizeof(USHORT); 1062 1063 INFO("Default Media: %04lx\n", DefaultMedia); 1064 1065 /* Direction of the GPIO pins */ 1066 if (Adapter->ChipType == DC21140) 1067 { 1068 GpioCtrl = *Data++; 1069 1070 INFO("GPIO Direction: %04lx\n", GpioCtrl); 1071 1072 GpioCtrl |= DC_GPIO_CONTROL; 1073 1074 for (Index = 0; Index < MEDIA_LIST_MAX; ++Index) 1075 { 1076 Adapter->Media[Index].GpioCtrl = GpioCtrl; 1077 } 1078 1079 /* Control word for block type 1 */ 1080 Adapter->MiiMedia.SetupStream[0] = GpioCtrl; 1081 } 1082 1083 BlockCount = *Data++; 1084 1085 INFO("Block Count: %u\n", BlockCount); 1086 1087 if (BlockCount == 0 || BlockCount == 0xFF) 1088 { 1089 WARN("No media information found\n"); 1090 return NDIS_STATUS_SUCCESS; 1091 } 1092 1093 /* Analyze and decode blocks */ 1094 for (Index = 0; Index < BlockCount; ++Index) 1095 { 1096 if (Adapter->ChipType == DC21041) 1097 { 1098 Status = SRomParse21041Block(Adapter, SRomEnd, Data, &BlockSize); 1099 } 1100 else 1101 { 1102 if (Data > (SRomEnd - 1)) 1103 return NDIS_STATUS_BUFFER_OVERFLOW; 1104 1105 if (SRomIsBlockExtended(*Data)) 1106 { 1107 Status = SRomParseExtendedBlock(Adapter, SRomEnd, Data, &BlockSize); 1108 } 1109 else 1110 { 1111 Status = SRomDecodeBlockGpr(Adapter, SRomEnd, Data); 1112 BlockSize = 4; 1113 } 1114 } 1115 if (Status != NDIS_STATUS_SUCCESS) 1116 return Status; 1117 1118 Data += BlockSize; 1119 } 1120 1121 if ((Adapter->MediaBitmap == 0) && !(Adapter->Features & DC_HAS_MII)) 1122 { 1123 WARN("No media information found\n"); 1124 } 1125 1126 return NDIS_STATUS_SUCCESS; 1127 } 1128 1129 static 1130 CODE_SEG("PAGE") 1131 VOID 1132 SRomShiftOut( 1133 _In_ PDC21X4_ADAPTER Adapter, 1134 _In_ ULONG Sequence, 1135 _In_ ULONG BitCount) 1136 { 1137 LONG i; 1138 1139 PAGED_CODE(); 1140 1141 for (i = BitCount - 1; i >= 0; --i) 1142 { 1143 ULONG DataIn = ((Sequence >> i) & 1) << DC_SERIAL_EE_DI_SHIFT; 1144 1145 SROM_WRITE(Adapter, DataIn | DC_SERIAL_EE_RD | DC_SERIAL_EE_SR | DC_SERIAL_EE_CS); 1146 SROM_WRITE(Adapter, DataIn | DC_SERIAL_EE_RD | DC_SERIAL_EE_SR | DC_SERIAL_EE_CS | 1147 DC_SERIAL_EE_SK); 1148 SROM_WRITE(Adapter, DataIn | DC_SERIAL_EE_RD | DC_SERIAL_EE_SR | DC_SERIAL_EE_CS); 1149 } 1150 } 1151 1152 static 1153 CODE_SEG("PAGE") 1154 USHORT 1155 SRomShiftIn( 1156 _In_ PDC21X4_ADAPTER Adapter) 1157 { 1158 ULONG i, Csr; 1159 USHORT SerialData; 1160 1161 PAGED_CODE(); 1162 1163 /* Shift the data out of the EEPROM */ 1164 SerialData = 0; 1165 for (i = 0; i < RTL_BITS_OF(USHORT); ++i) 1166 { 1167 SROM_WRITE(Adapter, DC_SERIAL_EE_RD | DC_SERIAL_EE_SR | DC_SERIAL_EE_CS | DC_SERIAL_EE_SK); 1168 1169 SROM_READ(Adapter, &Csr); 1170 SerialData = (SerialData << 1) | ((Csr >> DC_SERIAL_EE_DO_SHIFT) & 1); 1171 1172 SROM_WRITE(Adapter, DC_SERIAL_EE_RD | DC_SERIAL_EE_SR | DC_SERIAL_EE_CS); 1173 } 1174 1175 /* End the read cycle */ 1176 SROM_WRITE(Adapter, DC_SERIAL_EE_RD | DC_SERIAL_EE_SR); 1177 1178 return SerialData; 1179 } 1180 1181 static 1182 CODE_SEG("PAGE") 1183 ULONG 1184 SRomDetectAddressBusWidth( 1185 _In_ PDC21X4_ADAPTER Adapter) 1186 { 1187 ULONG Csr, BusWidth; 1188 1189 PAGED_CODE(); 1190 1191 /* Assume the SROM is a 1kB ROM, send the read command and zero address (6 bits) */ 1192 SRomShiftOut(Adapter, EEPROM_CMD_READ << 6, EEPROM_CMD_LENGTH + 6); 1193 1194 /* Check the preceding dummy zero bit */ 1195 Csr = DC_READ(Adapter, DcCsr9_SerialInterface); 1196 if (Csr & DC_SERIAL_EE_DO) 1197 { 1198 /* 4kB EEPROM */ 1199 BusWidth = 8; 1200 1201 /* Send the remaining part of the address */ 1202 SRomShiftOut(Adapter, 0, 8 - 6); 1203 1204 /* The preceding dummy bit must be zero */ 1205 Csr = DC_READ(Adapter, DcCsr9_SerialInterface); 1206 if (Csr & DC_SERIAL_EE_DO) 1207 return 0; 1208 } 1209 else 1210 { 1211 /* 1kB EEPROM */ 1212 BusWidth = 6; 1213 } 1214 1215 /* Complete the read cycle */ 1216 (VOID)SRomShiftIn(Adapter); 1217 1218 return BusWidth; 1219 } 1220 1221 static 1222 CODE_SEG("PAGE") 1223 BOOLEAN 1224 SRomReadSRom( 1225 _In_ PDC21X4_ADAPTER Adapter, 1226 _Out_writes_all_(EE_SIZE) PVOID SRom) 1227 { 1228 PUSHORT SRomWord = SRom; 1229 BOOLEAN Success = TRUE; 1230 ULONG BusWidth, Address; 1231 1232 PAGED_CODE(); 1233 1234 /* Select the device */ 1235 SROM_WRITE(Adapter, DC_SERIAL_EE_RD | DC_SERIAL_EE_SR); 1236 SROM_WRITE(Adapter, DC_SERIAL_EE_RD | DC_SERIAL_EE_SR | DC_SERIAL_EE_CS); 1237 1238 BusWidth = SRomDetectAddressBusWidth(Adapter); 1239 if (BusWidth == 0) 1240 { 1241 Success = FALSE; 1242 goto Done; 1243 } 1244 INFO("SROM Bus width: %u\n", BusWidth); 1245 1246 /* Read the SROM contents once */ 1247 for (Address = 0; Address < (EE_SIZE / sizeof(USHORT)); ++Address) 1248 { 1249 /* Send the command and address */ 1250 SRomShiftOut(Adapter, 1251 (EEPROM_CMD_READ << BusWidth) | Address, 1252 EEPROM_CMD_LENGTH + BusWidth); 1253 1254 /* Read the data */ 1255 SRomWord[Address] = SRomShiftIn(Adapter); 1256 } 1257 1258 Done: 1259 /* End chip select */ 1260 DC_WRITE(Adapter, DcCsr9_SerialInterface, 0); 1261 1262 return Success; 1263 } 1264 1265 #if DBG 1266 static 1267 CODE_SEG("PAGE") 1268 VOID 1269 SRomDumpContents( 1270 _In_reads_bytes_(Length) const VOID* Buffer, 1271 _In_ ULONG Length) 1272 { 1273 ULONG Offset, Count, i; 1274 const UCHAR* Data = Buffer; 1275 1276 PAGED_CODE(); 1277 1278 DbgPrint("SROM data:\n"); 1279 1280 Offset = 0; 1281 while (Offset < Length) 1282 { 1283 DbgPrint("%04x:\t", Offset); 1284 1285 Count = min(Length - Offset, 16); 1286 for (i = 0; i < Count; ++i, ++Offset) 1287 { 1288 DbgPrint("0x%02x, ", Data[Offset], (i == 7) ? '-' : ' '); 1289 } 1290 1291 DbgPrint("\n"); 1292 } 1293 } 1294 #endif // DBG 1295 1296 static 1297 CODE_SEG("PAGE") 1298 NDIS_STATUS 1299 SRomRead( 1300 _In_ PDC21X4_ADAPTER Adapter) 1301 { 1302 PDC_SROM_ENTRY SRomEntry; 1303 NDIS_STATUS Status; 1304 BOOLEAN ReleaseImage; 1305 1306 PAGED_CODE(); 1307 1308 Status = NdisAllocateMemoryWithTag((PVOID*)&SRomEntry, 1309 FIELD_OFFSET(DC_SROM_ENTRY, SRomImage[EE_SIZE]), 1310 DC21X4_TAG); 1311 if (Status != NDIS_STATUS_SUCCESS) 1312 return NDIS_STATUS_RESOURCES; 1313 NdisZeroMemory(SRomEntry, FIELD_OFFSET(DC_SROM_ENTRY, SRomImage)); 1314 1315 ReleaseImage = FALSE; 1316 1317 if (SRomReadSRom(Adapter, SRomEntry->SRomImage)) 1318 { 1319 if (!SRomRegisterMasterAdapter(Adapter, SRomEntry)) 1320 ReleaseImage = TRUE; 1321 } 1322 else 1323 { 1324 NdisFreeMemory(SRomEntry, 0, 0); 1325 1326 if (!SRomFindMasterAdapter(Adapter, &SRomEntry)) 1327 { 1328 ERR("Failed to retrieve the SROM contents\n"); 1329 return NDIS_STATUS_FAILURE; 1330 } 1331 } 1332 1333 Status = SRomParse(Adapter, SRomEntry->SRomImage); 1334 if (Status != NDIS_STATUS_SUCCESS) 1335 { 1336 ERR("Failed to parse SROM\n"); 1337 } 1338 1339 #if DBG 1340 if (Status != NDIS_STATUS_SUCCESS) 1341 SRomDumpContents(SRomEntry->SRomImage, EE_SIZE); 1342 #endif 1343 1344 if (ReleaseImage) 1345 NdisFreeMemory(SRomEntry, 0, 0); 1346 1347 return Status; 1348 } 1349 1350 static 1351 CODE_SEG("PAGE") 1352 BOOLEAN 1353 AddressRomReadData( 1354 _In_ PDC21X4_ADAPTER Adapter, 1355 _Out_writes_all_(EAR_SIZE) PUCHAR AddressRom) 1356 { 1357 ULONG Data, i, j; 1358 1359 PAGED_CODE(); 1360 1361 /* Reset the ROM pointer */ 1362 DC_WRITE(Adapter, DcCsr9_SerialInterface, 0); 1363 1364 for (i = 0; i < EAR_SIZE; ++i) 1365 { 1366 for (j = 10000; j > 0; --j) 1367 { 1368 NdisStallExecution(1); 1369 Data = DC_READ(Adapter, DcCsr9_SerialInterface); 1370 1371 if (!(Data & DC_SERIAL_EAR_DN)) 1372 break; 1373 } 1374 AddressRom[i] = Data & DC_SERIAL_EAR_DT; 1375 } 1376 1377 if (SRomIsEmpty(AddressRom, EAR_SIZE)) 1378 return FALSE; 1379 1380 return TRUE; 1381 } 1382 1383 static 1384 CODE_SEG("PAGE") 1385 NDIS_STATUS 1386 AddressRomRead( 1387 _In_ PDC21X4_ADAPTER Adapter) 1388 { 1389 PDC_SROM_ENTRY SRomEntry; 1390 NDIS_STATUS Status; 1391 BOOLEAN ReleaseImage; 1392 1393 PAGED_CODE(); 1394 1395 Status = NdisAllocateMemoryWithTag((PVOID*)&SRomEntry, 1396 FIELD_OFFSET(DC_SROM_ENTRY, SRomImage[EAR_SIZE]), 1397 DC21X4_TAG); 1398 if (Status != NDIS_STATUS_SUCCESS) 1399 return NDIS_STATUS_RESOURCES; 1400 NdisZeroMemory(SRomEntry, FIELD_OFFSET(DC_SROM_ENTRY, SRomImage)); 1401 1402 ReleaseImage = FALSE; 1403 1404 if (AddressRomReadData(Adapter, SRomEntry->SRomImage)) 1405 { 1406 if (!SRomRegisterMasterAdapter(Adapter, SRomEntry)) 1407 ReleaseImage = TRUE; 1408 } 1409 else 1410 { 1411 NdisFreeMemory(SRomEntry, 0, 0); 1412 1413 if (!SRomFindMasterAdapter(Adapter, &SRomEntry)) 1414 { 1415 ERR("Failed to retrieve the EAR contents\n"); 1416 return NDIS_STATUS_FAILURE; 1417 } 1418 } 1419 1420 if (!SRomReadMacAddress(Adapter, SRomEntry->SRomImage, NULL)) 1421 { 1422 ERR("Unable to read the MAC address\n"); 1423 Status = NDIS_STATUS_FAILURE; 1424 } 1425 1426 /* Update the base address on multiport boards */ 1427 Adapter->PermanentMacAddress[5] += Adapter->ControllerIndex; 1428 1429 #if DBG 1430 if (Status != NDIS_STATUS_SUCCESS) 1431 SRomDumpContents(SRomEntry->SRomImage, EAR_SIZE); 1432 #endif 1433 1434 if (ReleaseImage) 1435 NdisFreeMemory(SRomEntry, 0, 0); 1436 1437 return Status; 1438 } 1439 1440 /* PUBLIC FUNCTIONS ***********************************************************/ 1441 1442 CODE_SEG("PAGE") 1443 VOID 1444 DcFreeEeprom( 1445 _In_ PDC21X4_ADAPTER Adapter) 1446 { 1447 PDC_SROM_ENTRY SRomEntry; 1448 1449 PAGED_CODE(); 1450 1451 SRomEntry = Adapter->SRomEntry; 1452 if (!SRomEntry) 1453 return; 1454 1455 SRomAcquireListMutex(); 1456 1457 /* Unregister the port */ 1458 SRomEntry->DeviceBitmap &= ~(1 << Adapter->DeviceNumber); 1459 1460 /* 1461 * Free the SROM as soon as the last registered port has removed. 1462 * We can't free it in an unload handler 1463 * as the bus numbers can be changed by a resource rebalance. 1464 */ 1465 if (SRomEntry->DeviceBitmap == 0) 1466 { 1467 INFO("Freeing SROM %p at %u:%u\n", 1468 SRomEntry, 1469 SRomEntry->BusNumber, 1470 SRomEntry->DeviceNumber); 1471 1472 RemoveEntryList(&SRomEntry->ListEntry); 1473 1474 NdisFreeMemory(SRomEntry, 0, 0); 1475 } 1476 1477 SRomReleaseListMutex(); 1478 } 1479 1480 CODE_SEG("PAGE") 1481 NDIS_STATUS 1482 DcReadEeprom( 1483 _In_ PDC21X4_ADAPTER Adapter) 1484 { 1485 NDIS_STATUS Status; 1486 1487 PAGED_CODE(); 1488 1489 if (Adapter->ChipType == DC21040) 1490 { 1491 /* Ethernet Address ROM */ 1492 Status = AddressRomRead(Adapter); 1493 } 1494 else 1495 { 1496 /* MicroWire Compatible Serial EEPROM */ 1497 Status = SRomRead(Adapter); 1498 } 1499 1500 if (Status != NDIS_STATUS_SUCCESS) 1501 return Status; 1502 1503 INFO("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", 1504 Adapter->PermanentMacAddress[0], 1505 Adapter->PermanentMacAddress[1], 1506 Adapter->PermanentMacAddress[2], 1507 Adapter->PermanentMacAddress[3], 1508 Adapter->PermanentMacAddress[4], 1509 Adapter->PermanentMacAddress[5]); 1510 1511 if (ETH_IS_BROADCAST(Adapter->PermanentMacAddress) || 1512 ETH_IS_EMPTY(Adapter->PermanentMacAddress) || 1513 ETH_IS_MULTICAST(Adapter->PermanentMacAddress)) 1514 { 1515 ERR("Invalid permanent MAC address %02x:%02x:%02x:%02x:%02x:%02x\n", 1516 Adapter->PermanentMacAddress[0], 1517 Adapter->PermanentMacAddress[1], 1518 Adapter->PermanentMacAddress[2], 1519 Adapter->PermanentMacAddress[3], 1520 Adapter->PermanentMacAddress[4], 1521 Adapter->PermanentMacAddress[5]); 1522 1523 NdisWriteErrorLogEntry(Adapter->AdapterHandle, NDIS_ERROR_CODE_NETWORK_ADDRESS, 0); 1524 1525 return NDIS_STATUS_INVALID_ADDRESS; 1526 } 1527 1528 return NDIS_STATUS_SUCCESS; 1529 } 1530