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
26device_manager_info* gDeviceManager = NULL;
27pci_module_info* gPCIManager = NULL;
28dpc_module_info* gDPC = NULL;
29
30module_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
38static float
39acpi_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
53static status_t
54acpi_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
68static status_t
69acpi_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
126static status_t
127acpi_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
140static status_t
141acpi_module_init(device_node* node, void** _cookie)
142{
143	*_cookie = node;
144	return B_OK;
145}
146
147
148static void
149acpi_module_uninit(void* cookie)
150{
151}
152
153
154static int32
155acpi_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
173static 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	prepare_sleep_state,
225	enter_sleep_state,
226	reboot,
227	get_table
228};
229
230
231module_info* modules[] = {
232	(module_info*)&gACPIModule,
233	(module_info*)&sACPIRootModule,
234	(module_info*)&acpi_ns_dump_module,
235	(module_info*)&gACPIDeviceModule,
236	(module_info*)&embedded_controller_driver_module,
237	(module_info*)&embedded_controller_device_module,
238	NULL
239};
240