xref: /reactos/hal/halx86/legacy/halpnpdd.c (revision bbabe248)
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         case BusQueryHardwareIDs:
563 
564             /* This is our hardware ID */
565             Id = HalHardwareIdString;
566             break;
567 
568         case BusQueryInstanceID:
569 
570             /* And our instance ID */
571             Id = L"0";
572             break;
573 
574         default:
575 
576             /* We don't support anything else */
577             return STATUS_NOT_SUPPORTED;
578     }
579 
580     /* Calculate the length */
581     Length = (wcslen(Id) * sizeof(WCHAR)) + sizeof(UNICODE_NULL);
582 
583     /* Allocate the buffer */
584     Buffer = ExAllocatePoolWithTag(PagedPool,
585                                    Length + sizeof(UNICODE_NULL),
586                                    TAG_HAL);
587     if (Buffer)
588     {
589         /* Copy the string and null-terminate it */
590         RtlCopyMemory(Buffer, Id, Length);
591         Buffer[Length / sizeof(WCHAR)] = UNICODE_NULL;
592 
593         /* Return string */
594         *BusQueryId = Buffer;
595         Status = STATUS_SUCCESS;
596         DPRINT("Returning: %S\n", *BusQueryId);
597     }
598     else
599     {
600         /* Fail */
601         Status = STATUS_INSUFFICIENT_RESOURCES;
602     }
603 
604     /* Return status */
605     return Status;
606 }
607 
608 NTSTATUS
609 NTAPI
610 HalpDispatchPnp(IN PDEVICE_OBJECT DeviceObject,
611                 IN PIRP Irp)
612 {
613     PIO_STACK_LOCATION IoStackLocation;
614     //PPDO_EXTENSION PdoExtension;
615     PFDO_EXTENSION FdoExtension;
616     NTSTATUS Status;
617     UCHAR Minor;
618 
619     /* Get the device extension and stack location */
620     FdoExtension = DeviceObject->DeviceExtension;
621     IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
622     Minor = IoStackLocation->MinorFunction;
623 
624     /* FDO? */
625     if (FdoExtension->ExtensionType == FdoExtensionType)
626     {
627         /* Query the IRP type */
628         switch (Minor)
629         {
630             case IRP_MN_QUERY_DEVICE_RELATIONS:
631 
632                 /* Call the worker */
633                 DPRINT("Querying device relations for FDO\n");
634                 Status = HalpQueryDeviceRelations(DeviceObject,
635                                                   IoStackLocation->Parameters.QueryDeviceRelations.Type,
636                                                   (PVOID)&Irp->IoStatus.Information);
637                 break;
638 
639             case IRP_MN_QUERY_INTERFACE:
640 
641                 /* Call the worker */
642                 DPRINT("Querying interface for FDO\n");
643                 Status = HalpQueryInterface(DeviceObject,
644                                             IoStackLocation->Parameters.QueryInterface.InterfaceType,
645                                             IoStackLocation->Parameters.QueryInterface.Size,
646                                             IoStackLocation->Parameters.QueryInterface.InterfaceSpecificData,
647                                             IoStackLocation->Parameters.QueryInterface.Version,
648                                             IoStackLocation->Parameters.QueryInterface.Interface,
649                                             (PVOID)&Irp->IoStatus.Information);
650                 break;
651 
652             case IRP_MN_QUERY_ID:
653 
654                 /* Call the worker */
655                 DPRINT("Querying ID for FDO\n");
656                 Status = HalpQueryIdFdo(DeviceObject,
657                                         IoStackLocation->Parameters.QueryId.IdType,
658                                         (PVOID)&Irp->IoStatus.Information);
659                 break;
660 
661             case IRP_MN_QUERY_CAPABILITIES:
662 
663                 /* Call the worker */
664                 DPRINT("Querying the capabilities for the FDO\n");
665                 Status = HalpQueryCapabilities(DeviceObject,
666                                                IoStackLocation->Parameters.DeviceCapabilities.Capabilities);
667                 break;
668 
669             default:
670 
671                 DPRINT("Other IRP: %lx\n", Minor);
672                 Status = STATUS_NOT_SUPPORTED;
673                 break;
674         }
675 
676         /* What happpened? */
677         if ((NT_SUCCESS(Status)) || (Status == STATUS_NOT_SUPPORTED))
678         {
679             /* Set the IRP status, unless this isn't understood */
680             if (Status != STATUS_NOT_SUPPORTED)
681             {
682                 Irp->IoStatus.Status = Status;
683             }
684 
685             /* Pass it on */
686             IoSkipCurrentIrpStackLocation(Irp);
687             return IoCallDriver(FdoExtension->AttachedDeviceObject, Irp);
688         }
689 
690         /* Otherwise, we failed, so set the status and complete the request */
691         DPRINT1("IRP failed with status: %lx\n", Status);
692         Irp->IoStatus.Status = Status;
693         IoCompleteRequest(Irp, IO_NO_INCREMENT);
694         return Status;
695     }
696     else
697     {
698         /* This is a PDO instead */
699         ASSERT(FdoExtension->ExtensionType == PdoExtensionType);
700         //PdoExtension = (PPDO_EXTENSION)FdoExtension;
701 
702         /* Query the IRP type */
703         Status = STATUS_SUCCESS;
704         switch (Minor)
705         {
706             case IRP_MN_START_DEVICE:
707 
708                 /* We only care about a PCI PDO */
709                 DPRINT("Start device received\n");
710                 /* Complete the IRP normally */
711                 break;
712 
713             case IRP_MN_REMOVE_DEVICE:
714 
715                 /* Check if this is a PCI device */
716                 DPRINT("Remove device received\n");
717 
718                 /* We're done */
719                 Status = STATUS_SUCCESS;
720                 break;
721 
722             case IRP_MN_SURPRISE_REMOVAL:
723 
724                 /* Inherit whatever status we had */
725                 DPRINT("Surprise removal IRP\n");
726                 Status = Irp->IoStatus.Status;
727                 break;
728 
729             case IRP_MN_QUERY_DEVICE_RELATIONS:
730 
731                 /* Query the device relations */
732                 DPRINT("Querying PDO relations\n");
733                 Status = HalpQueryDeviceRelations(DeviceObject,
734                                                   IoStackLocation->Parameters.QueryDeviceRelations.Type,
735                                                   (PVOID)&Irp->IoStatus.Information);
736                 break;
737 
738             case IRP_MN_QUERY_INTERFACE:
739 
740                 /* Call the worker */
741                 DPRINT("Querying interface for PDO\n");
742                 Status = HalpQueryInterface(DeviceObject,
743                                             IoStackLocation->Parameters.QueryInterface.InterfaceType,
744                                             IoStackLocation->Parameters.QueryInterface.Size,
745                                             IoStackLocation->Parameters.QueryInterface.InterfaceSpecificData,
746                                             IoStackLocation->Parameters.QueryInterface.Version,
747                                             IoStackLocation->Parameters.QueryInterface.Interface,
748                                             (PVOID)&Irp->IoStatus.Information);
749                 break;
750 
751             case IRP_MN_QUERY_CAPABILITIES:
752 
753                 /* Call the worker */
754                 DPRINT("Querying the capabilities for the PDO\n");
755                 Status = HalpQueryCapabilities(DeviceObject,
756                                                IoStackLocation->Parameters.DeviceCapabilities.Capabilities);
757                 break;
758 
759             case IRP_MN_QUERY_RESOURCES:
760 
761                 /* Call the worker */
762                 DPRINT("Querying the resources for the PDO\n");
763                 Status = HalpQueryResources(DeviceObject, (PVOID)&Irp->IoStatus.Information);
764                 break;
765 
766             case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
767 
768                 /* Call the worker */
769                 DPRINT("Querying the resource requirements for the PDO\n");
770                 Status = HalpQueryResourceRequirements(DeviceObject,
771                                                        (PVOID)&Irp->IoStatus.Information);
772                 break;
773 
774             case IRP_MN_QUERY_ID:
775 
776                 /* Call the worker */
777                 DPRINT("Query the ID for the PDO\n");
778                 Status = HalpQueryIdPdo(DeviceObject,
779                                         IoStackLocation->Parameters.QueryId.IdType,
780                                         (PVOID)&Irp->IoStatus.Information);
781                 break;
782 
783             case IRP_MN_QUERY_DEVICE_TEXT:
784 
785                 /* Inherit whatever status we had */
786                 DPRINT("Query text for the PDO\n");
787                 Status = Irp->IoStatus.Status;
788                 break;
789 
790             case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
791 
792                 /* Inherit whatever status we had */
793                 DPRINT("Filter resource requirements for the PDO\n");
794                 Status = Irp->IoStatus.Status;
795                 break;
796 
797             case IRP_MN_QUERY_PNP_DEVICE_STATE:
798 
799                 /* Inherit whatever status we had */
800                 DPRINT("Query device state for the PDO\n");
801                 Status = Irp->IoStatus.Status;
802                 break;
803 
804             case IRP_MN_QUERY_BUS_INFORMATION:
805 
806                 /* Inherit whatever status we had */
807                 DPRINT("Query bus information for the PDO\n");
808                 Status = Irp->IoStatus.Status;
809                 break;
810 
811             default:
812 
813                 /* We don't handle anything else, so inherit the old state */
814                 DPRINT1("Illegal IRP: %lx\n", Minor);
815                 Status = Irp->IoStatus.Status;
816                 break;
817         }
818 
819         /* If it's not supported, inherit the old status */
820         if (Status == STATUS_NOT_SUPPORTED) Status = Irp->IoStatus.Status;
821 
822         /* Complete the IRP */
823         DPRINT("IRP completed with status: %lx\n", Status);
824         Irp->IoStatus.Status = Status;
825         IoCompleteRequest(Irp, IO_NO_INCREMENT);
826         return Status;
827     }
828 }
829 
830 NTSTATUS
831 NTAPI
832 HalpDispatchWmi(IN PDEVICE_OBJECT DeviceObject,
833                 IN PIRP Irp)
834 {
835     UNIMPLEMENTED_DBGBREAK("HAL: PnP Driver WMI!\n");
836     return STATUS_SUCCESS;
837 }
838 
839 NTSTATUS
840 NTAPI
841 HalpDispatchPower(IN PDEVICE_OBJECT DeviceObject,
842                   IN PIRP Irp)
843 {
844     PFDO_EXTENSION FdoExtension;
845 
846     DPRINT1("HAL: PnP Driver Power!\n");
847     FdoExtension = DeviceObject->DeviceExtension;
848     if (FdoExtension->ExtensionType == FdoExtensionType)
849     {
850         PoStartNextPowerIrp(Irp);
851         IoSkipCurrentIrpStackLocation(Irp);
852         return PoCallDriver(FdoExtension->AttachedDeviceObject, Irp);
853     }
854     else
855     {
856         PoStartNextPowerIrp(Irp);
857         Irp->IoStatus.Status = STATUS_SUCCESS;
858         IoCompleteRequest(Irp, IO_NO_INCREMENT);
859         return STATUS_SUCCESS;
860     }
861 }
862 
863 NTSTATUS
864 NTAPI
865 HalpDriverEntry(IN PDRIVER_OBJECT DriverObject,
866                 IN PUNICODE_STRING RegistryPath)
867 {
868     NTSTATUS Status;
869     PDEVICE_OBJECT TargetDevice = NULL;
870 
871     DPRINT("HAL: PnP Driver ENTRY!\n");
872 
873     /* This is us */
874     HalpDriverObject = DriverObject;
875 
876     /* Set up add device */
877     DriverObject->DriverExtension->AddDevice = HalpAddDevice;
878 
879     /* Set up the callouts */
880     DriverObject->MajorFunction[IRP_MJ_PNP] = HalpDispatchPnp;
881     DriverObject->MajorFunction[IRP_MJ_POWER] = HalpDispatchPower;
882     DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = HalpDispatchWmi;
883 
884     /* Create the PDO and tell the PnP manager about us*/
885     Status = IoReportDetectedDevice(DriverObject,
886                                     InterfaceTypeUndefined,
887                                     -1,
888                                     -1,
889                                     NULL,
890                                     NULL,
891                                     FALSE,
892                                     &TargetDevice);
893     if (!NT_SUCCESS(Status))
894         return Status;
895 
896     TargetDevice->Flags &= ~DO_DEVICE_INITIALIZING;
897 
898     /* Set up the device stack */
899     Status = HalpAddDevice(DriverObject, TargetDevice);
900     if (!NT_SUCCESS(Status))
901     {
902         IoDeleteDevice(TargetDevice);
903         return Status;
904     }
905 
906     /* Return to kernel */
907     return Status;
908 }
909 
910 NTSTATUS
911 NTAPI
912 HaliInitPnpDriver(VOID)
913 {
914     NTSTATUS Status;
915     UNICODE_STRING DriverString;
916     PAGED_CODE();
917 
918     /* Create the driver */
919     RtlInitUnicodeString(&DriverString, L"\\Driver\\PCI_HAL");
920     Status = IoCreateDriver(&DriverString, HalpDriverEntry);
921 
922     /* Return status */
923     return Status;
924 }
925 
926 /* EOF */
927