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 NdisMoveMemory(&TestPatterm, &Octet[24], 8); 863 if (TestPatterm != EAR_TEST_PATTERN) 864 return FALSE; 865 866 for (i = 0; i < 8; ++i) 867 { 868 if (Octet[i] != Octet[15 - i]) 869 return FALSE; 870 } 871 872 Checksum = (Octet[0] << 10) + (Octet[2] << 9) + (Octet[4] << 8) + 873 (Octet[1] << 2) + (Octet[3] << 1) + Octet[5]; 874 Checksum %= 0xFFFF; 875 876 return ((USHORT)Checksum == ((Octet[6] << 8) | Octet[7])); 877 } 878 879 static 880 CODE_SEG("PAGE") 881 BOOLEAN 882 SRomReadMacAddress( 883 _In_ PDC21X4_ADAPTER Adapter, 884 _In_ PUCHAR SRom, 885 _Out_opt_ PULONG AddressOffset) 886 { 887 ULONG MacOffset; 888 889 /* Check if we have a board with an old EAR format */ 890 if (NdisEqualMemory(SRom, &SRom[16], 8)) 891 { 892 /* Validate the EAR checksum */ 893 if (!AddressRomChecksumValid(SRom)) 894 { 895 ERR("EAR has an invalid checksum\n"); 896 return FALSE; 897 } 898 899 MacOffset = 0; 900 goto ReadMac; 901 } 902 903 /* Check for a new SROM format */ 904 if (Adapter->ChipType != DC21040) 905 { 906 /* Validate the SROM checksum */ 907 if (SRomChecksumValid(SRom)) 908 { 909 MacOffset = SROM_MAC_ADDRESS; 910 goto ReadMac; 911 } 912 } 913 914 /* Sanity check */ 915 if (*(PULONG)SRom == 0xFFFFFFF || *(PULONG)SRom == 0) 916 return FALSE; 917 918 WARN("Legacy/unknown board found\n"); 919 MacOffset = 0; 920 921 ReadMac: 922 if (AddressOffset) 923 *AddressOffset = MacOffset; 924 925 NdisMoveMemory(Adapter->PermanentMacAddress, 926 &SRom[MacOffset], 927 ETH_LENGTH_OF_ADDRESS); 928 929 return TRUE; 930 } 931 932 static 933 CODE_SEG("PAGE") 934 NDIS_STATUS 935 SRomParseHeader( 936 _In_ PDC21X4_ADAPTER Adapter, 937 _In_ PUCHAR SRom, 938 _Out_ PUCHAR* InfoLeaf, 939 _Out_ PUCHAR* SRomEnd) 940 { 941 ULONG i, MacOffset, LeafOffset; 942 943 PAGED_CODE(); 944 945 if (!SRomReadMacAddress(Adapter, SRom, &MacOffset)) 946 { 947 ERR("Unable to read the MAC address\n"); 948 return NDIS_STATUS_FAILURE; 949 } 950 951 /* Assign our own fake info leaf */ 952 if (MacOffset != SROM_MAC_ADDRESS) 953 { 954 for (i = 0; SRompRepairData[i].InfoLeaf; ++i) 955 { 956 /* Check for a MAC match */ 957 if (NdisEqualMemory(SRompRepairData[i].InfoLeaf, &Adapter->PermanentMacAddress, 3)) 958 { 959 /* This check is used to distinguish Accton EN1207 from Maxtech */ 960 if ((Adapter->PermanentMacAddress[0] == 0xE8) && (SRom[0x1A] == 0x55)) 961 ++i; 962 963 break; 964 } 965 } 966 if (!SRompRepairData[i].InfoLeaf) 967 { 968 ERR("Non-standard SROM format, OUI %02x:%02x:%02x\n", 969 Adapter->PermanentMacAddress[0], 970 Adapter->PermanentMacAddress[1], 971 Adapter->PermanentMacAddress[2]); 972 973 return NDIS_STATUS_ADAPTER_NOT_FOUND; 974 } 975 976 *InfoLeaf = &SRompRepairData[i].InfoLeaf[3]; 977 *SRomEnd = *InfoLeaf + SRompRepairData[i].Length; 978 979 /* Update the base address on multiport boards */ 980 Adapter->PermanentMacAddress[5] += Adapter->ControllerIndex; 981 982 #if DBG 983 WARN("Non-standard SROM format, using '%s' info leaf\n", SRompRepairData[i].Name); 984 #endif 985 return STATUS_SUCCESS; 986 } 987 988 /* Check if the SROM chip is shared between multiple controllers on a multiport board */ 989 if (SRom[SROM_CONTROLLER_COUNT] > 1) 990 { 991 INFO("Multiport board, controller number %u (%u/%u)\n", 992 Adapter->DeviceNumber, 993 Adapter->ControllerIndex + 1, 994 SRom[SROM_CONTROLLER_COUNT]); 995 996 for (i = 0; i < SRom[SROM_CONTROLLER_COUNT]; ++i) 997 { 998 if (SROM_DEVICE_NUMBER(i) >= EE_SIZE) 999 return NDIS_STATUS_BUFFER_OVERFLOW; 1000 1001 if (SRom[SROM_DEVICE_NUMBER(i)] == Adapter->DeviceNumber) 1002 break; 1003 } 1004 if (i == SRom[SROM_CONTROLLER_COUNT]) 1005 { 1006 ERR("Controller %u was not found in the SROM\n", Adapter->DeviceNumber); 1007 return NDIS_STATUS_ADAPTER_NOT_FOUND; 1008 } 1009 1010 if (SROM_LEAF_OFFSET(i) >= EE_SIZE) 1011 return NDIS_STATUS_BUFFER_OVERFLOW; 1012 1013 /* Update the base address */ 1014 Adapter->PermanentMacAddress[5] += i; 1015 } 1016 else 1017 { 1018 i = 0; 1019 } 1020 1021 /* Controller info block offset */ 1022 LeafOffset = DcRetrieveWord(SRom + SROM_LEAF_OFFSET(i)); 1023 if (LeafOffset > (EE_SIZE - sizeof(DC_SROM_COMPACT_BLOCK))) 1024 return NDIS_STATUS_BUFFER_OVERFLOW; 1025 1026 /* Controller info leaf */ 1027 *InfoLeaf = &SRom[LeafOffset]; 1028 1029 *SRomEnd = SRom + EE_SIZE; 1030 1031 return STATUS_SUCCESS; 1032 } 1033 1034 static 1035 CODE_SEG("PAGE") 1036 NDIS_STATUS 1037 SRomParse( 1038 _In_ PDC21X4_ADAPTER Adapter, 1039 _In_ PUCHAR SRom) 1040 { 1041 ULONG Index, BlockCount, BlockSize, DefaultMedia; 1042 NDIS_STATUS Status; 1043 USHORT GpioCtrl; 1044 PUCHAR Data, SRomEnd; 1045 1046 PAGED_CODE(); 1047 1048 INFO("SROM Version %u, Controller count %u\n", 1049 SRom[SROM_VERSION], 1050 SRom[SROM_CONTROLLER_COUNT]); 1051 1052 Status = SRomParseHeader(Adapter, SRom, &Data, &SRomEnd); 1053 if (Status != NDIS_STATUS_SUCCESS) 1054 return Status; 1055 1056 DefaultMedia = DcRetrieveWord(Data); 1057 Data += sizeof(USHORT); 1058 1059 INFO("Default Media: %04lx\n", DefaultMedia); 1060 1061 /* Direction of the GPIO pins */ 1062 if (Adapter->ChipType == DC21140) 1063 { 1064 GpioCtrl = *Data++; 1065 1066 INFO("GPIO Direction: %04lx\n", GpioCtrl); 1067 1068 GpioCtrl |= DC_GPIO_CONTROL; 1069 1070 for (Index = 0; Index < MEDIA_LIST_MAX; ++Index) 1071 { 1072 Adapter->Media[Index].GpioCtrl = GpioCtrl; 1073 } 1074 1075 /* Control word for block type 1 */ 1076 Adapter->MiiMedia.SetupStream[0] = GpioCtrl; 1077 } 1078 1079 BlockCount = *Data++; 1080 1081 INFO("Block Count: %u\n", BlockCount); 1082 1083 if (BlockCount == 0 || BlockCount == 0xFF) 1084 { 1085 WARN("No media information found\n"); 1086 return NDIS_STATUS_SUCCESS; 1087 } 1088 1089 /* Analyze and decode blocks */ 1090 for (Index = 0; Index < BlockCount; ++Index) 1091 { 1092 if (Adapter->ChipType == DC21041) 1093 { 1094 Status = SRomParse21041Block(Adapter, SRomEnd, Data, &BlockSize); 1095 } 1096 else 1097 { 1098 if (Data > (SRomEnd - 1)) 1099 return NDIS_STATUS_BUFFER_OVERFLOW; 1100 1101 if (SRomIsBlockExtended(*Data)) 1102 { 1103 Status = SRomParseExtendedBlock(Adapter, SRomEnd, Data, &BlockSize); 1104 } 1105 else 1106 { 1107 Status = SRomDecodeBlockGpr(Adapter, SRomEnd, Data); 1108 BlockSize = 4; 1109 } 1110 } 1111 if (Status != NDIS_STATUS_SUCCESS) 1112 return Status; 1113 1114 Data += BlockSize; 1115 } 1116 1117 if ((Adapter->MediaBitmap == 0) && !(Adapter->Features & DC_HAS_MII)) 1118 { 1119 WARN("No media information found\n"); 1120 } 1121 1122 return NDIS_STATUS_SUCCESS; 1123 } 1124 1125 static 1126 CODE_SEG("PAGE") 1127 VOID 1128 SRomShiftOut( 1129 _In_ PDC21X4_ADAPTER Adapter, 1130 _In_ ULONG Sequence, 1131 _In_ ULONG BitCount) 1132 { 1133 LONG i; 1134 1135 PAGED_CODE(); 1136 1137 for (i = BitCount - 1; i >= 0; --i) 1138 { 1139 ULONG DataIn = ((Sequence >> i) & 1) << DC_SERIAL_EE_DI_SHIFT; 1140 1141 SROM_WRITE(Adapter, DataIn | DC_SERIAL_EE_RD | DC_SERIAL_EE_SR | DC_SERIAL_EE_CS); 1142 SROM_WRITE(Adapter, DataIn | DC_SERIAL_EE_RD | DC_SERIAL_EE_SR | DC_SERIAL_EE_CS | 1143 DC_SERIAL_EE_SK); 1144 SROM_WRITE(Adapter, DataIn | DC_SERIAL_EE_RD | DC_SERIAL_EE_SR | DC_SERIAL_EE_CS); 1145 } 1146 } 1147 1148 static 1149 CODE_SEG("PAGE") 1150 USHORT 1151 SRomShiftIn( 1152 _In_ PDC21X4_ADAPTER Adapter) 1153 { 1154 ULONG i, Csr; 1155 USHORT SerialData; 1156 1157 PAGED_CODE(); 1158 1159 /* Shift the data out of the EEPROM */ 1160 SerialData = 0; 1161 for (i = 0; i < RTL_BITS_OF(USHORT); ++i) 1162 { 1163 SROM_WRITE(Adapter, DC_SERIAL_EE_RD | DC_SERIAL_EE_SR | DC_SERIAL_EE_CS | DC_SERIAL_EE_SK); 1164 1165 SROM_READ(Adapter, &Csr); 1166 SerialData = (SerialData << 1) | ((Csr >> DC_SERIAL_EE_DO_SHIFT) & 1); 1167 1168 SROM_WRITE(Adapter, DC_SERIAL_EE_RD | DC_SERIAL_EE_SR | DC_SERIAL_EE_CS); 1169 } 1170 1171 /* End the read cycle */ 1172 SROM_WRITE(Adapter, DC_SERIAL_EE_RD | DC_SERIAL_EE_SR); 1173 1174 return SerialData; 1175 } 1176 1177 static 1178 CODE_SEG("PAGE") 1179 ULONG 1180 SRomDetectAddressBusWidth( 1181 _In_ PDC21X4_ADAPTER Adapter) 1182 { 1183 ULONG Csr, BusWidth; 1184 1185 PAGED_CODE(); 1186 1187 /* Assume the SROM is a 1kB ROM, send the read command and zero address (6 bits) */ 1188 SRomShiftOut(Adapter, EEPROM_CMD_READ << 6, EEPROM_CMD_LENGTH + 6); 1189 1190 /* Check the preceding dummy zero bit */ 1191 Csr = DC_READ(Adapter, DcCsr9_SerialInterface); 1192 if (Csr & DC_SERIAL_EE_DO) 1193 { 1194 /* 4kB EEPROM */ 1195 BusWidth = 8; 1196 1197 /* Send the remaining part of the address */ 1198 SRomShiftOut(Adapter, 0, 8 - 6); 1199 1200 /* The preceding dummy bit must be zero */ 1201 Csr = DC_READ(Adapter, DcCsr9_SerialInterface); 1202 if (Csr & DC_SERIAL_EE_DO) 1203 return 0; 1204 } 1205 else 1206 { 1207 /* 1kB EEPROM */ 1208 BusWidth = 6; 1209 } 1210 1211 /* Complete the read cycle */ 1212 (VOID)SRomShiftIn(Adapter); 1213 1214 return BusWidth; 1215 } 1216 1217 static 1218 CODE_SEG("PAGE") 1219 BOOLEAN 1220 SRomReadSRom( 1221 _In_ PDC21X4_ADAPTER Adapter, 1222 _Out_writes_all_(EE_SIZE) PVOID SRom) 1223 { 1224 PUSHORT SRomWord = SRom; 1225 BOOLEAN Success = TRUE; 1226 ULONG BusWidth, Address; 1227 1228 PAGED_CODE(); 1229 1230 /* Select the device */ 1231 SROM_WRITE(Adapter, DC_SERIAL_EE_RD | DC_SERIAL_EE_SR); 1232 SROM_WRITE(Adapter, DC_SERIAL_EE_RD | DC_SERIAL_EE_SR | DC_SERIAL_EE_CS); 1233 1234 BusWidth = SRomDetectAddressBusWidth(Adapter); 1235 if (BusWidth == 0) 1236 { 1237 Success = FALSE; 1238 goto Done; 1239 } 1240 INFO("SROM Bus width: %u\n", BusWidth); 1241 1242 /* Read the SROM contents once */ 1243 for (Address = 0; Address < (EE_SIZE / sizeof(USHORT)); ++Address) 1244 { 1245 /* Send the command and address */ 1246 SRomShiftOut(Adapter, 1247 (EEPROM_CMD_READ << BusWidth) | Address, 1248 EEPROM_CMD_LENGTH + BusWidth); 1249 1250 /* Read the data */ 1251 SRomWord[Address] = SRomShiftIn(Adapter); 1252 } 1253 1254 Done: 1255 /* End chip select */ 1256 DC_WRITE(Adapter, DcCsr9_SerialInterface, 0); 1257 1258 return Success; 1259 } 1260 1261 #if DBG 1262 static 1263 CODE_SEG("PAGE") 1264 VOID 1265 SRomDumpContents( 1266 _In_reads_bytes_(Length) const VOID* Buffer, 1267 _In_ ULONG Length) 1268 { 1269 ULONG Offset, Count, i; 1270 const UCHAR* Data = Buffer; 1271 1272 PAGED_CODE(); 1273 1274 DbgPrint("SROM data:\n"); 1275 1276 Offset = 0; 1277 while (Offset < Length) 1278 { 1279 DbgPrint("%04x:\t", Offset); 1280 1281 Count = min(Length - Offset, 16); 1282 for (i = 0; i < Count; ++i, ++Offset) 1283 { 1284 DbgPrint("0x%02x, ", Data[Offset], (i == 7) ? '-' : ' '); 1285 } 1286 1287 DbgPrint("\n"); 1288 } 1289 } 1290 #endif // DBG 1291 1292 static 1293 CODE_SEG("PAGE") 1294 NDIS_STATUS 1295 SRomRead( 1296 _In_ PDC21X4_ADAPTER Adapter) 1297 { 1298 PDC_SROM_ENTRY SRomEntry; 1299 NDIS_STATUS Status; 1300 BOOLEAN ReleaseImage; 1301 1302 PAGED_CODE(); 1303 1304 Status = NdisAllocateMemoryWithTag((PVOID*)&SRomEntry, 1305 FIELD_OFFSET(DC_SROM_ENTRY, SRomImage[EE_SIZE]), 1306 DC21X4_TAG); 1307 if (Status != NDIS_STATUS_SUCCESS) 1308 return NDIS_STATUS_RESOURCES; 1309 NdisZeroMemory(SRomEntry, FIELD_OFFSET(DC_SROM_ENTRY, SRomImage)); 1310 1311 ReleaseImage = FALSE; 1312 1313 if (SRomReadSRom(Adapter, SRomEntry->SRomImage)) 1314 { 1315 if (!SRomRegisterMasterAdapter(Adapter, SRomEntry)) 1316 ReleaseImage = TRUE; 1317 } 1318 else 1319 { 1320 NdisFreeMemory(SRomEntry, 0, 0); 1321 1322 if (!SRomFindMasterAdapter(Adapter, &SRomEntry)) 1323 { 1324 ERR("Failed to retrieve the SROM contents\n"); 1325 return NDIS_STATUS_FAILURE; 1326 } 1327 } 1328 1329 Status = SRomParse(Adapter, SRomEntry->SRomImage); 1330 if (Status != NDIS_STATUS_SUCCESS) 1331 { 1332 ERR("Failed to parse SROM\n"); 1333 } 1334 1335 #if DBG 1336 if (Status != NDIS_STATUS_SUCCESS) 1337 SRomDumpContents(SRomEntry->SRomImage, EE_SIZE); 1338 #endif 1339 1340 if (ReleaseImage) 1341 NdisFreeMemory(SRomEntry, 0, 0); 1342 1343 return Status; 1344 } 1345 1346 static 1347 CODE_SEG("PAGE") 1348 BOOLEAN 1349 AddressRomReadData( 1350 _In_ PDC21X4_ADAPTER Adapter, 1351 _Out_writes_all_(EAR_SIZE) PUCHAR AddressRom) 1352 { 1353 ULONG Data, i, j; 1354 1355 PAGED_CODE(); 1356 1357 /* Reset the ROM pointer */ 1358 DC_WRITE(Adapter, DcCsr9_SerialInterface, 0); 1359 1360 for (i = 0; i < EAR_SIZE; ++i) 1361 { 1362 for (j = 10000; j > 0; --j) 1363 { 1364 NdisStallExecution(1); 1365 Data = DC_READ(Adapter, DcCsr9_SerialInterface); 1366 1367 if (!(Data & DC_SERIAL_EAR_DN)) 1368 break; 1369 } 1370 AddressRom[i] = Data & DC_SERIAL_EAR_DT; 1371 } 1372 1373 if (SRomIsEmpty(AddressRom, EAR_SIZE)) 1374 return FALSE; 1375 1376 return TRUE; 1377 } 1378 1379 static 1380 CODE_SEG("PAGE") 1381 NDIS_STATUS 1382 AddressRomRead( 1383 _In_ PDC21X4_ADAPTER Adapter) 1384 { 1385 PDC_SROM_ENTRY SRomEntry; 1386 NDIS_STATUS Status; 1387 BOOLEAN ReleaseImage; 1388 1389 PAGED_CODE(); 1390 1391 Status = NdisAllocateMemoryWithTag((PVOID*)&SRomEntry, 1392 FIELD_OFFSET(DC_SROM_ENTRY, SRomImage[EAR_SIZE]), 1393 DC21X4_TAG); 1394 if (Status != NDIS_STATUS_SUCCESS) 1395 return NDIS_STATUS_RESOURCES; 1396 NdisZeroMemory(SRomEntry, FIELD_OFFSET(DC_SROM_ENTRY, SRomImage)); 1397 1398 ReleaseImage = FALSE; 1399 1400 if (AddressRomReadData(Adapter, SRomEntry->SRomImage)) 1401 { 1402 if (!SRomRegisterMasterAdapter(Adapter, SRomEntry)) 1403 ReleaseImage = TRUE; 1404 } 1405 else 1406 { 1407 NdisFreeMemory(SRomEntry, 0, 0); 1408 1409 if (!SRomFindMasterAdapter(Adapter, &SRomEntry)) 1410 { 1411 ERR("Failed to retrieve the EAR contents\n"); 1412 return NDIS_STATUS_FAILURE; 1413 } 1414 } 1415 1416 if (!SRomReadMacAddress(Adapter, SRomEntry->SRomImage, NULL)) 1417 { 1418 ERR("Unable to read the MAC address\n"); 1419 Status = NDIS_STATUS_FAILURE; 1420 } 1421 1422 /* Update the base address on multiport boards */ 1423 Adapter->PermanentMacAddress[5] += Adapter->ControllerIndex; 1424 1425 #if DBG 1426 if (Status != NDIS_STATUS_SUCCESS) 1427 SRomDumpContents(SRomEntry->SRomImage, EAR_SIZE); 1428 #endif 1429 1430 if (ReleaseImage) 1431 NdisFreeMemory(SRomEntry, 0, 0); 1432 1433 return Status; 1434 } 1435 1436 /* PUBLIC FUNCTIONS ***********************************************************/ 1437 1438 CODE_SEG("PAGE") 1439 VOID 1440 DcFreeEeprom( 1441 _In_ PDC21X4_ADAPTER Adapter) 1442 { 1443 PDC_SROM_ENTRY SRomEntry; 1444 1445 PAGED_CODE(); 1446 1447 SRomEntry = Adapter->SRomEntry; 1448 if (!SRomEntry) 1449 return; 1450 1451 SRomAcquireListMutex(); 1452 1453 /* Unregister the port */ 1454 SRomEntry->DeviceBitmap &= ~(1 << Adapter->DeviceNumber); 1455 1456 /* 1457 * Free the SROM as soon as the last registered port has removed. 1458 * We can't free it in an unload handler 1459 * as the bus numbers can be changed by a resource rebalance. 1460 */ 1461 if (SRomEntry->DeviceBitmap == 0) 1462 { 1463 INFO("Freeing SROM %p at %u:%u\n", 1464 SRomEntry, 1465 SRomEntry->BusNumber, 1466 SRomEntry->DeviceNumber); 1467 1468 RemoveEntryList(&SRomEntry->ListEntry); 1469 1470 NdisFreeMemory(SRomEntry, 0, 0); 1471 } 1472 1473 SRomReleaseListMutex(); 1474 } 1475 1476 CODE_SEG("PAGE") 1477 NDIS_STATUS 1478 DcReadEeprom( 1479 _In_ PDC21X4_ADAPTER Adapter) 1480 { 1481 NDIS_STATUS Status; 1482 1483 PAGED_CODE(); 1484 1485 if (Adapter->ChipType == DC21040) 1486 { 1487 /* Ethernet Address ROM */ 1488 Status = AddressRomRead(Adapter); 1489 } 1490 else 1491 { 1492 /* MicroWire Compatible Serial EEPROM */ 1493 Status = SRomRead(Adapter); 1494 } 1495 1496 if (Status != NDIS_STATUS_SUCCESS) 1497 return Status; 1498 1499 INFO("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", 1500 Adapter->PermanentMacAddress[0], 1501 Adapter->PermanentMacAddress[1], 1502 Adapter->PermanentMacAddress[2], 1503 Adapter->PermanentMacAddress[3], 1504 Adapter->PermanentMacAddress[4], 1505 Adapter->PermanentMacAddress[5]); 1506 1507 if (ETH_IS_BROADCAST(Adapter->PermanentMacAddress) || 1508 ETH_IS_EMPTY(Adapter->PermanentMacAddress) || 1509 ETH_IS_MULTICAST(Adapter->PermanentMacAddress)) 1510 { 1511 ERR("Invalid permanent MAC address %02x:%02x:%02x:%02x:%02x:%02x\n", 1512 Adapter->PermanentMacAddress[0], 1513 Adapter->PermanentMacAddress[1], 1514 Adapter->PermanentMacAddress[2], 1515 Adapter->PermanentMacAddress[3], 1516 Adapter->PermanentMacAddress[4], 1517 Adapter->PermanentMacAddress[5]); 1518 1519 NdisWriteErrorLogEntry(Adapter->AdapterHandle, NDIS_ERROR_CODE_NETWORK_ADDRESS, 0); 1520 1521 return NDIS_STATUS_INVALID_ADDRESS; 1522 } 1523 1524 return NDIS_STATUS_SUCCESS; 1525 } 1526