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
PciIdeXPdoStartDevice(_In_ PPDO_DEVICE_EXTENSION PdoExtension,_In_ PCM_RESOURCE_LIST ResourceList)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
PciIdeXPdoStopDevice(_In_ PPDO_DEVICE_EXTENSION PdoExtension)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
PciIdeXPdoRemoveDevice(_In_ PPDO_DEVICE_EXTENSION PdoExtension,_In_ BOOLEAN FinalRemove)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
PciIdeXPdoQueryStopRemoveDevice(_In_ PPDO_DEVICE_EXTENSION PdoExtension)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
PciIdeXPdoQueryTargetDeviceRelations(_In_ PPDO_DEVICE_EXTENSION PdoExtension,_In_ PIRP Irp)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
PciIdeXPdoRepeatRequest(_In_ PPDO_DEVICE_EXTENSION PdoExtension,_In_ PIRP Irp,_In_opt_ PDEVICE_CAPABILITIES DeviceCapabilities)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
PciIdeXPdoQueryCapabilities(_In_ PPDO_DEVICE_EXTENSION PdoExtension,_In_ PIRP Irp)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
PciIdeXPdoQueryPnpDeviceState(_In_ PPDO_DEVICE_EXTENSION PdoExtension,_In_ PIRP Irp)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
PciIdeXPdoQueryResources(_In_ PPDO_DEVICE_EXTENSION PdoExtension,_In_ PIRP Irp)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
PciIdeXPdoQueryResourceRequirements(_In_ PPDO_DEVICE_EXTENSION PdoExtension,_In_ PIRP Irp)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
PciIdeXGetControllerVendorId(_In_ PFDO_DEVICE_EXTENSION FdoExtension)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
PciIdeXGetControllerDeviceId(_In_ PFDO_DEVICE_EXTENSION FdoExtension)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
PciIdeXPdoQueryId(_In_ PPDO_DEVICE_EXTENSION PdoExtension,_In_ PIRP Irp)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
PciIdeXPdoQueryDeviceText(_In_ PPDO_DEVICE_EXTENSION PdoExtension,_In_ PIRP Irp)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
PciIdeXPdoQueryDeviceUsageNotification(_In_ PPDO_DEVICE_EXTENSION PdoExtension,_In_ PIRP Irp)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
PciIdeXPdoDispatchPnp(_In_ PPDO_DEVICE_EXTENSION PdoExtension,_Inout_ PIRP Irp)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
PciIdeXDispatchPnp(_In_ PDEVICE_OBJECT DeviceObject,_Inout_ PIRP Irp)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