xref: /haiku/src/add-ons/kernel/bus_managers/acpi/Module.cpp (revision 4c07199d8201fcf267e90be0d24b76799d03cea6)
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
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
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
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
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
233 acpi_module_init(device_node* node, void** _cookie)
234 {
235 	*_cookie = node;
236 	return B_OK;
237 }
238 
239 
240 static void
241 acpi_module_uninit(void* cookie)
242 {
243 }
244 
245 
246 static int32
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