xref: /haiku/src/add-ons/kernel/bus_managers/acpi/Module.cpp (revision 04d1d2da0b27294f0f1e623071df310a0820d4b6)
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 
62 		{ B_DEVICE_FLAGS, B_UINT32_TYPE, { ui32: B_KEEP_DRIVER_LOADED }},
63 		{}
64 	};
65 
66 	return gDeviceManager->register_node(parent, ACPI_ROOT_MODULE_NAME, attrs,
67 		NULL, NULL);
68 }
69 
70 
71 static status_t
72 acpi_enumerate_child_devices(device_node* node, const char* root)
73 {
74 	char result[255];
75 	void* counter = NULL;
76 
77 	TRACE(("acpi_enumerate_child_devices: recursing from %s\n", root));
78 
79 	while (get_next_entry(ACPI_TYPE_ANY, root, result,
80 			sizeof(result), &counter) == B_OK) {
81 		uint32 type = get_object_type(result);
82 		device_node* deviceNode;
83 
84 		switch (type) {
85 			case ACPI_TYPE_POWER:
86 			case ACPI_TYPE_PROCESSOR:
87 			case ACPI_TYPE_THERMAL:
88 			case ACPI_TYPE_DEVICE: {
89 				device_attr attrs[15] = {
90 					// info about device
91 					{ B_DEVICE_BUS, B_STRING_TYPE, { string: "acpi" }},
92 
93 					// location on ACPI bus
94 					{ ACPI_DEVICE_PATH_ITEM, B_STRING_TYPE, { string: result }},
95 
96 					// info about the device
97 					{ ACPI_DEVICE_TYPE_ITEM, B_UINT32_TYPE, { ui32: type }},
98 
99 					{ B_DEVICE_FLAGS, B_UINT32_TYPE, { ui32: B_FIND_MULTIPLE_CHILDREN }},
100 					{ NULL }
101 				};
102 
103 				uint32 attrCount = 4;
104 				char* hid = NULL;
105 				char* cidList[8] = { NULL };
106 				if (type == ACPI_TYPE_DEVICE) {
107 					if (get_device_info(result, &hid, (char**)&cidList, 8)
108 						== B_OK) {
109 						if (hid != NULL) {
110 							attrs[attrCount].name = ACPI_DEVICE_HID_ITEM;
111 							attrs[attrCount].type = B_STRING_TYPE;
112 							attrs[attrCount].value.string = hid;
113 							attrCount++;
114 						}
115 						for (int i = 0; cidList[i] != NULL; i++) {
116 							attrs[attrCount].name = ACPI_DEVICE_CID_ITEM;
117 							attrs[attrCount].type = B_STRING_TYPE;
118 							attrs[attrCount].value.string = cidList[i];
119 							attrCount++;
120 						}
121 					}
122 					uint32 addr;
123 					if (get_device_addr(result, &addr) == B_OK) {
124 						attrs[attrCount].name = ACPI_DEVICE_ADDR_ITEM;
125 						attrs[attrCount].type = B_UINT32_TYPE;
126 						attrs[attrCount].value.ui32 = addr;
127 						attrCount++;
128 					}
129 				}
130 
131 				status_t status = gDeviceManager->register_node(node,
132 						ACPI_DEVICE_MODULE_NAME, attrs, NULL, &deviceNode);
133 				free(hid);
134 				for (int i = 0; cidList[i] != NULL; i++)
135 					free(cidList[i]);
136 				if (status != B_OK)
137 					break;
138 				acpi_enumerate_child_devices(deviceNode, result);
139 				break;
140 			}
141 			default:
142 				acpi_enumerate_child_devices(node, result);
143 				break;
144 		}
145 
146 	}
147 
148 	return B_OK;
149 }
150 
151 
152 static status_t
153 acpi_module_register_child_devices(void* cookie)
154 {
155 	device_node* node = (device_node*)cookie;
156 
157 	status_t status = gDeviceManager->publish_device(node, "acpi/namespace",
158 		ACPI_NS_DUMP_DEVICE_MODULE_NAME);
159 	if (status != B_OK)
160 		return status;
161 
162 	if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) == 0) {
163 		dprintf("registering power button\n");
164 		device_attr attrs[] = {
165 			// info about device
166 			{ B_DEVICE_BUS, B_STRING_TYPE, { string: "acpi" }},
167 
168 			// info about the device
169 			{ ACPI_DEVICE_HID_ITEM, B_STRING_TYPE, { string: "ACPI_FPB" }},
170 			{ ACPI_DEVICE_TYPE_ITEM, B_UINT32_TYPE, { ui32: ACPI_TYPE_DEVICE }},
171 
172 			// consumer specification
173 			{ B_DEVICE_FLAGS, B_UINT32_TYPE, { ui32: B_FIND_MULTIPLE_CHILDREN }},
174 			{ NULL }
175 		};
176 		device_node* deviceNode;
177 		gDeviceManager->register_node(node, ACPI_DEVICE_MODULE_NAME, attrs,
178 				NULL, &deviceNode);
179 	}
180 	if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) == 0) {
181 		dprintf("registering sleep button\n");
182 		device_attr attrs[] = {
183 			// info about device
184 			{ B_DEVICE_BUS, B_STRING_TYPE, { string: "acpi" }},
185 
186 			// info about the device
187 			{ ACPI_DEVICE_HID_ITEM, B_STRING_TYPE, { string: "ACPI_FSB" }},
188 			{ ACPI_DEVICE_TYPE_ITEM, B_UINT32_TYPE, { ui32: ACPI_TYPE_DEVICE }},
189 
190 			// consumer specification
191 			{ B_DEVICE_FLAGS, B_UINT32_TYPE, { ui32: B_FIND_MULTIPLE_CHILDREN }},
192 			{ NULL }
193 		};
194 		device_node* deviceNode;
195 		gDeviceManager->register_node(node, ACPI_DEVICE_MODULE_NAME, attrs,
196 				NULL, &deviceNode);
197 
198 	}
199 
200 	return acpi_enumerate_child_devices(node, "\\");
201 }
202 
203 
204 static status_t
205 acpi_module_init(device_node* node, void** _cookie)
206 {
207 	*_cookie = node;
208 	return B_OK;
209 }
210 
211 
212 static void
213 acpi_module_uninit(void* cookie)
214 {
215 }
216 
217 
218 static int32
219 acpi_module_std_ops(int32 op, ...)
220 {
221 	switch (op) {
222 		case B_MODULE_INIT:
223 		{
224 			module_info* module;
225 			return get_module(B_ACPI_MODULE_NAME, &module);
226 				// this serializes our module initialization
227 		}
228 
229 		case B_MODULE_UNINIT:
230 			return put_module(B_ACPI_MODULE_NAME);
231 	}
232 
233 	return B_BAD_VALUE;
234 }
235 
236 
237 static struct acpi_root_info sACPIRootModule = {
238 	{
239 		{
240 			ACPI_ROOT_MODULE_NAME,
241 			0,
242 			acpi_module_std_ops
243 		},
244 
245 		acpi_module_supports_device,
246 		acpi_module_register_device,
247 		acpi_module_init,
248 		acpi_module_uninit,
249 		acpi_module_register_child_devices,
250 		NULL,	// rescan devices
251 		NULL,	// device removed
252 	},
253 
254 	get_handle,
255 	get_name,
256 	acquire_global_lock,
257 	release_global_lock,
258 	install_notify_handler,
259 	remove_notify_handler,
260 	update_all_gpes,
261 	enable_gpe,
262 	disable_gpe,
263 	clear_gpe,
264 	set_gpe,
265 	finish_gpe,
266 	install_gpe_handler,
267 	remove_gpe_handler,
268 	install_address_space_handler,
269 	remove_address_space_handler,
270 	enable_fixed_event,
271 	disable_fixed_event,
272 	fixed_event_status,
273 	reset_fixed_event,
274 	install_fixed_event_handler,
275 	remove_fixed_event_handler,
276 	get_next_entry,
277 	get_next_object,
278 	get_device,
279 	get_device_info,
280 	get_object_type,
281 	get_object,
282 	get_object_typed,
283 	ns_handle_to_pathname,
284 	evaluate_object,
285 	evaluate_method,
286 	get_irq_routing_table,
287 	get_current_resources,
288 	get_possible_resources,
289 	set_current_resources,
290 	walk_resources,
291 	prepare_sleep_state,
292 	enter_sleep_state,
293 	reboot,
294 	get_table
295 };
296 
297 
298 module_info* modules[] = {
299 	(module_info*)&gACPIModule,
300 	(module_info*)&sACPIRootModule,
301 	(module_info*)&acpi_ns_dump_module,
302 	(module_info*)&gACPIDeviceModule,
303 	(module_info*)&embedded_controller_driver_module,
304 	(module_info*)&embedded_controller_device_module,
305 	NULL
306 };
307