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