xref: /haiku/src/add-ons/kernel/bus_managers/acpi/Module.cpp (revision de5c16f10ad133de6e8f864e3bbb16679d6ad900)
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 				char hid[16] = "";
90 				device_attr attrs[] = {
91 					// info about device
92 					{ B_DEVICE_BUS, B_STRING_TYPE, { string: "acpi" }},
93 
94 					// location on ACPI bus
95 					{ ACPI_DEVICE_PATH_ITEM, B_STRING_TYPE, { string: result }},
96 
97 					// info about the device
98 					{ ACPI_DEVICE_HID_ITEM, B_STRING_TYPE, { string: hid }},
99 					{ ACPI_DEVICE_TYPE_ITEM, B_UINT32_TYPE, { ui32: type }},
100 
101 					// consumer specification
102 					/*{ B_DRIVER_MAPPING, B_STRING_TYPE, { string:
103 						"hid_%" ACPI_DEVICE_HID_ITEM "%" }},
104 					{ B_DRIVER_MAPPING "/0", B_STRING_TYPE, { string:
105 						"type_%" ACPI_DEVICE_TYPE_ITEM "%" }},*/
106 					{ B_DEVICE_FLAGS, B_UINT32_TYPE, { ui32: /*B_FIND_CHILD_ON_DEMAND|*/B_FIND_MULTIPLE_CHILDREN }},
107 					{ NULL }
108 				};
109 
110 				if (type == ACPI_TYPE_DEVICE)
111 					get_device_hid(result, hid, sizeof(hid));
112 
113 				if (gDeviceManager->register_node(node, ACPI_DEVICE_MODULE_NAME, attrs,
114 						NULL, &deviceNode) == B_OK)
115 	                acpi_enumerate_child_devices(deviceNode, result);
116 				break;
117 			}
118 			default:
119 				acpi_enumerate_child_devices(node, result);
120 				break;
121 		}
122 
123 	}
124 
125 	return B_OK;
126 }
127 
128 
129 static status_t
130 acpi_module_register_child_devices(void* cookie)
131 {
132 	device_node* node = (device_node*)cookie;
133 
134 	status_t status = gDeviceManager->publish_device(node, "acpi/namespace",
135 		ACPI_NS_DUMP_DEVICE_MODULE_NAME);
136 	if (status != B_OK)
137 		return status;
138 
139 	if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) == 0) {
140 		dprintf("registering power button\n");
141 		device_attr attrs[] = {
142 			// info about device
143 			{ B_DEVICE_BUS, B_STRING_TYPE, { string: "acpi" }},
144 
145 			// info about the device
146 			{ ACPI_DEVICE_HID_ITEM, B_STRING_TYPE, { string: "ACPI_FPB" }},
147 			{ ACPI_DEVICE_TYPE_ITEM, B_UINT32_TYPE, { ui32: ACPI_TYPE_DEVICE }},
148 
149 			// consumer specification
150 			{ B_DEVICE_FLAGS, B_UINT32_TYPE, { ui32: B_FIND_MULTIPLE_CHILDREN }},
151 			{ NULL }
152 		};
153 		device_node* deviceNode;
154 		gDeviceManager->register_node(node, ACPI_DEVICE_MODULE_NAME, attrs,
155 				NULL, &deviceNode);
156 	}
157 	if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) == 0) {
158 		dprintf("registering sleep button\n");
159 		device_attr attrs[] = {
160 			// info about device
161 			{ B_DEVICE_BUS, B_STRING_TYPE, { string: "acpi" }},
162 
163 			// info about the device
164 			{ ACPI_DEVICE_HID_ITEM, B_STRING_TYPE, { string: "ACPI_FSB" }},
165 			{ ACPI_DEVICE_TYPE_ITEM, B_UINT32_TYPE, { ui32: ACPI_TYPE_DEVICE }},
166 
167 			// consumer specification
168 			{ B_DEVICE_FLAGS, B_UINT32_TYPE, { ui32: B_FIND_MULTIPLE_CHILDREN }},
169 			{ NULL }
170 		};
171 		device_node* deviceNode;
172 		gDeviceManager->register_node(node, ACPI_DEVICE_MODULE_NAME, attrs,
173 				NULL, &deviceNode);
174 
175 	}
176 
177 	return acpi_enumerate_child_devices(node, "\\");
178 }
179 
180 
181 static status_t
182 acpi_module_init(device_node* node, void** _cookie)
183 {
184 	*_cookie = node;
185 	return B_OK;
186 }
187 
188 
189 static void
190 acpi_module_uninit(void* cookie)
191 {
192 }
193 
194 
195 static int32
196 acpi_module_std_ops(int32 op, ...)
197 {
198 	switch (op) {
199 		case B_MODULE_INIT:
200 		{
201 			module_info* module;
202 			return get_module(B_ACPI_MODULE_NAME, &module);
203 				// this serializes our module initialization
204 		}
205 
206 		case B_MODULE_UNINIT:
207 			return put_module(B_ACPI_MODULE_NAME);
208 	}
209 
210 	return B_BAD_VALUE;
211 }
212 
213 
214 static struct acpi_root_info sACPIRootModule = {
215 	{
216 		{
217 			ACPI_ROOT_MODULE_NAME,
218 			0,
219 			acpi_module_std_ops
220 		},
221 
222 		acpi_module_supports_device,
223 		acpi_module_register_device,
224 		acpi_module_init,
225 		acpi_module_uninit,
226 		acpi_module_register_child_devices,
227 		NULL,	// rescan devices
228 		NULL,	// device removed
229 	},
230 
231 	get_handle,
232 	acquire_global_lock,
233 	release_global_lock,
234 	install_notify_handler,
235 	remove_notify_handler,
236 	update_all_gpes,
237 	enable_gpe,
238 	disable_gpe,
239 	clear_gpe,
240 	set_gpe,
241 	finish_gpe,
242 	install_gpe_handler,
243 	remove_gpe_handler,
244 	install_address_space_handler,
245 	remove_address_space_handler,
246 	enable_fixed_event,
247 	disable_fixed_event,
248 	fixed_event_status,
249 	reset_fixed_event,
250 	install_fixed_event_handler,
251 	remove_fixed_event_handler,
252 	get_next_entry,
253 	get_device,
254 	get_device_hid,
255 	get_object_type,
256 	get_object,
257 	get_object_typed,
258 	ns_handle_to_pathname,
259 	evaluate_object,
260 	evaluate_method,
261 	get_irq_routing_table,
262 	get_current_resources,
263 	get_possible_resources,
264 	set_current_resources,
265 	walk_resources,
266 	prepare_sleep_state,
267 	enter_sleep_state,
268 	reboot,
269 	get_table
270 };
271 
272 
273 module_info* modules[] = {
274 	(module_info*)&gACPIModule,
275 	(module_info*)&sACPIRootModule,
276 	(module_info*)&acpi_ns_dump_module,
277 	(module_info*)&gACPIDeviceModule,
278 	(module_info*)&embedded_controller_driver_module,
279 	(module_info*)&embedded_controller_device_module,
280 	NULL
281 };
282