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