xref: /haiku/src/add-ons/kernel/bus_managers/acpi/Module.cpp (revision ce2d7d5ac8d220cb661fd12529fd5c88f5d80d6e)
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 #include "ACPIPrivate.h"
13 
14 #include <dpc.h>
15 #include <PCI.h>
16 
17 
18 //#define TRACE_ACPI_MODULE
19 #ifdef TRACE_ACPI_MODULE
20 #	define TRACE(x) dprintf x
21 #else
22 #	define TRACE(x) ;
23 #endif
24 
25 
26 device_manager_info* gDeviceManager = NULL;
27 pci_module_info* gPCIManager = NULL;
28 dpc_module_info* gDPC = NULL;
29 
30 module_dependency module_dependencies[] = {
31 	{B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager},
32 	{B_PCI_MODULE_NAME, (module_info**)&gPCIManager},
33 	{B_DPC_MODULE_NAME, (module_info**)&gDPC},
34 	{}
35 };
36 
37 
38 static float
39 acpi_module_supports_device(device_node* parent)
40 {
41 	// make sure parent is really device root
42 	const char* bus;
43 	if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false))
44 		return B_ERROR;
45 
46 	if (strcmp(bus, "root"))
47 		return 0.0;
48 
49 	return 1.0;
50 }
51 
52 
53 static status_t
54 acpi_module_register_device(device_node* parent)
55 {
56 	device_attr attrs[] = {
57 		{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { string: "ACPI" }},
58 
59 		{ B_DEVICE_FLAGS, B_UINT32_TYPE, { ui32: B_KEEP_DRIVER_LOADED }},
60 		{}
61 	};
62 
63 	return gDeviceManager->register_node(parent, ACPI_ROOT_MODULE_NAME, attrs,
64 		NULL, NULL);
65 }
66 
67 
68 static status_t
69 acpi_enumerate_child_devices(device_node* node, const char* root)
70 {
71 	char result[255];
72 	void* counter = NULL;
73 
74 	TRACE(("acpi_enumerate_child_devices: recursing from %s\n", root));
75 
76 	while (get_next_entry(ACPI_TYPE_ANY, root, result,
77 			sizeof(result), &counter) == B_OK) {
78 		uint32 type = get_object_type(result);
79 		device_node* deviceNode;
80 
81 		switch (type) {
82 			case ACPI_TYPE_POWER:
83 			case ACPI_TYPE_PROCESSOR:
84 			case ACPI_TYPE_THERMAL:
85 			case ACPI_TYPE_DEVICE: {
86 				char hid[16] = "";
87 				device_attr attrs[] = {
88 					// info about device
89 					{ B_DEVICE_BUS, B_STRING_TYPE, { string: "acpi" }},
90 
91 					// location on ACPI bus
92 					{ ACPI_DEVICE_PATH_ITEM, B_STRING_TYPE, { string: result }},
93 
94 					// info about the device
95 					{ ACPI_DEVICE_HID_ITEM, B_STRING_TYPE, { string: hid }},
96 					{ ACPI_DEVICE_TYPE_ITEM, B_UINT32_TYPE, { ui32: type }},
97 
98 					// consumer specification
99 					/*{ B_DRIVER_MAPPING, B_STRING_TYPE, { string:
100 						"hid_%" ACPI_DEVICE_HID_ITEM "%" }},
101 					{ B_DRIVER_MAPPING "/0", B_STRING_TYPE, { string:
102 						"type_%" ACPI_DEVICE_TYPE_ITEM "%" }},*/
103 					{ B_DEVICE_FLAGS, B_UINT32_TYPE, { ui32: /*B_FIND_CHILD_ON_DEMAND|*/B_FIND_MULTIPLE_CHILDREN }},
104 					{ NULL }
105 				};
106 
107 				if (type == ACPI_TYPE_DEVICE)
108 					get_device_hid(result, hid, sizeof(hid));
109 
110 				if (gDeviceManager->register_node(node, ACPI_DEVICE_MODULE_NAME, attrs,
111 						NULL, &deviceNode) == B_OK)
112 	                acpi_enumerate_child_devices(deviceNode, result);
113 				break;
114 			}
115 			default:
116 				acpi_enumerate_child_devices(node, result);
117 				break;
118 		}
119 
120 	}
121 
122 	return B_OK;
123 }
124 
125 
126 static status_t
127 acpi_module_register_child_devices(void* cookie)
128 {
129 	device_node* node = (device_node*)cookie;
130 
131 	status_t status = gDeviceManager->publish_device(node, "acpi/namespace",
132 		ACPI_NS_DUMP_DEVICE_MODULE_NAME);
133 	if (status != B_OK)
134 		return status;
135 
136 	return acpi_enumerate_child_devices(node, "\\");
137 }
138 
139 
140 static status_t
141 acpi_module_init(device_node* node, void** _cookie)
142 {
143 	*_cookie = node;
144 	return B_OK;
145 }
146 
147 
148 static void
149 acpi_module_uninit(void* cookie)
150 {
151 }
152 
153 
154 static int32
155 acpi_module_std_ops(int32 op, ...)
156 {
157 	switch (op) {
158 		case B_MODULE_INIT:
159 		{
160 			module_info* module;
161 			return get_module(B_ACPI_MODULE_NAME, &module);
162 				// this serializes our module initialization
163 		}
164 
165 		case B_MODULE_UNINIT:
166 			return put_module(B_ACPI_MODULE_NAME);
167 	}
168 
169 	return B_BAD_VALUE;
170 }
171 
172 
173 static struct acpi_root_info sACPIRootModule = {
174 	{
175 		{
176 			ACPI_ROOT_MODULE_NAME,
177 			0,
178 			acpi_module_std_ops
179 		},
180 
181 		acpi_module_supports_device,
182 		acpi_module_register_device,
183 		acpi_module_init,
184 		acpi_module_uninit,
185 		acpi_module_register_child_devices,
186 		NULL,	// rescan devices
187 		NULL,	// device removed
188 	},
189 
190 	get_handle,
191 	acquire_global_lock,
192 	release_global_lock,
193 	install_notify_handler,
194 	remove_notify_handler,
195 	update_all_gpes,
196 	enable_gpe,
197 	disable_gpe,
198 	clear_gpe,
199 	set_gpe,
200 	finish_gpe,
201 	install_gpe_handler,
202 	remove_gpe_handler,
203 	install_address_space_handler,
204 	remove_address_space_handler,
205 	enable_fixed_event,
206 	disable_fixed_event,
207 	fixed_event_status,
208 	reset_fixed_event,
209 	install_fixed_event_handler,
210 	remove_fixed_event_handler,
211 	get_next_entry,
212 	get_device,
213 	get_device_hid,
214 	get_object_type,
215 	get_object,
216 	get_object_typed,
217 	ns_handle_to_pathname,
218 	evaluate_object,
219 	evaluate_method,
220 	get_irq_routing_table,
221 	get_current_resources,
222 	get_possible_resources,
223 	set_current_resources,
224 	walk_resources,
225 	prepare_sleep_state,
226 	enter_sleep_state,
227 	reboot,
228 	get_table
229 };
230 
231 
232 module_info* modules[] = {
233 	(module_info*)&gACPIModule,
234 	(module_info*)&sACPIRootModule,
235 	(module_info*)&acpi_ns_dump_module,
236 	(module_info*)&gACPIDeviceModule,
237 	(module_info*)&embedded_controller_driver_module,
238 	(module_info*)&embedded_controller_device_module,
239 	NULL
240 };
241