xref: /reactos/hal/halx86/acpi/halpnpdd.c (revision 50cf16b3)
1 /*
2  * PROJECT:         ReactOS HAL
3  * LICENSE:         BSD - See COPYING.ARM in the top level directory
4  * FILE:            hal/halx86/acpi/halpnpdd.c
5  * PURPOSE:         HAL Plug and Play Device Driver
6  * PROGRAMMERS:     ReactOS Portable Systems Group
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include <hal.h>
12 #define NDEBUG
13 #include <debug.h>
14 
15 typedef enum _EXTENSION_TYPE
16 {
17     PdoExtensionType = 0xC0,
18     FdoExtensionType
19 } EXTENSION_TYPE;
20 
21 typedef enum _PDO_TYPE
22 {
23     AcpiPdo = 0x80,
24     WdPdo
25 } PDO_TYPE;
26 
27 typedef struct _FDO_EXTENSION
28 {
29     EXTENSION_TYPE ExtensionType;
30     struct _PDO_EXTENSION* ChildPdoList;
31     PDEVICE_OBJECT PhysicalDeviceObject;
32     PDEVICE_OBJECT FunctionalDeviceObject;
33     PDEVICE_OBJECT AttachedDeviceObject;
34 } FDO_EXTENSION, *PFDO_EXTENSION;
35 
36 typedef struct _PDO_EXTENSION
37 {
38     EXTENSION_TYPE ExtensionType;
39     struct _PDO_EXTENSION* Next;
40     PDEVICE_OBJECT PhysicalDeviceObject;
41     PFDO_EXTENSION ParentFdoExtension;
42     PDO_TYPE PdoType;
43     PDESCRIPTION_HEADER WdTable;
44     LONG InterfaceReferenceCount;
45 } PDO_EXTENSION, *PPDO_EXTENSION;
46 
47 /* GLOBALS ********************************************************************/
48 
49 PDRIVER_OBJECT HalpDriverObject;
50 
51 /* PRIVATE FUNCTIONS **********************************************************/
52 
53 VOID
54 NTAPI
55 HalpReportDetectedDevices(IN PDRIVER_OBJECT DriverObject,
56                           IN PVOID Context,
57                           IN ULONG Count)
58 {
59     PFDO_EXTENSION FdoExtension = Context;
60     PPDO_EXTENSION PdoExtension;
61     PDEVICE_OBJECT PdoDeviceObject;
62     PDESCRIPTION_HEADER Wdrt;
63     NTSTATUS Status;
64 
65     /* Create the PDO */
66     Status = IoCreateDevice(DriverObject,
67                             sizeof(PDO_EXTENSION),
68                             NULL,
69                             FILE_DEVICE_BUS_EXTENDER,
70                             FILE_AUTOGENERATED_DEVICE_NAME,
71                             FALSE,
72                             &PdoDeviceObject);
73     if (!NT_SUCCESS(Status))
74     {
75         /* Fail */
76         DPRINT1("HAL: Could not create ACPI device object status=0x%08x\n", Status);
77         return;
78     }
79 
80     /* Setup the PDO device extension */
81     PdoExtension = PdoDeviceObject->DeviceExtension;
82     PdoExtension->ExtensionType = PdoExtensionType;
83     PdoExtension->PhysicalDeviceObject = PdoDeviceObject;
84     PdoExtension->ParentFdoExtension = FdoExtension;
85     PdoExtension->PdoType = AcpiPdo;
86 
87     /* Add the PDO to the head of the list */
88     PdoExtension->Next = FdoExtension->ChildPdoList;
89     FdoExtension->ChildPdoList = PdoExtension;
90 
91     /* Initialization is finished */
92     PdoDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
93 
94     /* Find the ACPI watchdog table */
95     Wdrt = HalAcpiGetTable(0, 'TRDW');
96     if (Wdrt)
97     {
98         /* FIXME: TODO */
99         DPRINT1("You have an ACPI Watchdog. That's great! You should be proud ;-)\n");
100     }
101 
102     /* This will synchronously load the ACPI driver (needed because we're critical for boot) */
103     IoSynchronousInvalidateDeviceRelations(FdoExtension->PhysicalDeviceObject, BusRelations);
104 }
105 
106 NTSTATUS
107 NTAPI
108 HalpAddDevice(IN PDRIVER_OBJECT DriverObject,
109               IN PDEVICE_OBJECT TargetDevice)
110 {
111     NTSTATUS Status;
112     PFDO_EXTENSION FdoExtension;
113     PDEVICE_OBJECT DeviceObject, AttachedDevice;
114 
115     DPRINT("HAL: PnP Driver ADD!\n");
116 
117     /* Create the FDO */
118     Status = IoCreateDevice(DriverObject,
119                             sizeof(FDO_EXTENSION),
120                             NULL,
121                             FILE_DEVICE_BUS_EXTENDER,
122                             0,
123                             FALSE,
124                             &DeviceObject);
125     if (!NT_SUCCESS(Status))
126     {
127         /* Should not happen */
128         DbgBreakPoint();
129         return Status;
130     }
131 
132     /* Setup the FDO extension */
133     FdoExtension = DeviceObject->DeviceExtension;
134     FdoExtension->ExtensionType = FdoExtensionType;
135     FdoExtension->PhysicalDeviceObject = TargetDevice;
136     FdoExtension->FunctionalDeviceObject = DeviceObject;
137     FdoExtension->ChildPdoList = NULL;
138 
139     /* FDO is done initializing */
140     DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
141 
142     /* Attach to the physical device object (the bus) */
143     AttachedDevice = IoAttachDeviceToDeviceStack(DeviceObject, TargetDevice);
144     if (!AttachedDevice)
145     {
146         /* Failed, undo everything */
147         IoDeleteDevice(DeviceObject);
148         return STATUS_NO_SUCH_DEVICE;
149     }
150 
151     /* Save the attachment */
152     FdoExtension->AttachedDeviceObject = AttachedDevice;
153 
154     /* Register for reinitialization to report devices later */
155     IoRegisterBootDriverReinitialization(DriverObject,
156                                          HalpReportDetectedDevices,
157                                          FdoExtension);
158 
159     /* Return status */
160     DPRINT("Device added %lx\n", Status);
161     return Status;
162 }
163 
164 NTSTATUS
165 NTAPI
166 HalpQueryInterface(IN PDEVICE_OBJECT DeviceObject,
167                    IN CONST GUID* InterfaceType,
168                    IN USHORT Version,
169                    IN PVOID InterfaceSpecificData,
170                    IN ULONG InterfaceBufferSize,
171                    IN PINTERFACE Interface,
172                    OUT PULONG Length)
173 {
174     UNIMPLEMENTED;
175     return STATUS_NOT_SUPPORTED;
176 }
177 
178 NTSTATUS
179 NTAPI
180 HalpQueryDeviceRelations(IN PDEVICE_OBJECT DeviceObject,
181                          IN DEVICE_RELATION_TYPE RelationType,
182                          OUT PDEVICE_RELATIONS* DeviceRelations)
183 {
184     EXTENSION_TYPE ExtensionType;
185     PPDO_EXTENSION PdoExtension;
186     PFDO_EXTENSION FdoExtension;
187     PDEVICE_RELATIONS PdoRelations, FdoRelations;
188     PDEVICE_OBJECT* ObjectEntry;
189     ULONG i = 0, PdoCount = 0;
190 
191     /* Get FDO device extension and PDO count */
192     FdoExtension = DeviceObject->DeviceExtension;
193     ExtensionType = FdoExtension->ExtensionType;
194 
195     /* What do they want? */
196     if (RelationType == BusRelations)
197     {
198         /* This better be an FDO */
199         if (ExtensionType == FdoExtensionType)
200         {
201             /* Count how many PDOs we have */
202             PdoExtension = FdoExtension->ChildPdoList;
203             while (PdoExtension)
204             {
205                 /* Next one */
206                 PdoExtension = PdoExtension->Next;
207                 PdoCount++;
208             }
209 
210             /* Add the PDOs that already exist in the device relations */
211             if (*DeviceRelations)
212             {
213                 PdoCount += (*DeviceRelations)->Count;
214             }
215 
216             /* Allocate our structure */
217             FdoRelations = ExAllocatePoolWithTag(PagedPool,
218                                                  FIELD_OFFSET(DEVICE_RELATIONS,
219                                                               Objects) +
220                                                  sizeof(PDEVICE_OBJECT) * PdoCount,
221                                                  TAG_HAL);
222             if (!FdoRelations) return STATUS_INSUFFICIENT_RESOURCES;
223 
224             /* Save our count */
225             FdoRelations->Count = PdoCount;
226 
227             /* Query existing relations */
228             ObjectEntry = FdoRelations->Objects;
229             if (*DeviceRelations)
230             {
231                 /* Check if there were any */
232                 if ((*DeviceRelations)->Count)
233                 {
234                     /* Loop them all */
235                     do
236                     {
237                         /* Copy into our structure */
238                         *ObjectEntry++ = (*DeviceRelations)->Objects[i];
239                     }
240                     while (++i < (*DeviceRelations)->Count);
241                 }
242 
243                 /* Free existing structure */
244                 ExFreePool(*DeviceRelations);
245             }
246 
247             /* Now check if we have a PDO list */
248             PdoExtension = FdoExtension->ChildPdoList;
249             if (PdoExtension)
250             {
251                 /* Loop the PDOs */
252                 do
253                 {
254                     /* Save our own PDO and reference it */
255                     *ObjectEntry++ = PdoExtension->PhysicalDeviceObject;
256                     ObReferenceObject(PdoExtension->PhysicalDeviceObject);
257 
258                     /* Go to our next PDO */
259                     PdoExtension = PdoExtension->Next;
260                 }
261                 while (PdoExtension);
262             }
263 
264             /* Return the new structure */
265             *DeviceRelations = FdoRelations;
266             return STATUS_SUCCESS;
267         }
268     }
269     else
270     {
271         /* The only other thing we support is a target relation for the PDO */
272         if ((RelationType == TargetDeviceRelation) &&
273             (ExtensionType == PdoExtensionType))
274         {
275             /* Only one entry */
276             PdoRelations = ExAllocatePoolWithTag(PagedPool,
277                                                  sizeof(DEVICE_RELATIONS),
278                                                  TAG_HAL);
279             if (!PdoRelations) return STATUS_INSUFFICIENT_RESOURCES;
280 
281             /* Fill it out and reference us */
282             PdoRelations->Count = 1;
283             PdoRelations->Objects[0] = DeviceObject;
284             ObReferenceObject(DeviceObject);
285 
286             /* Return it */
287             *DeviceRelations = PdoRelations;
288             return STATUS_SUCCESS;
289         }
290     }
291 
292     /* We don't support anything else */
293     return STATUS_NOT_SUPPORTED;
294 }
295 
296 NTSTATUS
297 NTAPI
298 HalpQueryCapabilities(IN PDEVICE_OBJECT DeviceObject,
299                       OUT PDEVICE_CAPABILITIES Capabilities)
300 {
301     //PPDO_EXTENSION PdoExtension;
302     NTSTATUS Status;
303     PAGED_CODE();
304 
305     /* Get the extension and check for valid version */
306     //PdoExtension = DeviceObject->DeviceExtension;
307     ASSERT(Capabilities->Version == 1);
308     if (Capabilities->Version == 1)
309     {
310         /* Can't lock or eject us */
311         Capabilities->LockSupported = FALSE;
312         Capabilities->EjectSupported = FALSE;
313 
314         /* Can't remove or dock us */
315         Capabilities->Removable = FALSE;
316         Capabilities->DockDevice = FALSE;
317 
318         /* Can't access us raw */
319         Capabilities->RawDeviceOK = FALSE;
320 
321         /* We have a unique ID, and don't bother the user */
322         Capabilities->UniqueID = TRUE;
323         Capabilities->SilentInstall = TRUE;
324 
325         /* Fill out the adress */
326         Capabilities->Address = InterfaceTypeUndefined;
327         Capabilities->UINumber = InterfaceTypeUndefined;
328 
329         /* Fill out latencies */
330         Capabilities->D1Latency = 0;
331         Capabilities->D2Latency = 0;
332         Capabilities->D3Latency = 0;
333 
334         /* Fill out supported device states */
335         Capabilities->DeviceState[PowerSystemWorking] = PowerDeviceD0;
336         Capabilities->DeviceState[PowerSystemHibernate] = PowerDeviceD3;
337         Capabilities->DeviceState[PowerSystemShutdown] = PowerDeviceD3;
338         Capabilities->DeviceState[PowerSystemSleeping3] = PowerDeviceD3;
339 
340         /* Done */
341         Status = STATUS_SUCCESS;
342     }
343     else
344     {
345         /* Fail */
346         Status = STATUS_NOT_SUPPORTED;
347     }
348 
349     /* Return status */
350     return Status;
351 }
352 
353 NTSTATUS
354 NTAPI
355 HalpQueryResources(IN PDEVICE_OBJECT DeviceObject,
356                    OUT PCM_RESOURCE_LIST *Resources)
357 {
358     PPDO_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
359     NTSTATUS Status;
360     PCM_RESOURCE_LIST ResourceList;
361     PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
362     PIO_RESOURCE_DESCRIPTOR Descriptor;
363     PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDesc;
364     ULONG i;
365     PAGED_CODE();
366 
367     /* Only the ACPI PDO has requirements */
368     if (DeviceExtension->PdoType == AcpiPdo)
369     {
370         /* Query ACPI requirements */
371         Status = HalpQueryAcpiResourceRequirements(&RequirementsList);
372         if (!NT_SUCCESS(Status)) return Status;
373 
374         ASSERT(RequirementsList->AlternativeLists == 1);
375 
376         /* Allocate the resourcel ist */
377         ResourceList = ExAllocatePoolWithTag(PagedPool,
378                                              sizeof(CM_RESOURCE_LIST),
379                                              TAG_HAL);
380         if (!ResourceList )
381         {
382             /* Fail, no memory */
383             Status = STATUS_INSUFFICIENT_RESOURCES;
384             ExFreePoolWithTag(RequirementsList, TAG_HAL);
385             return Status;
386         }
387 
388         /* Initialize it */
389         RtlZeroMemory(ResourceList, sizeof(CM_RESOURCE_LIST));
390         ResourceList->Count = 1;
391 
392         /* Setup the list fields */
393         ResourceList->List[0].BusNumber = -1;
394         ResourceList->List[0].InterfaceType = PNPBus;
395         ResourceList->List[0].PartialResourceList.Version = 1;
396         ResourceList->List[0].PartialResourceList.Revision = 1;
397         ResourceList->List[0].PartialResourceList.Count = 0;
398 
399         /* Setup the first descriptor */
400         PartialDesc = ResourceList->List[0].PartialResourceList.PartialDescriptors;
401 
402         /* Find the requirement descriptor for the SCI */
403         for (i = 0; i < RequirementsList->List[0].Count; i++)
404         {
405             /* Get this descriptor */
406             Descriptor = &RequirementsList->List[0].Descriptors[i];
407             if (Descriptor->Type == CmResourceTypeInterrupt)
408             {
409                 /* Copy requirements descriptor into resource descriptor */
410                 PartialDesc->Type = CmResourceTypeInterrupt;
411                 PartialDesc->ShareDisposition = Descriptor->ShareDisposition;
412                 PartialDesc->Flags = Descriptor->Flags;
413                 ASSERT(Descriptor->u.Interrupt.MinimumVector ==
414                        Descriptor->u.Interrupt.MaximumVector);
415                 PartialDesc->u.Interrupt.Vector = Descriptor->u.Interrupt.MinimumVector;
416                 PartialDesc->u.Interrupt.Level = Descriptor->u.Interrupt.MinimumVector;
417                 PartialDesc->u.Interrupt.Affinity = 0xFFFFFFFF;
418 
419                 ResourceList->List[0].PartialResourceList.Count++;
420 
421                 break;
422             }
423         }
424 
425         /* Return resources and success */
426         *Resources = ResourceList;
427 
428         ExFreePoolWithTag(RequirementsList, TAG_HAL);
429 
430         return STATUS_SUCCESS;
431     }
432     else if (DeviceExtension->PdoType == WdPdo)
433     {
434         /* Watchdog doesn't */
435         return STATUS_NOT_SUPPORTED;
436     }
437     else
438     {
439         /* This shouldn't happen */
440         return STATUS_UNSUCCESSFUL;
441     }
442 }
443 
444 NTSTATUS
445 NTAPI
446 HalpQueryResourceRequirements(IN PDEVICE_OBJECT DeviceObject,
447                               OUT PIO_RESOURCE_REQUIREMENTS_LIST *Requirements)
448 {
449     PPDO_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
450     PAGED_CODE();
451 
452     /* Only the ACPI PDO has requirements */
453     if (DeviceExtension->PdoType == AcpiPdo)
454     {
455         /* Query ACPI requirements */
456         return HalpQueryAcpiResourceRequirements(Requirements);
457     }
458     else if (DeviceExtension->PdoType == WdPdo)
459     {
460         /* Watchdog doesn't */
461         return STATUS_NOT_SUPPORTED;
462     }
463     else
464     {
465         /* This shouldn't happen */
466         return STATUS_UNSUCCESSFUL;
467     }
468 }
469 
470 NTSTATUS
471 NTAPI
472 HalpQueryIdPdo(IN PDEVICE_OBJECT DeviceObject,
473                IN BUS_QUERY_ID_TYPE IdType,
474                OUT PUSHORT *BusQueryId)
475 {
476     PPDO_EXTENSION PdoExtension;
477     PDO_TYPE PdoType;
478     PWCHAR CurrentId;
479     WCHAR Id[100];
480     NTSTATUS Status;
481     SIZE_T Length = 0;
482     PWCHAR Buffer;
483 
484     /* Get the PDO type */
485     PdoExtension = DeviceObject->DeviceExtension;
486     PdoType = PdoExtension->PdoType;
487 
488     /* What kind of ID is being requested? */
489     DPRINT("ID: %d\n", IdType);
490     switch (IdType)
491     {
492         case BusQueryDeviceID:
493         case BusQueryHardwareIDs:
494 
495             /* What kind of PDO is this? */
496             if (PdoType == AcpiPdo)
497             {
498                 /* ACPI ID */
499                 CurrentId = L"ACPI_HAL\\PNP0C08";
500                 RtlCopyMemory(Id, CurrentId, (wcslen(CurrentId) * sizeof(WCHAR)) + sizeof(UNICODE_NULL));
501                 Length += (wcslen(CurrentId) * sizeof(WCHAR)) + sizeof(UNICODE_NULL);
502 
503                 CurrentId = L"*PNP0C08";
504                 RtlCopyMemory(&Id[wcslen(Id) + 1], CurrentId, (wcslen(CurrentId) * sizeof(WCHAR)) + sizeof(UNICODE_NULL));
505                 Length += (wcslen(CurrentId) * sizeof(WCHAR)) + sizeof(UNICODE_NULL);
506             }
507             else if (PdoType == WdPdo)
508             {
509                 /* WatchDog ID */
510                 CurrentId = L"ACPI_HAL\\PNP0C18";
511                 RtlCopyMemory(Id, CurrentId, (wcslen(CurrentId) * sizeof(WCHAR)) + sizeof(UNICODE_NULL));
512                 Length += (wcslen(CurrentId) * sizeof(WCHAR)) + sizeof(UNICODE_NULL);
513 
514                 CurrentId = L"*PNP0C18";
515                 RtlCopyMemory(&Id[wcslen(Id) + 1], CurrentId, (wcslen(CurrentId) * sizeof(WCHAR)) + sizeof(UNICODE_NULL));
516                 Length += (wcslen(CurrentId) * sizeof(WCHAR)) + sizeof(UNICODE_NULL);
517             }
518             else
519             {
520                 /* Unknown */
521                 return STATUS_NOT_SUPPORTED;
522             }
523             break;
524 
525         case BusQueryInstanceID:
526 
527             /* Instance ID */
528             CurrentId = L"0";
529             RtlCopyMemory(Id, CurrentId, (wcslen(CurrentId) * sizeof(WCHAR)) + sizeof(UNICODE_NULL));
530             Length += (wcslen(CurrentId) * sizeof(WCHAR)) + sizeof(UNICODE_NULL);
531             break;
532 
533         case BusQueryCompatibleIDs:
534         default:
535 
536             /* We don't support anything else */
537             return STATUS_NOT_SUPPORTED;
538     }
539 
540 
541     /* Allocate the buffer */
542     Buffer = ExAllocatePoolWithTag(PagedPool,
543                                    Length + sizeof(UNICODE_NULL),
544                                    TAG_HAL);
545     if (Buffer)
546     {
547         /* Copy the string and null-terminate it */
548         RtlCopyMemory(Buffer, Id, Length);
549         Buffer[Length / sizeof(WCHAR)] = UNICODE_NULL;
550 
551         /* Return string */
552         *BusQueryId = Buffer;
553         Status = STATUS_SUCCESS;
554         DPRINT("Returning: %S\n", *BusQueryId);
555     }
556     else
557     {
558         /* Fail */
559         Status = STATUS_INSUFFICIENT_RESOURCES;
560     }
561 
562     /* Return status */
563     return Status;
564 }
565 
566 NTSTATUS
567 NTAPI
568 HalpQueryIdFdo(IN PDEVICE_OBJECT DeviceObject,
569                IN BUS_QUERY_ID_TYPE IdType,
570                OUT PUSHORT *BusQueryId)
571 {
572     NTSTATUS Status;
573     SIZE_T Length;
574     PWCHAR Id;
575     PWCHAR Buffer;
576 
577     /* What kind of ID is being requested? */
578     DPRINT("ID: %d\n", IdType);
579     switch (IdType)
580     {
581         case BusQueryDeviceID:
582             /* HACK */
583             Id = L"Root\\ACPI_HAL";
584             break;
585 
586         case BusQueryHardwareIDs:
587 
588             /* This is our hardware ID */
589             Id = HalHardwareIdString;
590             break;
591 
592         case BusQueryInstanceID:
593 
594             /* And our instance ID */
595             Id = L"0";
596             break;
597 
598         default:
599 
600             /* We don't support anything else */
601             return STATUS_NOT_SUPPORTED;
602     }
603 
604     /* Calculate the length */
605     Length = (wcslen(Id) * sizeof(WCHAR)) + sizeof(UNICODE_NULL);
606 
607     /* Allocate the buffer */
608     Buffer = ExAllocatePoolWithTag(PagedPool,
609                                    Length + sizeof(UNICODE_NULL),
610                                    TAG_HAL);
611     if (Buffer)
612     {
613         /* Copy the string and null-terminate it */
614         RtlCopyMemory(Buffer, Id, Length);
615         Buffer[Length / sizeof(WCHAR)] = UNICODE_NULL;
616 
617         /* Return string */
618         *BusQueryId = Buffer;
619         Status = STATUS_SUCCESS;
620         DPRINT("Returning: %S\n", *BusQueryId);
621     }
622     else
623     {
624         /* Fail */
625         Status = STATUS_INSUFFICIENT_RESOURCES;
626     }
627 
628     /* Return status */
629     return Status;
630 }
631 
632 NTSTATUS
633 NTAPI
634 HalpDispatchPnp(IN PDEVICE_OBJECT DeviceObject,
635                 IN PIRP Irp)
636 {
637     PIO_STACK_LOCATION IoStackLocation;
638     //PPDO_EXTENSION PdoExtension;
639     PFDO_EXTENSION FdoExtension;
640     NTSTATUS Status;
641     UCHAR Minor;
642 
643     /* Get the device extension and stack location */
644     FdoExtension = DeviceObject->DeviceExtension;
645     IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
646     Minor = IoStackLocation->MinorFunction;
647 
648     /* FDO? */
649     if (FdoExtension->ExtensionType == FdoExtensionType)
650     {
651         /* Query the IRP type */
652         switch (Minor)
653         {
654             case IRP_MN_QUERY_DEVICE_RELATIONS:
655 
656                 /* Call the worker */
657                 DPRINT("Querying device relations for FDO\n");
658                 Status = HalpQueryDeviceRelations(DeviceObject,
659                                                   IoStackLocation->Parameters.QueryDeviceRelations.Type,
660                                                   (PVOID)&Irp->IoStatus.Information);
661                 break;
662 
663             case IRP_MN_QUERY_INTERFACE:
664 
665                 /* Call the worker */
666                 DPRINT("Querying interface for FDO\n");
667                 Status = HalpQueryInterface(DeviceObject,
668                                             IoStackLocation->Parameters.QueryInterface.InterfaceType,
669                                             IoStackLocation->Parameters.QueryInterface.Size,
670                                             IoStackLocation->Parameters.QueryInterface.InterfaceSpecificData,
671                                             IoStackLocation->Parameters.QueryInterface.Version,
672                                             IoStackLocation->Parameters.QueryInterface.Interface,
673                                             (PVOID)&Irp->IoStatus.Information);
674                 break;
675 
676 
677             case IRP_MN_QUERY_ID:
678 
679                 /* Call the worker */
680                 DPRINT("Querying ID for FDO\n");
681                 Status = HalpQueryIdFdo(DeviceObject,
682                                         IoStackLocation->Parameters.QueryId.IdType,
683                                         (PVOID)&Irp->IoStatus.Information);
684                 break;
685 
686             case IRP_MN_QUERY_CAPABILITIES:
687 
688                 /* Call the worker */
689                 DPRINT("Querying the capabilities for the FDO\n");
690                 Status = HalpQueryCapabilities(DeviceObject,
691                                                IoStackLocation->Parameters.DeviceCapabilities.Capabilities);
692                 break;
693 
694             default:
695 
696                 DPRINT("Other IRP: %lx\n", Minor);
697                 Status = Irp->IoStatus.Status;
698                 break;
699         }
700 
701         /* Nowhere for the IRP to go since we also own the PDO */
702         Irp->IoStatus.Status = Status;
703         IoCompleteRequest(Irp, IO_NO_INCREMENT);
704         return Status;
705     }
706     else
707     {
708         /* This is a PDO instead */
709         ASSERT(FdoExtension->ExtensionType == PdoExtensionType);
710         //PdoExtension = (PPDO_EXTENSION)FdoExtension;
711         /* Query the IRP type */
712         Status = STATUS_SUCCESS;
713         switch (Minor)
714         {
715             case IRP_MN_START_DEVICE:
716 
717                 /* We only care about a PCI PDO */
718                 DPRINT1("Start device received\n");
719                 /* Complete the IRP normally */
720                 break;
721 
722             case IRP_MN_REMOVE_DEVICE:
723 
724                 /* Check if this is a PCI device */
725                 DPRINT1("Remove device received\n");
726 
727                 /* We're done */
728                 Status = STATUS_SUCCESS;
729                 break;
730 
731             case IRP_MN_SURPRISE_REMOVAL:
732 
733                 /* Inherit whatever status we had */
734                 DPRINT1("Surprise removal IRP\n");
735                 Status = Irp->IoStatus.Status;
736                 break;
737 
738             case IRP_MN_QUERY_DEVICE_RELATIONS:
739 
740                 /* Query the device relations */
741                 DPRINT("Querying PDO relations\n");
742                 Status = HalpQueryDeviceRelations(DeviceObject,
743                                                   IoStackLocation->Parameters.QueryDeviceRelations.Type,
744                                                   (PVOID)&Irp->IoStatus.Information);
745                 break;
746 
747             case IRP_MN_QUERY_INTERFACE:
748 
749                 /* Call the worker */
750                 DPRINT("Querying interface for PDO\n");
751                 Status = HalpQueryInterface(DeviceObject,
752                                             IoStackLocation->Parameters.QueryInterface.InterfaceType,
753                                             IoStackLocation->Parameters.QueryInterface.Size,
754                                             IoStackLocation->Parameters.QueryInterface.InterfaceSpecificData,
755                                             IoStackLocation->Parameters.QueryInterface.Version,
756                                             IoStackLocation->Parameters.QueryInterface.Interface,
757                                             (PVOID)&Irp->IoStatus.Information);
758                 break;
759 
760             case IRP_MN_QUERY_CAPABILITIES:
761 
762                 /* Call the worker */
763                 DPRINT("Querying the capabilities for the PDO\n");
764                 Status = HalpQueryCapabilities(DeviceObject,
765                                                IoStackLocation->Parameters.DeviceCapabilities.Capabilities);
766                 break;
767 
768             case IRP_MN_QUERY_RESOURCES:
769 
770                 /* Call the worker */
771                 DPRINT("Querying the resources for the PDO\n");
772                 Status = HalpQueryResources(DeviceObject, (PVOID)&Irp->IoStatus.Information);
773                 break;
774 
775             case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
776 
777                 /* Call the worker */
778                 DPRINT("Querying the resource requirements for the PDO\n");
779                 Status = HalpQueryResourceRequirements(DeviceObject,
780                                                        (PVOID)&Irp->IoStatus.Information);
781                 break;
782 
783             case IRP_MN_QUERY_ID:
784 
785                 /* Call the worker */
786                 DPRINT("Query the ID for the PDO\n");
787                 Status = HalpQueryIdPdo(DeviceObject,
788                                         IoStackLocation->Parameters.QueryId.IdType,
789                                         (PVOID)&Irp->IoStatus.Information);
790                 break;
791 
792             default:
793 
794                 /* We don't handle anything else, so inherit the old state */
795                 DPRINT("Illegal IRP: %lx\n", Minor);
796                 Status = Irp->IoStatus.Status;
797                 break;
798         }
799 
800         /* If it's not supported, inherit the old status */
801         if (Status == STATUS_NOT_SUPPORTED) Status = Irp->IoStatus.Status;
802 
803         /* Complete the IRP */
804         DPRINT("IRP completed with status: %lx\n", Status);
805         Irp->IoStatus.Status = Status;
806         IoCompleteRequest(Irp, IO_NO_INCREMENT);
807         return Status;
808     }
809 }
810 
811 NTSTATUS
812 NTAPI
813 HalpDispatchWmi(IN PDEVICE_OBJECT DeviceObject,
814                 IN PIRP Irp)
815 {
816     UNIMPLEMENTED_DBGBREAK("HAL: PnP Driver WMI!\n");
817     return STATUS_SUCCESS;
818 }
819 
820 NTSTATUS
821 NTAPI
822 HalpDispatchPower(IN PDEVICE_OBJECT DeviceObject,
823                   IN PIRP Irp)
824 {
825     PFDO_EXTENSION FdoExtension;
826 
827     DPRINT("HAL: PnP Driver Power!\n");
828     FdoExtension = DeviceObject->DeviceExtension;
829     if (FdoExtension->ExtensionType == FdoExtensionType)
830     {
831         PoStartNextPowerIrp(Irp);
832         IoSkipCurrentIrpStackLocation(Irp);
833         return PoCallDriver(FdoExtension->AttachedDeviceObject, Irp);
834     }
835     else
836     {
837         PoStartNextPowerIrp(Irp);
838         Irp->IoStatus.Status = STATUS_SUCCESS;
839         IoCompleteRequest(Irp, IO_NO_INCREMENT);
840         return STATUS_SUCCESS;
841     }
842 }
843 
844 NTSTATUS
845 NTAPI
846 HalpDriverEntry(IN PDRIVER_OBJECT DriverObject,
847                 IN PUNICODE_STRING RegistryPath)
848 {
849     NTSTATUS Status;
850     PDEVICE_OBJECT TargetDevice = NULL;
851 
852     DPRINT("HAL: PnP Driver ENTRY!\n");
853 
854     /* This is us */
855     HalpDriverObject = DriverObject;
856 
857     /* Set up add device */
858     DriverObject->DriverExtension->AddDevice = HalpAddDevice;
859 
860     /* Set up the callouts */
861     DriverObject->MajorFunction[IRP_MJ_PNP] = HalpDispatchPnp;
862     DriverObject->MajorFunction[IRP_MJ_POWER] = HalpDispatchPower;
863     DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = HalpDispatchWmi;
864 
865     /* Create the PDO */
866     Status = IoCreateDevice(DriverObject,
867                             0,
868                             NULL,
869                             FILE_DEVICE_CONTROLLER,
870                             0,
871                             FALSE,
872                             &TargetDevice);
873     if (!NT_SUCCESS(Status))
874         return Status;
875 
876     TargetDevice->Flags &= ~DO_DEVICE_INITIALIZING;
877 
878     /* Set up the device stack */
879     Status = HalpAddDevice(DriverObject, TargetDevice);
880     if (!NT_SUCCESS(Status))
881     {
882         IoDeleteDevice(TargetDevice);
883         return Status;
884     }
885 
886     /* Tell the PnP manager about us */
887     Status = IoReportDetectedDevice(DriverObject,
888                                     InterfaceTypeUndefined,
889                                     -1,
890                                     -1,
891                                     NULL,
892                                     NULL,
893                                     FALSE,
894                                     &TargetDevice);
895 
896     /* Return to kernel */
897     return Status;
898 }
899 
900 NTSTATUS
901 NTAPI
902 HaliInitPnpDriver(VOID)
903 {
904     NTSTATUS Status;
905     UNICODE_STRING DriverString;
906     PAGED_CODE();
907 
908     /* Create the driver */
909     RtlInitUnicodeString(&DriverString, L"\\Driver\\ACPI_HAL");
910     Status = IoCreateDriver(&DriverString, HalpDriverEntry);
911 
912     /* Return status */
913     return Status;
914 }
915 
916 /* EOF */
917