2 * PROJECT: ReactOS ACPI bus driver
3 * FILE: acpi/ospm/acpienum.c
4 * PURPOSE: ACPI namespace enumerator
5 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * 01-05-2001 CSH Created
15 #define HAS_CHILDREN(d) ((d)->children.next != &((d)->children))
16 #define HAS_SIBLINGS(d) (((d)->parent) && ((d)->node.next != &(d)->parent->children))
17 #define NODE_TO_DEVICE(n) (list_entry(n, struct acpi_device, node))
19 extern struct acpi_device
*acpi_root
;
23 struct acpi_device
*Device
,
24 PFDO_DEVICE_DATA FdoData
28 PPDO_DEVICE_DATA pdoData
;
36 //Don't enumerate the root device
37 if (Device
->handle
== ACPI_ROOT_OBJECT
)
38 return STATUS_SUCCESS
;
40 /* Check we didnt add this already */
41 for (entry
= FdoData
->ListOfPDOs
.Flink
;
42 entry
!= &FdoData
->ListOfPDOs
; entry
= entry
->Flink
)
44 struct acpi_device
*CurrentDevice
;
46 pdoData
= CONTAINING_RECORD (entry
, PDO_DEVICE_DATA
, Link
);
48 //dont duplicate devices
49 if (pdoData
->AcpiHandle
== Device
->handle
)
50 return STATUS_SUCCESS
;
52 //check everything but fixed feature devices
53 if (pdoData
->AcpiHandle
)
54 acpi_bus_get_device(pdoData
->AcpiHandle
, &CurrentDevice
);
58 //check if the HID matches
59 if (!strcmp(Device
->pnp
.hardware_id
, CurrentDevice
->pnp
.hardware_id
))
61 //check if UID exists for both and matches
62 if (Device
->flags
.unique_id
&& CurrentDevice
->flags
.unique_id
&&
63 !strcmp(Device
->pnp
.unique_id
, CurrentDevice
->pnp
.unique_id
))
65 /* We have a UID on both but they're the same so we have to ignore it */
66 DPRINT1("Detected duplicate device: %hs %hs\n", Device
->pnp
.hardware_id
, Device
->pnp
.unique_id
);
67 return STATUS_SUCCESS
;
69 else if (!Device
->flags
.unique_id
&& !CurrentDevice
->flags
.unique_id
)
71 /* No UID so we can only legally have 1 of these devices */
72 DPRINT1("Detected duplicate device: %hs\n", Device
->pnp
.hardware_id
);
73 return STATUS_SUCCESS
;
78 DPRINT("Exposing PDO\n"
79 "======AcpiHandle: %p\n"
80 "======HardwareId: %s\n",
82 Device
->pnp
.hardware_id
);
89 DPRINT("FdoData->NextLowerDriver = 0x%p\n", FdoData
->NextLowerDriver
);
91 status
= IoCreateDevice(FdoData
->Common
.Self
->DriverObject
,
92 sizeof(PDO_DEVICE_DATA
),
94 FILE_DEVICE_CONTROLLER
,
95 FILE_AUTOGENERATED_DEVICE_NAME
,
99 if (!NT_SUCCESS (status
)) {
103 pdoData
= (PPDO_DEVICE_DATA
) pdo
->DeviceExtension
;
104 pdoData
->AcpiHandle
= Device
->handle
;
107 // Copy the hardware IDs
110 index
+= swprintf(&temp
[index
],
112 Device
->pnp
.hardware_id
);
115 index
+= swprintf(&temp
[index
],
117 Device
->pnp
.hardware_id
);
119 temp
[++index
] = UNICODE_NULL
;
121 pdoData
->HardwareIDs
= ExAllocatePoolWithTag(NonPagedPool
, index
*sizeof(WCHAR
), 'IPCA');
124 if (!pdoData
->HardwareIDs
) {
126 return STATUS_INSUFFICIENT_RESOURCES
;
129 RtlCopyMemory (pdoData
->HardwareIDs
, temp
, index
*sizeof(WCHAR
));
130 Bus_InitializePdo (pdo
, FdoData
);
133 // Device Relation changes if a new pdo is created. So let
134 // the PNP system now about that. This forces it to send bunch of pnp
135 // queries and cause the function driver to be loaded.
138 //IoInvalidateDeviceRelations (FdoData->UnderlyingPDO, BusRelations);
144 /* looks alot like acpi_bus_walk doesnt it */
146 ACPIEnumerateDevices(PFDO_DEVICE_DATA DeviceExtension
)
149 struct acpi_device
*Device
= acpi_root
;
153 if (Device
->status
.present
&& Device
->status
.enabled
&&
154 Device
->flags
.hardware_id
)
156 Bus_PlugInDevice(Device
, DeviceExtension
);
160 if (HAS_CHILDREN(Device
)) {
161 Device
= NODE_TO_DEVICE(Device
->children
.next
);
164 if (HAS_SIBLINGS(Device
)) {
165 Device
= NODE_TO_DEVICE(Device
->node
.next
);
168 while ((Device
= Device
->parent
)) {
169 if (HAS_SIBLINGS(Device
)) {
170 Device
= NODE_TO_DEVICE(Device
->node
.next
);
175 DPRINT("acpi device count: %d\n", Count
);
176 return STATUS_SUCCESS
;