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