Merge from amd64 branch:
[reactos.git] / reactos / drivers / bus / acpi / acpienum.c
1 /* $Id: acpienum.c 21698 2006-04-22 05:55:17Z tretiakov $
2 *
3 * PROJECT: ReactOS ACPI bus driver
4 * FILE: acpi/ospm/acpienum.c
5 * PURPOSE: ACPI namespace enumerator
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * UPDATE HISTORY:
8 * 01-05-2001 CSH Created
9 */
10 #include <acpi.h>
11 #include <acpisys.h>
12 #include <acpi_bus.h>
13 #include <acpi_drivers.h>
14 #include <list.h>
15
16 #define NDEBUG
17 #include <debug.h>
18
19 #define HAS_CHILDREN(d) ((d)->children.next != &((d)->children))
20 #define HAS_SIBLINGS(d) (((d)->parent) && ((d)->node.next != &(d)->parent->children))
21 #define NODE_TO_DEVICE(n) (list_entry(n, struct acpi_device, node))
22
23 extern struct acpi_device *acpi_root;
24
25 NTSTATUS
26 Bus_PlugInDevice (
27 struct acpi_device *Device,
28 PFDO_DEVICE_DATA FdoData
29 )
30 {
31 PDEVICE_OBJECT pdo;
32 PPDO_DEVICE_DATA pdoData;
33 NTSTATUS status;
34 ULONG index;
35 WCHAR temp[256];
36 PLIST_ENTRY entry;
37
38 PAGED_CODE ();
39
40 //Don't enumerate the root device
41 if (Device->handle == ACPI_ROOT_OBJECT)
42 return STATUS_SUCCESS;
43
44 /* Check we didnt add this already */
45 for (entry = FdoData->ListOfPDOs.Flink;
46 entry != &FdoData->ListOfPDOs; entry = entry->Flink)
47 {
48 pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);
49 //dont duplicate devices
50 if(pdoData->AcpiHandle == Device->handle)
51 return STATUS_SUCCESS;
52 }
53
54 DPRINT("Exposing PDO\n"
55 "======AcpiHandle: %p\n"
56 "======HardwareId: %s\n",
57 Device->handle,
58 Device->pnp.hardware_id);
59
60
61 //
62 // Create the PDO
63 //
64
65 DPRINT("FdoData->NextLowerDriver = 0x%p\n", FdoData->NextLowerDriver);
66
67 status = IoCreateDevice(FdoData->Common.Self->DriverObject,
68 sizeof(PDO_DEVICE_DATA),
69 NULL,
70 FILE_DEVICE_CONTROLLER,
71 FILE_AUTOGENERATED_DEVICE_NAME,
72 FALSE,
73 &pdo);
74
75 if (!NT_SUCCESS (status)) {
76 return status;
77 }
78
79 pdoData = (PPDO_DEVICE_DATA) pdo->DeviceExtension;
80 pdoData->AcpiHandle = Device->handle;
81
82 //
83 // Copy the hardware IDs
84 //
85 index = 0;
86 index += swprintf(&temp[index],
87 L"ACPI\\%hs",
88 Device->pnp.hardware_id);
89 index++;
90
91 index += swprintf(&temp[index],
92 L"*%hs",
93 Device->pnp.hardware_id);
94 index++;
95 temp[index] = UNICODE_NULL;
96
97 pdoData->HardwareIDs = ExAllocatePool(NonPagedPool, index*sizeof(WCHAR));
98
99
100 if (!pdoData->HardwareIDs) {
101 IoDeleteDevice(pdo);
102 return STATUS_INSUFFICIENT_RESOURCES;
103 }
104
105 RtlCopyMemory (pdoData->HardwareIDs, temp, index*sizeof(WCHAR));
106 Bus_InitializePdo (pdo, FdoData);
107
108 //
109 // Device Relation changes if a new pdo is created. So let
110 // the PNP system now about that. This forces it to send bunch of pnp
111 // queries and cause the function driver to be loaded.
112 //
113
114 //IoInvalidateDeviceRelations (FdoData->UnderlyingPDO, BusRelations);
115
116 return status;
117 }
118
119
120 /* looks alot like acpi_bus_walk doesnt it */
121 NTSTATUS
122 ACPIEnumerateDevices(PFDO_DEVICE_DATA DeviceExtension)
123 {
124 ULONG Count = 0;
125 struct acpi_device *Device = acpi_root;
126
127 while(Device)
128 {
129 if (Device->status.present && Device->status.enabled &&
130 Device->flags.hardware_id)
131 {
132 Bus_PlugInDevice(Device, DeviceExtension);
133 Count++;
134 }
135
136 if (HAS_CHILDREN(Device)) {
137 Device = NODE_TO_DEVICE(Device->children.next);
138 continue;
139 }
140 if (HAS_SIBLINGS(Device)) {
141 Device = NODE_TO_DEVICE(Device->node.next);
142 continue;
143 }
144 while ((Device = Device->parent)) {
145 if (HAS_SIBLINGS(Device)) {
146 Device = NODE_TO_DEVICE(Device->node.next);
147 break;
148 }
149 }
150 }
151 DPRINT("acpi device count: %d\n", Count);
152 return STATUS_SUCCESS;
153 }
154
155 /* EOF */