1 /* 2 * PROJECT: ReactOS ISA PnP Bus driver 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Hardware support code 5 * COPYRIGHT: Copyright 2010 Cameron Gutman <cameron.gutman@reactos.org> 6 * Copyright 2020 Hervé Poussineau <hpoussin@reactos.org> 7 * Copyright 2021 Dmitry Borisov <di.sean@protonmail.com> 8 */ 9 10 #ifndef UNIT_TEST 11 12 #include "isapnp.h" 13 14 #define NDEBUG 15 #include <debug.h> 16 17 #ifdef _MSC_VER 18 #pragma warning(disable:28138) /* ISA bus always uses hardcoded port addresses */ 19 #endif 20 21 #endif /* UNIT_TEST */ 22 23 ULONG IsaConfigPorts[2] = 24 { 25 ISAPNP_WRITE_DATA_PCAT, 26 ISAPNP_ADDRESS_PCAT 27 }; 28 29 static 30 inline 31 VOID 32 WriteAddress( 33 _In_ UCHAR Address) 34 { 35 WRITE_PORT_UCHAR(UlongToPtr(IsaConfigPorts[1]), Address); 36 } 37 38 static 39 inline 40 VOID 41 WriteData( 42 _In_ UCHAR Data) 43 { 44 WRITE_PORT_UCHAR(UlongToPtr(IsaConfigPorts[0]), Data); 45 } 46 47 static 48 inline 49 UCHAR 50 ReadData( 51 _In_ PUCHAR ReadDataPort) 52 { 53 return READ_PORT_UCHAR(ReadDataPort); 54 } 55 56 static 57 CODE_SEG("PAGE") 58 VOID 59 WriteByte( 60 _In_ UCHAR Address, 61 _In_ UCHAR Value) 62 { 63 PAGED_CODE(); 64 65 WriteAddress(Address); 66 WriteData(Value); 67 } 68 69 static 70 inline 71 VOID 72 WriteWord( 73 _In_ UCHAR Address, 74 _In_ USHORT Value) 75 { 76 WriteByte(Address + 1, (UCHAR)Value); 77 WriteByte(Address, Value >> 8); 78 } 79 80 static 81 inline 82 VOID 83 WriteDoubleWord( 84 _In_ UCHAR Address, 85 _In_ ULONG Value) 86 { 87 WriteWord(Address + 2, (USHORT)Value); 88 WriteWord(Address, Value >> 16); 89 } 90 91 static 92 CODE_SEG("PAGE") 93 UCHAR 94 ReadByte( 95 _In_ PUCHAR ReadDataPort, 96 _In_ UCHAR Address) 97 { 98 PAGED_CODE(); 99 100 WriteAddress(Address); 101 return ReadData(ReadDataPort); 102 } 103 104 static 105 inline 106 USHORT 107 ReadWord( 108 _In_ PUCHAR ReadDataPort, 109 _In_ UCHAR Address) 110 { 111 return ((ReadByte(ReadDataPort, Address) << 8) | 112 (ReadByte(ReadDataPort, Address + 1))); 113 } 114 115 static 116 inline 117 ULONG 118 ReadDoubleWord( 119 _In_ PUCHAR ReadDataPort, 120 _In_ UCHAR Address) 121 { 122 return ((ReadWord(ReadDataPort, Address) << 16) | 123 (ReadWord(ReadDataPort, Address + 2))); 124 } 125 126 static 127 inline 128 VOID 129 SetReadDataPort( 130 _In_ PUCHAR ReadDataPort) 131 { 132 WriteByte(ISAPNP_READPORT, (UCHAR)((ULONG_PTR)ReadDataPort >> 2)); 133 } 134 135 static 136 inline 137 VOID 138 EnterIsolationState(VOID) 139 { 140 WriteAddress(ISAPNP_SERIALISOLATION); 141 } 142 143 static 144 inline 145 VOID 146 WaitForKey(VOID) 147 { 148 WriteByte(ISAPNP_CONFIGCONTROL, ISAPNP_CONFIG_WAIT_FOR_KEY); 149 } 150 151 static 152 inline 153 VOID 154 Wake( 155 _In_ UCHAR Csn) 156 { 157 WriteByte(ISAPNP_WAKE, Csn); 158 } 159 160 static 161 inline 162 UCHAR 163 ReadResourceData( 164 _In_ PUCHAR ReadDataPort) 165 { 166 return ReadByte(ReadDataPort, ISAPNP_RESOURCEDATA); 167 } 168 169 static 170 inline 171 UCHAR 172 ReadStatus( 173 _In_ PUCHAR ReadDataPort) 174 { 175 return ReadByte(ReadDataPort, ISAPNP_STATUS); 176 } 177 178 static 179 inline 180 VOID 181 WriteCsn( 182 _In_ UCHAR Csn) 183 { 184 WriteByte(ISAPNP_CARDSELECTNUMBER, Csn); 185 } 186 187 static 188 inline 189 VOID 190 WriteLogicalDeviceNumber( 191 _In_ UCHAR LogDev) 192 { 193 WriteByte(ISAPNP_LOGICALDEVICENUMBER, LogDev); 194 } 195 196 static 197 inline 198 VOID 199 ActivateDevice( 200 _In_ PUCHAR ReadDataPort, 201 _In_ UCHAR LogDev) 202 { 203 WriteLogicalDeviceNumber(LogDev); 204 205 WriteByte(ISAPNP_IORANGECHECK, 206 ReadByte(ReadDataPort, ISAPNP_IORANGECHECK) & ~2); 207 208 WriteByte(ISAPNP_ACTIVATE, 1); 209 } 210 211 static 212 inline 213 VOID 214 DeactivateDevice( 215 _In_ UCHAR LogDev) 216 { 217 WriteLogicalDeviceNumber(LogDev); 218 WriteByte(ISAPNP_ACTIVATE, 0); 219 } 220 221 static 222 inline 223 USHORT 224 ReadIoBase( 225 _In_ PUCHAR ReadDataPort, 226 _In_ UCHAR Index) 227 { 228 return ReadWord(ReadDataPort, ISAPNP_IOBASE(Index)); 229 } 230 231 static 232 inline 233 UCHAR 234 ReadIrqNo( 235 _In_ PUCHAR ReadDataPort, 236 _In_ UCHAR Index) 237 { 238 return ReadByte(ReadDataPort, ISAPNP_IRQNO(Index)) & 0x0F; 239 } 240 241 static 242 inline 243 UCHAR 244 ReadIrqType( 245 _In_ PUCHAR ReadDataPort, 246 _In_ UCHAR Index) 247 { 248 return ReadByte(ReadDataPort, ISAPNP_IRQTYPE(Index)); 249 } 250 251 static 252 inline 253 UCHAR 254 ReadDmaChannel( 255 _In_ PUCHAR ReadDataPort, 256 _In_ UCHAR Index) 257 { 258 return ReadByte(ReadDataPort, ISAPNP_DMACHANNEL(Index)) & 0x07; 259 } 260 261 static 262 inline 263 USHORT 264 ReadMemoryBase( 265 _In_ PUCHAR ReadDataPort, 266 _In_ UCHAR Index) 267 { 268 return ReadWord(ReadDataPort, ISAPNP_MEMBASE(Index)); 269 } 270 271 static 272 inline 273 UCHAR 274 ReadMemoryControl( 275 _In_ PUCHAR ReadDataPort, 276 _In_ UCHAR Index) 277 { 278 return ReadByte(ReadDataPort, ISAPNP_MEMCONTROL(Index)); 279 } 280 281 static 282 inline 283 USHORT 284 ReadMemoryLimit( 285 _In_ PUCHAR ReadDataPort, 286 _In_ UCHAR Index) 287 { 288 return ReadWord(ReadDataPort, ISAPNP_MEMLIMIT(Index)); 289 } 290 291 static 292 inline 293 ULONG 294 ReadMemoryBase32( 295 _In_ PUCHAR ReadDataPort, 296 _In_ UCHAR Index) 297 { 298 return ReadDoubleWord(ReadDataPort, ISAPNP_MEMBASE32(Index)); 299 } 300 301 static 302 inline 303 UCHAR 304 ReadMemoryControl32( 305 _In_ PUCHAR ReadDataPort, 306 _In_ UCHAR Index) 307 { 308 return ReadByte(ReadDataPort, ISAPNP_MEMCONTROL32(Index)); 309 } 310 311 static 312 inline 313 ULONG 314 ReadMemoryLimit32( 315 _In_ PUCHAR ReadDataPort, 316 _In_ UCHAR Index) 317 { 318 return ReadDoubleWord(ReadDataPort, ISAPNP_MEMLIMIT32(Index)); 319 } 320 321 static 322 inline 323 UCHAR 324 NextLFSR( 325 _In_ UCHAR Lfsr, 326 _In_ UCHAR InputBit) 327 { 328 UCHAR NextLfsr = Lfsr >> 1; 329 330 NextLfsr |= (((Lfsr ^ NextLfsr) ^ InputBit)) << 7; 331 332 return NextLfsr; 333 } 334 335 static 336 CODE_SEG("PAGE") 337 VOID 338 SendKey(VOID) 339 { 340 UCHAR i, Lfsr; 341 342 PAGED_CODE(); 343 344 WriteAddress(0x00); 345 WriteAddress(0x00); 346 347 Lfsr = ISAPNP_LFSR_SEED; 348 for (i = 0; i < 32; i++) 349 { 350 WriteAddress(Lfsr); 351 Lfsr = NextLFSR(Lfsr, 0); 352 } 353 } 354 355 static 356 CODE_SEG("PAGE") 357 UCHAR 358 PeekByte( 359 _In_ PUCHAR ReadDataPort) 360 { 361 UCHAR i; 362 363 PAGED_CODE(); 364 365 for (i = 0; i < 20; i++) 366 { 367 if (ReadStatus(ReadDataPort) & 0x01) 368 return ReadResourceData(ReadDataPort); 369 370 KeStallExecutionProcessor(1000); 371 } 372 373 return 0xFF; 374 } 375 376 static 377 CODE_SEG("PAGE") 378 VOID 379 Peek( 380 _In_ PUCHAR ReadDataPort, 381 _Out_writes_bytes_all_opt_(Length) PVOID Buffer, 382 _In_ USHORT Length) 383 { 384 USHORT i; 385 386 PAGED_CODE(); 387 388 for (i = 0; i < Length; i++) 389 { 390 UCHAR Byte = PeekByte(ReadDataPort); 391 392 if (Buffer) 393 ((PUCHAR)Buffer)[i] = Byte; 394 } 395 } 396 397 static 398 CODE_SEG("PAGE") 399 UCHAR 400 IsaPnpChecksum( 401 _In_ PISAPNP_IDENTIFIER Identifier) 402 { 403 UCHAR i, j, Lfsr; 404 405 PAGED_CODE(); 406 407 Lfsr = ISAPNP_LFSR_SEED; 408 for (i = 0; i < FIELD_OFFSET(ISAPNP_IDENTIFIER, Checksum); i++) 409 { 410 UCHAR Byte = ((PUCHAR)Identifier)[i]; 411 412 for (j = 0; j < RTL_BITS_OF(Byte); j++) 413 { 414 Lfsr = NextLFSR(Lfsr, Byte); 415 Byte >>= 1; 416 } 417 } 418 419 return Lfsr; 420 } 421 422 static 423 CODE_SEG("PAGE") 424 VOID 425 IsaPnpExtractAscii( 426 _Out_writes_all_(3) PUCHAR Buffer, 427 _In_ USHORT CompressedData) 428 { 429 PAGED_CODE(); 430 431 Buffer[0] = ((CompressedData >> 2) & 0x1F) + 'A' - 1; 432 Buffer[1] = (((CompressedData & 0x3) << 3) | ((CompressedData >> 13) & 0x7)) + 'A' - 1; 433 Buffer[2] = ((CompressedData >> 8) & 0x1F) + 'A' - 1; 434 } 435 436 static 437 CODE_SEG("PAGE") 438 NTSTATUS 439 ReadTags( 440 _In_ PUCHAR ReadDataPort, 441 _Out_writes_(ISAPNP_MAX_RESOURCEDATA) PUCHAR Buffer, 442 _In_ ULONG MaxLength, 443 _Out_ PUSHORT MaxLogDev, 444 _Out_ PULONG MaxTagsPerDevice) 445 { 446 ULONG TagCount = 0; 447 448 PAGED_CODE(); 449 450 *MaxLogDev = 0; 451 *MaxTagsPerDevice = 0; 452 453 while (TRUE) 454 { 455 UCHAR Tag; 456 USHORT TagLen; 457 458 ++TagCount; 459 460 if (MaxLength < 1) 461 { 462 DPRINT("Too small tag\n"); 463 return STATUS_BUFFER_OVERFLOW; 464 } 465 466 Tag = PeekByte(ReadDataPort); 467 if (Tag == 0) 468 { 469 DPRINT("Invalid tag\n"); 470 return STATUS_INVALID_PARAMETER_1; 471 } 472 *Buffer++ = Tag; 473 --MaxLength; 474 475 if (ISAPNP_IS_SMALL_TAG(Tag)) 476 { 477 TagLen = ISAPNP_SMALL_TAG_LEN(Tag); 478 Tag = ISAPNP_SMALL_TAG_NAME(Tag); 479 } 480 else 481 { 482 UCHAR Temp[2]; 483 484 if (MaxLength < sizeof(Temp)) 485 { 486 DPRINT("Too small tag\n"); 487 return STATUS_BUFFER_OVERFLOW; 488 } 489 490 Peek(ReadDataPort, &Temp, sizeof(Temp)); 491 *Buffer++ = Temp[0]; 492 *Buffer++ = Temp[1]; 493 MaxLength -= sizeof(Temp); 494 495 TagLen = Temp[0] + (Temp[1] << 8); 496 Tag = ISAPNP_LARGE_TAG_NAME(Tag); 497 } 498 499 if (Tag == 0xFF && TagLen == 0xFFFF) 500 { 501 DPRINT("Invalid tag\n"); 502 return STATUS_INVALID_PARAMETER_2; 503 } 504 505 if (TagLen > MaxLength) 506 { 507 DPRINT("Too large resource data structure\n"); 508 return STATUS_BUFFER_OVERFLOW; 509 } 510 511 Peek(ReadDataPort, Buffer, TagLen); 512 MaxLength -= TagLen; 513 Buffer += TagLen; 514 515 if (Tag == ISAPNP_TAG_LOGDEVID) 516 { 517 /* Attempt to guess the allocation size based on the tags available */ 518 *MaxTagsPerDevice = max(*MaxTagsPerDevice, TagCount); 519 TagCount = 0; 520 521 (*MaxLogDev)++; 522 } 523 else if (Tag == ISAPNP_TAG_END) 524 { 525 *MaxTagsPerDevice = max(*MaxTagsPerDevice, TagCount); 526 break; 527 } 528 } 529 530 return STATUS_SUCCESS; 531 } 532 533 static 534 CODE_SEG("PAGE") 535 VOID 536 FreeLogicalDevice( 537 _In_ __drv_freesMem(Mem) PISAPNP_LOGICAL_DEVICE LogDevice) 538 { 539 PLIST_ENTRY Entry; 540 541 PAGED_CODE(); 542 543 if (LogDevice->FriendlyName) 544 ExFreePoolWithTag(LogDevice->FriendlyName, TAG_ISAPNP); 545 546 if (LogDevice->Resources) 547 ExFreePoolWithTag(LogDevice->Resources, TAG_ISAPNP); 548 549 Entry = LogDevice->CompatibleIdList.Flink; 550 while (Entry != &LogDevice->CompatibleIdList) 551 { 552 PISAPNP_COMPATIBLE_ID_ENTRY CompatibleId = 553 CONTAINING_RECORD(Entry, ISAPNP_COMPATIBLE_ID_ENTRY, IdLink); 554 555 RemoveEntryList(&CompatibleId->IdLink); 556 557 Entry = Entry->Flink; 558 559 ExFreePoolWithTag(CompatibleId, TAG_ISAPNP); 560 } 561 562 ExFreePoolWithTag(LogDevice, TAG_ISAPNP); 563 } 564 565 static 566 CODE_SEG("PAGE") 567 NTSTATUS 568 ParseTags( 569 _In_ PUCHAR ResourceData, 570 _In_ USHORT LogDevToParse, 571 _Inout_ PISAPNP_LOGICAL_DEVICE LogDevice) 572 { 573 USHORT LogDev; 574 ISAPNP_DEPENDENT_FUNCTION_STATE DfState = dfNotStarted; 575 PISAPNP_RESOURCE Resource = LogDevice->Resources; 576 PUCHAR IdStrPos = NULL; 577 USHORT IdStrLen = 0; 578 579 PAGED_CODE(); 580 581 DPRINT("%s for CSN %u, LDN %u\n", __FUNCTION__, LogDevice->CSN, LogDevice->LDN); 582 583 LogDev = LogDevToParse + 1; 584 585 while (TRUE) 586 { 587 UCHAR Tag; 588 USHORT TagLen; 589 590 Tag = *ResourceData++; 591 592 if (ISAPNP_IS_SMALL_TAG(Tag)) 593 { 594 TagLen = ISAPNP_SMALL_TAG_LEN(Tag); 595 Tag = ISAPNP_SMALL_TAG_NAME(Tag); 596 } 597 else 598 { 599 TagLen = *ResourceData++; 600 TagLen += *ResourceData++ << 8; 601 602 Tag = ISAPNP_LARGE_TAG_NAME(Tag); 603 } 604 605 switch (Tag) 606 { 607 case ISAPNP_TAG_LOGDEVID: 608 { 609 ISAPNP_LOGDEVID Temp; 610 611 --LogDev; 612 613 if (LogDev != 0 || 614 (TagLen > sizeof(ISAPNP_LOGDEVID) || 615 TagLen < (sizeof(ISAPNP_LOGDEVID) - 1))) 616 { 617 goto SkipTag; 618 } 619 620 RtlCopyMemory(&Temp, ResourceData, TagLen); 621 ResourceData += TagLen; 622 623 DPRINT("Found tag 0x%X (len %u)\n" 624 " VendorId 0x%04X\n" 625 " ProdId 0x%04X\n", 626 Tag, TagLen, 627 Temp.VendorId, 628 Temp.ProdId); 629 630 IsaPnpExtractAscii(LogDevice->LogVendorId, Temp.VendorId); 631 LogDevice->LogProdId = RtlUshortByteSwap(Temp.ProdId); 632 633 break; 634 } 635 636 case ISAPNP_TAG_COMPATDEVID: 637 { 638 ISAPNP_COMPATID Temp; 639 PISAPNP_COMPATIBLE_ID_ENTRY CompatibleId; 640 641 if (LogDev != 0 || TagLen != sizeof(ISAPNP_COMPATID)) 642 goto SkipTag; 643 644 CompatibleId = ExAllocatePoolWithTag(PagedPool, 645 sizeof(ISAPNP_COMPATIBLE_ID_ENTRY), 646 TAG_ISAPNP); 647 if (!CompatibleId) 648 return STATUS_INSUFFICIENT_RESOURCES; 649 650 RtlCopyMemory(&Temp, ResourceData, TagLen); 651 ResourceData += TagLen; 652 653 DPRINT("Found tag 0x%X (len %u)\n" 654 " VendorId 0x%04X\n" 655 " ProdId 0x%04X\n", 656 Tag, TagLen, 657 Temp.VendorId, 658 Temp.ProdId); 659 660 IsaPnpExtractAscii(CompatibleId->VendorId, Temp.VendorId); 661 CompatibleId->ProdId = RtlUshortByteSwap(Temp.ProdId); 662 663 InsertTailList(&LogDevice->CompatibleIdList, &CompatibleId->IdLink); 664 665 break; 666 } 667 668 case ISAPNP_TAG_IRQ: 669 { 670 PISAPNP_IRQ_DESCRIPTION Description; 671 672 if (LogDev != 0) 673 goto SkipTag; 674 675 if (TagLen > sizeof(ISAPNP_IRQ_DESCRIPTION) || 676 TagLen < (sizeof(ISAPNP_IRQ_DESCRIPTION) - 1)) 677 { 678 DPRINT1("Invalid tag %x\n", ISAPNP_TAG_IRQ); 679 return STATUS_UNSUCCESSFUL; 680 } 681 682 Resource->Type = ISAPNP_RESOURCE_TYPE_IRQ; 683 Description = &Resource->IrqDescription; 684 ++Resource; 685 686 RtlCopyMemory(Description, ResourceData, TagLen); 687 ResourceData += TagLen; 688 689 if (TagLen == (sizeof(ISAPNP_IRQ_DESCRIPTION) - 1)) 690 Description->Information = 0x01; 691 692 DPRINT("Found tag 0x%X (len %u)\n" 693 " Mask 0x%X\n" 694 " Information 0x%X\n", 695 Tag, TagLen, 696 Description->Mask, 697 Description->Information); 698 699 break; 700 } 701 702 case ISAPNP_TAG_DMA: 703 { 704 PISAPNP_DMA_DESCRIPTION Description; 705 706 if (LogDev != 0) 707 goto SkipTag; 708 709 if (TagLen != sizeof(ISAPNP_DMA_DESCRIPTION)) 710 { 711 DPRINT1("Invalid tag %x\n", ISAPNP_TAG_DMA); 712 return STATUS_UNSUCCESSFUL; 713 } 714 715 Resource->Type = ISAPNP_RESOURCE_TYPE_DMA; 716 Description = &Resource->DmaDescription; 717 ++Resource; 718 719 RtlCopyMemory(Description, ResourceData, TagLen); 720 ResourceData += TagLen; 721 722 DPRINT("Found tag 0x%X (len %u)\n" 723 " Mask 0x%X\n" 724 " Information 0x%X\n", 725 Tag, TagLen, 726 Description->Mask, 727 Description->Information); 728 729 break; 730 } 731 732 case ISAPNP_TAG_STARTDEP: 733 { 734 if (LogDev != 0) 735 goto SkipTag; 736 737 if (TagLen > 1) 738 { 739 DPRINT1("Invalid tag %x\n", ISAPNP_TAG_STARTDEP); 740 return STATUS_UNSUCCESSFUL; 741 } 742 743 if (DfState == dfNotStarted) 744 { 745 DfState = dfStarted; 746 } 747 else if (DfState != dfStarted) 748 { 749 goto SkipTag; 750 } 751 752 Resource->Type = ISAPNP_RESOURCE_TYPE_START_DEPENDENT; 753 ++Resource; 754 755 if (TagLen != 1) 756 { 757 Resource->Priority = 1; 758 } 759 else 760 { 761 RtlCopyMemory(&Resource->Priority, ResourceData, TagLen); 762 ResourceData += TagLen; 763 } 764 765 DPRINT("*** Start dependent set, priority %u ***\n", 766 Resource->Priority); 767 768 break; 769 } 770 771 case ISAPNP_TAG_ENDDEP: 772 { 773 if (LogDev != 0 || DfState != dfStarted) 774 goto SkipTag; 775 776 Resource->Type = ISAPNP_RESOURCE_TYPE_END_DEPENDENT; 777 ++Resource; 778 779 DfState = dfDone; 780 781 ResourceData += TagLen; 782 783 DPRINT("*** End of dependent set ***\n"); 784 785 break; 786 } 787 788 case ISAPNP_TAG_IOPORT: 789 { 790 PISAPNP_IO_DESCRIPTION Description; 791 792 if (LogDev != 0) 793 goto SkipTag; 794 795 if (TagLen != sizeof(ISAPNP_IO_DESCRIPTION)) 796 { 797 DPRINT1("Invalid tag %x\n", ISAPNP_TAG_IOPORT); 798 return STATUS_UNSUCCESSFUL; 799 } 800 801 Resource->Type = ISAPNP_RESOURCE_TYPE_IO; 802 Description = &Resource->IoDescription; 803 ++Resource; 804 805 RtlCopyMemory(Description, ResourceData, TagLen); 806 ResourceData += TagLen; 807 808 DPRINT("Found tag 0x%X (len %u)\n" 809 " Information 0x%X\n" 810 " Minimum 0x%X\n" 811 " Maximum 0x%X\n" 812 " Alignment 0x%X\n" 813 " Length 0x%X\n", 814 Tag, TagLen, 815 Description->Information, 816 Description->Minimum, 817 Description->Maximum, 818 Description->Alignment, 819 Description->Length); 820 821 break; 822 } 823 824 case ISAPNP_TAG_FIXEDIO: 825 { 826 ISAPNP_FIXED_IO_DESCRIPTION Temp; 827 PISAPNP_IO_DESCRIPTION Description; 828 829 if (LogDev != 0) 830 goto SkipTag; 831 832 if (TagLen != sizeof(ISAPNP_FIXED_IO_DESCRIPTION)) 833 { 834 DPRINT1("Invalid tag %x\n", ISAPNP_TAG_FIXEDIO); 835 return STATUS_UNSUCCESSFUL; 836 } 837 838 Resource->Type = ISAPNP_RESOURCE_TYPE_IO; 839 Description = &Resource->IoDescription; 840 ++Resource; 841 842 RtlCopyMemory(&Temp, ResourceData, TagLen); 843 ResourceData += TagLen; 844 845 /* Save the address bits [0:9] */ 846 Temp.IoBase &= ((1 << 10) - 1); 847 848 Description->Information = 0; 849 Description->Minimum = 850 Description->Maximum = Temp.IoBase; 851 Description->Alignment = 1; 852 Description->Length = Temp.Length; 853 854 DPRINT("Found tag 0x%X (len %u)\n" 855 " IoBase 0x%X\n" 856 " Length 0x%X\n", 857 Tag, TagLen, 858 Temp.IoBase, 859 Temp.Length); 860 861 break; 862 } 863 864 case ISAPNP_TAG_END: 865 { 866 if (IdStrPos) 867 { 868 PSTR End; 869 870 LogDevice->FriendlyName = ExAllocatePoolWithTag(PagedPool, 871 IdStrLen + sizeof(ANSI_NULL), 872 TAG_ISAPNP); 873 if (!LogDevice->FriendlyName) 874 return STATUS_INSUFFICIENT_RESOURCES; 875 876 RtlCopyMemory(LogDevice->FriendlyName, IdStrPos, IdStrLen); 877 878 End = LogDevice->FriendlyName + IdStrLen - 1; 879 while (End > LogDevice->FriendlyName && *End == ' ') 880 { 881 --End; 882 } 883 *++End = ANSI_NULL; 884 } 885 886 Resource->Type = ISAPNP_RESOURCE_TYPE_END; 887 888 return STATUS_SUCCESS; 889 } 890 891 case ISAPNP_TAG_MEMRANGE: 892 { 893 PISAPNP_MEMRANGE_DESCRIPTION Description; 894 895 if (LogDev != 0) 896 goto SkipTag; 897 898 if (TagLen != sizeof(ISAPNP_MEMRANGE_DESCRIPTION)) 899 { 900 DPRINT1("Invalid tag %x\n", ISAPNP_TAG_MEMRANGE); 901 return STATUS_UNSUCCESSFUL; 902 } 903 904 LogDevice->Flags |= ISAPNP_HAS_MEM24_DECODER; 905 ASSERT(!(LogDevice->Flags & ISAPNP_HAS_MEM32_DECODER)); 906 907 Resource->Type = ISAPNP_RESOURCE_TYPE_MEMRANGE; 908 Description = &Resource->MemRangeDescription; 909 ++Resource; 910 911 RtlCopyMemory(Description, ResourceData, TagLen); 912 ResourceData += TagLen; 913 914 DPRINT("Found tag 0x%X (len %u)\n" 915 " Information 0x%X\n" 916 " Minimum 0x%X\n" 917 " Maximum 0x%X\n" 918 " Alignment 0x%X\n" 919 " Length 0x%X\n", 920 Tag, TagLen, 921 Description->Information, 922 Description->Minimum, 923 Description->Maximum, 924 Description->Alignment, 925 Description->Length); 926 927 break; 928 } 929 930 case ISAPNP_TAG_ANSISTR: 931 { 932 /* If logical device identifier is not supplied, use card identifier */ 933 if (LogDev == LogDevToParse + 1 || LogDev == 0) 934 { 935 IdStrPos = ResourceData; 936 IdStrLen = TagLen; 937 938 ResourceData += TagLen; 939 940 DPRINT("Found tag 0x%X (len %u)\n" 941 " '%.*s'\n", 942 Tag, TagLen, 943 IdStrLen, 944 IdStrPos); 945 } 946 else 947 { 948 goto SkipTag; 949 } 950 951 break; 952 } 953 954 case ISAPNP_TAG_MEM32RANGE: 955 { 956 PISAPNP_MEMRANGE32_DESCRIPTION Description; 957 958 if (LogDev != 0) 959 goto SkipTag; 960 961 if (TagLen != sizeof(ISAPNP_MEMRANGE32_DESCRIPTION)) 962 { 963 DPRINT1("Invalid tag %x\n", ISAPNP_TAG_MEM32RANGE); 964 return STATUS_UNSUCCESSFUL; 965 } 966 967 LogDevice->Flags |= ISAPNP_HAS_MEM32_DECODER; 968 ASSERT(!(LogDevice->Flags & ISAPNP_HAS_MEM24_DECODER)); 969 970 Resource->Type = ISAPNP_RESOURCE_TYPE_MEMRANGE32; 971 Description = &Resource->MemRange32Description; 972 ++Resource; 973 974 RtlCopyMemory(Description, ResourceData, TagLen); 975 ResourceData += TagLen; 976 977 DPRINT("Found tag 0x%X (len %u)\n" 978 " Information 0x%X\n" 979 " Minimum 0x%08lX\n" 980 " Maximum 0x%08lX\n" 981 " Alignment 0x%08lX\n" 982 " Length 0x%08lX\n", 983 Tag, TagLen, 984 Description->Information, 985 Description->Minimum, 986 Description->Maximum, 987 Description->Alignment, 988 Description->Length); 989 990 break; 991 } 992 993 case ISAPNP_TAG_FIXEDMEM32RANGE: 994 { 995 ISAPNP_FIXEDMEMRANGE_DESCRIPTION Temp; 996 PISAPNP_MEMRANGE32_DESCRIPTION Description; 997 998 if (LogDev != 0) 999 goto SkipTag; 1000 1001 if (TagLen != sizeof(ISAPNP_FIXEDMEMRANGE_DESCRIPTION)) 1002 { 1003 DPRINT1("Invalid tag %x\n", ISAPNP_TAG_FIXEDMEM32RANGE); 1004 return STATUS_UNSUCCESSFUL; 1005 } 1006 1007 LogDevice->Flags |= ISAPNP_HAS_MEM32_DECODER; 1008 ASSERT(!(LogDevice->Flags & ISAPNP_HAS_MEM24_DECODER)); 1009 1010 Resource->Type = ISAPNP_RESOURCE_TYPE_MEMRANGE32; 1011 Description = &Resource->MemRange32Description; 1012 ++Resource; 1013 1014 RtlCopyMemory(&Temp, ResourceData, TagLen); 1015 ResourceData += TagLen; 1016 1017 Description->Information = Temp.Information; 1018 Description->Minimum = 1019 Description->Maximum = Temp.MemoryBase; 1020 Description->Alignment = 1; 1021 Description->Length = Temp.Length; 1022 1023 DPRINT("Found tag 0x%X (len %u)\n" 1024 " Information 0x%X\n" 1025 " MemoryBase 0x%08lX\n" 1026 " Length 0x%08lX\n", 1027 Tag, TagLen, 1028 Temp.Information, 1029 Temp.MemoryBase, 1030 Temp.Length); 1031 1032 break; 1033 } 1034 1035 SkipTag: 1036 default: 1037 { 1038 if (LogDev == 0) 1039 DPRINT("Found unknown tag 0x%X (len %u)\n", Tag, TagLen); 1040 1041 /* We don't want to read informations on this 1042 * logical device, or we don't know the tag. */ 1043 ResourceData += TagLen; 1044 break; 1045 } 1046 } 1047 } 1048 } 1049 1050 static 1051 CODE_SEG("PAGE") 1052 BOOLEAN 1053 ReadCurrentResources( 1054 _In_ PUCHAR ReadDataPort, 1055 _Inout_ PISAPNP_LOGICAL_DEVICE LogDevice) 1056 { 1057 UCHAR i; 1058 1059 PAGED_CODE(); 1060 1061 DPRINT("%s for CSN %u, LDN %u\n", __FUNCTION__, LogDevice->CSN, LogDevice->LDN); 1062 1063 WriteLogicalDeviceNumber(LogDevice->LDN); 1064 1065 /* If the device is not activated by BIOS then the device has no boot resources */ 1066 if (!(ReadByte(ReadDataPort, ISAPNP_ACTIVATE) & 1)) 1067 { 1068 LogDevice->Flags &= ~ISAPNP_HAS_RESOURCES; 1069 return FALSE; 1070 } 1071 1072 for (i = 0; i < RTL_NUMBER_OF(LogDevice->Io); i++) 1073 { 1074 LogDevice->Io[i].CurrentBase = ReadIoBase(ReadDataPort, i); 1075 1076 /* Skip empty descriptors */ 1077 if (!LogDevice->Io[i].CurrentBase) 1078 break; 1079 } 1080 for (i = 0; i < RTL_NUMBER_OF(LogDevice->Irq); i++) 1081 { 1082 LogDevice->Irq[i].CurrentNo = ReadIrqNo(ReadDataPort, i); 1083 1084 if (!LogDevice->Irq[i].CurrentNo) 1085 break; 1086 1087 LogDevice->Irq[i].CurrentType = ReadIrqType(ReadDataPort, i); 1088 } 1089 for (i = 0; i < RTL_NUMBER_OF(LogDevice->Dma); i++) 1090 { 1091 LogDevice->Dma[i].CurrentChannel = ReadDmaChannel(ReadDataPort, i); 1092 1093 if (LogDevice->Dma[i].CurrentChannel == DMACHANNEL_NONE) 1094 break; 1095 } 1096 for (i = 0; i < RTL_NUMBER_OF(LogDevice->MemRange); i++) 1097 { 1098 LogDevice->MemRange[i].CurrentBase = ReadMemoryBase(ReadDataPort, i) << 8; 1099 1100 if (!LogDevice->MemRange[i].CurrentBase) 1101 break; 1102 1103 LogDevice->MemRange[i].CurrentLength = ReadMemoryLimit(ReadDataPort, i) << 8; 1104 1105 if (ReadMemoryControl(ReadDataPort, i) & MEMORY_UPPER_LIMIT) 1106 { 1107 LogDevice->MemRange[i].CurrentLength -= LogDevice->MemRange[i].CurrentBase; 1108 } 1109 else 1110 { 1111 LogDevice->MemRange[i].CurrentLength = 1112 RANGE_LENGTH_TO_LENGTH(LogDevice->MemRange[i].CurrentLength); 1113 } 1114 } 1115 for (i = 0; i < RTL_NUMBER_OF(LogDevice->MemRange32); i++) 1116 { 1117 LogDevice->MemRange32[i].CurrentBase = ReadMemoryBase32(ReadDataPort, i); 1118 1119 if (!LogDevice->MemRange32[i].CurrentBase) 1120 break; 1121 1122 LogDevice->MemRange32[i].CurrentLength = ReadMemoryLimit32(ReadDataPort, i); 1123 1124 if (ReadMemoryControl32(ReadDataPort, i) & MEMORY_UPPER_LIMIT) 1125 { 1126 LogDevice->MemRange32[i].CurrentLength -= LogDevice->MemRange32[i].CurrentBase; 1127 } 1128 else 1129 { 1130 LogDevice->MemRange32[i].CurrentLength = 1131 RANGE_LENGTH_TO_LENGTH(LogDevice->MemRange32[i].CurrentLength); 1132 } 1133 } 1134 1135 LogDevice->Flags |= ISAPNP_HAS_RESOURCES; 1136 return TRUE; 1137 } 1138 1139 static 1140 CODE_SEG("PAGE") 1141 VOID 1142 IsaProgramIoDecoder( 1143 _In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor, 1144 _In_ UCHAR Index) 1145 { 1146 PAGED_CODE(); 1147 1148 ASSERT(Descriptor->u.Port.Start.QuadPart <= 0xFFFF); 1149 1150 WriteWord(ISAPNP_IOBASE(Index), Descriptor->u.Port.Start.LowPart); 1151 } 1152 1153 static 1154 CODE_SEG("PAGE") 1155 VOID 1156 IsaProgramIrqSelect( 1157 _In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor, 1158 _In_ UCHAR Index) 1159 { 1160 UCHAR TypeSelect; 1161 1162 PAGED_CODE(); 1163 1164 ASSERT(Descriptor->u.Interrupt.Level <= 15); 1165 1166 if (Descriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED) 1167 TypeSelect = IRQTYPE_HIGH_EDGE; 1168 else 1169 TypeSelect = IRQTYPE_LOW_LEVEL; 1170 1171 WriteByte(ISAPNP_IRQNO(Index), Descriptor->u.Interrupt.Level); 1172 WriteByte(ISAPNP_IRQTYPE(Index), TypeSelect); 1173 } 1174 1175 static 1176 CODE_SEG("PAGE") 1177 VOID 1178 IsaProgramDmaSelect( 1179 _In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor, 1180 _In_ UCHAR Index) 1181 { 1182 PAGED_CODE(); 1183 1184 ASSERT(Descriptor->u.Dma.Channel <= 7); 1185 1186 WriteByte(ISAPNP_DMACHANNEL(Index), Descriptor->u.Dma.Channel); 1187 } 1188 1189 static 1190 CODE_SEG("PAGE") 1191 NTSTATUS 1192 IsaProgramMemoryDecoder( 1193 _In_ PUCHAR ReadDataPort, 1194 _In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor, 1195 _In_ BOOLEAN IsMemory32, 1196 _In_ UCHAR Information, 1197 _In_ UCHAR Index) 1198 { 1199 UCHAR MemoryControl; 1200 ULONG LengthLimit; 1201 1202 PAGED_CODE(); 1203 1204 if (!IsMemory32) 1205 { 1206 /* The 24-bit memory address decoder always considers bits 0:7 to be zeros */ 1207 if (Descriptor->u.Memory.Start.LowPart & 0xFF) 1208 return STATUS_INVALID_PARAMETER; 1209 1210 if (Information & MEMRANGE_16_BIT_MEMORY_MASK) 1211 MemoryControl = MEMORY_USE_16_BIT_DECODER; 1212 else 1213 MemoryControl = MEMORY_USE_8_BIT_DECODER; 1214 1215 if (ReadMemoryControl(ReadDataPort, Index) & MEMORY_UPPER_LIMIT) 1216 { 1217 MemoryControl |= MEMORY_UPPER_LIMIT; 1218 LengthLimit = Descriptor->u.Memory.Start.LowPart + Descriptor->u.Memory.Length; 1219 } 1220 else 1221 { 1222 LengthLimit = LENGTH_TO_RANGE_LENGTH(Descriptor->u.Memory.Length); 1223 } 1224 LengthLimit >>= 8; 1225 1226 WriteWord(ISAPNP_MEMBASE(Index), Descriptor->u.Memory.Start.LowPart >> 8); 1227 WriteByte(ISAPNP_MEMCONTROL(Index), MemoryControl); 1228 WriteWord(ISAPNP_MEMLIMIT(Index), LengthLimit); 1229 } 1230 else 1231 { 1232 if ((Information & MEMRANGE_16_BIT_MEMORY_MASK) == MEMRANGE_32_BIT_MEMORY_ONLY) 1233 MemoryControl = MEMORY_USE_32_BIT_DECODER; 1234 else if (Information & MEMRANGE_16_BIT_MEMORY_MASK) 1235 MemoryControl = MEMORY_USE_16_BIT_DECODER; 1236 else 1237 MemoryControl = MEMORY_USE_8_BIT_DECODER; 1238 1239 if (ReadMemoryControl32(ReadDataPort, Index) & MEMORY_UPPER_LIMIT) 1240 { 1241 MemoryControl |= MEMORY_UPPER_LIMIT; 1242 LengthLimit = Descriptor->u.Memory.Start.LowPart + Descriptor->u.Memory.Length; 1243 } 1244 else 1245 { 1246 LengthLimit = LENGTH_TO_RANGE_LENGTH(Descriptor->u.Memory.Length); 1247 } 1248 1249 WriteDoubleWord(ISAPNP_MEMBASE32(Index), Descriptor->u.Memory.Start.LowPart); 1250 WriteByte(ISAPNP_MEMCONTROL32(Index), MemoryControl); 1251 WriteDoubleWord(ISAPNP_MEMLIMIT32(Index), LengthLimit); 1252 } 1253 1254 return STATUS_SUCCESS; 1255 } 1256 1257 CODE_SEG("PAGE") 1258 UCHAR 1259 IsaHwTryReadDataPort( 1260 _In_ PUCHAR ReadDataPort) 1261 { 1262 ULONG NumberOfRead = 0; 1263 UCHAR Csn = 0; 1264 1265 PAGED_CODE(); 1266 1267 DPRINT("Setting read data port: 0x%p\n", ReadDataPort); 1268 1269 SendKey(); 1270 1271 WriteByte(ISAPNP_CONFIGCONTROL, 1272 ISAPNP_CONFIG_RESET_CSN | ISAPNP_CONFIG_WAIT_FOR_KEY); 1273 KeStallExecutionProcessor(2000); 1274 1275 SendKey(); 1276 1277 Wake(0x00); 1278 KeStallExecutionProcessor(1000); 1279 1280 SetReadDataPort(ReadDataPort); 1281 1282 Wake(0x00); 1283 1284 while (TRUE) 1285 { 1286 ISAPNP_IDENTIFIER Identifier; 1287 UCHAR i, j; 1288 BOOLEAN Seen55aa = FALSE; 1289 1290 EnterIsolationState(); 1291 KeStallExecutionProcessor(1000); 1292 1293 RtlZeroMemory(&Identifier, sizeof(Identifier)); 1294 1295 for (i = 0; i < sizeof(Identifier); i++) 1296 { 1297 UCHAR Byte = 0; 1298 1299 for (j = 0; j < RTL_BITS_OF(Byte); j++) 1300 { 1301 USHORT Data; 1302 1303 Data = ReadData(ReadDataPort) << 8; 1304 KeStallExecutionProcessor(250); 1305 Data |= ReadData(ReadDataPort); 1306 KeStallExecutionProcessor(250); 1307 1308 Byte >>= 1; 1309 1310 if (Data == 0x55AA) 1311 { 1312 Byte |= 0x80; 1313 Seen55aa = TRUE; 1314 } 1315 } 1316 1317 ((PUCHAR)&Identifier)[i] = Byte; 1318 } 1319 1320 ++NumberOfRead; 1321 1322 if (Identifier.Checksum != 0x00 && 1323 Identifier.Checksum != IsaPnpChecksum(&Identifier)) 1324 { 1325 DPRINT("Bad checksum\n"); 1326 break; 1327 } 1328 1329 if (!Seen55aa) 1330 { 1331 DPRINT("Saw no sign of life\n"); 1332 break; 1333 } 1334 1335 Csn++; 1336 1337 WriteCsn(Csn); 1338 KeStallExecutionProcessor(1000); 1339 1340 Wake(0x00); 1341 } 1342 1343 Wake(0x00); 1344 1345 if (NumberOfRead == 1) 1346 { 1347 DPRINT("Trying next read data port\n"); 1348 return 0; 1349 } 1350 else 1351 { 1352 DPRINT("Found %u cards at read port 0x%p\n", Csn, ReadDataPort); 1353 return Csn; 1354 } 1355 } 1356 1357 _Requires_lock_held_(FdoExt->DeviceSyncEvent) 1358 CODE_SEG("PAGE") 1359 NTSTATUS 1360 IsaHwFillDeviceList( 1361 _In_ PISAPNP_FDO_EXTENSION FdoExt) 1362 { 1363 PISAPNP_LOGICAL_DEVICE LogDevice; 1364 UCHAR Csn; 1365 PLIST_ENTRY Entry; 1366 PUCHAR ResourceData; 1367 1368 PAGED_CODE(); 1369 ASSERT(FdoExt->ReadDataPort); 1370 1371 DPRINT("%s for read port 0x%p\n", __FUNCTION__, FdoExt->ReadDataPort); 1372 1373 ResourceData = ExAllocatePoolWithTag(PagedPool, ISAPNP_MAX_RESOURCEDATA, TAG_ISAPNP); 1374 if (!ResourceData) 1375 { 1376 DPRINT1("Failed to allocate memory for cache data\n"); 1377 return STATUS_INSUFFICIENT_RESOURCES; 1378 } 1379 1380 for (Entry = FdoExt->DeviceListHead.Flink; 1381 Entry != &FdoExt->DeviceListHead; 1382 Entry = Entry->Flink) 1383 { 1384 LogDevice = CONTAINING_RECORD(Entry, ISAPNP_LOGICAL_DEVICE, DeviceLink); 1385 1386 LogDevice->Flags &= ~ISAPNP_PRESENT; 1387 } 1388 1389 for (Csn = 1; Csn <= FdoExt->Cards; Csn++) 1390 { 1391 NTSTATUS Status; 1392 UCHAR TempId[3], LogDev; 1393 ISAPNP_IDENTIFIER Identifier; 1394 ULONG MaxTagsPerDevice; 1395 USHORT MaxLogDev; 1396 1397 Wake(Csn); 1398 1399 Peek(FdoExt->ReadDataPort, &Identifier, sizeof(Identifier)); 1400 1401 IsaPnpExtractAscii(TempId, Identifier.VendorId); 1402 Identifier.ProdId = RtlUshortByteSwap(Identifier.ProdId); 1403 1404 Status = ReadTags(FdoExt->ReadDataPort, 1405 ResourceData, 1406 ISAPNP_MAX_RESOURCEDATA, 1407 &MaxLogDev, 1408 &MaxTagsPerDevice); 1409 if (!NT_SUCCESS(Status)) 1410 { 1411 DPRINT1("Failed to read tags with status 0x%08lx, CSN %u\n", Status, Csn); 1412 continue; 1413 } 1414 1415 DPRINT("Detected ISA PnP device - VID: '%.3s' PID: 0x%04x SN: 0x%08lX\n", 1416 TempId, Identifier.ProdId, Identifier.Serial); 1417 1418 for (LogDev = 0; LogDev < MaxLogDev; LogDev++) 1419 { 1420 BOOLEAN IsAlreadyEnumerated = FALSE; 1421 1422 #ifndef UNIT_TEST 1423 for (Entry = FdoExt->DeviceListHead.Flink; 1424 Entry != &FdoExt->DeviceListHead; 1425 Entry = Entry->Flink) 1426 { 1427 LogDevice = CONTAINING_RECORD(Entry, ISAPNP_LOGICAL_DEVICE, DeviceLink); 1428 1429 /* This logical device has already been enumerated */ 1430 if ((LogDevice->SerialNumber == Identifier.Serial) && 1431 (RtlCompareMemory(LogDevice->VendorId, TempId, 3) == 3) && 1432 (LogDevice->ProdId == Identifier.ProdId) && 1433 (LogDevice->LDN == LogDev)) 1434 { 1435 LogDevice->Flags |= ISAPNP_PRESENT; 1436 1437 /* Assign a new CSN */ 1438 LogDevice->CSN = Csn; 1439 1440 if (LogDevice->Pdo) 1441 { 1442 PISAPNP_PDO_EXTENSION PdoExt = LogDevice->Pdo->DeviceExtension; 1443 1444 if (PdoExt->Common.State == dsStarted) 1445 ActivateDevice(FdoExt->ReadDataPort, LogDev); 1446 } 1447 1448 DPRINT("Skip CSN %u, LDN %u\n", LogDevice->CSN, LogDevice->LDN); 1449 IsAlreadyEnumerated = TRUE; 1450 break; 1451 } 1452 } 1453 #endif /* UNIT_TEST */ 1454 1455 if (IsAlreadyEnumerated) 1456 continue; 1457 1458 LogDevice = ExAllocatePoolZero(NonPagedPool, sizeof(ISAPNP_LOGICAL_DEVICE), TAG_ISAPNP); 1459 if (!LogDevice) 1460 { 1461 DPRINT1("Failed to allocate logical device!\n"); 1462 goto Deactivate; 1463 } 1464 1465 InitializeListHead(&LogDevice->CompatibleIdList); 1466 1467 LogDevice->CSN = Csn; 1468 LogDevice->LDN = LogDev; 1469 1470 LogDevice->Resources = ExAllocatePoolWithTag(PagedPool, 1471 MaxTagsPerDevice * sizeof(ISAPNP_RESOURCE), 1472 TAG_ISAPNP); 1473 if (!LogDevice->Resources) 1474 { 1475 DPRINT1("Failed to allocate the resources array\n"); 1476 FreeLogicalDevice(LogDevice); 1477 goto Deactivate; 1478 } 1479 1480 Status = ParseTags(ResourceData, LogDev, LogDevice); 1481 if (!NT_SUCCESS(Status)) 1482 { 1483 DPRINT1("Failed to parse tags with status 0x%08lx, CSN %u, LDN %u\n", 1484 Status, LogDevice->CSN, LogDevice->LDN); 1485 FreeLogicalDevice(LogDevice); 1486 goto Deactivate; 1487 } 1488 1489 if (!ReadCurrentResources(FdoExt->ReadDataPort, LogDevice)) 1490 DPRINT("Unable to read boot resources\n"); 1491 1492 IsaPnpExtractAscii(LogDevice->VendorId, Identifier.VendorId); 1493 LogDevice->ProdId = Identifier.ProdId; 1494 LogDevice->SerialNumber = Identifier.Serial; 1495 1496 if (MaxLogDev > 1) 1497 LogDevice->Flags |= ISAPNP_HAS_MULTIPLE_LOGDEVS; 1498 1499 LogDevice->Flags |= ISAPNP_PRESENT; 1500 1501 InsertTailList(&FdoExt->DeviceListHead, &LogDevice->DeviceLink); 1502 FdoExt->DeviceCount++; 1503 1504 /* Now we wait for the start device IRP */ 1505 Deactivate: 1506 DeactivateDevice(LogDev); 1507 } 1508 } 1509 1510 ExFreePoolWithTag(ResourceData, TAG_ISAPNP); 1511 1512 return STATUS_SUCCESS; 1513 } 1514 1515 CODE_SEG("PAGE") 1516 NTSTATUS 1517 IsaHwConfigureDevice( 1518 _In_ PISAPNP_FDO_EXTENSION FdoExt, 1519 _In_ PISAPNP_LOGICAL_DEVICE LogicalDevice, 1520 _In_ PCM_RESOURCE_LIST Resources) 1521 { 1522 ULONG i; 1523 UCHAR NumberOfIo = 0, 1524 NumberOfIrq = 0, 1525 NumberOfDma = 0, 1526 NumberOfMemory = 0, 1527 NumberOfMemory32 = 0; 1528 1529 PAGED_CODE(); 1530 1531 if (!Resources) 1532 return STATUS_INSUFFICIENT_RESOURCES; 1533 1534 WriteLogicalDeviceNumber(LogicalDevice->LDN); 1535 1536 for (i = 0; i < Resources->List[0].PartialResourceList.Count; i++) 1537 { 1538 PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = 1539 &Resources->List[0].PartialResourceList.PartialDescriptors[i]; 1540 1541 switch (Descriptor->Type) 1542 { 1543 case CmResourceTypePort: 1544 { 1545 if (NumberOfIo >= RTL_NUMBER_OF(LogicalDevice->Io)) 1546 return STATUS_INVALID_PARAMETER_1; 1547 1548 IsaProgramIoDecoder(Descriptor, NumberOfIo++); 1549 break; 1550 } 1551 1552 case CmResourceTypeInterrupt: 1553 { 1554 if (NumberOfIrq >= RTL_NUMBER_OF(LogicalDevice->Irq)) 1555 return STATUS_INVALID_PARAMETER_2; 1556 1557 IsaProgramIrqSelect(Descriptor, NumberOfIrq++); 1558 break; 1559 } 1560 1561 case CmResourceTypeDma: 1562 { 1563 if (NumberOfDma >= RTL_NUMBER_OF(LogicalDevice->Dma)) 1564 return STATUS_INVALID_PARAMETER_3; 1565 1566 IsaProgramDmaSelect(Descriptor, NumberOfDma++); 1567 break; 1568 } 1569 1570 case CmResourceTypeMemory: 1571 { 1572 BOOLEAN IsMemory32; 1573 UCHAR Index, Information; 1574 NTSTATUS Status; 1575 1576 if ((NumberOfMemory + NumberOfMemory32) >= RTL_NUMBER_OF(LogicalDevice->MemRange)) 1577 return STATUS_INVALID_PARAMETER_4; 1578 1579 /* 1580 * The PNP ROM provides an information byte for each memory descriptor 1581 * which is then used to program the memory control register. 1582 */ 1583 if (!FindMemoryDescriptor(LogicalDevice, 1584 Descriptor->u.Memory.Start.LowPart, 1585 Descriptor->u.Memory.Start.LowPart + 1586 Descriptor->u.Memory.Length - 1, 1587 &Information)) 1588 { 1589 return STATUS_RESOURCE_DATA_NOT_FOUND; 1590 } 1591 1592 /* We can have a 24- or 32-bit memory decoder, but not both */ 1593 IsMemory32 = !!(LogicalDevice->Flags & ISAPNP_HAS_MEM32_DECODER); 1594 1595 if (IsMemory32) 1596 Index = NumberOfMemory32++; 1597 else 1598 Index = NumberOfMemory++; 1599 1600 Status = IsaProgramMemoryDecoder(FdoExt->ReadDataPort, 1601 Descriptor, 1602 IsMemory32, 1603 Information, 1604 Index); 1605 if (!NT_SUCCESS(Status)) 1606 return Status; 1607 1608 break; 1609 } 1610 1611 default: 1612 break; 1613 } 1614 } 1615 1616 /* Disable the unclaimed device resources */ 1617 for (i = NumberOfIo; i < RTL_NUMBER_OF(LogicalDevice->Io); i++) 1618 { 1619 WriteWord(ISAPNP_IOBASE(i), 0); 1620 } 1621 for (i = NumberOfIrq; i < RTL_NUMBER_OF(LogicalDevice->Irq); i++) 1622 { 1623 WriteByte(ISAPNP_IRQNO(i), 0); 1624 WriteByte(ISAPNP_IRQTYPE(i), 0); 1625 } 1626 for (i = NumberOfDma; i < RTL_NUMBER_OF(LogicalDevice->Dma); i++) 1627 { 1628 WriteByte(ISAPNP_DMACHANNEL(i), DMACHANNEL_NONE); 1629 } 1630 for (i = NumberOfMemory; i < RTL_NUMBER_OF(LogicalDevice->MemRange); i++) 1631 { 1632 WriteWord(ISAPNP_MEMBASE(i), 0); 1633 WriteByte(ISAPNP_MEMCONTROL(i), 0); 1634 WriteWord(ISAPNP_MEMLIMIT(i), 0); 1635 } 1636 for (i = NumberOfMemory32; i < RTL_NUMBER_OF(LogicalDevice->MemRange32); i++) 1637 { 1638 WriteDoubleWord(ISAPNP_MEMBASE32(i), 0); 1639 WriteByte(ISAPNP_MEMCONTROL32(i), 0); 1640 WriteDoubleWord(ISAPNP_MEMLIMIT32(i), 0); 1641 } 1642 1643 KeStallExecutionProcessor(10000); 1644 1645 return STATUS_SUCCESS; 1646 } 1647 1648 CODE_SEG("PAGE") 1649 VOID 1650 IsaHwWakeDevice( 1651 _In_ PISAPNP_LOGICAL_DEVICE LogicalDevice) 1652 { 1653 PAGED_CODE(); 1654 1655 SendKey(); 1656 Wake(LogicalDevice->CSN); 1657 } 1658 1659 CODE_SEG("PAGE") 1660 VOID 1661 IsaHwActivateDevice( 1662 _In_ PISAPNP_FDO_EXTENSION FdoExt, 1663 _In_ PISAPNP_LOGICAL_DEVICE LogicalDevice) 1664 { 1665 PAGED_CODE(); 1666 1667 ActivateDevice(FdoExt->ReadDataPort, LogicalDevice->LDN); 1668 } 1669 1670 #ifndef UNIT_TEST 1671 CODE_SEG("PAGE") 1672 VOID 1673 IsaHwDeactivateDevice( 1674 _In_ PISAPNP_LOGICAL_DEVICE LogicalDevice) 1675 { 1676 PAGED_CODE(); 1677 1678 DeactivateDevice(LogicalDevice->LDN); 1679 } 1680 #endif /* UNIT_TEST */ 1681 1682 CODE_SEG("PAGE") 1683 VOID 1684 IsaHwWaitForKey(VOID) 1685 { 1686 PAGED_CODE(); 1687 1688 WaitForKey(); 1689 } 1690