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 extern ULONG IsaConfigPorts[2]; 32 33 /* FUNCTIONS ******************************************************************/ 34 35 static 36 CODE_SEG("PAGE") 37 VOID 38 IsaConvertIoRequirement( 39 _Out_ PIO_RESOURCE_DESCRIPTOR Descriptor, 40 _In_ PISAPNP_IO_DESCRIPTION Description) 41 { 42 PAGED_CODE(); 43 44 Descriptor->Type = CmResourceTypePort; 45 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 46 Descriptor->Flags = CM_RESOURCE_PORT_IO; 47 if (Description->Information & 0x1) 48 Descriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE; 49 else 50 Descriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE; 51 Descriptor->u.Port.Length = Description->Length; 52 Descriptor->u.Port.Alignment = Description->Alignment; 53 Descriptor->u.Port.MinimumAddress.LowPart = Description->Minimum; 54 Descriptor->u.Port.MaximumAddress.LowPart = Description->Maximum + 55 Description->Length - 1; 56 } 57 58 static 59 CODE_SEG("PAGE") 60 VOID 61 IsaConvertIrqRequirement( 62 _Out_ PIO_RESOURCE_DESCRIPTOR Descriptor, 63 _In_ PISAPNP_IRQ_DESCRIPTION Description, 64 _In_ ULONG Vector, 65 _In_ BOOLEAN FirstDescriptor) 66 { 67 PAGED_CODE(); 68 69 if (!FirstDescriptor) 70 Descriptor->Option = IO_RESOURCE_ALTERNATIVE; 71 Descriptor->Type = CmResourceTypeInterrupt; 72 if (Description->Information & 0xC) 73 { 74 Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; 75 Descriptor->ShareDisposition = CmResourceShareShared; 76 } 77 else 78 { 79 Descriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; 80 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 81 } 82 Descriptor->u.Interrupt.MinimumVector = 83 Descriptor->u.Interrupt.MaximumVector = Vector; 84 } 85 86 static 87 CODE_SEG("PAGE") 88 VOID 89 IsaConvertDmaRequirement( 90 _Out_ PIO_RESOURCE_DESCRIPTOR Descriptor, 91 _In_ PISAPNP_DMA_DESCRIPTION Description, 92 _In_ ULONG Channel, 93 _In_ BOOLEAN FirstDescriptor) 94 { 95 UNREFERENCED_PARAMETER(Description); 96 97 PAGED_CODE(); 98 99 if (!FirstDescriptor) 100 Descriptor->Option = IO_RESOURCE_ALTERNATIVE; 101 Descriptor->Type = CmResourceTypeDma; 102 Descriptor->ShareDisposition = CmResourceShareUndetermined; 103 Descriptor->Flags = CM_RESOURCE_DMA_8; /* Ignore information byte for compatibility */ 104 Descriptor->u.Dma.MinimumChannel = 105 Descriptor->u.Dma.MaximumChannel = Channel; 106 } 107 108 static 109 CODE_SEG("PAGE") 110 VOID 111 IsaConvertMemRangeRequirement( 112 _Out_ PIO_RESOURCE_DESCRIPTOR Descriptor, 113 _In_ PISAPNP_MEMRANGE_DESCRIPTION Description) 114 { 115 PAGED_CODE(); 116 117 Descriptor->Type = CmResourceTypeMemory; 118 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 119 Descriptor->Flags = CM_RESOURCE_MEMORY_24; 120 if ((Description->Information & 0x40) || !(Description->Information & 0x01)) 121 Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY; 122 else 123 Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE; 124 Descriptor->u.Memory.Length = Description->Length << 8; 125 if (Description->Alignment == 0) 126 Descriptor->u.Memory.Alignment = 0x10000; 127 else 128 Descriptor->u.Memory.Alignment = Description->Alignment; 129 Descriptor->u.Memory.MinimumAddress.LowPart = Description->Minimum << 8; 130 Descriptor->u.Memory.MaximumAddress.LowPart = (Description->Maximum << 8) + 131 (Description->Length << 8) - 1; 132 } 133 134 static 135 CODE_SEG("PAGE") 136 VOID 137 IsaConvertMemRange32Requirement( 138 _Out_ PIO_RESOURCE_DESCRIPTOR Descriptor, 139 _In_ PISAPNP_MEMRANGE32_DESCRIPTION Description) 140 { 141 PAGED_CODE(); 142 143 Descriptor->Type = CmResourceTypeMemory; 144 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 145 Descriptor->Flags = CM_RESOURCE_MEMORY_24; 146 if ((Description->Information & 0x40) || !(Description->Information & 0x01)) 147 Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY; 148 else 149 Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE; 150 Descriptor->u.Memory.Length = Description->Length; 151 Descriptor->u.Memory.Alignment = Description->Alignment; 152 Descriptor->u.Memory.MinimumAddress.LowPart = Description->Minimum; 153 Descriptor->u.Memory.MaximumAddress.LowPart = Description->Maximum + 154 Description->Length - 1; 155 } 156 157 /* 158 * For example, the PnP ROM 159 * 0x15, 0x04, ... // Logical device ID 160 * 0x47, 0x01, 0x30, 0x03, 0x30, 0x03, 0x04, 0x04, // IO 330, len 4, align 4 161 * 0x30, // **** Start DF **** 162 * 0x22, 0x04, 0x00, // IRQ 2 163 * 0x31, 0x02, // **** Start DF **** 164 * 0x22, 0xC0, 0x00, // IRQ 6 or 7 165 * 0x38, // **** End DF ****** 166 * 0x2A, 0x20, 0x3A, // DMA 5 167 * 0x22, 0x00, 0x08, // IRQ 12 168 * 0x79, 0x00, // END 169 * 170 * becomes the following resource requirements list: 171 * Interface 1 Bus 0 Slot 0 AlternativeLists 2 172 * 173 * AltList #0, AltList->Count 4 174 * [Option 0, ShareDisposition 1, Flags 11] IO: Min 0:330, Max 0:333, Align 4 Len 4 175 * [Option 0, ShareDisposition 1, Flags 1] INT: Min 2 Max 2 176 * [Option 0, ShareDisposition 0, Flags 0] DMA: Min 5 Max 5 177 * [Option 0, ShareDisposition 1, Flags 1] INT: Min B Max B 178 * 179 * AltList #1, AltList->Count 5 180 * [Option 0, ShareDisposition 1, Flags 11] IO: Min 0:330, Max 0:333, Align 4 Len 4 181 * [Option 0, ShareDisposition 1, Flags 1] INT: Min 6 Max 6 182 * [Option 8, ShareDisposition 1, Flags 1] INT: Min 7 Max 7 183 * [Option 0, ShareDisposition 0, Flags 0] DMA: Min 5 Max 5 184 * [Option 0, ShareDisposition 1, Flags 1] INT: Min B Max B 185 */ 186 static 187 CODE_SEG("PAGE") 188 NTSTATUS 189 IsaPnpCreateLogicalDeviceRequirements( 190 _In_ PISAPNP_PDO_EXTENSION PdoExt) 191 { 192 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList; 193 PIO_RESOURCE_DESCRIPTOR Descriptor; 194 ISAPNP_DEPENDENT_FUNCTION_STATE DfState; 195 ULONG FirstFixedDescriptors, LastFixedDescriptors; 196 ULONG ResourceCount, AltListCount, ListSize, i; 197 BOOLEAN IsFirstAltList, IsFirstDescriptor; 198 PIO_RESOURCE_LIST AltList; 199 PISAPNP_RESOURCE Resource; 200 201 PAGED_CODE(); 202 203 /* Count the number of requirements */ 204 DfState = dfNotStarted; 205 FirstFixedDescriptors = 0; 206 LastFixedDescriptors = 0; 207 ResourceCount = 0; 208 AltListCount = 1; 209 Resource = PdoExt->IsaPnpDevice->Resources; 210 while (Resource->Type != ISAPNP_RESOURCE_TYPE_END) 211 { 212 switch (Resource->Type) 213 { 214 case ISAPNP_RESOURCE_TYPE_START_DEPENDENT: 215 { 216 if (DfState == dfStarted) 217 ++AltListCount; 218 219 DfState = dfStarted; 220 break; 221 } 222 223 case ISAPNP_RESOURCE_TYPE_END_DEPENDENT: 224 { 225 DfState = dfDone; 226 break; 227 } 228 229 case ISAPNP_RESOURCE_TYPE_IRQ: 230 case ISAPNP_RESOURCE_TYPE_DMA: 231 { 232 RTL_BITMAP ResourceBitmap; 233 ULONG BitmapSize, BitmapBuffer, BitCount; 234 235 if (Resource->Type == ISAPNP_RESOURCE_TYPE_IRQ) 236 { 237 BitmapSize = RTL_BITS_OF(Resource->IrqDescription.Mask); 238 BitmapBuffer = Resource->IrqDescription.Mask; 239 } 240 else 241 { 242 BitmapSize = RTL_BITS_OF(Resource->DmaDescription.Mask); 243 BitmapBuffer = Resource->DmaDescription.Mask; 244 } 245 RtlInitializeBitMap(&ResourceBitmap, &BitmapBuffer, BitmapSize); 246 247 BitCount = RtlNumberOfSetBits(&ResourceBitmap); 248 switch (DfState) 249 { 250 case dfNotStarted: 251 FirstFixedDescriptors += BitCount; 252 break; 253 254 case dfStarted: 255 ResourceCount += BitCount; 256 break; 257 258 case dfDone: 259 LastFixedDescriptors += BitCount; 260 break; 261 262 DEFAULT_UNREACHABLE; 263 } 264 265 break; 266 } 267 268 case ISAPNP_RESOURCE_TYPE_IO: 269 case ISAPNP_RESOURCE_TYPE_MEMRANGE: 270 case ISAPNP_RESOURCE_TYPE_MEMRANGE32: 271 { 272 switch (DfState) 273 { 274 case dfNotStarted: 275 ++FirstFixedDescriptors; 276 break; 277 278 case dfStarted: 279 ++ResourceCount; 280 break; 281 282 case dfDone: 283 ++LastFixedDescriptors; 284 break; 285 286 DEFAULT_UNREACHABLE; 287 } 288 break; 289 } 290 291 default: 292 ASSERT(FALSE); 293 UNREACHABLE; 294 break; 295 } 296 297 ++Resource; 298 } 299 300 /* This logical device has no resource requirements */ 301 if ((ResourceCount == 0) && (FirstFixedDescriptors == 0) && (LastFixedDescriptors == 0)) 302 return STATUS_SUCCESS; 303 304 /* Allocate memory to store requirements */ 305 ListSize = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List) + 306 FIELD_OFFSET(IO_RESOURCE_LIST, Descriptors) * AltListCount + 307 sizeof(IO_RESOURCE_DESCRIPTOR) * ResourceCount + 308 sizeof(IO_RESOURCE_DESCRIPTOR) * AltListCount * 309 (FirstFixedDescriptors + LastFixedDescriptors); 310 RequirementsList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP); 311 if (!RequirementsList) 312 return STATUS_NO_MEMORY; 313 314 RequirementsList->ListSize = ListSize; 315 RequirementsList->InterfaceType = Isa; 316 RequirementsList->AlternativeLists = AltListCount; 317 318 RequirementsList->List[0].Version = 1; 319 RequirementsList->List[0].Revision = 1; 320 321 /* Store requirements */ 322 IsFirstAltList = TRUE; 323 AltList = &RequirementsList->List[0]; 324 Descriptor = &RequirementsList->List[0].Descriptors[0]; 325 Resource = PdoExt->IsaPnpDevice->Resources; 326 while (Resource->Type != ISAPNP_RESOURCE_TYPE_END) 327 { 328 switch (Resource->Type) 329 { 330 case ISAPNP_RESOURCE_TYPE_START_DEPENDENT: 331 { 332 if (!IsFirstAltList) 333 { 334 /* Add room for the fixed descriptors */ 335 AltList->Count += LastFixedDescriptors; 336 337 /* Move on to the next list */ 338 AltList = (PIO_RESOURCE_LIST)(AltList->Descriptors + AltList->Count); 339 AltList->Version = 1; 340 AltList->Revision = 1; 341 342 /* Propagate the fixed resources to our new list */ 343 RtlCopyMemory(&AltList->Descriptors, 344 RequirementsList->List[0].Descriptors, 345 sizeof(IO_RESOURCE_DESCRIPTOR) * FirstFixedDescriptors); 346 AltList->Count += FirstFixedDescriptors; 347 348 Descriptor = &AltList->Descriptors[FirstFixedDescriptors]; 349 } 350 351 IsFirstAltList = FALSE; 352 break; 353 } 354 355 case ISAPNP_RESOURCE_TYPE_END_DEPENDENT: 356 break; 357 358 case ISAPNP_RESOURCE_TYPE_IO: 359 { 360 IsaConvertIoRequirement(Descriptor++, &Resource->IoDescription); 361 362 ++AltList->Count; 363 break; 364 } 365 366 case ISAPNP_RESOURCE_TYPE_IRQ: 367 { 368 IsFirstDescriptor = TRUE; 369 370 for (i = 0; i < RTL_BITS_OF(Resource->IrqDescription.Mask); i++) 371 { 372 if (!(Resource->IrqDescription.Mask & (1 << i))) 373 continue; 374 375 IsaConvertIrqRequirement(Descriptor++, 376 &Resource->IrqDescription, 377 i, 378 IsFirstDescriptor); 379 ++AltList->Count; 380 381 IsFirstDescriptor = FALSE; 382 } 383 384 break; 385 } 386 387 case ISAPNP_RESOURCE_TYPE_DMA: 388 { 389 IsFirstDescriptor = TRUE; 390 391 for (i = 0; i < RTL_BITS_OF(Resource->DmaDescription.Mask); i++) 392 { 393 if (!(Resource->DmaDescription.Mask & (1 << i))) 394 continue; 395 396 IsaConvertDmaRequirement(Descriptor++, 397 &Resource->DmaDescription, 398 i, 399 IsFirstDescriptor); 400 ++AltList->Count; 401 402 IsFirstDescriptor = FALSE; 403 } 404 405 break; 406 } 407 408 case ISAPNP_RESOURCE_TYPE_MEMRANGE: 409 { 410 IsaConvertMemRangeRequirement(Descriptor++, &Resource->MemRangeDescription); 411 412 ++AltList->Count; 413 break; 414 } 415 416 case ISAPNP_RESOURCE_TYPE_MEMRANGE32: 417 { 418 IsaConvertMemRange32Requirement(Descriptor++, &Resource->MemRange32Description); 419 420 ++AltList->Count; 421 break; 422 } 423 424 default: 425 ASSERT(FALSE); 426 UNREACHABLE; 427 break; 428 } 429 430 ++Resource; 431 } 432 433 /* Append the fixed resources */ 434 if (LastFixedDescriptors) 435 { 436 PIO_RESOURCE_LIST NextList = &RequirementsList->List[0]; 437 438 /* Make the descriptor point to the fixed resources */ 439 Descriptor -= LastFixedDescriptors; 440 441 /* Propagate the fixed resources onto previous lists */ 442 AltListCount = RequirementsList->AlternativeLists - 1; 443 for (i = 0; i < AltListCount; i++) 444 { 445 RtlCopyMemory(&NextList->Descriptors[NextList->Count - LastFixedDescriptors], 446 Descriptor, 447 sizeof(IO_RESOURCE_DESCRIPTOR) * LastFixedDescriptors); 448 449 NextList = (PIO_RESOURCE_LIST)(NextList->Descriptors + NextList->Count); 450 } 451 } 452 453 PdoExt->RequirementsList = RequirementsList; 454 return STATUS_SUCCESS; 455 } 456 457 CODE_SEG("PAGE") 458 BOOLEAN 459 FindIoDescriptor( 460 _In_ PISAPNP_LOGICAL_DEVICE LogDevice, 461 _In_opt_ ULONG Base, 462 _In_ ULONG RangeStart, 463 _In_ ULONG RangeEnd, 464 _Out_opt_ PUCHAR Information, 465 _Out_opt_ PULONG Length) 466 { 467 PISAPNP_RESOURCE Resource; 468 469 PAGED_CODE(); 470 471 Resource = LogDevice->Resources; 472 while (Resource->Type != ISAPNP_RESOURCE_TYPE_END) 473 { 474 if (Resource->Type == ISAPNP_RESOURCE_TYPE_IO) 475 { 476 PISAPNP_IO_DESCRIPTION Description = &Resource->IoDescription; 477 BOOLEAN Match; 478 479 if (Base) 480 { 481 Match = (Base >= Description->Minimum) && (Base <= Description->Maximum); 482 } 483 else 484 { 485 Match = (RangeStart >= Description->Minimum) && 486 (RangeEnd <= (ULONG)(Description->Maximum + Description->Length - 1)); 487 } 488 489 if (Match) 490 { 491 if (Information) 492 *Information = Description->Information; 493 if (Length) 494 *Length = Description->Length; 495 496 return TRUE; 497 } 498 } 499 500 ++Resource; 501 } 502 503 return FALSE; 504 } 505 506 CODE_SEG("PAGE") 507 BOOLEAN 508 FindIrqDescriptor( 509 _In_ PISAPNP_LOGICAL_DEVICE LogDevice, 510 _In_ ULONG Vector) 511 { 512 PISAPNP_RESOURCE Resource; 513 514 PAGED_CODE(); 515 516 Resource = LogDevice->Resources; 517 while (Resource->Type != ISAPNP_RESOURCE_TYPE_END) 518 { 519 if (Resource->Type == ISAPNP_RESOURCE_TYPE_IRQ) 520 { 521 PISAPNP_IRQ_DESCRIPTION Description = &Resource->IrqDescription; 522 523 if (Description->Mask & (1 << Vector)) 524 return TRUE; 525 } 526 527 ++Resource; 528 } 529 530 return FALSE; 531 } 532 533 CODE_SEG("PAGE") 534 BOOLEAN 535 FindDmaDescriptor( 536 _In_ PISAPNP_LOGICAL_DEVICE LogDevice, 537 _In_ ULONG Channel) 538 { 539 PISAPNP_RESOURCE Resource; 540 541 PAGED_CODE(); 542 543 Resource = LogDevice->Resources; 544 while (Resource->Type != ISAPNP_RESOURCE_TYPE_END) 545 { 546 if (Resource->Type == ISAPNP_RESOURCE_TYPE_DMA) 547 { 548 PISAPNP_DMA_DESCRIPTION Description = &Resource->DmaDescription; 549 550 if (Description->Mask & (1 << Channel)) 551 return TRUE; 552 } 553 554 ++Resource; 555 } 556 557 return FALSE; 558 } 559 560 CODE_SEG("PAGE") 561 BOOLEAN 562 FindMemoryDescriptor( 563 _In_ PISAPNP_LOGICAL_DEVICE LogDevice, 564 _In_ ULONG RangeStart, 565 _In_ ULONG RangeEnd, 566 _Out_opt_ PUCHAR Information) 567 { 568 PISAPNP_RESOURCE Resource; 569 570 PAGED_CODE(); 571 572 Resource = LogDevice->Resources; 573 while (Resource->Type != ISAPNP_RESOURCE_TYPE_END) 574 { 575 switch (Resource->Type) 576 { 577 case ISAPNP_RESOURCE_TYPE_MEMRANGE: 578 { 579 PISAPNP_MEMRANGE_DESCRIPTION Description; 580 581 Description = &Resource->MemRangeDescription; 582 583 if ((RangeStart >= (ULONG)(Description->Minimum << 8)) && 584 (RangeEnd <= (ULONG)((Description->Maximum << 8) + 585 (Description->Length << 8) - 1))) 586 { 587 if (Information) 588 *Information = Description->Information; 589 590 return TRUE; 591 } 592 break; 593 } 594 595 case ISAPNP_RESOURCE_TYPE_MEMRANGE32: 596 { 597 PISAPNP_MEMRANGE32_DESCRIPTION Description32; 598 599 Description32 = &Resource->MemRange32Description; 600 601 if ((RangeStart >= Description32->Minimum) && 602 (RangeEnd <= (Description32->Maximum + Description32->Length - 1))) 603 { 604 if (Information) 605 *Information = Description32->Information; 606 607 return TRUE; 608 } 609 break; 610 } 611 612 default: 613 break; 614 } 615 616 ++Resource; 617 } 618 619 return FALSE; 620 } 621 622 static 623 CODE_SEG("PAGE") 624 NTSTATUS 625 IsaPnpCreateLogicalDeviceResources( 626 _In_ PISAPNP_PDO_EXTENSION PdoExt) 627 { 628 PISAPNP_LOGICAL_DEVICE LogDev = PdoExt->IsaPnpDevice; 629 ULONG ResourceCount = 0; 630 UCHAR Information; 631 ULONG ListSize, i; 632 PCM_RESOURCE_LIST ResourceList; 633 PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor; 634 635 PAGED_CODE(); 636 637 if (!(LogDev->Flags & ISAPNP_HAS_RESOURCES)) 638 return STATUS_SUCCESS; 639 640 /* Count number of required resources */ 641 for (i = 0; i < RTL_NUMBER_OF(LogDev->Io); i++) 642 { 643 if (LogDev->Io[i].CurrentBase) 644 ResourceCount++; 645 else 646 break; 647 } 648 for (i = 0; i < RTL_NUMBER_OF(LogDev->Irq); i++) 649 { 650 if (LogDev->Irq[i].CurrentNo) 651 ResourceCount++; 652 else 653 break; 654 } 655 for (i = 0; i < RTL_NUMBER_OF(LogDev->Dma); i++) 656 { 657 if (LogDev->Dma[i].CurrentChannel != DMACHANNEL_NONE) 658 ResourceCount++; 659 else 660 break; 661 } 662 for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange); i++) 663 { 664 if (LogDev->MemRange[i].CurrentBase) 665 ResourceCount++; 666 else 667 break; 668 } 669 for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange32); i++) 670 { 671 if (LogDev->MemRange32[i].CurrentBase) 672 ResourceCount++; 673 else 674 break; 675 } 676 if (ResourceCount == 0) 677 return STATUS_SUCCESS; 678 679 /* Allocate memory to store resources */ 680 ListSize = sizeof(CM_RESOURCE_LIST) 681 + (ResourceCount - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR); 682 ResourceList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP); 683 if (!ResourceList) 684 return STATUS_NO_MEMORY; 685 686 ResourceList->Count = 1; 687 ResourceList->List[0].InterfaceType = Isa; 688 ResourceList->List[0].PartialResourceList.Version = 1; 689 ResourceList->List[0].PartialResourceList.Revision = 1; 690 ResourceList->List[0].PartialResourceList.Count = ResourceCount; 691 692 /* Store resources */ 693 ResourceCount = 0; 694 for (i = 0; i < RTL_NUMBER_OF(LogDev->Io); i++) 695 { 696 ULONG CurrentLength; 697 698 if (!LogDev->Io[i].CurrentBase) 699 break; 700 701 if (!FindIoDescriptor(LogDev, 702 LogDev->Io[i].CurrentBase, 703 0, 704 0, 705 &Information, 706 &CurrentLength)) 707 { 708 DPRINT1("I/O entry #%lu %x not found\n", i, LogDev->Io[i].CurrentBase); 709 goto InvalidBiosResources; 710 } 711 712 Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++]; 713 Descriptor->Type = CmResourceTypePort; 714 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 715 Descriptor->Flags = CM_RESOURCE_PORT_IO; 716 if (Information & 0x1) 717 Descriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE; 718 else 719 Descriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE; 720 Descriptor->u.Port.Length = CurrentLength; 721 Descriptor->u.Port.Start.LowPart = LogDev->Io[i].CurrentBase; 722 } 723 for (i = 0; i < RTL_NUMBER_OF(LogDev->Irq); i++) 724 { 725 if (!LogDev->Irq[i].CurrentNo) 726 break; 727 728 Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++]; 729 Descriptor->Type = CmResourceTypeInterrupt; 730 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 731 if (LogDev->Irq[i].CurrentType & 0x01) 732 Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; 733 else 734 Descriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; 735 Descriptor->u.Interrupt.Level = LogDev->Irq[i].CurrentNo; 736 Descriptor->u.Interrupt.Vector = LogDev->Irq[i].CurrentNo; 737 Descriptor->u.Interrupt.Affinity = (KAFFINITY)-1; 738 } 739 for (i = 0; i < RTL_NUMBER_OF(LogDev->Dma); i++) 740 { 741 if (LogDev->Dma[i].CurrentChannel == DMACHANNEL_NONE) 742 break; 743 744 Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++]; 745 Descriptor->Type = CmResourceTypeDma; 746 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 747 Descriptor->Flags = CM_RESOURCE_DMA_8; /* Ignore information byte for compatibility */ 748 Descriptor->u.Dma.Channel = LogDev->Dma[i].CurrentChannel; 749 } 750 for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange); i++) 751 { 752 if (!LogDev->MemRange[i].CurrentBase) 753 break; 754 755 if (!FindMemoryDescriptor(LogDev, 756 LogDev->MemRange[i].CurrentBase, 757 LogDev->MemRange[i].CurrentLength, 758 &Information)) 759 { 760 DPRINT1("MEM entry #%lu %lx %lx not found\n", 761 i, 762 LogDev->MemRange[i].CurrentBase, 763 LogDev->MemRange[i].CurrentLength); 764 goto InvalidBiosResources; 765 } 766 767 Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++]; 768 Descriptor->Type = CmResourceTypeMemory; 769 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 770 Descriptor->Flags = CM_RESOURCE_MEMORY_24; 771 if ((Information & 0x40) || !(Information & 0x01)) 772 Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY; 773 else 774 Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE; 775 Descriptor->u.Memory.Length = LogDev->MemRange[i].CurrentLength; 776 Descriptor->u.Memory.Start.QuadPart = LogDev->MemRange[i].CurrentBase; 777 } 778 for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange32); i++) 779 { 780 if (!LogDev->MemRange32[i].CurrentBase) 781 break; 782 783 if (!FindMemoryDescriptor(LogDev, 784 LogDev->MemRange32[i].CurrentBase, 785 LogDev->MemRange32[i].CurrentLength, 786 &Information)) 787 { 788 DPRINT1("MEM32 entry #%lu %lx %lx not found\n", 789 i, 790 LogDev->MemRange32[i].CurrentBase, 791 LogDev->MemRange32[i].CurrentLength); 792 goto InvalidBiosResources; 793 } 794 795 Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++]; 796 Descriptor->Type = CmResourceTypeMemory; 797 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 798 Descriptor->Flags = CM_RESOURCE_MEMORY_24; 799 if ((Information & 0x40) || !(Information & 0x01)) 800 Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY; 801 else 802 Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE; 803 Descriptor->u.Memory.Length = LogDev->MemRange32[i].CurrentLength; 804 Descriptor->u.Memory.Start.QuadPart = LogDev->MemRange32[i].CurrentBase; 805 } 806 807 PdoExt->ResourceList = ResourceList; 808 PdoExt->ResourceListSize = ListSize; 809 return STATUS_SUCCESS; 810 811 InvalidBiosResources: 812 DPRINT1("Invalid boot resources! (CSN %u, LDN %u)\n", LogDev->CSN, LogDev->LDN); 813 814 LogDev->Flags &= ~ISAPNP_HAS_RESOURCES; 815 ExFreePoolWithTag(ResourceList, TAG_ISAPNP); 816 return STATUS_SUCCESS; 817 } 818 819 CODE_SEG("PAGE") 820 PIO_RESOURCE_REQUIREMENTS_LIST 821 IsaPnpCreateReadPortDORequirements( 822 _In_opt_ ULONG SelectedReadPort) 823 { 824 ULONG ResourceCount, ListSize, i; 825 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList; 826 PIO_RESOURCE_DESCRIPTOR Descriptor; 827 const ULONG ReadPorts[] = { 0x274, 0x3E4, 0x204, 0x2E4, 0x354, 0x2F4 }; 828 829 PAGED_CODE(); 830 831 if (SelectedReadPort) 832 { 833 /* 834 * [IO descriptor: ISAPNP_WRITE_DATA, required] 835 * [IO descriptor: ISAPNP_WRITE_DATA, optional] 836 * [IO descriptor: ISAPNP_ADDRESS, required] 837 * [IO descriptor: ISAPNP_ADDRESS, optional] 838 * [IO descriptor: Selected Read Port, required] 839 * [IO descriptor: Read Port 1, optional] 840 * [IO descriptor: Read Port 2, optional] 841 * [...] 842 * [IO descriptor: Read Port X - 1, optional] 843 */ 844 ResourceCount = RTL_NUMBER_OF(IsaConfigPorts) * 2 + RTL_NUMBER_OF(ReadPorts); 845 } 846 else 847 { 848 /* 849 * [IO descriptor: ISAPNP_WRITE_DATA, required] 850 * [IO descriptor: ISAPNP_WRITE_DATA, optional] 851 * [IO descriptor: ISAPNP_ADDRESS, required] 852 * [IO descriptor: ISAPNP_ADDRESS, optional] 853 * [IO descriptor: Read Port 1, required] 854 * [IO descriptor: Read Port 1, optional] 855 * [IO descriptor: Read Port 2, required] 856 * [IO descriptor: Read Port 2, optional] 857 * [...] 858 * [IO descriptor: Read Port X, required] 859 * [IO descriptor: Read Port X, optional] 860 */ 861 ResourceCount = (RTL_NUMBER_OF(IsaConfigPorts) + RTL_NUMBER_OF(ReadPorts)) * 2; 862 } 863 ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) + 864 sizeof(IO_RESOURCE_DESCRIPTOR) * (ResourceCount - 1); 865 RequirementsList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP); 866 if (!RequirementsList) 867 return NULL; 868 869 RequirementsList->ListSize = ListSize; 870 RequirementsList->AlternativeLists = 1; 871 872 RequirementsList->List[0].Version = 1; 873 RequirementsList->List[0].Revision = 1; 874 RequirementsList->List[0].Count = ResourceCount; 875 876 Descriptor = &RequirementsList->List[0].Descriptors[0]; 877 878 /* Store the Data port and the Address port */ 879 for (i = 0; i < RTL_NUMBER_OF(IsaConfigPorts) * 2; i++) 880 { 881 if ((i % 2) == 0) 882 { 883 /* Expected port */ 884 Descriptor->Type = CmResourceTypePort; 885 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 886 Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE; 887 Descriptor->u.Port.Length = 0x01; 888 Descriptor->u.Port.Alignment = 0x01; 889 Descriptor->u.Port.MinimumAddress.LowPart = 890 Descriptor->u.Port.MaximumAddress.LowPart = IsaConfigPorts[i / 2]; 891 } 892 else 893 { 894 /* ... but mark it as optional */ 895 Descriptor->Option = IO_RESOURCE_ALTERNATIVE; 896 Descriptor->Type = CmResourceTypePort; 897 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 898 Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE; 899 Descriptor->u.Port.Alignment = 0x01; 900 } 901 902 Descriptor++; 903 } 904 905 /* Store the Read Ports */ 906 if (SelectedReadPort) 907 { 908 BOOLEAN Selected = FALSE; 909 910 DBG_UNREFERENCED_LOCAL_VARIABLE(Selected); 911 912 for (i = 0; i < RTL_NUMBER_OF(ReadPorts); i++) 913 { 914 if (ReadPorts[i] != SelectedReadPort) 915 Descriptor->Option = IO_RESOURCE_ALTERNATIVE; 916 else 917 Selected = TRUE; 918 Descriptor->Type = CmResourceTypePort; 919 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 920 Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE; 921 Descriptor->u.Port.Length = 0x04; 922 Descriptor->u.Port.Alignment = 0x01; 923 Descriptor->u.Port.MinimumAddress.LowPart = ReadPorts[i]; 924 Descriptor->u.Port.MaximumAddress.LowPart = ReadPorts[i] + 925 Descriptor->u.Port.Length - 1; 926 927 Descriptor++; 928 } 929 930 ASSERT(Selected == TRUE); 931 } 932 else 933 { 934 for (i = 0; i < RTL_NUMBER_OF(ReadPorts) * 2; i++) 935 { 936 if ((i % 2) == 0) 937 { 938 /* Expected port */ 939 Descriptor->Type = CmResourceTypePort; 940 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 941 Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE; 942 Descriptor->u.Port.Length = 0x04; 943 Descriptor->u.Port.Alignment = 0x01; 944 Descriptor->u.Port.MinimumAddress.LowPart = ReadPorts[i / 2]; 945 Descriptor->u.Port.MaximumAddress.LowPart = ReadPorts[i / 2] + 946 Descriptor->u.Port.Length - 1; 947 } 948 else 949 { 950 /* ... but mark it as optional */ 951 Descriptor->Option = IO_RESOURCE_ALTERNATIVE; 952 Descriptor->Type = CmResourceTypePort; 953 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 954 Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE; 955 Descriptor->u.Port.Alignment = 0x01; 956 } 957 958 Descriptor++; 959 } 960 } 961 962 return RequirementsList; 963 } 964 965 CODE_SEG("PAGE") 966 PCM_RESOURCE_LIST 967 IsaPnpCreateReadPortDOResources(VOID) 968 { 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(IsaConfigPorts) - 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(IsaConfigPorts); 986 987 Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[0]; 988 for (i = 0; i < RTL_NUMBER_OF(IsaConfigPorts); 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 = IsaConfigPorts[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 if (IsNEC_98) 1419 { 1420 IsaConfigPorts[0] = ISAPNP_WRITE_DATA_PC98; 1421 IsaConfigPorts[1] = ISAPNP_ADDRESS_PC98; 1422 } 1423 1424 DriverObject->MajorFunction[IRP_MJ_CREATE] = IsaCreateClose; 1425 DriverObject->MajorFunction[IRP_MJ_CLOSE] = IsaCreateClose; 1426 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IsaForwardOrIgnore; 1427 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = IsaForwardOrIgnore; 1428 DriverObject->MajorFunction[IRP_MJ_PNP] = IsaPnp; 1429 DriverObject->MajorFunction[IRP_MJ_POWER] = IsaPower; 1430 DriverObject->DriverExtension->AddDevice = IsaAddDevice; 1431 1432 /* FIXME: Fix SDK headers */ 1433 #if 0 1434 _No_competing_thread_begin_ 1435 #endif 1436 1437 KeInitializeEvent(&BusSyncEvent, SynchronizationEvent, TRUE); 1438 InitializeListHead(&BusListHead); 1439 1440 /* FIXME: Fix SDK headers */ 1441 #if 0 1442 _No_competing_thread_end_ 1443 #endif 1444 1445 return STATUS_SUCCESS; 1446 } 1447 1448 #endif /* UNIT_TEST */ 1449 1450 /* EOF */ 1451