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