1 /* 2 * PROJECT: PCI IDE bus driver extension 3 * LICENSE: See COPYING in the top level directory 4 * PURPOSE: IRP_MJ_PNP operations for PDOs 5 * COPYRIGHT: Copyright 2005 Hervé Poussineau <hpoussin@reactos.org> 6 * Copyright 2023 Dmitry Borisov <di.sean@protonmail.com> 7 */ 8 9 #include "pciidex.h" 10 11 #define NDEBUG 12 #include <debug.h> 13 14 static 15 CODE_SEG("PAGE") 16 NTSTATUS 17 PciIdeXPdoStartDevice( 18 _In_ PPDO_DEVICE_EXTENSION PdoExtension, 19 _In_ PCM_RESOURCE_LIST ResourceList) 20 { 21 PUCHAR IoBase; 22 23 PAGED_CODE(); 24 25 IoBase = PdoExtension->ParentController->BusMasterPortBase; 26 if (!IS_PRIMARY_CHANNEL(PdoExtension)) 27 { 28 IoBase += BM_SECONDARY_CHANNEL_OFFSET; 29 } 30 DPRINT("Bus Master Base %p\n", IoBase); 31 32 return STATUS_SUCCESS; 33 } 34 35 static 36 CODE_SEG("PAGE") 37 NTSTATUS 38 PciIdeXPdoStopDevice( 39 _In_ PPDO_DEVICE_EXTENSION PdoExtension) 40 { 41 PAGED_CODE(); 42 43 return STATUS_SUCCESS; 44 } 45 46 static 47 CODE_SEG("PAGE") 48 NTSTATUS 49 PciIdeXPdoRemoveDevice( 50 _In_ PPDO_DEVICE_EXTENSION PdoExtension, 51 _In_ BOOLEAN FinalRemove) 52 { 53 PFDO_DEVICE_EXTENSION FdoExtension = PdoExtension->ParentController; 54 ULONG i; 55 56 PAGED_CODE(); 57 58 if (FinalRemove && PdoExtension->ReportedMissing) 59 { 60 ExAcquireFastMutex(&FdoExtension->DeviceSyncMutex); 61 62 for (i = 0; i < MAX_IDE_CHANNEL; ++i) 63 { 64 if (FdoExtension->Channels[i] == PdoExtension) 65 { 66 FdoExtension->Channels[i] = NULL; 67 break; 68 } 69 } 70 71 ExReleaseFastMutex(&FdoExtension->DeviceSyncMutex); 72 73 IoDeleteDevice(PdoExtension->Common.Self); 74 } 75 76 return STATUS_SUCCESS; 77 } 78 79 static 80 CODE_SEG("PAGE") 81 NTSTATUS 82 PciIdeXPdoQueryStopRemoveDevice( 83 _In_ PPDO_DEVICE_EXTENSION PdoExtension) 84 { 85 PAGED_CODE(); 86 87 if (PdoExtension->Common.PageFiles || 88 PdoExtension->Common.HibernateFiles || 89 PdoExtension->Common.DumpFiles) 90 { 91 return STATUS_DEVICE_BUSY; 92 } 93 94 return STATUS_SUCCESS; 95 } 96 97 static 98 CODE_SEG("PAGE") 99 NTSTATUS 100 PciIdeXPdoQueryTargetDeviceRelations( 101 _In_ PPDO_DEVICE_EXTENSION PdoExtension, 102 _In_ PIRP Irp) 103 { 104 PDEVICE_RELATIONS DeviceRelations; 105 106 PAGED_CODE(); 107 108 DeviceRelations = ExAllocatePoolWithTag(PagedPool, 109 sizeof(DEVICE_RELATIONS), 110 TAG_PCIIDEX); 111 if (!DeviceRelations) 112 return STATUS_INSUFFICIENT_RESOURCES; 113 114 DeviceRelations->Count = 1; 115 DeviceRelations->Objects[0] = PdoExtension->Common.Self; 116 ObReferenceObject(PdoExtension->Common.Self); 117 118 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations; 119 return STATUS_SUCCESS; 120 } 121 122 static IO_COMPLETION_ROUTINE PciIdeXOnRepeaterCompletion; 123 124 static 125 NTSTATUS 126 NTAPI 127 PciIdeXOnRepeaterCompletion( 128 _In_ PDEVICE_OBJECT DeviceObject, 129 _In_ PIRP Irp, 130 _In_reads_opt_(_Inexpressible_("varies")) PVOID Context) 131 { 132 UNREFERENCED_PARAMETER(DeviceObject); 133 134 if (Irp->PendingReturned) 135 KeSetEvent(Context, IO_NO_INCREMENT, FALSE); 136 137 return STATUS_MORE_PROCESSING_REQUIRED; 138 } 139 140 static 141 CODE_SEG("PAGE") 142 NTSTATUS 143 PciIdeXPdoRepeatRequest( 144 _In_ PPDO_DEVICE_EXTENSION PdoExtension, 145 _In_ PIRP Irp, 146 _In_opt_ PDEVICE_CAPABILITIES DeviceCapabilities) 147 { 148 PDEVICE_OBJECT Fdo, TopDeviceObject; 149 PIO_STACK_LOCATION IoStack, SubStack; 150 PIRP SubIrp; 151 KEVENT Event; 152 NTSTATUS Status; 153 154 PAGED_CODE(); 155 156 Fdo = PdoExtension->ParentController->Common.Self; 157 TopDeviceObject = IoGetAttachedDeviceReference(Fdo); 158 159 SubIrp = IoAllocateIrp(TopDeviceObject->StackSize, FALSE); 160 if (!SubIrp) 161 { 162 ObDereferenceObject(TopDeviceObject); 163 return STATUS_INSUFFICIENT_RESOURCES; 164 } 165 166 KeInitializeEvent(&Event, NotificationEvent, FALSE); 167 168 IoStack = IoGetCurrentIrpStackLocation(Irp); 169 SubStack = IoGetNextIrpStackLocation(SubIrp); 170 RtlCopyMemory(SubStack, IoStack, sizeof(IO_STACK_LOCATION)); 171 172 if (DeviceCapabilities) 173 SubStack->Parameters.DeviceCapabilities.Capabilities = DeviceCapabilities; 174 175 IoSetCompletionRoutine(SubIrp, 176 PciIdeXOnRepeaterCompletion, 177 &Event, 178 TRUE, 179 TRUE, 180 TRUE); 181 182 SubIrp->IoStatus.Status = STATUS_NOT_SUPPORTED; 183 184 Status = IoCallDriver(TopDeviceObject, SubIrp); 185 if (Status == STATUS_PENDING) 186 { 187 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 188 } 189 190 ObDereferenceObject(TopDeviceObject); 191 192 Status = SubIrp->IoStatus.Status; 193 IoFreeIrp(SubIrp); 194 195 return Status; 196 } 197 198 static 199 CODE_SEG("PAGE") 200 NTSTATUS 201 PciIdeXPdoQueryCapabilities( 202 _In_ PPDO_DEVICE_EXTENSION PdoExtension, 203 _In_ PIRP Irp) 204 { 205 DEVICE_CAPABILITIES ParentCapabilities; 206 PDEVICE_CAPABILITIES DeviceCapabilities; 207 PIO_STACK_LOCATION IoStack; 208 NTSTATUS Status; 209 210 PAGED_CODE(); 211 212 /* Get the capabilities of the parent device */ 213 RtlZeroMemory(&ParentCapabilities, sizeof(ParentCapabilities)); 214 ParentCapabilities.Size = sizeof(ParentCapabilities); 215 ParentCapabilities.Version = 1; 216 ParentCapabilities.Address = MAXULONG; 217 ParentCapabilities.UINumber = MAXULONG; 218 Status = PciIdeXPdoRepeatRequest(PdoExtension, Irp, &ParentCapabilities); 219 if (!NT_SUCCESS(Status)) 220 return Status; 221 222 IoStack = IoGetCurrentIrpStackLocation(Irp); 223 DeviceCapabilities = IoStack->Parameters.DeviceCapabilities.Capabilities; 224 *DeviceCapabilities = ParentCapabilities; 225 226 /* Override some fields */ 227 DeviceCapabilities->UniqueID = FALSE; 228 DeviceCapabilities->Address = PdoExtension->Channel; 229 230 return STATUS_SUCCESS; 231 } 232 233 static 234 CODE_SEG("PAGE") 235 NTSTATUS 236 PciIdeXPdoQueryPnpDeviceState( 237 _In_ PPDO_DEVICE_EXTENSION PdoExtension, 238 _In_ PIRP Irp) 239 { 240 PAGED_CODE(); 241 242 if (PdoExtension->Common.PageFiles || 243 PdoExtension->Common.HibernateFiles || 244 PdoExtension->Common.DumpFiles) 245 { 246 Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE; 247 } 248 249 return STATUS_SUCCESS; 250 } 251 252 static 253 CODE_SEG("PAGE") 254 NTSTATUS 255 PciIdeXPdoQueryResources( 256 _In_ PPDO_DEVICE_EXTENSION PdoExtension, 257 _In_ PIRP Irp) 258 { 259 PFDO_DEVICE_EXTENSION FdoExtension; 260 IDE_CHANNEL_STATE ChannelState; 261 PCM_RESOURCE_LIST ResourceList; 262 PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor; 263 ULONG CommandPortBase, ControlPortBase, InterruptVector; 264 ULONG ListSize; 265 266 PAGED_CODE(); 267 268 FdoExtension = PdoExtension->ParentController; 269 if (FdoExtension->InNativeMode) 270 return Irp->IoStatus.Status; 271 272 ChannelState = PciIdeXChannelState(FdoExtension, PdoExtension->Channel); 273 if (ChannelState == ChannelDisabled) 274 return Irp->IoStatus.Status; 275 276 ListSize = sizeof(CM_RESOURCE_LIST) + 277 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * (PCIIDE_LEGACY_RESOURCE_COUNT - 1); 278 ResourceList = ExAllocatePoolZero(PagedPool, ListSize, TAG_PCIIDEX); 279 if (!ResourceList) 280 return STATUS_INSUFFICIENT_RESOURCES; 281 282 /* Legacy mode resources */ 283 ResourceList->Count = 1; 284 ResourceList->List[0].InterfaceType = Isa; 285 ResourceList->List[0].PartialResourceList.Version = 1; 286 ResourceList->List[0].PartialResourceList.Revision = 1; 287 ResourceList->List[0].PartialResourceList.Count = PCIIDE_LEGACY_RESOURCE_COUNT; 288 289 if (IS_PRIMARY_CHANNEL(PdoExtension)) 290 { 291 CommandPortBase = PCIIDE_LEGACY_PRIMARY_COMMAND_BASE; 292 ControlPortBase = PCIIDE_LEGACY_PRIMARY_CONTROL_BASE; 293 InterruptVector = PCIIDE_LEGACY_PRIMARY_IRQ; 294 } 295 else 296 { 297 CommandPortBase = PCIIDE_LEGACY_SECONDARY_COMMAND_BASE; 298 ControlPortBase = PCIIDE_LEGACY_SECONDARY_CONTROL_BASE; 299 InterruptVector = PCIIDE_LEGACY_SECONDARY_IRQ; 300 } 301 302 Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[0]; 303 304 /* Command port base */ 305 Descriptor->Type = CmResourceTypePort; 306 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 307 Descriptor->Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE; 308 Descriptor->u.Port.Length = PCIIDE_LEGACY_COMMAND_IO_RANGE_LENGTH; 309 Descriptor->u.Port.Start.LowPart = CommandPortBase; 310 ++Descriptor; 311 312 /* Control port base */ 313 Descriptor->Type = CmResourceTypePort; 314 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 315 Descriptor->Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE; 316 Descriptor->u.Port.Length = PCIIDE_LEGACY_CONTROL_IO_RANGE_LENGTH; 317 Descriptor->u.Port.Start.LowPart = ControlPortBase; 318 ++Descriptor; 319 320 /* Interrupt */ 321 Descriptor->Type = CmResourceTypeInterrupt; 322 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 323 Descriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; 324 Descriptor->u.Interrupt.Level = InterruptVector; 325 Descriptor->u.Interrupt.Vector = InterruptVector; 326 Descriptor->u.Interrupt.Affinity = (KAFFINITY)-1; 327 328 Irp->IoStatus.Information = (ULONG_PTR)ResourceList; 329 return STATUS_SUCCESS; 330 } 331 332 static 333 CODE_SEG("PAGE") 334 NTSTATUS 335 PciIdeXPdoQueryResourceRequirements( 336 _In_ PPDO_DEVICE_EXTENSION PdoExtension, 337 _In_ PIRP Irp) 338 { 339 PFDO_DEVICE_EXTENSION FdoExtension; 340 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList; 341 PIO_RESOURCE_DESCRIPTOR Descriptor; 342 IDE_CHANNEL_STATE ChannelState; 343 ULONG CommandPortBase, ControlPortBase, InterruptVector; 344 ULONG ListSize; 345 346 PAGED_CODE(); 347 348 FdoExtension = PdoExtension->ParentController; 349 if (FdoExtension->InNativeMode) 350 return Irp->IoStatus.Status; 351 352 ChannelState = PciIdeXChannelState(FdoExtension, PdoExtension->Channel); 353 if (ChannelState == ChannelDisabled) 354 return Irp->IoStatus.Status; 355 356 ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) + 357 sizeof(IO_RESOURCE_DESCRIPTOR) * (PCIIDE_LEGACY_RESOURCE_COUNT - 1); 358 RequirementsList = ExAllocatePoolZero(PagedPool, ListSize, TAG_PCIIDEX); 359 if (!RequirementsList) 360 return STATUS_INSUFFICIENT_RESOURCES; 361 362 /* Legacy mode resources */ 363 RequirementsList->InterfaceType = Isa; 364 RequirementsList->ListSize = ListSize; 365 RequirementsList->AlternativeLists = 1; 366 RequirementsList->List[0].Version = 1; 367 RequirementsList->List[0].Revision = 1; 368 RequirementsList->List[0].Count = PCIIDE_LEGACY_RESOURCE_COUNT; 369 370 if (IS_PRIMARY_CHANNEL(PdoExtension)) 371 { 372 CommandPortBase = PCIIDE_LEGACY_PRIMARY_COMMAND_BASE; 373 ControlPortBase = PCIIDE_LEGACY_PRIMARY_CONTROL_BASE; 374 InterruptVector = PCIIDE_LEGACY_PRIMARY_IRQ; 375 } 376 else 377 { 378 CommandPortBase = PCIIDE_LEGACY_SECONDARY_COMMAND_BASE; 379 ControlPortBase = PCIIDE_LEGACY_SECONDARY_CONTROL_BASE; 380 InterruptVector = PCIIDE_LEGACY_SECONDARY_IRQ; 381 } 382 383 Descriptor = &RequirementsList->List[0].Descriptors[0]; 384 385 /* Command port base */ 386 Descriptor->Type = CmResourceTypePort; 387 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 388 Descriptor->Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE; 389 Descriptor->u.Port.Length = PCIIDE_LEGACY_COMMAND_IO_RANGE_LENGTH; 390 Descriptor->u.Port.Alignment = 1; 391 Descriptor->u.Port.MinimumAddress.LowPart = CommandPortBase; 392 Descriptor->u.Port.MaximumAddress.LowPart = CommandPortBase + 393 PCIIDE_LEGACY_COMMAND_IO_RANGE_LENGTH - 1; 394 ++Descriptor; 395 396 /* Control port base */ 397 Descriptor->Type = CmResourceTypePort; 398 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 399 Descriptor->Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE; 400 Descriptor->u.Port.Length = PCIIDE_LEGACY_CONTROL_IO_RANGE_LENGTH; 401 Descriptor->u.Port.Alignment = 1; 402 Descriptor->u.Port.MinimumAddress.LowPart = ControlPortBase; 403 Descriptor->u.Port.MaximumAddress.LowPart = ControlPortBase + 404 PCIIDE_LEGACY_CONTROL_IO_RANGE_LENGTH - 1; 405 ++Descriptor; 406 407 /* Interrupt */ 408 Descriptor->Type = CmResourceTypeInterrupt; 409 Descriptor->ShareDisposition = CmResourceShareShared; 410 Descriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; 411 Descriptor->u.Interrupt.MinimumVector = InterruptVector; 412 Descriptor->u.Interrupt.MaximumVector = InterruptVector; 413 414 Irp->IoStatus.Information = (ULONG_PTR)RequirementsList; 415 return STATUS_SUCCESS; 416 } 417 418 static 419 CODE_SEG("PAGE") 420 PCWSTR 421 PciIdeXGetControllerVendorId( 422 _In_ PFDO_DEVICE_EXTENSION FdoExtension) 423 { 424 PAGED_CODE(); 425 426 switch (FdoExtension->VendorId) 427 { 428 case 0x0E11: 429 return L"Compaq"; 430 case 0x1039: 431 return L"SiS"; 432 case 0x1050: 433 return L"WinBond"; 434 case 0x1095: 435 return L"CMD"; 436 case 0x10B9: 437 return L"ALi"; 438 case 0x8086: 439 return L"Intel"; 440 441 default: 442 break; 443 } 444 445 /* Only certain controllers have a non-numeric identifier */ 446 return NULL; 447 } 448 449 static 450 CODE_SEG("PAGE") 451 PCWSTR 452 PciIdeXGetControllerDeviceId( 453 _In_ PFDO_DEVICE_EXTENSION FdoExtension) 454 { 455 PAGED_CODE(); 456 457 /* Intel */ 458 if (FdoExtension->VendorId == 0x8086) 459 { 460 switch (FdoExtension->DeviceId) 461 { 462 case 0x1230: 463 return L"PIIX"; 464 case 0x7010: 465 return L"PIIX3"; 466 case 0x7111: 467 return L"PIIX4"; 468 469 default: 470 break; 471 } 472 } 473 474 return NULL; 475 } 476 477 static 478 CODE_SEG("PAGE") 479 NTSTATUS 480 PciIdeXPdoQueryId( 481 _In_ PPDO_DEVICE_EXTENSION PdoExtension, 482 _In_ PIRP Irp) 483 { 484 PIO_STACK_LOCATION IoStack; 485 NTSTATUS Status; 486 PWCHAR Buffer, End; 487 size_t CharCount, Remaining; 488 static const WCHAR IdeCompatibleId[] = L"*PNP0600"; 489 490 PAGED_CODE(); 491 492 IoStack = IoGetCurrentIrpStackLocation(Irp); 493 switch (IoStack->Parameters.QueryId.IdType) 494 { 495 case BusQueryDeviceID: 496 { 497 static const WCHAR PciIdeDeviceId[] = L"PCIIDE\\IDEChannel"; 498 499 Buffer = ExAllocatePoolWithTag(PagedPool, sizeof(PciIdeDeviceId), TAG_PCIIDEX); 500 if (!Buffer) 501 return STATUS_INSUFFICIENT_RESOURCES; 502 503 RtlCopyMemory(Buffer, PciIdeDeviceId, sizeof(PciIdeDeviceId)); 504 505 DPRINT("Device ID: '%S'\n", Buffer); 506 break; 507 } 508 509 case BusQueryHardwareIDs: 510 { 511 PFDO_DEVICE_EXTENSION FdoExtension; 512 PCWSTR VendorString; 513 PWCHAR IdStart; 514 515 DBG_UNREFERENCED_LOCAL_VARIABLE(IdStart); 516 517 /* Maximum string length */ 518 CharCount = sizeof("WinBond-1234") + 519 sizeof("Secondary_IDE_Channel") + 520 sizeof(IdeCompatibleId) + 521 sizeof(ANSI_NULL); /* multi-string */ 522 523 Buffer = ExAllocatePoolWithTag(PagedPool, 524 CharCount * sizeof(WCHAR), 525 TAG_PCIIDEX); 526 if (!Buffer) 527 return STATUS_INSUFFICIENT_RESOURCES; 528 529 FdoExtension = PdoExtension->ParentController; 530 VendorString = PciIdeXGetControllerVendorId(FdoExtension); 531 532 DPRINT("HardwareIDs:\n"); 533 534 /* ID 1 */ 535 if (VendorString) 536 { 537 PCWSTR DeviceString = PciIdeXGetControllerDeviceId(FdoExtension); 538 539 if (DeviceString) 540 { 541 Status = RtlStringCchPrintfExW(Buffer, 542 CharCount, 543 &End, 544 &Remaining, 545 0, 546 L"%ls-%ls", 547 VendorString, 548 DeviceString); 549 } 550 else 551 { 552 Status = RtlStringCchPrintfExW(Buffer, 553 CharCount, 554 &End, 555 &Remaining, 556 0, 557 L"%ls-%04x", 558 VendorString, 559 FdoExtension->DeviceId); 560 } 561 } 562 else 563 { 564 Status = RtlStringCchPrintfExW(Buffer, 565 CharCount, 566 &End, 567 &Remaining, 568 0, 569 L"%04x-%04x", 570 FdoExtension->VendorId, 571 FdoExtension->DeviceId); 572 } 573 ASSERT(NT_SUCCESS(Status)); 574 575 DPRINT(" '%S'\n", Buffer); 576 577 ++End; 578 --Remaining; 579 580 /* ID 2 */ 581 IdStart = End; 582 Status = RtlStringCchPrintfExW(End, 583 Remaining, 584 &End, 585 &Remaining, 586 0, 587 L"%ls", 588 IS_PRIMARY_CHANNEL(PdoExtension) ? 589 L"Primary_IDE_Channel" : 590 L"Secondary_IDE_Channel"); 591 ASSERT(NT_SUCCESS(Status)); 592 593 DPRINT(" '%S'\n", IdStart); 594 595 ++End; 596 --Remaining; 597 598 /* ID 3 */ 599 IdStart = End; 600 Status = RtlStringCchPrintfExW(End, 601 Remaining, 602 &End, 603 &Remaining, 604 0, 605 L"%ls", 606 IdeCompatibleId); 607 ASSERT(NT_SUCCESS(Status)); 608 609 DPRINT(" '%S'\n", IdStart); 610 611 *++End = UNICODE_NULL; /* multi-string */ 612 break; 613 } 614 615 case BusQueryCompatibleIDs: 616 { 617 Buffer = ExAllocatePoolWithTag(PagedPool, 618 sizeof(IdeCompatibleId) + sizeof(UNICODE_NULL), 619 TAG_PCIIDEX); 620 if (!Buffer) 621 return STATUS_INSUFFICIENT_RESOURCES; 622 623 RtlCopyMemory(Buffer, IdeCompatibleId, sizeof(IdeCompatibleId)); 624 625 Buffer[sizeof(IdeCompatibleId) / sizeof(WCHAR)] = UNICODE_NULL; /* multi-string */ 626 627 DPRINT("Compatible ID: '%S'\n", Buffer); 628 break; 629 } 630 631 case BusQueryInstanceID: 632 { 633 CharCount = sizeof("0"); 634 635 Buffer = ExAllocatePoolWithTag(PagedPool, 636 CharCount * sizeof(WCHAR), 637 TAG_PCIIDEX); 638 if (!Buffer) 639 return STATUS_INSUFFICIENT_RESOURCES; 640 641 Status = RtlStringCchPrintfExW(Buffer, 642 CharCount, 643 NULL, 644 NULL, 645 0, 646 L"%lu", 647 PdoExtension->Channel); 648 ASSERT(NT_SUCCESS(Status)); 649 650 DPRINT("Instance ID: '%S'\n", Buffer); 651 break; 652 } 653 654 default: 655 return Irp->IoStatus.Status; 656 } 657 658 Irp->IoStatus.Information = (ULONG_PTR)Buffer; 659 return STATUS_SUCCESS; 660 } 661 662 static 663 CODE_SEG("PAGE") 664 NTSTATUS 665 PciIdeXPdoQueryDeviceText( 666 _In_ PPDO_DEVICE_EXTENSION PdoExtension, 667 _In_ PIRP Irp) 668 { 669 PIO_STACK_LOCATION IoStack; 670 PWCHAR Buffer; 671 ULONG Size; 672 673 PAGED_CODE(); 674 675 IoStack = IoGetCurrentIrpStackLocation(Irp); 676 switch (IoStack->Parameters.QueryDeviceText.DeviceTextType) 677 { 678 case DeviceTextLocationInformation: 679 { 680 static const WCHAR PrimaryChannelText[] = L"Primary channel"; 681 static const WCHAR SecondaryChannelText[] = L"Secondary channel"; 682 683 if (IS_PRIMARY_CHANNEL(PdoExtension)) 684 Size = sizeof(PrimaryChannelText); 685 else 686 Size = sizeof(SecondaryChannelText); 687 688 Buffer = ExAllocatePoolWithTag(PagedPool, Size, TAG_PCIIDEX); 689 if (!Buffer) 690 return STATUS_INSUFFICIENT_RESOURCES; 691 692 RtlCopyMemory(Buffer, 693 IS_PRIMARY_CHANNEL(PdoExtension) ? 694 PrimaryChannelText : SecondaryChannelText, 695 Size); 696 697 DPRINT("Device ID: '%S'\n", Buffer); 698 break; 699 } 700 701 default: 702 return Irp->IoStatus.Status; 703 } 704 705 Irp->IoStatus.Information = (ULONG_PTR)Buffer; 706 return STATUS_SUCCESS; 707 } 708 709 static 710 CODE_SEG("PAGE") 711 NTSTATUS 712 PciIdeXPdoQueryDeviceUsageNotification( 713 _In_ PPDO_DEVICE_EXTENSION PdoExtension, 714 _In_ PIRP Irp) 715 { 716 PIO_STACK_LOCATION IoStack; 717 NTSTATUS Status; 718 volatile LONG* Counter; 719 720 PAGED_CODE(); 721 722 Status = PciIdeXPdoRepeatRequest(PdoExtension, Irp, NULL); 723 if (!NT_SUCCESS(Status)) 724 return Status; 725 726 IoStack = IoGetCurrentIrpStackLocation(Irp); 727 switch (IoStack->Parameters.UsageNotification.Type) 728 { 729 case DeviceUsageTypePaging: 730 Counter = &PdoExtension->Common.PageFiles; 731 break; 732 733 case DeviceUsageTypeHibernation: 734 Counter = &PdoExtension->Common.HibernateFiles; 735 break; 736 737 case DeviceUsageTypeDumpFile: 738 Counter = &PdoExtension->Common.DumpFiles; 739 break; 740 741 default: 742 return Status; 743 } 744 745 IoAdjustPagingPathCount(Counter, IoStack->Parameters.UsageNotification.InPath); 746 IoInvalidateDeviceState(PdoExtension->Common.Self); 747 748 return STATUS_SUCCESS; 749 } 750 751 static 752 CODE_SEG("PAGE") 753 NTSTATUS 754 PciIdeXPdoDispatchPnp( 755 _In_ PPDO_DEVICE_EXTENSION PdoExtension, 756 _Inout_ PIRP Irp) 757 { 758 NTSTATUS Status; 759 PIO_STACK_LOCATION IoStack; 760 761 PAGED_CODE(); 762 763 IoStack = IoGetCurrentIrpStackLocation(Irp); 764 switch (IoStack->MinorFunction) 765 { 766 case IRP_MN_START_DEVICE: 767 Status = PciIdeXPdoStartDevice(PdoExtension, 768 IoStack->Parameters.StartDevice.AllocatedResources); 769 break; 770 771 case IRP_MN_STOP_DEVICE: 772 Status = PciIdeXPdoStopDevice(PdoExtension); 773 break; 774 775 case IRP_MN_QUERY_STOP_DEVICE: 776 case IRP_MN_QUERY_REMOVE_DEVICE: 777 Status = PciIdeXPdoQueryStopRemoveDevice(PdoExtension); 778 break; 779 780 case IRP_MN_CANCEL_REMOVE_DEVICE: 781 case IRP_MN_CANCEL_STOP_DEVICE: 782 Status = STATUS_SUCCESS; 783 break; 784 785 case IRP_MN_SURPRISE_REMOVAL: 786 case IRP_MN_REMOVE_DEVICE: 787 Status = PciIdeXPdoRemoveDevice(PdoExtension, 788 IoStack->MinorFunction == IRP_MN_REMOVE_DEVICE); 789 break; 790 791 case IRP_MN_QUERY_DEVICE_RELATIONS: 792 if (IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation) 793 Status = PciIdeXPdoQueryTargetDeviceRelations(PdoExtension, Irp); 794 else 795 Status = Irp->IoStatus.Status; 796 break; 797 798 case IRP_MN_QUERY_CAPABILITIES: 799 Status = PciIdeXPdoQueryCapabilities(PdoExtension, Irp); 800 break; 801 802 case IRP_MN_QUERY_PNP_DEVICE_STATE: 803 Status = PciIdeXPdoQueryPnpDeviceState(PdoExtension, Irp); 804 break; 805 806 case IRP_MN_QUERY_RESOURCES: 807 Status = PciIdeXPdoQueryResources(PdoExtension, Irp); 808 break; 809 810 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: 811 Status = PciIdeXPdoQueryResourceRequirements(PdoExtension, Irp); 812 break; 813 814 case IRP_MN_QUERY_ID: 815 Status = PciIdeXPdoQueryId(PdoExtension, Irp); 816 break; 817 818 case IRP_MN_QUERY_DEVICE_TEXT: 819 Status = PciIdeXPdoQueryDeviceText(PdoExtension, Irp); 820 break; 821 822 case IRP_MN_DEVICE_USAGE_NOTIFICATION: 823 Status = PciIdeXPdoQueryDeviceUsageNotification(PdoExtension, Irp); 824 break; 825 826 default: 827 Status = Irp->IoStatus.Status; 828 break; 829 } 830 831 Irp->IoStatus.Status = Status; 832 IoCompleteRequest(Irp, IO_NO_INCREMENT); 833 834 return Status; 835 } 836 837 CODE_SEG("PAGE") 838 NTSTATUS 839 NTAPI 840 PciIdeXDispatchPnp( 841 _In_ PDEVICE_OBJECT DeviceObject, 842 _Inout_ PIRP Irp) 843 { 844 PAGED_CODE(); 845 846 if (IS_FDO(DeviceObject->DeviceExtension)) 847 return PciIdeXFdoDispatchPnp(DeviceObject->DeviceExtension, Irp); 848 else 849 return PciIdeXPdoDispatchPnp(DeviceObject->DeviceExtension, Irp); 850 } 851