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: Driver entry 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 /* INCLUDES *******************************************************************/ 11 12 #include "isapnp.h" 13 14 #include <search.h> 15 16 #define NDEBUG 17 #include <debug.h> 18 19 /* GLOBALS ********************************************************************/ 20 21 KEVENT BusSyncEvent; 22 23 _Guarded_by_(BusSyncEvent) 24 BOOLEAN ReadPortCreated = FALSE; 25 26 _Guarded_by_(BusSyncEvent) 27 LIST_ENTRY BusListHead; 28 29 static PUCHAR Priority; 30 31 /* FUNCTIONS ******************************************************************/ 32 33 static 34 CODE_SEG("PAGE") 35 int 36 __cdecl 37 IsaComparePriority( 38 const void *A, 39 const void *B) 40 { 41 PAGED_CODE(); 42 43 return Priority[*(PUCHAR)A] - Priority[*(PUCHAR)B]; 44 } 45 46 static 47 CODE_SEG("PAGE") 48 VOID 49 IsaDetermineBestConfig( 50 _Out_writes_all_(ISAPNP_MAX_ALTERNATIVES) PUCHAR BestConfig, 51 _In_ PISAPNP_ALTERNATIVES Alternatives) 52 { 53 UCHAR i; 54 55 PAGED_CODE(); 56 57 for (i = 0; i < ISAPNP_MAX_ALTERNATIVES; i++) 58 { 59 BestConfig[i] = i; 60 } 61 62 Priority = Alternatives->Priority; 63 qsort(BestConfig, 64 Alternatives->Count, 65 sizeof(*BestConfig), 66 IsaComparePriority); 67 } 68 69 static 70 CODE_SEG("PAGE") 71 VOID 72 IsaConvertIoRequirement( 73 _Out_ PIO_RESOURCE_DESCRIPTOR Descriptor, 74 _In_ PISAPNP_IO_DESCRIPTION Description) 75 { 76 PAGED_CODE(); 77 78 Descriptor->Type = CmResourceTypePort; 79 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 80 Descriptor->Flags = CM_RESOURCE_PORT_IO; 81 if (Description->Information & 0x1) 82 Descriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE; 83 else 84 Descriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE; 85 Descriptor->u.Port.Length = Description->Length; 86 Descriptor->u.Port.Alignment = Description->Alignment; 87 Descriptor->u.Port.MinimumAddress.LowPart = Description->Minimum; 88 Descriptor->u.Port.MaximumAddress.LowPart = Description->Maximum + 89 Description->Length - 1; 90 } 91 92 static 93 CODE_SEG("PAGE") 94 VOID 95 IsaConvertIrqRequirement( 96 _Out_ PIO_RESOURCE_DESCRIPTOR Descriptor, 97 _In_ PISAPNP_IRQ_DESCRIPTION Description, 98 _In_ ULONG Vector, 99 _In_ BOOLEAN FirstDescriptor) 100 { 101 PAGED_CODE(); 102 103 if (!FirstDescriptor) 104 Descriptor->Option = IO_RESOURCE_ALTERNATIVE; 105 Descriptor->Type = CmResourceTypeInterrupt; 106 if (Description->Information & 0xC) 107 { 108 Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; 109 Descriptor->ShareDisposition = CmResourceShareShared; 110 } 111 else 112 { 113 Descriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; 114 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 115 } 116 Descriptor->u.Interrupt.MinimumVector = 117 Descriptor->u.Interrupt.MaximumVector = Vector; 118 } 119 120 static 121 CODE_SEG("PAGE") 122 VOID 123 IsaConvertDmaRequirement( 124 _Out_ PIO_RESOURCE_DESCRIPTOR Descriptor, 125 _In_ PISAPNP_DMA_DESCRIPTION Description, 126 _In_ ULONG Channel, 127 _In_ BOOLEAN FirstDescriptor) 128 { 129 UNREFERENCED_PARAMETER(Description); 130 131 PAGED_CODE(); 132 133 if (!FirstDescriptor) 134 Descriptor->Option = IO_RESOURCE_ALTERNATIVE; 135 Descriptor->Type = CmResourceTypeDma; 136 Descriptor->ShareDisposition = CmResourceShareUndetermined; 137 Descriptor->Flags = CM_RESOURCE_DMA_8; /* Ignore information byte for compatibility */ 138 Descriptor->u.Dma.MinimumChannel = 139 Descriptor->u.Dma.MaximumChannel = Channel; 140 } 141 142 static 143 CODE_SEG("PAGE") 144 VOID 145 IsaConvertMemRangeRequirement( 146 _Out_ PIO_RESOURCE_DESCRIPTOR Descriptor, 147 _In_ PISAPNP_MEMRANGE_DESCRIPTION Description) 148 { 149 PAGED_CODE(); 150 151 Descriptor->Type = CmResourceTypeMemory; 152 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 153 Descriptor->Flags = CM_RESOURCE_MEMORY_24; 154 if ((Description->Information & 0x40) || !(Description->Information & 0x01)) 155 Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY; 156 else 157 Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE; 158 Descriptor->u.Memory.Length = Description->Length << 8; 159 if (Description->Alignment == 0) 160 Descriptor->u.Memory.Alignment = 0x10000; 161 else 162 Descriptor->u.Memory.Alignment = Description->Alignment; 163 Descriptor->u.Memory.MinimumAddress.LowPart = Description->Minimum << 8; 164 Descriptor->u.Memory.MaximumAddress.LowPart = (Description->Maximum << 8) + 165 (Description->Length << 8) - 1; 166 } 167 168 static 169 CODE_SEG("PAGE") 170 VOID 171 IsaConvertMemRange32Requirement( 172 _Out_ PIO_RESOURCE_DESCRIPTOR Descriptor, 173 _In_ PISAPNP_MEMRANGE32_DESCRIPTION Description) 174 { 175 PAGED_CODE(); 176 177 Descriptor->Type = CmResourceTypeMemory; 178 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 179 Descriptor->Flags = CM_RESOURCE_MEMORY_24; 180 if ((Description->Information & 0x40) || !(Description->Information & 0x01)) 181 Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY; 182 else 183 Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE; 184 Descriptor->u.Memory.Length = Description->Length; 185 Descriptor->u.Memory.Alignment = Description->Alignment; 186 Descriptor->u.Memory.MinimumAddress.LowPart = Description->Minimum; 187 Descriptor->u.Memory.MaximumAddress.LowPart = Description->Maximum + 188 Description->Length - 1; 189 } 190 191 static 192 CODE_SEG("PAGE") 193 NTSTATUS 194 IsaPnpCreateLogicalDeviceRequirements( 195 _In_ PISAPNP_PDO_EXTENSION PdoExt) 196 { 197 PISAPNP_LOGICAL_DEVICE LogDev = PdoExt->IsaPnpDevice; 198 RTL_BITMAP TempBitmap; 199 ULONG TempBuffer; 200 ULONG ResourceCount = 0, AltCount = 0, AltOptionalCount = 0; 201 ULONG ListSize, i, j; 202 BOOLEAN FirstDescriptor; 203 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList; 204 PIO_RESOURCE_DESCRIPTOR Descriptor; 205 PISAPNP_ALTERNATIVES Alternatives = LogDev->Alternatives; 206 207 PAGED_CODE(); 208 209 /* Count number of requirements */ 210 for (i = 0; i < RTL_NUMBER_OF(LogDev->Io); i++) 211 { 212 /* 213 * Use the continue statement to count the number of requirements. 214 * We handle a possible gap because depedent function can appear at 215 * any position in the logical device's requirements list. 216 */ 217 if (!LogDev->Io[i].Description.Length) 218 continue; 219 220 ResourceCount++; 221 } 222 for (i = 0; i < RTL_NUMBER_OF(LogDev->Irq); i++) 223 { 224 if (!LogDev->Irq[i].Description.Mask) 225 continue; 226 227 TempBuffer = LogDev->Irq[i].Description.Mask; 228 RtlInitializeBitMap(&TempBitmap, 229 &TempBuffer, 230 RTL_BITS_OF(LogDev->Irq[i].Description.Mask)); 231 ResourceCount += RtlNumberOfSetBits(&TempBitmap); 232 } 233 for (i = 0; i < RTL_NUMBER_OF(LogDev->Dma); i++) 234 { 235 if (!LogDev->Dma[i].Description.Mask) 236 continue; 237 238 TempBuffer = LogDev->Dma[i].Description.Mask; 239 RtlInitializeBitMap(&TempBitmap, 240 &TempBuffer, 241 RTL_BITS_OF(LogDev->Dma[i].Description.Mask)); 242 ResourceCount += RtlNumberOfSetBits(&TempBitmap); 243 } 244 for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange); i++) 245 { 246 if (!LogDev->MemRange[i].Description.Length) 247 continue; 248 249 ResourceCount++; 250 } 251 for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange32); i++) 252 { 253 if (!LogDev->MemRange32[i].Description.Length) 254 continue; 255 256 ResourceCount++; 257 } 258 if (Alternatives) 259 { 260 ULONG BitCount; 261 262 if (HasIoAlternatives(Alternatives)) 263 AltCount++; 264 if (HasIrqAlternatives(Alternatives)) 265 AltCount++; 266 if (HasDmaAlternatives(Alternatives)) 267 AltCount++; 268 if (HasMemoryAlternatives(Alternatives)) 269 AltCount++; 270 if (HasMemory32Alternatives(Alternatives)) 271 AltCount++; 272 ResourceCount += AltCount; 273 274 if (HasIrqAlternatives(Alternatives)) 275 { 276 for (i = 0; i < Alternatives->Count; i++) 277 { 278 TempBuffer = Alternatives->Irq[i].Mask; 279 RtlInitializeBitMap(&TempBitmap, 280 &TempBuffer, 281 RTL_BITS_OF(Alternatives->Irq[i].Mask)); 282 BitCount = RtlNumberOfSetBits(&TempBitmap); 283 284 if (BitCount > 1) 285 AltOptionalCount += BitCount - 1; 286 } 287 } 288 if (HasDmaAlternatives(Alternatives)) 289 { 290 for (i = 0; i < Alternatives->Count; i++) 291 { 292 TempBuffer = Alternatives->Dma[i].Mask; 293 RtlInitializeBitMap(&TempBitmap, 294 &TempBuffer, 295 RTL_BITS_OF(Alternatives->Dma[i].Mask)); 296 BitCount = RtlNumberOfSetBits(&TempBitmap); 297 298 if (BitCount > 1) 299 AltOptionalCount += BitCount - 1; 300 } 301 } 302 } 303 if (ResourceCount == 0) 304 return STATUS_SUCCESS; 305 306 /* Allocate memory to store requirements */ 307 ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST); 308 if (Alternatives) 309 { 310 ListSize += sizeof(IO_RESOURCE_DESCRIPTOR) * (ResourceCount - 1) * Alternatives->Count 311 + sizeof(IO_RESOURCE_LIST) * (Alternatives->Count - 1) 312 + sizeof(IO_RESOURCE_DESCRIPTOR) * AltOptionalCount; 313 } 314 else 315 { 316 ListSize += sizeof(IO_RESOURCE_DESCRIPTOR) * (ResourceCount - 1); 317 } 318 RequirementsList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP); 319 if (!RequirementsList) 320 return STATUS_NO_MEMORY; 321 322 RequirementsList->ListSize = ListSize; 323 RequirementsList->InterfaceType = Isa; 324 RequirementsList->AlternativeLists = Alternatives ? Alternatives->Count : 1; 325 326 RequirementsList->List[0].Version = 1; 327 RequirementsList->List[0].Revision = 1; 328 RequirementsList->List[0].Count = ResourceCount; 329 330 /* Store requirements */ 331 Descriptor = RequirementsList->List[0].Descriptors; 332 for (i = 0; i < RTL_NUMBER_OF(LogDev->Io); i++) 333 { 334 if (!LogDev->Io[i].Description.Length) 335 break; 336 337 IsaConvertIoRequirement(Descriptor++, &LogDev->Io[i].Description); 338 } 339 for (i = 0; i < RTL_NUMBER_OF(LogDev->Irq); i++) 340 { 341 if (!LogDev->Irq[i].Description.Mask) 342 continue; 343 344 FirstDescriptor = TRUE; 345 346 for (j = 0; j < RTL_BITS_OF(LogDev->Irq[i].Description.Mask); j++) 347 { 348 if (!(LogDev->Irq[i].Description.Mask & (1 << j))) 349 continue; 350 351 IsaConvertIrqRequirement(Descriptor++, 352 &LogDev->Irq[i].Description, 353 j, 354 FirstDescriptor); 355 356 if (FirstDescriptor) 357 FirstDescriptor = FALSE; 358 } 359 } 360 for (i = 0; i < RTL_NUMBER_OF(LogDev->Dma); i++) 361 { 362 if (!LogDev->Dma[i].Description.Mask) 363 continue; 364 365 FirstDescriptor = TRUE; 366 367 for (j = 0; j < RTL_BITS_OF(LogDev->Dma[i].Description.Mask); j++) 368 { 369 if (!(LogDev->Dma[i].Description.Mask & (1 << j))) 370 continue; 371 372 IsaConvertDmaRequirement(Descriptor++, 373 &LogDev->Dma[i].Description, 374 j, 375 FirstDescriptor); 376 377 if (FirstDescriptor) 378 FirstDescriptor = FALSE; 379 } 380 } 381 for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange); i++) 382 { 383 if (!LogDev->MemRange[i].Description.Length) 384 continue; 385 386 IsaConvertMemRangeRequirement(Descriptor++, 387 &LogDev->MemRange[i].Description); 388 } 389 for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange32); i++) 390 { 391 if (!LogDev->MemRange32[i].Description.Length) 392 continue; 393 394 IsaConvertMemRange32Requirement(Descriptor++, 395 &LogDev->MemRange32[i].Description); 396 } 397 if (Alternatives) 398 { 399 UCHAR BestConfig[ISAPNP_MAX_ALTERNATIVES]; 400 PIO_RESOURCE_LIST AltList = &RequirementsList->List[0]; 401 PIO_RESOURCE_LIST NextList = AltList; 402 403 IsaDetermineBestConfig(BestConfig, Alternatives); 404 405 for (i = 0; i < RequirementsList->AlternativeLists; i++) 406 { 407 RtlMoveMemory(NextList, AltList, sizeof(IO_RESOURCE_LIST)); 408 409 /* Just because the 'NextList->Count++' correction */ 410 NextList->Count = ResourceCount; 411 /* 412 * For example, the ROM 413 * 0x15, ... // Logical device ID 414 * 0x30, // Start DF 415 * 0x22, 0x04, 0x00 // IRQ 416 * 0x30, // Start DF 417 * 0x22, 0xC0, 0x00 // IRQ 418 * 0x38, // End DF 419 * 0x2A, 0x20, 0x3A // DMA 420 * 0x22, 0x00, 0x08 // IRQ 421 * 0x79, 0x00 // END 422 * 423 * will be represented as the following resource requirements list: 424 * Interface 1 Bus 0 Slot 0 AlternativeLists 2 425 * AltList 1, AltList->Count 3 426 * [Option 0, ShareDisposition 1, Flags 1] INT: Min B Max B 427 * [Option 0, ShareDisposition 0, Flags 0] DMA: Min 5 Max 5 428 * [Option 0, ShareDisposition 1, Flags 1] INT: Min 2 Max 2 429 * End Descriptors 430 * AltList 2, AltList->Count 4 431 * [Option 0, ShareDisposition 1, Flags 1] INT: Min B Max B 432 * [Option 0, ShareDisposition 0, Flags 0] DMA: Min 5 Max 5 433 * [Option 0, ShareDisposition 1, Flags 1] INT: Min 6 Max 6 434 * [Option 8, ShareDisposition 1, Flags 1] INT: Min 7 Max 7 435 * End Descriptors 436 */ 437 438 /* Propagate the fixed resources to our new list */ 439 for (j = 0; j < AltList->Count - AltCount; j++) 440 { 441 RtlMoveMemory(&NextList->Descriptors[j], 442 &AltList->Descriptors[j], 443 sizeof(IO_RESOURCE_DESCRIPTOR)); 444 } 445 446 Descriptor = &NextList->Descriptors[NextList->Count - AltCount]; 447 448 /* 449 * Append alternatives. 450 * NOTE: To keep it simple, we append these to the end of the list. 451 */ 452 if (HasIoAlternatives(Alternatives)) 453 { 454 IsaConvertIoRequirement(Descriptor++, 455 &Alternatives->Io[BestConfig[i]]); 456 } 457 if (HasIrqAlternatives(Alternatives)) 458 { 459 FirstDescriptor = TRUE; 460 461 for (j = 0; j < RTL_BITS_OF(Alternatives->Irq[BestConfig[i]].Mask); j++) 462 { 463 if (!(Alternatives->Irq[BestConfig[i]].Mask & (1 << j))) 464 continue; 465 466 IsaConvertIrqRequirement(Descriptor++, 467 &Alternatives->Irq[BestConfig[i]], 468 j, 469 FirstDescriptor); 470 471 if (FirstDescriptor) 472 FirstDescriptor = FALSE; 473 else 474 NextList->Count++; 475 } 476 } 477 if (HasDmaAlternatives(Alternatives)) 478 { 479 FirstDescriptor = TRUE; 480 481 for (j = 0; j < RTL_BITS_OF(Alternatives->Dma[BestConfig[i]].Mask); j++) 482 { 483 if (!(Alternatives->Dma[BestConfig[i]].Mask & (1 << j))) 484 continue; 485 486 IsaConvertDmaRequirement(Descriptor++, 487 &Alternatives->Dma[BestConfig[i]], 488 j, 489 FirstDescriptor); 490 491 if (FirstDescriptor) 492 FirstDescriptor = FALSE; 493 else 494 NextList->Count++; 495 } 496 } 497 if (HasMemoryAlternatives(Alternatives)) 498 { 499 IsaConvertMemRangeRequirement(Descriptor++, 500 &Alternatives->MemRange[BestConfig[i]]); 501 } 502 if (HasMemory32Alternatives(Alternatives)) 503 { 504 IsaConvertMemRange32Requirement(Descriptor++, 505 &Alternatives->MemRange32[BestConfig[i]]); 506 } 507 508 NextList = (PIO_RESOURCE_LIST)(NextList->Descriptors + NextList->Count); 509 } 510 } 511 512 PdoExt->RequirementsList = RequirementsList; 513 return STATUS_SUCCESS; 514 } 515 516 CODE_SEG("PAGE") 517 BOOLEAN 518 FindIoDescriptor( 519 _In_ PISAPNP_LOGICAL_DEVICE LogDevice, 520 _In_opt_ ULONG Base, 521 _In_ ULONG RangeStart, 522 _In_ ULONG RangeEnd, 523 _Out_opt_ PUCHAR Information, 524 _Out_opt_ PULONG Length, 525 _Out_opt_ PUCHAR WriteOrder) 526 { 527 ULONG i; 528 BOOLEAN Match; 529 PISAPNP_IO_DESCRIPTION Description; 530 531 PAGED_CODE(); 532 533 for (i = 0; i < RTL_NUMBER_OF(LogDevice->Io); i++) 534 { 535 Description = &LogDevice->Io[i].Description; 536 537 Match = Base ? (Base >= Description->Minimum) && (Base <= Description->Maximum) 538 : (RangeStart >= Description->Minimum) && 539 (RangeEnd <= (ULONG)(Description->Maximum + Description->Length - 1)); 540 541 if (Match) 542 { 543 if (Information) 544 *Information = Description->Information; 545 if (Length) 546 *Length = Description->Length; 547 if (WriteOrder) 548 *WriteOrder = LogDevice->Io[i].Index; 549 550 return TRUE; 551 } 552 } 553 554 if (!LogDevice->Alternatives) 555 return FALSE; 556 557 for (i = 0; i < LogDevice->Alternatives->Count; i++) 558 { 559 Description = &LogDevice->Alternatives->Io[i]; 560 561 Match = Base ? (Base >= Description->Minimum) && (Base <= Description->Maximum) 562 : (RangeStart >= Description->Minimum) && 563 (RangeEnd <= (ULONG)(Description->Maximum + Description->Length - 1)); 564 565 if (Match) 566 { 567 if (Information) 568 *Information = Description->Information; 569 if (Length) 570 *Length = Description->Length; 571 if (WriteOrder) 572 *WriteOrder = LogDevice->Alternatives->IoIndex; 573 574 return TRUE; 575 } 576 } 577 578 return FALSE; 579 } 580 581 CODE_SEG("PAGE") 582 BOOLEAN 583 FindIrqDescriptor( 584 _In_ PISAPNP_LOGICAL_DEVICE LogDevice, 585 _In_ ULONG Vector, 586 _Out_opt_ PUCHAR WriteOrder) 587 { 588 ULONG i, j; 589 PISAPNP_IRQ_DESCRIPTION Description; 590 591 PAGED_CODE(); 592 593 for (i = 0; i < RTL_NUMBER_OF(LogDevice->Irq); i++) 594 { 595 Description = &LogDevice->Irq[i].Description; 596 597 for (j = 0; j < RTL_BITS_OF(Description->Mask); j++) 598 { 599 if (Description->Mask & (1 << j)) 600 { 601 if (j == Vector) 602 { 603 if (WriteOrder) 604 *WriteOrder = LogDevice->Irq[i].Index; 605 606 return TRUE; 607 } 608 } 609 } 610 } 611 612 if (!LogDevice->Alternatives) 613 return FALSE; 614 615 for (i = 0; i < LogDevice->Alternatives->Count; i++) 616 { 617 Description = &LogDevice->Alternatives->Irq[i]; 618 619 for (j = 0; j < RTL_BITS_OF(Description->Mask); j++) 620 { 621 if (Description->Mask & (1 << j)) 622 { 623 if (j == Vector) 624 { 625 if (WriteOrder) 626 *WriteOrder = LogDevice->Alternatives->IrqIndex; 627 628 return TRUE; 629 } 630 } 631 } 632 } 633 634 return FALSE; 635 } 636 637 CODE_SEG("PAGE") 638 BOOLEAN 639 FindDmaDescriptor( 640 _In_ PISAPNP_LOGICAL_DEVICE LogDevice, 641 _In_ ULONG Channel, 642 _Out_opt_ PUCHAR WriteOrder) 643 { 644 ULONG i, j; 645 PISAPNP_DMA_DESCRIPTION Description; 646 647 PAGED_CODE(); 648 649 for (i = 0; i < RTL_NUMBER_OF(LogDevice->Dma); i++) 650 { 651 Description = &LogDevice->Dma[i].Description; 652 653 for (j = 0; j < RTL_BITS_OF(Description->Mask); j++) 654 { 655 if (Description->Mask & (1 << j)) 656 { 657 if (j == Channel) 658 { 659 if (WriteOrder) 660 *WriteOrder = LogDevice->Dma[i].Index; 661 662 return TRUE; 663 } 664 } 665 } 666 } 667 668 if (!LogDevice->Alternatives) 669 return FALSE; 670 671 for (i = 0; i < LogDevice->Alternatives->Count; i++) 672 { 673 Description = &LogDevice->Alternatives->Dma[i]; 674 675 for (j = 0; j < RTL_BITS_OF(Description->Mask); j++) 676 { 677 if (Description->Mask & (1 << j)) 678 { 679 if (j == Channel) 680 { 681 if (WriteOrder) 682 *WriteOrder = LogDevice->Alternatives->DmaIndex; 683 684 return TRUE; 685 } 686 } 687 } 688 } 689 690 return FALSE; 691 } 692 693 CODE_SEG("PAGE") 694 BOOLEAN 695 FindMemoryDescriptor( 696 _In_ PISAPNP_LOGICAL_DEVICE LogDevice, 697 _In_ ULONG RangeStart, 698 _In_ ULONG RangeEnd, 699 _Out_opt_ PBOOLEAN Memory32, 700 _Out_opt_ PUCHAR Information, 701 _Out_opt_ PUCHAR WriteOrder) 702 { 703 ULONG i; 704 PISAPNP_MEMRANGE_DESCRIPTION Description; 705 PISAPNP_MEMRANGE32_DESCRIPTION Description32; 706 707 PAGED_CODE(); 708 709 for (i = 0; i < RTL_NUMBER_OF(LogDevice->MemRange); i++) 710 { 711 Description = &LogDevice->MemRange[i].Description; 712 713 if ((RangeStart >= (ULONG)(Description->Minimum << 8)) && 714 (RangeEnd <= (ULONG)((Description->Maximum << 8) + (Description->Length << 8) - 1))) 715 { 716 if (Memory32) 717 *Memory32 = FALSE; 718 if (Information) 719 *Information = Description->Information; 720 if (WriteOrder) 721 *WriteOrder = LogDevice->MemRange[i].Index; 722 723 return TRUE; 724 } 725 } 726 for (i = 0; i < RTL_NUMBER_OF(LogDevice->MemRange32); i++) 727 { 728 Description32 = &LogDevice->MemRange32[i].Description; 729 730 if ((RangeStart >= Description32->Minimum) && 731 (RangeEnd <= (Description32->Maximum + Description32->Length - 1))) 732 { 733 if (Memory32) 734 *Memory32 = TRUE; 735 if (Information) 736 *Information = Description32->Information; 737 if (WriteOrder) 738 *WriteOrder = LogDevice->MemRange32[i].Index; 739 740 return TRUE; 741 } 742 } 743 744 if (!LogDevice->Alternatives) 745 return FALSE; 746 747 for (i = 0; i < LogDevice->Alternatives->Count; i++) 748 { 749 Description = &LogDevice->Alternatives->MemRange[i]; 750 751 if ((RangeStart >= (ULONG)(Description->Minimum << 8)) && 752 (RangeEnd <= (ULONG)((Description->Maximum << 8) + (Description->Length << 8) - 1))) 753 { 754 if (Memory32) 755 *Memory32 = FALSE; 756 if (Information) 757 *Information = Description->Information; 758 if (WriteOrder) 759 *WriteOrder = LogDevice->Alternatives->MemRangeIndex; 760 761 return TRUE; 762 } 763 } 764 for (i = 0; i < LogDevice->Alternatives->Count; i++) 765 { 766 Description32 = &LogDevice->Alternatives->MemRange32[i]; 767 768 if ((RangeStart >= Description32->Minimum) && 769 (RangeEnd <= (Description32->Maximum + Description32->Length - 1))) 770 { 771 if (Memory32) 772 *Memory32 = TRUE; 773 if (Information) 774 *Information = Description32->Information; 775 if (WriteOrder) 776 *WriteOrder = LogDevice->Alternatives->MemRange32Index; 777 778 return TRUE; 779 } 780 } 781 782 return FALSE; 783 } 784 785 static 786 CODE_SEG("PAGE") 787 NTSTATUS 788 IsaPnpCreateLogicalDeviceResources( 789 _In_ PISAPNP_PDO_EXTENSION PdoExt) 790 { 791 PISAPNP_LOGICAL_DEVICE LogDev = PdoExt->IsaPnpDevice; 792 ULONG ResourceCount = 0; 793 UCHAR Information; 794 ULONG ListSize, i; 795 PCM_RESOURCE_LIST ResourceList; 796 PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor; 797 798 PAGED_CODE(); 799 800 if (!(LogDev->Flags & ISAPNP_HAS_RESOURCES)) 801 return STATUS_SUCCESS; 802 803 /* Count number of required resources */ 804 for (i = 0; i < RTL_NUMBER_OF(LogDev->Io); i++) 805 { 806 if (LogDev->Io[i].CurrentBase) 807 ResourceCount++; 808 else 809 break; 810 } 811 for (i = 0; i < RTL_NUMBER_OF(LogDev->Irq); i++) 812 { 813 if (LogDev->Irq[i].CurrentNo) 814 ResourceCount++; 815 else 816 break; 817 } 818 for (i = 0; i < RTL_NUMBER_OF(LogDev->Dma); i++) 819 { 820 if (LogDev->Dma[i].CurrentChannel != 4) 821 ResourceCount++; 822 else 823 break; 824 } 825 for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange); i++) 826 { 827 if (LogDev->MemRange[i].CurrentBase) 828 ResourceCount++; 829 else 830 break; 831 } 832 for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange32); i++) 833 { 834 if (LogDev->MemRange32[i].CurrentBase) 835 ResourceCount++; 836 else 837 break; 838 } 839 if (ResourceCount == 0) 840 return STATUS_SUCCESS; 841 842 /* Allocate memory to store resources */ 843 ListSize = sizeof(CM_RESOURCE_LIST) 844 + (ResourceCount - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR); 845 ResourceList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP); 846 if (!ResourceList) 847 return STATUS_NO_MEMORY; 848 849 ResourceList->Count = 1; 850 ResourceList->List[0].InterfaceType = Isa; 851 ResourceList->List[0].PartialResourceList.Version = 1; 852 ResourceList->List[0].PartialResourceList.Revision = 1; 853 ResourceList->List[0].PartialResourceList.Count = ResourceCount; 854 855 /* Store resources */ 856 ResourceCount = 0; 857 for (i = 0; i < RTL_NUMBER_OF(LogDev->Io); i++) 858 { 859 ULONG CurrentLength; 860 861 if (!LogDev->Io[i].CurrentBase) 862 break; 863 864 if (!FindIoDescriptor(LogDev, 865 LogDev->Io[i].CurrentBase, 866 0, 867 0, 868 &Information, 869 &CurrentLength, 870 NULL)) 871 { 872 goto InvalidBiosResources; 873 } 874 875 Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++]; 876 Descriptor->Type = CmResourceTypePort; 877 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 878 Descriptor->Flags = CM_RESOURCE_PORT_IO; 879 if (Information & 0x1) 880 Descriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE; 881 else 882 Descriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE; 883 Descriptor->u.Port.Length = CurrentLength; 884 Descriptor->u.Port.Start.LowPart = LogDev->Io[i].CurrentBase; 885 } 886 for (i = 0; i < RTL_NUMBER_OF(LogDev->Irq); i++) 887 { 888 if (!LogDev->Irq[i].CurrentNo) 889 break; 890 891 if (!FindIrqDescriptor(LogDev, LogDev->Irq[i].CurrentNo, NULL)) 892 goto InvalidBiosResources; 893 894 Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++]; 895 Descriptor->Type = CmResourceTypeInterrupt; 896 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 897 if (LogDev->Irq[i].CurrentType & 0x01) 898 Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; 899 else 900 Descriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; 901 Descriptor->u.Interrupt.Level = LogDev->Irq[i].CurrentNo; 902 Descriptor->u.Interrupt.Vector = LogDev->Irq[i].CurrentNo; 903 Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF; 904 } 905 for (i = 0; i < RTL_NUMBER_OF(LogDev->Dma); i++) 906 { 907 if (LogDev->Dma[i].CurrentChannel == 4) 908 break; 909 910 if (!FindDmaDescriptor(LogDev, LogDev->Dma[i].CurrentChannel, NULL)) 911 goto InvalidBiosResources; 912 913 Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++]; 914 Descriptor->Type = CmResourceTypeDma; 915 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 916 Descriptor->Flags = CM_RESOURCE_DMA_8; /* Ignore information byte for compatibility */ 917 Descriptor->u.Dma.Channel = LogDev->Dma[i].CurrentChannel; 918 } 919 for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange); i++) 920 { 921 if (!LogDev->MemRange[i].CurrentBase) 922 break; 923 924 if (!FindMemoryDescriptor(LogDev, 925 LogDev->MemRange[i].CurrentBase, 926 LogDev->MemRange[i].CurrentLength, 927 NULL, 928 &Information, 929 NULL)) 930 { 931 goto InvalidBiosResources; 932 } 933 934 Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++]; 935 Descriptor->Type = CmResourceTypeMemory; 936 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 937 Descriptor->Flags = CM_RESOURCE_MEMORY_24; 938 if ((Information & 0x40) || !(Information & 0x01)) 939 Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY; 940 else 941 Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE; 942 Descriptor->u.Memory.Length = LogDev->MemRange[i].Description.Length; 943 Descriptor->u.Memory.Start.QuadPart = LogDev->MemRange[i].CurrentBase; 944 } 945 for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange32); i++) 946 { 947 if (!LogDev->MemRange32[i].CurrentBase) 948 break; 949 950 if (!FindMemoryDescriptor(LogDev, 951 LogDev->MemRange32[i].CurrentBase, 952 LogDev->MemRange32[i].CurrentLength, 953 NULL, 954 &Information, 955 NULL)) 956 { 957 goto InvalidBiosResources; 958 } 959 960 Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++]; 961 Descriptor->Type = CmResourceTypeMemory; 962 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 963 Descriptor->Flags = CM_RESOURCE_MEMORY_24; 964 if ((Information & 0x40) || !(Information & 0x01)) 965 Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY; 966 else 967 Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE; 968 Descriptor->u.Memory.Length = LogDev->MemRange32[i].Description.Length; 969 Descriptor->u.Memory.Start.QuadPart = LogDev->MemRange32[i].CurrentBase; 970 } 971 972 PdoExt->ResourceList = ResourceList; 973 PdoExt->ResourceListSize = ListSize; 974 return STATUS_SUCCESS; 975 976 InvalidBiosResources: 977 DPRINT("Invalid boot resources! (CSN %u, LDN %u)\n", LogDev->CSN, LogDev->LDN); 978 979 LogDev->Flags &= ~ISAPNP_HAS_RESOURCES; 980 ExFreePoolWithTag(ResourceList, TAG_ISAPNP); 981 return STATUS_SUCCESS; 982 } 983 984 _Dispatch_type_(IRP_MJ_CREATE) 985 _Dispatch_type_(IRP_MJ_CLOSE) 986 static CODE_SEG("PAGE") DRIVER_DISPATCH_PAGED IsaCreateClose; 987 988 static 989 CODE_SEG("PAGE") 990 NTSTATUS 991 NTAPI 992 IsaCreateClose( 993 _In_ PDEVICE_OBJECT DeviceObject, 994 _Inout_ PIRP Irp) 995 { 996 PAGED_CODE(); 997 998 Irp->IoStatus.Status = STATUS_SUCCESS; 999 1000 DPRINT("%s(%p, %p)\n", __FUNCTION__, DeviceObject, Irp); 1001 1002 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1003 1004 return STATUS_SUCCESS; 1005 } 1006 1007 _Dispatch_type_(IRP_MJ_DEVICE_CONTROL) 1008 _Dispatch_type_(IRP_MJ_SYSTEM_CONTROL) 1009 static CODE_SEG("PAGE") DRIVER_DISPATCH_PAGED IsaForwardOrIgnore; 1010 1011 static 1012 CODE_SEG("PAGE") 1013 NTSTATUS 1014 NTAPI 1015 IsaForwardOrIgnore( 1016 _In_ PDEVICE_OBJECT DeviceObject, 1017 _Inout_ PIRP Irp) 1018 { 1019 PISAPNP_COMMON_EXTENSION CommonExt = DeviceObject->DeviceExtension; 1020 1021 PAGED_CODE(); 1022 1023 DPRINT("%s(%p, %p) Minor - %X\n", __FUNCTION__, DeviceObject, Irp, 1024 IoGetCurrentIrpStackLocation(Irp)->MinorFunction); 1025 1026 if (CommonExt->Signature == IsaPnpBus) 1027 { 1028 IoSkipCurrentIrpStackLocation(Irp); 1029 return IoCallDriver(((PISAPNP_FDO_EXTENSION)CommonExt)->Ldo, Irp); 1030 } 1031 else 1032 { 1033 NTSTATUS Status = Irp->IoStatus.Status; 1034 1035 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1036 return Status; 1037 } 1038 } 1039 1040 CODE_SEG("PAGE") 1041 NTSTATUS 1042 IsaPnpCreateReadPortDORequirements( 1043 _In_ PISAPNP_PDO_EXTENSION PdoExt, 1044 _In_opt_ ULONG SelectedReadPort) 1045 { 1046 ULONG ResourceCount, ListSize, i; 1047 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList; 1048 PIO_RESOURCE_DESCRIPTOR Descriptor; 1049 const ULONG Ports[] = { ISAPNP_WRITE_DATA, ISAPNP_ADDRESS }; 1050 const ULONG ReadPorts[] = { 0x274, 0x3E4, 0x204, 0x2E4, 0x354, 0x2F4 }; 1051 1052 PAGED_CODE(); 1053 1054 if (SelectedReadPort) 1055 { 1056 /* 1057 * [IO descriptor: ISAPNP_WRITE_DATA, required] 1058 * [IO descriptor: ISAPNP_WRITE_DATA, optional] 1059 * [IO descriptor: ISAPNP_ADDRESS, required] 1060 * [IO descriptor: ISAPNP_ADDRESS, optional] 1061 * [IO descriptor: Selected Read Port, required] 1062 * [IO descriptor: Read Port 1, optional] 1063 * [IO descriptor: Read Port 2, optional] 1064 * [...] 1065 * [IO descriptor: Read Port X - 1, optional] 1066 */ 1067 ResourceCount = RTL_NUMBER_OF(Ports) * 2 + RTL_NUMBER_OF(ReadPorts); 1068 } 1069 else 1070 { 1071 /* 1072 * [IO descriptor: ISAPNP_WRITE_DATA, required] 1073 * [IO descriptor: ISAPNP_WRITE_DATA, optional] 1074 * [IO descriptor: ISAPNP_ADDRESS, required] 1075 * [IO descriptor: ISAPNP_ADDRESS, optional] 1076 * [IO descriptor: Read Port 1, required] 1077 * [IO descriptor: Read Port 1, optional] 1078 * [IO descriptor: Read Port 2, required] 1079 * [IO descriptor: Read Port 2, optional] 1080 * [...] 1081 * [IO descriptor: Read Port X, required] 1082 * [IO descriptor: Read Port X, optional] 1083 */ 1084 ResourceCount = (RTL_NUMBER_OF(Ports) + RTL_NUMBER_OF(ReadPorts)) * 2; 1085 } 1086 ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) + 1087 sizeof(IO_RESOURCE_DESCRIPTOR) * (ResourceCount - 1); 1088 RequirementsList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP); 1089 if (!RequirementsList) 1090 return STATUS_NO_MEMORY; 1091 1092 RequirementsList->ListSize = ListSize; 1093 RequirementsList->AlternativeLists = 1; 1094 1095 RequirementsList->List[0].Version = 1; 1096 RequirementsList->List[0].Revision = 1; 1097 RequirementsList->List[0].Count = ResourceCount; 1098 1099 Descriptor = &RequirementsList->List[0].Descriptors[0]; 1100 1101 /* Store the Data port and the Address port */ 1102 for (i = 0; i < RTL_NUMBER_OF(Ports) * 2; i++) 1103 { 1104 if ((i % 2) == 0) 1105 { 1106 /* Expected port */ 1107 Descriptor->Type = CmResourceTypePort; 1108 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 1109 Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE; 1110 Descriptor->u.Port.Length = 0x01; 1111 Descriptor->u.Port.Alignment = 0x01; 1112 Descriptor->u.Port.MinimumAddress.LowPart = 1113 Descriptor->u.Port.MaximumAddress.LowPart = Ports[i / 2]; 1114 } 1115 else 1116 { 1117 /* ... but mark it as optional */ 1118 Descriptor->Option = IO_RESOURCE_ALTERNATIVE; 1119 Descriptor->Type = CmResourceTypePort; 1120 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 1121 Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE; 1122 Descriptor->u.Port.Alignment = 0x01; 1123 } 1124 1125 Descriptor++; 1126 } 1127 1128 /* Store the Read Ports */ 1129 if (SelectedReadPort) 1130 { 1131 BOOLEAN Selected = FALSE; 1132 1133 DBG_UNREFERENCED_LOCAL_VARIABLE(Selected); 1134 1135 for (i = 0; i < RTL_NUMBER_OF(ReadPorts); i++) 1136 { 1137 if (ReadPorts[i] != SelectedReadPort) 1138 Descriptor->Option = IO_RESOURCE_ALTERNATIVE; 1139 else 1140 Selected = TRUE; 1141 Descriptor->Type = CmResourceTypePort; 1142 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 1143 Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE; 1144 Descriptor->u.Port.Length = 0x04; 1145 Descriptor->u.Port.Alignment = 0x01; 1146 Descriptor->u.Port.MinimumAddress.LowPart = ReadPorts[i]; 1147 Descriptor->u.Port.MaximumAddress.LowPart = ReadPorts[i] + 1148 Descriptor->u.Port.Length - 1; 1149 1150 Descriptor++; 1151 } 1152 1153 ASSERT(Selected == TRUE); 1154 } 1155 else 1156 { 1157 for (i = 0; i < RTL_NUMBER_OF(ReadPorts) * 2; i++) 1158 { 1159 if ((i % 2) == 0) 1160 { 1161 /* Expected port */ 1162 Descriptor->Type = CmResourceTypePort; 1163 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 1164 Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE; 1165 Descriptor->u.Port.Length = 0x04; 1166 Descriptor->u.Port.Alignment = 0x01; 1167 Descriptor->u.Port.MinimumAddress.LowPart = ReadPorts[i / 2]; 1168 Descriptor->u.Port.MaximumAddress.LowPart = ReadPorts[i / 2] + 1169 Descriptor->u.Port.Length - 1; 1170 } 1171 else 1172 { 1173 /* ... but mark it as optional */ 1174 Descriptor->Option = IO_RESOURCE_ALTERNATIVE; 1175 Descriptor->Type = CmResourceTypePort; 1176 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 1177 Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE; 1178 Descriptor->u.Port.Alignment = 0x01; 1179 } 1180 1181 Descriptor++; 1182 } 1183 } 1184 1185 PdoExt->RequirementsList = RequirementsList; 1186 return STATUS_SUCCESS; 1187 } 1188 1189 static 1190 CODE_SEG("PAGE") 1191 NTSTATUS 1192 IsaPnpCreateReadPortDOResources( 1193 _In_ PISAPNP_PDO_EXTENSION PdoExt) 1194 { 1195 const USHORT Ports[] = { ISAPNP_WRITE_DATA, ISAPNP_ADDRESS }; 1196 ULONG ListSize, i; 1197 PCM_RESOURCE_LIST ResourceList; 1198 PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor; 1199 1200 PAGED_CODE(); 1201 1202 ListSize = sizeof(CM_RESOURCE_LIST) + 1203 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * (RTL_NUMBER_OF(Ports) - 1); 1204 ResourceList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP); 1205 if (!ResourceList) 1206 return STATUS_NO_MEMORY; 1207 1208 ResourceList->Count = 1; 1209 ResourceList->List[0].InterfaceType = Internal; 1210 ResourceList->List[0].PartialResourceList.Version = 1; 1211 ResourceList->List[0].PartialResourceList.Revision = 1; 1212 ResourceList->List[0].PartialResourceList.Count = RTL_NUMBER_OF(Ports); 1213 1214 Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[0]; 1215 for (i = 0; i < RTL_NUMBER_OF(Ports); i++) 1216 { 1217 Descriptor->Type = CmResourceTypePort; 1218 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 1219 Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE; 1220 Descriptor->u.Port.Length = 0x01; 1221 Descriptor->u.Port.Start.LowPart = Ports[i]; 1222 1223 Descriptor++; 1224 } 1225 1226 PdoExt->ResourceList = ResourceList; 1227 PdoExt->ResourceListSize = ListSize; 1228 return STATUS_SUCCESS; 1229 } 1230 1231 static 1232 CODE_SEG("PAGE") 1233 NTSTATUS 1234 IsaPnpCreateReadPortDO( 1235 _In_ PISAPNP_FDO_EXTENSION FdoExt) 1236 { 1237 PISAPNP_PDO_EXTENSION PdoExt; 1238 NTSTATUS Status; 1239 1240 PAGED_CODE(); 1241 ASSERT(ReadPortCreated == FALSE); 1242 1243 DPRINT("Creating Read Port\n"); 1244 1245 Status = IoCreateDevice(FdoExt->DriverObject, 1246 sizeof(ISAPNP_PDO_EXTENSION), 1247 NULL, 1248 FILE_DEVICE_CONTROLLER, 1249 FILE_DEVICE_SECURE_OPEN | FILE_AUTOGENERATED_DEVICE_NAME, 1250 FALSE, 1251 &FdoExt->ReadPortPdo); 1252 if (!NT_SUCCESS(Status)) 1253 return Status; 1254 1255 PdoExt = FdoExt->ReadPortPdo->DeviceExtension; 1256 RtlZeroMemory(PdoExt, sizeof(ISAPNP_PDO_EXTENSION)); 1257 PdoExt->Common.Signature = IsaPnpReadDataPort; 1258 PdoExt->Common.Self = FdoExt->ReadPortPdo; 1259 PdoExt->Common.State = dsStopped; 1260 PdoExt->FdoExt = FdoExt; 1261 1262 Status = IsaPnpCreateReadPortDORequirements(PdoExt, 0); 1263 if (!NT_SUCCESS(Status)) 1264 goto Failure; 1265 1266 Status = IsaPnpCreateReadPortDOResources(PdoExt); 1267 if (!NT_SUCCESS(Status)) 1268 goto Failure; 1269 1270 FdoExt->ReadPortPdo->Flags &= ~DO_DEVICE_INITIALIZING; 1271 1272 return Status; 1273 1274 Failure: 1275 IsaPnpRemoveReadPortDO(FdoExt->ReadPortPdo); 1276 1277 FdoExt->ReadPortPdo = NULL; 1278 1279 return Status; 1280 } 1281 1282 CODE_SEG("PAGE") 1283 VOID 1284 IsaPnpRemoveReadPortDO( 1285 _In_ PDEVICE_OBJECT Pdo) 1286 { 1287 PISAPNP_PDO_EXTENSION ReadPortExt = Pdo->DeviceExtension; 1288 1289 PAGED_CODE(); 1290 1291 DPRINT("Removing Read Port\n"); 1292 1293 if (ReadPortExt->RequirementsList) 1294 ExFreePoolWithTag(ReadPortExt->RequirementsList, TAG_ISAPNP); 1295 1296 if (ReadPortExt->ResourceList) 1297 ExFreePoolWithTag(ReadPortExt->ResourceList, TAG_ISAPNP); 1298 1299 IoDeleteDevice(Pdo); 1300 } 1301 1302 CODE_SEG("PAGE") 1303 NTSTATUS 1304 IsaPnpFillDeviceRelations( 1305 _In_ PISAPNP_FDO_EXTENSION FdoExt, 1306 _Inout_ PIRP Irp, 1307 _In_ BOOLEAN IncludeDataPort) 1308 { 1309 NTSTATUS Status = STATUS_SUCCESS; 1310 PLIST_ENTRY CurrentEntry; 1311 PISAPNP_LOGICAL_DEVICE IsaDevice; 1312 PDEVICE_RELATIONS DeviceRelations; 1313 ULONG PdoCount, i = 0; 1314 1315 PAGED_CODE(); 1316 1317 IsaPnpAcquireBusDataLock(); 1318 1319 /* Try to claim the Read Port for our FDO */ 1320 if (!ReadPortCreated) 1321 { 1322 Status = IsaPnpCreateReadPortDO(FdoExt); 1323 if (!NT_SUCCESS(Status)) 1324 return Status; 1325 1326 ReadPortCreated = TRUE; 1327 } 1328 1329 IsaPnpReleaseBusDataLock(); 1330 1331 /* Inactive ISA bus */ 1332 if (!FdoExt->ReadPortPdo) 1333 IncludeDataPort = FALSE; 1334 1335 IsaPnpAcquireDeviceDataLock(FdoExt); 1336 1337 /* If called from the FDO dispatch routine && Active bus */ 1338 if (IncludeDataPort && FdoExt->ReadPortPdo) 1339 { 1340 PISAPNP_PDO_EXTENSION ReadPortExt = FdoExt->ReadPortPdo->DeviceExtension; 1341 1342 if ((ReadPortExt->Flags & ISAPNP_READ_PORT_ALLOW_FDO_SCAN) && 1343 !(ReadPortExt->Flags & ISAPNP_SCANNED_BY_READ_PORT)) 1344 { 1345 DPRINT("Rescan ISA PnP bus\n"); 1346 1347 /* Run the isolation protocol */ 1348 FdoExt->Cards = IsaHwTryReadDataPort(FdoExt->ReadDataPort); 1349 1350 /* Card identification */ 1351 if (FdoExt->Cards > 0) 1352 (VOID)IsaHwFillDeviceList(FdoExt); 1353 1354 IsaHwWaitForKey(); 1355 } 1356 1357 ReadPortExt->Flags &= ~ISAPNP_SCANNED_BY_READ_PORT; 1358 } 1359 1360 PdoCount = FdoExt->DeviceCount; 1361 if (IncludeDataPort) 1362 ++PdoCount; 1363 1364 CurrentEntry = FdoExt->DeviceListHead.Flink; 1365 while (CurrentEntry != &FdoExt->DeviceListHead) 1366 { 1367 IsaDevice = CONTAINING_RECORD(CurrentEntry, ISAPNP_LOGICAL_DEVICE, DeviceLink); 1368 1369 if (!(IsaDevice->Flags & ISAPNP_PRESENT)) 1370 --PdoCount; 1371 1372 CurrentEntry = CurrentEntry->Flink; 1373 } 1374 1375 DeviceRelations = ExAllocatePoolWithTag(PagedPool, 1376 FIELD_OFFSET(DEVICE_RELATIONS, Objects[PdoCount]), 1377 TAG_ISAPNP); 1378 if (!DeviceRelations) 1379 { 1380 IsaPnpReleaseDeviceDataLock(FdoExt); 1381 return STATUS_NO_MEMORY; 1382 } 1383 1384 if (IncludeDataPort) 1385 { 1386 PISAPNP_PDO_EXTENSION ReadPortExt = FdoExt->ReadPortPdo->DeviceExtension; 1387 1388 DeviceRelations->Objects[i++] = FdoExt->ReadPortPdo; 1389 ObReferenceObject(FdoExt->ReadPortPdo); 1390 1391 /* The Read Port PDO can only be removed by FDO */ 1392 ReadPortExt->Flags |= ISAPNP_ENUMERATED; 1393 } 1394 1395 CurrentEntry = FdoExt->DeviceListHead.Flink; 1396 while (CurrentEntry != &FdoExt->DeviceListHead) 1397 { 1398 PISAPNP_PDO_EXTENSION PdoExt; 1399 1400 IsaDevice = CONTAINING_RECORD(CurrentEntry, ISAPNP_LOGICAL_DEVICE, DeviceLink); 1401 1402 if (!(IsaDevice->Flags & ISAPNP_PRESENT)) 1403 goto SkipPdo; 1404 1405 if (!IsaDevice->Pdo) 1406 { 1407 Status = IoCreateDevice(FdoExt->DriverObject, 1408 sizeof(ISAPNP_PDO_EXTENSION), 1409 NULL, 1410 FILE_DEVICE_CONTROLLER, 1411 FILE_DEVICE_SECURE_OPEN | FILE_AUTOGENERATED_DEVICE_NAME, 1412 FALSE, 1413 &IsaDevice->Pdo); 1414 if (!NT_SUCCESS(Status)) 1415 goto SkipPdo; 1416 1417 IsaDevice->Pdo->Flags &= ~DO_DEVICE_INITIALIZING; 1418 /* The power pagable flag is always unset */ 1419 1420 PdoExt = IsaDevice->Pdo->DeviceExtension; 1421 1422 RtlZeroMemory(PdoExt, sizeof(ISAPNP_PDO_EXTENSION)); 1423 PdoExt->Common.Signature = IsaPnpLogicalDevice; 1424 PdoExt->Common.Self = IsaDevice->Pdo; 1425 PdoExt->Common.State = dsStopped; 1426 PdoExt->IsaPnpDevice = IsaDevice; 1427 PdoExt->FdoExt = FdoExt; 1428 1429 if (!NT_SUCCESS(IsaPnpCreateLogicalDeviceRequirements(PdoExt)) || 1430 !NT_SUCCESS(IsaPnpCreateLogicalDeviceResources(PdoExt))) 1431 { 1432 if (PdoExt->RequirementsList) 1433 { 1434 ExFreePoolWithTag(PdoExt->RequirementsList, TAG_ISAPNP); 1435 PdoExt->RequirementsList = NULL; 1436 } 1437 1438 if (PdoExt->ResourceList) 1439 { 1440 ExFreePoolWithTag(PdoExt->ResourceList, TAG_ISAPNP); 1441 PdoExt->ResourceList = NULL; 1442 } 1443 1444 IoDeleteDevice(IsaDevice->Pdo); 1445 IsaDevice->Pdo = NULL; 1446 goto SkipPdo; 1447 } 1448 } 1449 else 1450 { 1451 PdoExt = IsaDevice->Pdo->DeviceExtension; 1452 } 1453 DeviceRelations->Objects[i++] = IsaDevice->Pdo; 1454 ObReferenceObject(IsaDevice->Pdo); 1455 1456 PdoExt->Flags |= ISAPNP_ENUMERATED; 1457 1458 CurrentEntry = CurrentEntry->Flink; 1459 continue; 1460 1461 SkipPdo: 1462 if (IsaDevice->Pdo) 1463 { 1464 PdoExt = IsaDevice->Pdo->DeviceExtension; 1465 1466 if (PdoExt) 1467 PdoExt->Flags &= ~ISAPNP_ENUMERATED; 1468 } 1469 1470 CurrentEntry = CurrentEntry->Flink; 1471 } 1472 1473 IsaPnpReleaseDeviceDataLock(FdoExt); 1474 1475 DeviceRelations->Count = i; 1476 1477 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations; 1478 1479 return Status; 1480 } 1481 1482 static CODE_SEG("PAGE") DRIVER_ADD_DEVICE IsaAddDevice; 1483 1484 static 1485 CODE_SEG("PAGE") 1486 NTSTATUS 1487 NTAPI 1488 IsaAddDevice( 1489 _In_ PDRIVER_OBJECT DriverObject, 1490 _In_ PDEVICE_OBJECT PhysicalDeviceObject) 1491 { 1492 PDEVICE_OBJECT Fdo; 1493 PISAPNP_FDO_EXTENSION FdoExt; 1494 NTSTATUS Status; 1495 static ULONG BusNumber = 0; 1496 1497 PAGED_CODE(); 1498 1499 DPRINT("%s(%p, %p)\n", __FUNCTION__, DriverObject, PhysicalDeviceObject); 1500 1501 Status = IoCreateDevice(DriverObject, 1502 sizeof(*FdoExt), 1503 NULL, 1504 FILE_DEVICE_BUS_EXTENDER, 1505 FILE_DEVICE_SECURE_OPEN, 1506 FALSE, 1507 &Fdo); 1508 if (!NT_SUCCESS(Status)) 1509 { 1510 DPRINT1("Failed to create FDO (0x%08lx)\n", Status); 1511 return Status; 1512 } 1513 1514 FdoExt = Fdo->DeviceExtension; 1515 RtlZeroMemory(FdoExt, sizeof(*FdoExt)); 1516 1517 FdoExt->Common.Self = Fdo; 1518 FdoExt->Common.Signature = IsaPnpBus; 1519 FdoExt->Common.State = dsStopped; 1520 FdoExt->DriverObject = DriverObject; 1521 FdoExt->BusNumber = BusNumber++; 1522 FdoExt->Pdo = PhysicalDeviceObject; 1523 FdoExt->Ldo = IoAttachDeviceToDeviceStack(Fdo, 1524 PhysicalDeviceObject); 1525 if (!FdoExt->Ldo) 1526 { 1527 IoDeleteDevice(Fdo); 1528 return STATUS_DEVICE_REMOVED; 1529 } 1530 1531 InitializeListHead(&FdoExt->DeviceListHead); 1532 KeInitializeEvent(&FdoExt->DeviceSyncEvent, SynchronizationEvent, TRUE); 1533 1534 IsaPnpAcquireBusDataLock(); 1535 InsertTailList(&BusListHead, &FdoExt->BusLink); 1536 IsaPnpReleaseBusDataLock(); 1537 1538 Fdo->Flags &= ~DO_DEVICE_INITIALIZING; 1539 1540 return STATUS_SUCCESS; 1541 } 1542 1543 _Dispatch_type_(IRP_MJ_POWER) 1544 static DRIVER_DISPATCH_RAISED IsaPower; 1545 1546 static 1547 NTSTATUS 1548 NTAPI 1549 IsaPower( 1550 _In_ PDEVICE_OBJECT DeviceObject, 1551 _Inout_ PIRP Irp) 1552 { 1553 PISAPNP_COMMON_EXTENSION DevExt = DeviceObject->DeviceExtension; 1554 NTSTATUS Status; 1555 1556 if (DevExt->Signature != IsaPnpBus) 1557 { 1558 switch (IoGetCurrentIrpStackLocation(Irp)->MinorFunction) 1559 { 1560 case IRP_MN_SET_POWER: 1561 case IRP_MN_QUERY_POWER: 1562 Status = STATUS_SUCCESS; 1563 Irp->IoStatus.Status = Status; 1564 break; 1565 1566 default: 1567 Status = Irp->IoStatus.Status; 1568 break; 1569 } 1570 1571 PoStartNextPowerIrp(Irp); 1572 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1573 return Status; 1574 } 1575 1576 PoStartNextPowerIrp(Irp); 1577 IoSkipCurrentIrpStackLocation(Irp); 1578 return PoCallDriver(((PISAPNP_FDO_EXTENSION)DevExt)->Ldo, Irp); 1579 } 1580 1581 _Dispatch_type_(IRP_MJ_PNP) 1582 static CODE_SEG("PAGE") DRIVER_DISPATCH_PAGED IsaPnp; 1583 1584 static 1585 CODE_SEG("PAGE") 1586 NTSTATUS 1587 NTAPI 1588 IsaPnp( 1589 _In_ PDEVICE_OBJECT DeviceObject, 1590 _Inout_ PIRP Irp) 1591 { 1592 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); 1593 PISAPNP_COMMON_EXTENSION DevExt = DeviceObject->DeviceExtension; 1594 1595 PAGED_CODE(); 1596 1597 if (DevExt->Signature == IsaPnpBus) 1598 return IsaFdoPnp((PISAPNP_FDO_EXTENSION)DevExt, Irp, IrpSp); 1599 else 1600 return IsaPdoPnp((PISAPNP_PDO_EXTENSION)DevExt, Irp, IrpSp); 1601 } 1602 1603 CODE_SEG("INIT") 1604 NTSTATUS 1605 NTAPI 1606 DriverEntry( 1607 _In_ PDRIVER_OBJECT DriverObject, 1608 _In_ PUNICODE_STRING RegistryPath) 1609 { 1610 DPRINT("%s(%p, %wZ)\n", __FUNCTION__, DriverObject, RegistryPath); 1611 1612 DriverObject->MajorFunction[IRP_MJ_CREATE] = IsaCreateClose; 1613 DriverObject->MajorFunction[IRP_MJ_CLOSE] = IsaCreateClose; 1614 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IsaForwardOrIgnore; 1615 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = IsaForwardOrIgnore; 1616 DriverObject->MajorFunction[IRP_MJ_PNP] = IsaPnp; 1617 DriverObject->MajorFunction[IRP_MJ_POWER] = IsaPower; 1618 DriverObject->DriverExtension->AddDevice = IsaAddDevice; 1619 1620 /* FIXME: Fix SDK headers */ 1621 #if 0 1622 _No_competing_thread_begin_ 1623 #endif 1624 1625 KeInitializeEvent(&BusSyncEvent, SynchronizationEvent, TRUE); 1626 InitializeListHead(&BusListHead); 1627 1628 /* FIXME: Fix SDK headers */ 1629 #if 0 1630 _No_competing_thread_end_ 1631 #endif 1632 1633 return STATUS_SUCCESS; 1634 } 1635 1636 /* EOF */ 1637