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