1 /*
2 * Copyright 2009, Clemens Zeidler. All rights reserved.
3 * Copyright 2006, Jérôme Duval. All rights reserved.
4 *
5 * Distributed under the terms of the MIT License.
6 */
7
8
9 #include <stdlib.h>
10 #include <string.h>
11
12
13 #include "ACPIPrivate.h"
14 extern "C" {
15 #include "acpi.h"
16 }
17 #include <dpc.h>
18 #include <PCI.h>
19
20
21 //#define TRACE_ACPI_MODULE
22 #ifdef TRACE_ACPI_MODULE
23 # define TRACE(x) dprintf x
24 #else
25 # define TRACE(x) ;
26 #endif
27
28
29 device_manager_info* gDeviceManager = NULL;
30 pci_module_info* gPCIManager = NULL;
31 dpc_module_info* gDPC = NULL;
32
33 module_dependency module_dependencies[] = {
34 {B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager},
35 {B_PCI_MODULE_NAME, (module_info**)&gPCIManager},
36 {B_DPC_MODULE_NAME, (module_info**)&gDPC},
37 {}
38 };
39
40
41 static float
acpi_module_supports_device(device_node * parent)42 acpi_module_supports_device(device_node* parent)
43 {
44 // make sure parent is really device root
45 const char* bus;
46 if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false))
47 return B_ERROR;
48
49 if (strcmp(bus, "root"))
50 return 0.0;
51
52 return 1.0;
53 }
54
55
56 static status_t
acpi_module_register_device(device_node * parent)57 acpi_module_register_device(device_node* parent)
58 {
59 device_attr attrs[] = {
60 { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { .string = "ACPI" }},
61 { B_DEVICE_FLAGS, B_UINT32_TYPE, { .ui32 = B_KEEP_DRIVER_LOADED }},
62 {}
63 };
64
65 return gDeviceManager->register_node(parent, ACPI_ROOT_MODULE_NAME, attrs,
66 NULL, NULL);
67 }
68
69
70 static status_t
acpi_enumerate_child_devices(device_node * node,const char * root)71 acpi_enumerate_child_devices(device_node* node, const char* root)
72 {
73 char result[255];
74 void* counter = NULL;
75
76 TRACE(("acpi_enumerate_child_devices: recursing from %s\n", root));
77
78 while (get_next_entry(ACPI_TYPE_ANY, root, result,
79 sizeof(result), &counter) == B_OK) {
80 uint32 type = get_object_type(result);
81 device_node* deviceNode;
82
83 switch (type) {
84 case ACPI_TYPE_POWER:
85 case ACPI_TYPE_PROCESSOR:
86 case ACPI_TYPE_THERMAL:
87 case ACPI_TYPE_DEVICE: {
88 device_attr attrs[16] = {
89 // info about device
90 { B_DEVICE_BUS, B_STRING_TYPE, { .string = "acpi" }},
91
92 // location on ACPI bus
93 { ACPI_DEVICE_PATH_ITEM, B_STRING_TYPE, { .string = result }},
94
95 // info about the device
96 { ACPI_DEVICE_TYPE_ITEM, B_UINT32_TYPE, { .ui32 = type }},
97
98 { B_DEVICE_FLAGS, B_UINT32_TYPE, { .ui32 = B_FIND_MULTIPLE_CHILDREN }},
99 { NULL }
100 };
101
102 uint32 attrCount = 4;
103 char* hid = NULL;
104 char* cidList[11] = { NULL };
105 char* uid = NULL;
106 char* cls = NULL;
107 if (type == ACPI_TYPE_DEVICE) {
108 if (get_device_info(result, &hid, (char**)&cidList, 8,
109 &uid, &cls) == B_OK) {
110 if (hid != NULL) {
111 attrs[attrCount].name = ACPI_DEVICE_HID_ITEM;
112 attrs[attrCount].type = B_STRING_TYPE;
113 attrs[attrCount].value.string = hid;
114 attrCount++;
115 }
116 for (int i = 0; cidList[i] != NULL; i++) {
117 attrs[attrCount].name = ACPI_DEVICE_CID_ITEM;
118 attrs[attrCount].type = B_STRING_TYPE;
119 attrs[attrCount].value.string = cidList[i];
120 attrCount++;
121 }
122 if (uid != NULL) {
123 attrs[attrCount].name = ACPI_DEVICE_UID_ITEM;
124 attrs[attrCount].type = B_STRING_TYPE;
125 attrs[attrCount].value.string = uid;
126 attrCount++;
127 }
128 if (cls != NULL) {
129 uint32 clsClass = strtoul(cls, NULL, 16);
130 attrs[attrCount].name = B_DEVICE_TYPE;
131 attrs[attrCount].type = B_UINT16_TYPE;
132 attrs[attrCount].value.ui16 = (clsClass >> 16) & 0xff ;
133 attrCount++;
134 attrs[attrCount].name = B_DEVICE_SUB_TYPE;
135 attrs[attrCount].type = B_UINT16_TYPE;
136 attrs[attrCount].value.ui16 = (clsClass >> 8) & 0xff ;
137 attrCount++;
138 attrs[attrCount].name = B_DEVICE_INTERFACE;
139 attrs[attrCount].type = B_UINT16_TYPE;
140 attrs[attrCount].value.ui16 = (clsClass >> 0) & 0xff ;
141 attrCount++;
142 }
143 }
144 uint32 addr;
145 if (get_device_addr(result, &addr) == B_OK) {
146 attrs[attrCount].name = ACPI_DEVICE_ADDR_ITEM;
147 attrs[attrCount].type = B_UINT32_TYPE;
148 attrs[attrCount].value.ui32 = addr;
149 attrCount++;
150 }
151 }
152
153 status_t status = gDeviceManager->register_node(node,
154 ACPI_DEVICE_MODULE_NAME, attrs, NULL, &deviceNode);
155 free(hid);
156 free(uid);
157 free(cls);
158 for (int i = 0; cidList[i] != NULL; i++)
159 free(cidList[i]);
160 if (status != B_OK)
161 break;
162 acpi_enumerate_child_devices(deviceNode, result);
163 break;
164 }
165 default:
166 acpi_enumerate_child_devices(node, result);
167 break;
168 }
169
170 }
171
172 return B_OK;
173 }
174
175
176 static status_t
acpi_module_register_child_devices(void * cookie)177 acpi_module_register_child_devices(void* cookie)
178 {
179 device_node* node = (device_node*)cookie;
180
181 status_t status = gDeviceManager->publish_device(node, "acpi/namespace",
182 ACPI_NS_DUMP_DEVICE_MODULE_NAME);
183 if (status != B_OK)
184 return status;
185 status = gDeviceManager->publish_device(node, "acpi/call",
186 ACPI_CALL_DEVICE_MODULE_NAME);
187 if (status != B_OK)
188 return status;
189
190 if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) == 0) {
191 dprintf("registering power button\n");
192 device_attr attrs[] = {
193 // info about device
194 { B_DEVICE_BUS, B_STRING_TYPE, { .string = "acpi" }},
195
196 // info about the device
197 { ACPI_DEVICE_HID_ITEM, B_STRING_TYPE, { .string = "ACPI_FPB" }},
198 { ACPI_DEVICE_TYPE_ITEM, B_UINT32_TYPE, { .ui32 = ACPI_TYPE_DEVICE }},
199
200 // consumer specification
201 { B_DEVICE_FLAGS, B_UINT32_TYPE, { .ui32 = B_FIND_MULTIPLE_CHILDREN }},
202 { NULL }
203 };
204 device_node* deviceNode;
205 gDeviceManager->register_node(node, ACPI_DEVICE_MODULE_NAME, attrs,
206 NULL, &deviceNode);
207 }
208 if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) == 0) {
209 dprintf("registering sleep button\n");
210 device_attr attrs[] = {
211 // info about device
212 { B_DEVICE_BUS, B_STRING_TYPE, { .string = "acpi" }},
213
214 // info about the device
215 { ACPI_DEVICE_HID_ITEM, B_STRING_TYPE, { .string = "ACPI_FSB" }},
216 { ACPI_DEVICE_TYPE_ITEM, B_UINT32_TYPE, { .ui32 = ACPI_TYPE_DEVICE }},
217
218 // consumer specification
219 { B_DEVICE_FLAGS, B_UINT32_TYPE, { .ui32 = B_FIND_MULTIPLE_CHILDREN }},
220 { NULL }
221 };
222 device_node* deviceNode;
223 gDeviceManager->register_node(node, ACPI_DEVICE_MODULE_NAME, attrs,
224 NULL, &deviceNode);
225
226 }
227
228 return acpi_enumerate_child_devices(node, "\\");
229 }
230
231
232 static status_t
acpi_module_init(device_node * node,void ** _cookie)233 acpi_module_init(device_node* node, void** _cookie)
234 {
235 *_cookie = node;
236 return B_OK;
237 }
238
239
240 static void
acpi_module_uninit(void * cookie)241 acpi_module_uninit(void* cookie)
242 {
243 }
244
245
246 static int32
acpi_module_std_ops(int32 op,...)247 acpi_module_std_ops(int32 op, ...)
248 {
249 switch (op) {
250 case B_MODULE_INIT:
251 {
252 module_info* module;
253 return get_module(B_ACPI_MODULE_NAME, &module);
254 // this serializes our module initialization
255 }
256
257 case B_MODULE_UNINIT:
258 return put_module(B_ACPI_MODULE_NAME);
259 }
260
261 return B_BAD_VALUE;
262 }
263
264
265 static struct acpi_root_info sACPIRootModule = {
266 {
267 {
268 ACPI_ROOT_MODULE_NAME,
269 0,
270 acpi_module_std_ops
271 },
272
273 acpi_module_supports_device,
274 acpi_module_register_device,
275 acpi_module_init,
276 acpi_module_uninit,
277 acpi_module_register_child_devices,
278 NULL, // rescan devices
279 NULL, // device removed
280 },
281
282 get_handle,
283 get_name,
284 acquire_global_lock,
285 release_global_lock,
286 install_notify_handler,
287 remove_notify_handler,
288 update_all_gpes,
289 enable_gpe,
290 disable_gpe,
291 clear_gpe,
292 set_gpe,
293 finish_gpe,
294 install_gpe_handler,
295 remove_gpe_handler,
296 install_address_space_handler,
297 remove_address_space_handler,
298 enable_fixed_event,
299 disable_fixed_event,
300 fixed_event_status,
301 reset_fixed_event,
302 install_fixed_event_handler,
303 remove_fixed_event_handler,
304 get_next_entry,
305 get_next_object,
306 get_device,
307 get_device_info,
308 get_object_type,
309 get_object,
310 get_object_typed,
311 ns_handle_to_pathname,
312 evaluate_object,
313 evaluate_method,
314 get_irq_routing_table,
315 get_current_resources,
316 get_possible_resources,
317 set_current_resources,
318 walk_resources,
319 prepare_sleep_state,
320 enter_sleep_state,
321 reboot,
322 get_table
323 };
324
325
326 module_info* modules[] = {
327 (module_info*)&gACPIModule,
328 (module_info*)&sACPIRootModule,
329 (module_info*)&acpi_ns_dump_module,
330 (module_info*)&gACPIDeviceModule,
331 (module_info*)&embedded_controller_driver_module,
332 (module_info*)&embedded_controller_device_module,
333 (module_info*)&gAcpiCallDeviceModule,
334 NULL
335 };
336