[ACPICA]
[reactos.git] / reactos / drivers / bus / acpi / acpienum.c
1 /*
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)
6 * UPDATE HISTORY:
7 * 01-05-2001 CSH Created
8 */
9
10 #include "precomp.h"
11
12 #define NDEBUG
13 #include <debug.h>
14
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))
18
19 extern struct acpi_device *acpi_root;
20
21 NTSTATUS
22 Bus_PlugInDevice (
23 struct acpi_device *Device,
24 PFDO_DEVICE_DATA FdoData
25 )
26 {
27 PDEVICE_OBJECT pdo;
28 PPDO_DEVICE_DATA pdoData;
29 NTSTATUS status;
30 ULONG index;
31 WCHAR temp[256];
32 PLIST_ENTRY entry;
33
34 PAGED_CODE ();
35
36 //Don't enumerate the root device
37 if (Device->handle == ACPI_ROOT_OBJECT)
38 return STATUS_SUCCESS;
39
40 /* Check we didnt add this already */
41 for (entry = FdoData->ListOfPDOs.Flink;
42 entry != &FdoData->ListOfPDOs; entry = entry->Flink)
43 {
44 struct acpi_device *CurrentDevice;
45
46 pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);
47
48 //dont duplicate devices
49 if (pdoData->AcpiHandle == Device->handle)
50 return STATUS_SUCCESS;
51
52 //check everything but fixed feature devices
53 if (pdoData->AcpiHandle)
54 acpi_bus_get_device(pdoData->AcpiHandle, &CurrentDevice);
55 else
56 continue;
57
58 //check if the HID matches
59 if (!strcmp(Device->pnp.hardware_id, CurrentDevice->pnp.hardware_id))
60 {
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))
64 {
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;
68 }
69 else if (!Device->flags.unique_id && !CurrentDevice->flags.unique_id)
70 {
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;
74 }
75 }
76 }
77
78 DPRINT("Exposing PDO\n"
79 "======AcpiHandle: %p\n"
80 "======HardwareId: %s\n",
81 Device->handle,
82 Device->pnp.hardware_id);
83
84
85 //
86 // Create the PDO
87 //
88
89 DPRINT("FdoData->NextLowerDriver = 0x%p\n", FdoData->NextLowerDriver);
90
91 status = IoCreateDevice(FdoData->Common.Self->DriverObject,
92 sizeof(PDO_DEVICE_DATA),
93 NULL,
94 FILE_DEVICE_CONTROLLER,
95 FILE_AUTOGENERATED_DEVICE_NAME,
96 FALSE,
97 &pdo);
98
99 if (!NT_SUCCESS (status)) {
100 return status;
101 }
102
103 pdoData = (PPDO_DEVICE_DATA) pdo->DeviceExtension;
104 pdoData->AcpiHandle = Device->handle;
105
106 //
107 // Copy the hardware IDs
108 //
109 index = 0;
110 index += swprintf(&temp[index],
111 L"ACPI\\%hs",
112 Device->pnp.hardware_id);
113 index++;
114
115 index += swprintf(&temp[index],
116 L"*%hs",
117 Device->pnp.hardware_id);
118 index++;
119 temp[++index] = UNICODE_NULL;
120
121 pdoData->HardwareIDs = ExAllocatePoolWithTag(NonPagedPool, index*sizeof(WCHAR), 'IPCA');
122
123
124 if (!pdoData->HardwareIDs) {
125 IoDeleteDevice(pdo);
126 return STATUS_INSUFFICIENT_RESOURCES;
127 }
128
129 RtlCopyMemory (pdoData->HardwareIDs, temp, index*sizeof(WCHAR));
130 Bus_InitializePdo (pdo, FdoData);
131
132 //
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.
136 //
137
138 //IoInvalidateDeviceRelations (FdoData->UnderlyingPDO, BusRelations);
139
140 return status;
141 }
142
143
144 /* looks alot like acpi_bus_walk doesnt it */
145 NTSTATUS
146 ACPIEnumerateDevices(PFDO_DEVICE_DATA DeviceExtension)
147 {
148 ULONG Count = 0;
149 struct acpi_device *Device = acpi_root;
150
151 while(Device)
152 {
153 if (Device->status.present && Device->status.enabled &&
154 Device->flags.hardware_id)
155 {
156 Bus_PlugInDevice(Device, DeviceExtension);
157 Count++;
158 }
159
160 if (HAS_CHILDREN(Device)) {
161 Device = NODE_TO_DEVICE(Device->children.next);
162 continue;
163 }
164 if (HAS_SIBLINGS(Device)) {
165 Device = NODE_TO_DEVICE(Device->node.next);
166 continue;
167 }
168 while ((Device = Device->parent)) {
169 if (HAS_SIBLINGS(Device)) {
170 Device = NODE_TO_DEVICE(Device->node.next);
171 break;
172 }
173 }
174 }
175 DPRINT("acpi device count: %d\n", Count);
176 return STATUS_SUCCESS;
177 }
178
179 /* EOF */