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
9 /* INCLUDES *******************************************************************/
15 typedef enum _EXTENSION_TYPE
17 PdoExtensionType
= 0xC0,
21 typedef enum _PDO_TYPE
27 typedef struct _FDO_EXTENSION
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
;
36 typedef struct _PDO_EXTENSION
38 EXTENSION_TYPE ExtensionType
;
39 struct _PDO_EXTENSION
* Next
;
40 PDEVICE_OBJECT PhysicalDeviceObject
;
41 PFDO_EXTENSION ParentFdoExtension
;
43 PDESCRIPTION_HEADER WdTable
;
44 LONG InterfaceReferenceCount
;
45 } PDO_EXTENSION
, *PPDO_EXTENSION
;
47 /* GLOBALS ********************************************************************/
49 PDRIVER_OBJECT HalpDriverObject
;
51 /* PRIVATE FUNCTIONS **********************************************************/
55 HalpAddDevice(IN PDRIVER_OBJECT DriverObject
,
56 IN PDEVICE_OBJECT TargetDevice
)
59 PFDO_EXTENSION FdoExtension
;
60 PPDO_EXTENSION PdoExtension
;
61 PDEVICE_OBJECT DeviceObject
, PdoDeviceObject
, AttachedDevice
;
62 PDESCRIPTION_HEADER Wdrt
;
63 DbgPrint("HAL: PnP Driver ADD!\n");
66 Status
= IoCreateDevice(DriverObject
,
67 sizeof(FDO_EXTENSION
),
69 FILE_DEVICE_BUS_EXTENDER
,
73 if (!NT_SUCCESS(Status
))
75 /* Should not happen */
80 /* Setup the FDO extension */
81 FdoExtension
= DeviceObject
->DeviceExtension
;
82 FdoExtension
->ExtensionType
= FdoExtensionType
;
83 FdoExtension
->PhysicalDeviceObject
= TargetDevice
;
84 FdoExtension
->FunctionalDeviceObject
= DeviceObject
;
86 /* FDO is done initializing */
87 DeviceObject
->Flags
&= DO_DEVICE_INITIALIZING
;
89 /* Attach to the physical device object (the bus) */
90 AttachedDevice
= IoAttachDeviceToDeviceStack(DeviceObject
, TargetDevice
);
93 /* Failed, undo everything */
94 IoDeleteDevice(DeviceObject
);
95 return STATUS_NO_SUCH_DEVICE
;
98 /* Save the attachment */
99 FdoExtension
->AttachedDeviceObject
= AttachedDevice
;
102 Status
= IoCreateDevice(DriverObject
,
103 sizeof(PDO_EXTENSION
),
105 FILE_DEVICE_BUS_EXTENDER
,
106 FILE_AUTOGENERATED_DEVICE_NAME
,
109 if (!NT_SUCCESS(Status
))
112 DbgPrint("HAL: Could not create ACPI device object status=0x%08x\n", Status
);
116 /* Setup the PDO device extension */
117 PdoExtension
= PdoDeviceObject
->DeviceExtension
;
118 PdoExtension
->Next
= NULL
;
119 PdoExtension
->ExtensionType
= PdoExtensionType
;
120 PdoExtension
->PhysicalDeviceObject
= PdoDeviceObject
;
121 PdoExtension
->ParentFdoExtension
= FdoExtension
;
122 PdoExtension
->PdoType
= AcpiPdo
;
124 /* Find the ACPI watchdog table */
125 Wdrt
= HalAcpiGetTable(0, 'TRDW');
128 /* None exists, there is nothing to do more */
129 PdoDeviceObject
->Flags
&= DO_DEVICE_INITIALIZING
;
130 FdoExtension
->ChildPdoList
= PdoExtension
;
135 DPRINT1("You have an ACPI Watchdog. That's great! You should be proud ;-)\n");
136 PdoDeviceObject
->Flags
&= DO_DEVICE_INITIALIZING
;
137 FdoExtension
->ChildPdoList
= PdoExtension
;
141 DPRINT1("Device added %lx\n", Status
);
147 HalpQueryInterface(IN PDEVICE_OBJECT DeviceObject
,
148 IN CONST GUID
* InterfaceType
,
150 IN PVOID InterfaceSpecificData
,
151 IN ULONG InterfaceBufferSize
,
152 IN PINTERFACE Interface
,
157 return STATUS_NO_SUCH_DEVICE
;
162 HalpQueryDeviceRelations(IN PDEVICE_OBJECT DeviceObject
,
163 IN DEVICE_RELATION_TYPE RelationType
,
164 OUT PDEVICE_RELATIONS
* DeviceRelations
)
166 EXTENSION_TYPE ExtensionType
;
167 PPDO_EXTENSION PdoExtension
;
168 PFDO_EXTENSION FdoExtension
;
169 PDEVICE_RELATIONS PdoRelations
, FdoRelations
;
170 PDEVICE_OBJECT
* ObjectEntry
;
171 ULONG i
= 0, PdoCount
= 0;
173 /* Get FDO device extension and PDO count */
174 FdoExtension
= DeviceObject
->DeviceExtension
;
175 ExtensionType
= FdoExtension
->ExtensionType
;
177 /* What do they want? */
178 if (RelationType
== BusRelations
)
180 /* This better be an FDO */
181 if (ExtensionType
== FdoExtensionType
)
183 /* Count how many PDOs we have */
184 PdoExtension
= FdoExtension
->ChildPdoList
;
188 PdoExtension
= PdoExtension
->Next
;
192 /* Allocate our structure */
193 FdoRelations
= ExAllocatePoolWithTag(PagedPool
,
194 FIELD_OFFSET(DEVICE_RELATIONS
,
198 if (!FdoRelations
) return STATUS_INSUFFICIENT_RESOURCES
;
201 FdoRelations
->Count
= PdoCount
;
203 /* Query existing relations */
204 ObjectEntry
= FdoRelations
->Objects
;
205 if (*DeviceRelations
)
207 /* Check if there were any */
208 if ((*DeviceRelations
)->Count
)
213 /* Copy into our structure */
214 *ObjectEntry
++ = (*DeviceRelations
)->Objects
[i
];
216 while (++i
< (*DeviceRelations
)->Count
);
219 /* Free existing structure */
220 ExFreePoolWithTag(*DeviceRelations
, 0);
223 /* Now check if we have a PDO list */
224 PdoExtension
= FdoExtension
->ChildPdoList
;
230 /* Save our own PDO and reference it */
231 *ObjectEntry
++ = PdoExtension
->PhysicalDeviceObject
;
232 ObfReferenceObject(PdoExtension
->PhysicalDeviceObject
);
234 /* Go to our next PDO */
235 PdoExtension
= PdoExtension
->Next
;
237 while (PdoExtension
);
240 /* Return the new structure */
241 *DeviceRelations
= FdoRelations
;
242 return STATUS_SUCCESS
;
247 /* The only other thing we support is a target relation for the PDO */
248 if ((RelationType
== TargetDeviceRelation
) &&
249 (ExtensionType
== PdoExtensionType
))
252 PdoRelations
= ExAllocatePoolWithTag(PagedPool
,
253 sizeof(DEVICE_RELATIONS
),
255 if (!PdoRelations
) return STATUS_INSUFFICIENT_RESOURCES
;
257 /* Fill it out and reference us */
258 PdoRelations
->Count
= 1;
259 PdoRelations
->Objects
[0] = DeviceObject
;
260 ObfReferenceObject(DeviceObject
);
263 *DeviceRelations
= PdoRelations
;
264 return STATUS_SUCCESS
;
268 /* We don't support anything else */
269 return STATUS_NOT_SUPPORTED
;
274 HalpQueryCapabilities(IN PDEVICE_OBJECT DeviceObject
,
275 OUT PDEVICE_CAPABILITIES Capabilities
)
277 PPDO_EXTENSION PdoExtension
;
281 /* Get the extension and check for valid version */
282 PdoExtension
= DeviceObject
->DeviceExtension
;
283 ASSERT(Capabilities
->Version
== 1);
284 if (Capabilities
->Version
== 1)
286 /* Can't lock or eject us */
287 Capabilities
->LockSupported
= FALSE
;
288 Capabilities
->EjectSupported
= FALSE
;
290 /* Can't remove or dock us */
291 Capabilities
->Removable
= FALSE
;
292 Capabilities
->DockDevice
= FALSE
;
294 /* Can't access us raw */
295 Capabilities
->RawDeviceOK
= FALSE
;
297 /* We have a unique ID, and don't bother the user */
298 Capabilities
->UniqueID
= TRUE
;
299 Capabilities
->SilentInstall
= TRUE
;
301 /* Fill out the adress */
302 Capabilities
->Address
= InterfaceTypeUndefined
;
303 Capabilities
->UINumber
= InterfaceTypeUndefined
;
305 /* Fill out latencies */
306 Capabilities
->D1Latency
= 0;
307 Capabilities
->D2Latency
= 0;
308 Capabilities
->D3Latency
= 0;
310 /* Fill out supported device states */
311 Capabilities
->DeviceState
[PowerSystemWorking
] = PowerDeviceD0
;
312 Capabilities
->DeviceState
[PowerSystemHibernate
] = PowerDeviceD3
;
313 Capabilities
->DeviceState
[PowerSystemShutdown
] = PowerDeviceD3
;
314 Capabilities
->DeviceState
[PowerSystemSleeping3
] = PowerDeviceD3
;
317 Status
= STATUS_SUCCESS
;
322 Status
= STATUS_NOT_SUPPORTED
;
331 HalpQueryResources(IN PDEVICE_OBJECT DeviceObject
,
332 OUT PCM_RESOURCE_LIST
*Resources
)
336 return STATUS_NO_SUCH_DEVICE
;
341 HalpQueryResourceRequirements(IN PDEVICE_OBJECT DeviceObject
,
342 OUT PIO_RESOURCE_REQUIREMENTS_LIST
*Requirements
)
344 PPDO_EXTENSION DeviceExtension
= DeviceObject
->DeviceExtension
;
348 /* Only the ACPI PDO has requirements */
349 if (DeviceExtension
->PdoType
== AcpiPdo
)
351 /* Query ACPI requirements */
352 Status
= HalpQueryAcpiResourceRequirements(Requirements
);
354 else if (DeviceExtension
->PdoType
== WdPdo
)
356 /* Watchdog doesn't */
357 return STATUS_NOT_SUPPORTED
;
361 /* This shouldn't happen */
362 return STATUS_UNSUCCESSFUL
;
365 /* Return the status */
371 HalpQueryIdPdo(IN PDEVICE_OBJECT DeviceObject
,
372 IN BUS_QUERY_ID_TYPE IdType
,
373 OUT PUSHORT
*BusQueryId
)
375 PPDO_EXTENSION PdoExtension
;
382 /* Get the PDO type */
383 PdoExtension
= DeviceObject
->DeviceExtension
;
384 PdoType
= PdoExtension
->PdoType
;
386 /* What kind of ID is being requested? */
387 DPRINT("ID: %d\n", IdType
);
390 case BusQueryDeviceID
:
391 case BusQueryHardwareIDs
:
393 /* What kind of PDO is this? */
394 if (PdoType
== AcpiPdo
)
397 Id
= L
"ACPI_HAL\\PNP0C08";
399 else if (PdoType
== WdPdo
)
402 Id
= L
"ACPI_HAL\\PNP0C18";
407 return STATUS_NOT_SUPPORTED
;
414 case BusQueryInstanceID
:
416 /* And our instance ID */
418 Length
= sizeof(L
"0") + sizeof(UNICODE_NULL
);
421 case BusQueryCompatibleIDs
:
424 /* We don't support anything else */
425 return STATUS_NOT_SUPPORTED
;
428 /* Allocate the buffer */
429 Buffer
= ExAllocatePoolWithTag(PagedPool
,
430 Length
+ sizeof(UNICODE_NULL
),
434 /* Copy the string and null-terminate it */
435 RtlCopyMemory(Buffer
, Id
, Length
);
436 Buffer
[Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
439 *BusQueryId
= Buffer
;
440 Status
= STATUS_SUCCESS
;
441 DPRINT("Returning: %S\n", *BusQueryId
);
446 Status
= STATUS_INSUFFICIENT_RESOURCES
;
455 HalpQueryIdFdo(IN PDEVICE_OBJECT DeviceObject
,
456 IN BUS_QUERY_ID_TYPE IdType
,
457 OUT PUSHORT
*BusQueryId
)
464 /* What kind of ID is being requested? */
465 DPRINT("ID: %d\n", IdType
);
468 case BusQueryDeviceID
:
469 case BusQueryHardwareIDs
:
471 /* This is our hardware ID */
472 Id
= HalHardwareIdString
;
473 Length
= wcslen(HalHardwareIdString
) + sizeof(UNICODE_NULL
);
476 case BusQueryInstanceID
:
478 /* And our instance ID */
480 Length
= sizeof(L
"0") + sizeof(UNICODE_NULL
);
485 /* We don't support anything else */
486 return STATUS_NOT_SUPPORTED
;
489 /* Allocate the buffer */
490 Buffer
= ExAllocatePoolWithTag(PagedPool
,
491 Length
+ sizeof(UNICODE_NULL
),
495 /* Copy the string and null-terminate it */
496 RtlCopyMemory(Buffer
, Id
, Length
);
497 Buffer
[Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
500 *BusQueryId
= Buffer
;
501 Status
= STATUS_SUCCESS
;
502 DPRINT("Returning: %S\n", *BusQueryId
);
507 Status
= STATUS_INSUFFICIENT_RESOURCES
;
516 HalpPassIrpFromFdoToPdo(IN PDEVICE_OBJECT DeviceObject
,
519 PFDO_EXTENSION FdoExtension
;
521 /* Get the extension */
522 FdoExtension
= DeviceObject
->DeviceExtension
;
524 /* Pass it to the attached device (our PDO) */
525 IoSkipCurrentIrpStackLocation(Irp
);
526 return IoCallDriver(FdoExtension
->AttachedDeviceObject
, Irp
);
531 HalpDispatchPnp(IN PDEVICE_OBJECT DeviceObject
,
534 PIO_STACK_LOCATION IoStackLocation
;
535 PPDO_EXTENSION PdoExtension
;
536 PFDO_EXTENSION FdoExtension
;
540 /* Get the device extension and stack location */
541 FdoExtension
= DeviceObject
->DeviceExtension
;
542 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
543 Minor
= IoStackLocation
->MinorFunction
;
546 if (FdoExtension
->ExtensionType
== FdoExtensionType
)
548 /* Query the IRP type */
551 case IRP_MN_QUERY_DEVICE_RELATIONS
:
553 /* Call the worker */
554 DPRINT("Querying device relations for FDO\n");
555 Status
= HalpQueryDeviceRelations(DeviceObject
,
556 IoStackLocation
->Parameters
.QueryDeviceRelations
.Type
,
557 (PVOID
)&Irp
->IoStatus
.Information
);
560 case IRP_MN_QUERY_INTERFACE
:
562 /* Call the worker */
563 DPRINT("Querying interface for FDO\n");
564 Status
= HalpQueryInterface(DeviceObject
,
565 IoStackLocation
->Parameters
.QueryInterface
.InterfaceType
,
566 IoStackLocation
->Parameters
.QueryInterface
.Size
,
567 IoStackLocation
->Parameters
.QueryInterface
.InterfaceSpecificData
,
568 IoStackLocation
->Parameters
.QueryInterface
.Version
,
569 IoStackLocation
->Parameters
.QueryInterface
.Interface
,
570 (PVOID
)&Irp
->IoStatus
.Information
);
574 case IRP_MN_QUERY_ID
:
576 /* Call the worker */
577 DPRINT("Querying ID for FDO\n");
578 Status
= HalpQueryIdFdo(DeviceObject
,
579 IoStackLocation
->Parameters
.QueryId
.IdType
,
580 (PVOID
)&Irp
->IoStatus
.Information
);
585 /* Pass it to the PDO */
586 DPRINT("Other IRP: %lx\n", Minor
);
587 return HalpPassIrpFromFdoToPdo(DeviceObject
, Irp
);
590 /* What happpened? */
591 if ((NT_SUCCESS(Status
)) || (Status
== STATUS_NOT_SUPPORTED
))
593 /* Set the IRP status, unless this isn't understood */
594 if (Status
!= STATUS_NOT_SUPPORTED
) Irp
->IoStatus
.Status
= Status
;
597 DPRINT("Passing IRP to PDO\n");
598 return HalpPassIrpFromFdoToPdo(DeviceObject
, Irp
);
601 /* Otherwise, we failed, so set the status and complete the request */
602 DPRINT1("IRP failed with status: %lx\n", Status
);
603 Irp
->IoStatus
.Status
= Status
;
604 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
609 /* This is a PDO instead */
610 ASSERT(FdoExtension
->ExtensionType
== PdoExtensionType
);
611 PdoExtension
= (PPDO_EXTENSION
)FdoExtension
;
613 /* Query the IRP type */
614 Status
= STATUS_SUCCESS
;
617 case IRP_MN_START_DEVICE
:
619 /* We only care about a PCI PDO */
620 DPRINT1("Start device received\n");
621 /* Complete the IRP normally */
624 case IRP_MN_REMOVE_DEVICE
:
626 /* Check if this is a PCI device */
627 DPRINT1("Remove device received\n");
630 Status
= STATUS_SUCCESS
;
633 case IRP_MN_SURPRISE_REMOVAL
:
635 /* Inherit whatever status we had */
636 DPRINT1("Surprise removal IRP\n");
637 Status
= Irp
->IoStatus
.Status
;
640 case IRP_MN_QUERY_DEVICE_RELATIONS
:
642 /* Query the device relations */
643 DPRINT("Querying PDO relations\n");
644 Status
= HalpQueryDeviceRelations(DeviceObject
,
645 IoStackLocation
->Parameters
.QueryDeviceRelations
.Type
,
646 (PVOID
)&Irp
->IoStatus
.Information
);
649 case IRP_MN_QUERY_INTERFACE
:
651 /* Call the worker */
652 DPRINT("Querying interface for PDO\n");
653 Status
= HalpQueryInterface(DeviceObject
,
654 IoStackLocation
->Parameters
.QueryInterface
.InterfaceType
,
655 IoStackLocation
->Parameters
.QueryInterface
.Size
,
656 IoStackLocation
->Parameters
.QueryInterface
.InterfaceSpecificData
,
657 IoStackLocation
->Parameters
.QueryInterface
.Version
,
658 IoStackLocation
->Parameters
.QueryInterface
.Interface
,
659 (PVOID
)&Irp
->IoStatus
.Information
);
662 case IRP_MN_QUERY_CAPABILITIES
:
664 /* Call the worker */
665 DPRINT("Querying the capabilities for the PDO\n");
666 Status
= HalpQueryCapabilities(DeviceObject
,
667 IoStackLocation
->Parameters
.DeviceCapabilities
.Capabilities
);
670 case IRP_MN_QUERY_RESOURCES
:
672 /* Call the worker */
673 DPRINT("Querying the resources for the PDO\n");
674 Status
= HalpQueryResources(DeviceObject
, (PVOID
)&Irp
->IoStatus
.Information
);
677 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
:
679 /* Call the worker */
680 DPRINT("Querying the resource requirements for the PDO\n");
681 Status
= HalpQueryResourceRequirements(DeviceObject
,
682 (PVOID
)&Irp
->IoStatus
.Information
);
685 case IRP_MN_QUERY_ID
:
687 /* Call the worker */
688 DPRINT("Query the ID for the PDO\n");
689 Status
= HalpQueryIdPdo(DeviceObject
,
690 IoStackLocation
->Parameters
.QueryId
.IdType
,
691 (PVOID
)&Irp
->IoStatus
.Information
);
696 /* We don't handle anything else, so inherit the old state */
697 DPRINT("Illegal IRP: %lx\n", Minor
);
698 Status
= Irp
->IoStatus
.Status
;
702 /* If it's not supported, inherit the old status */
703 if (Status
== STATUS_NOT_SUPPORTED
) Status
= Irp
->IoStatus
.Status
;
705 /* Complete the IRP */
706 DPRINT("IRP completed with status: %lx\n", Status
);
707 Irp
->IoStatus
.Status
= Status
;
708 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
715 HalpDispatchWmi(IN PDEVICE_OBJECT DeviceObject
,
718 DbgPrint("HAL: PnP Driver WMI!\n");
720 return STATUS_SUCCESS
;
725 HalpDispatchPower(IN PDEVICE_OBJECT DeviceObject
,
728 DbgPrint("HAL: PnP Driver Power!\n");
730 return STATUS_SUCCESS
;
735 HalpDriverEntry(IN PDRIVER_OBJECT DriverObject
,
736 IN PUNICODE_STRING RegistryPath
)
739 PDEVICE_OBJECT TargetDevice
= NULL
;
740 DPRINT("HAL: PnP Driver ENTRY!\n");
743 HalpDriverObject
= DriverObject
;
745 /* Set up add device */
746 DriverObject
->DriverExtension
->AddDevice
= HalpAddDevice
;
748 /* Set up the callouts */
749 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = HalpDispatchPnp
;
750 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = HalpDispatchPower
;
751 DriverObject
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = HalpDispatchWmi
;
753 /* Tell the PnP about us */
754 Status
= IoReportDetectedDevice(DriverObject
,
755 InterfaceTypeUndefined
,
764 if (NT_SUCCESS(Status
)) Status
= HalpAddDevice(DriverObject
, TargetDevice
);
766 /* Force re-enumeration??? */
767 IoInvalidateDeviceRelations(TargetDevice
, 0);
769 /* Return to kernel */
775 HaliInitPnpDriver(VOID
)
778 UNICODE_STRING DriverString
;
781 /* Create the driver */
782 RtlInitUnicodeString(&DriverString
, L
"\\Driver\\ACPI_HAL");
783 Status
= IoCreateDriver(&DriverString
, HalpDriverEntry
);