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