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