Sync with trunk head
[reactos.git] / 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 /* Check we didnt add this already */
41 for (entry = FdoData->ListOfPDOs.Flink;
42 entry != &FdoData->ListOfPDOs; entry = entry->Flink)
43 {
44 pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);
45 //dont duplicate devices
46 if(pdoData->AcpiHandle == Device->handle)
47 return STATUS_SUCCESS;
48 }
49
50 DPRINT("Exposing PDO\n"
51 "======AcpiHandle: %p\n"
52 "======HardwareId: %s\n",
53 Device->handle,
54 Device->pnp.hardware_id);
55
56
57 //
58 // Create the PDO
59 //
60
61 DPRINT("FdoData->NextLowerDriver = 0x%p\n", FdoData->NextLowerDriver);
62
63 status = IoCreateDevice(FdoData->Common.Self->DriverObject,
64 sizeof(PDO_DEVICE_DATA),
65 NULL,
66 FILE_DEVICE_CONTROLLER,
67 FILE_AUTOGENERATED_DEVICE_NAME,
68 FALSE,
69 &pdo);
70
71 if (!NT_SUCCESS (status)) {
72 return status;
73 }
74
75 pdoData = (PPDO_DEVICE_DATA) pdo->DeviceExtension;
76 pdoData->AcpiHandle = Device->handle;
77
78 //
79 // Copy the hardware IDs
80 //
81 index = 0;
82 index += swprintf(&temp[index],
83 L"ACPI\\%hs",
84 Device->pnp.hardware_id);
85 index++;
86
87 index += swprintf(&temp[index],
88 L"*%hs",
89 Device->pnp.hardware_id);
90 index++;
91 temp[index] = UNICODE_NULL;
92
93 pdoData->HardwareIDs = ExAllocatePool(NonPagedPool, index*sizeof(WCHAR));
94
95
96 if (!pdoData->HardwareIDs) {
97 IoDeleteDevice(pdo);
98 return STATUS_INSUFFICIENT_RESOURCES;
99 }
100
101 RtlCopyMemory (pdoData->HardwareIDs, temp, index*sizeof(WCHAR));
102 Bus_InitializePdo (pdo, FdoData);
103
104 //
105 // Device Relation changes if a new pdo is created. So let
106 // the PNP system now about that. This forces it to send bunch of pnp
107 // queries and cause the function driver to be loaded.
108 //
109
110 //IoInvalidateDeviceRelations (FdoData->UnderlyingPDO, BusRelations);
111
112 return status;
113 }
114
115
116 /* looks alot like acpi_bus_walk doesnt it */
117 NTSTATUS
118 ACPIEnumerateDevices(PFDO_DEVICE_DATA DeviceExtension)
119 {
120 ULONG Count = 0;
121 struct acpi_device *Device = acpi_root;
122
123 while(Device)
124 {
125 if (Device->status.present && Device->status.enabled &&
126 Device->flags.hardware_id)
127 {
128 Bus_PlugInDevice(Device, DeviceExtension);
129 Count++;
130 }
131
132 if (HAS_CHILDREN(Device)) {
133 Device = NODE_TO_DEVICE(Device->children.next);
134 continue;
135 }
136 if (HAS_SIBLINGS(Device)) {
137 Device = NODE_TO_DEVICE(Device->node.next);
138 continue;
139 }
140 while ((Device = Device->parent)) {
141 if (HAS_SIBLINGS(Device)) {
142 Device = NODE_TO_DEVICE(Device->node.next);
143 break;
144 }
145 }
146 }
147 DPRINT("acpi device count: %d\n", Count);
148 return STATUS_SUCCESS;
149 }
150
151 /* EOF */