xref: /haiku/src/add-ons/kernel/bus_managers/acpi/Device.cpp (revision 8f6d605714a4155991a2bd404c63f8f1725536f9)
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 #include <string.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 
12 #include "ACPIPrivate.h"
13 extern "C" {
14 #include "acpi.h"
15 }
16 
17 
18 static status_t
acpi_install_notify_handler(acpi_device device,uint32 handlerType,acpi_notify_handler handler,void * context)19 acpi_install_notify_handler(acpi_device device,	uint32 handlerType,
20 	acpi_notify_handler handler, void *context)
21 {
22 	return install_notify_handler(device->handle, handlerType, handler,
23 		context);
24 }
25 
26 static status_t
acpi_remove_notify_handler(acpi_device device,uint32 handlerType,acpi_notify_handler handler)27 acpi_remove_notify_handler(acpi_device device, uint32 handlerType,
28 	acpi_notify_handler handler)
29 {
30 	return remove_notify_handler(device->handle, handlerType, handler);
31 }
32 
33 
34 static status_t
acpi_install_address_space_handler(acpi_device device,uint32 spaceId,acpi_adr_space_handler handler,acpi_adr_space_setup setup,void * data)35 acpi_install_address_space_handler(acpi_device device, uint32 spaceId,
36 	acpi_adr_space_handler handler,	acpi_adr_space_setup setup,	void *data)
37 {
38 	return install_address_space_handler(device->handle, spaceId, handler,
39 		setup, data);
40 }
41 
42 static status_t
acpi_remove_address_space_handler(acpi_device device,uint32 spaceId,acpi_adr_space_handler handler)43 acpi_remove_address_space_handler(acpi_device device, uint32 spaceId,
44 	acpi_adr_space_handler handler)
45 {
46 	return remove_address_space_handler(device->handle, spaceId, handler);
47 }
48 
49 
50 static uint32
acpi_get_object_type(acpi_device device)51 acpi_get_object_type(acpi_device device)
52 {
53 	return device->type;
54 }
55 
56 
57 static status_t
acpi_get_object(acpi_device device,const char * path,acpi_object_type ** return_value)58 acpi_get_object(acpi_device device, const char *path, acpi_object_type **return_value)
59 {
60 	if (device->path == NULL)
61 		return B_BAD_VALUE;
62 	if (path) {
63 		char objname[255];
64 		snprintf(objname, sizeof(objname), "%s.%s", device->path, path);
65 		return get_object(objname, return_value);
66 	}
67 	return get_object(device->path, return_value);
68 }
69 
70 
71 static status_t
acpi_evaluate_method(acpi_device device,const char * method,acpi_objects * args,acpi_data * returnValue)72 acpi_evaluate_method(acpi_device device, const char *method,
73 	acpi_objects *args, acpi_data *returnValue)
74 {
75 	return evaluate_method(device->handle, method, args, returnValue);
76 }
77 
78 
79 static status_t
acpi_walk_resources(acpi_device device,char * method,acpi_walk_resources_callback callback,void * context)80 acpi_walk_resources(acpi_device device, char *method,
81 	acpi_walk_resources_callback callback, void* context)
82 {
83 	return walk_resources(device->handle, method, callback, context);
84 }
85 
86 
87 static status_t
acpi_walk_namespace(acpi_device device,uint32 objectType,uint32 maxDepth,acpi_walk_callback descendingCallback,acpi_walk_callback ascendingCallback,void * context,void ** returnValue)88 acpi_walk_namespace(acpi_device device, uint32 objectType, uint32 maxDepth,
89 	acpi_walk_callback descendingCallback,
90 	acpi_walk_callback ascendingCallback, void* context, void** returnValue)
91 {
92 	return walk_namespace(device->handle, objectType, maxDepth,
93 		descendingCallback, ascendingCallback, context, returnValue);
94 }
95 
96 
97 static status_t
acpi_device_init_driver(device_node * node,void ** cookie)98 acpi_device_init_driver(device_node *node, void **cookie)
99 {
100 	ACPI_HANDLE handle = NULL;
101 	const char *path = NULL;
102 	uint32 type;
103 
104 	if (gDeviceManager->get_attr_uint32(node, ACPI_DEVICE_TYPE_ITEM, &type, false) != B_OK)
105 		return B_ERROR;
106 	gDeviceManager->get_attr_string(node, ACPI_DEVICE_PATH_ITEM, &path, false);
107 
108 	acpi_device_cookie *device = (acpi_device_cookie*)malloc(sizeof(*device));
109 	if (device == NULL)
110 		return B_NO_MEMORY;
111 
112 	memset(device, 0, sizeof(*device));
113 
114 	if (path != NULL && AcpiGetHandle(NULL, (ACPI_STRING)path, &handle) != AE_OK) {
115 		free(device);
116 		return B_ENTRY_NOT_FOUND;
117 	}
118 
119 	device->handle = handle;
120 	device->path = path != NULL ? strdup(path) : NULL;
121 	device->type = type;
122 	device->node = node;
123 
124 	snprintf(device->name, sizeof(device->name), "acpi_device %s", path);
125 	*cookie = device;
126 	return B_OK;
127 }
128 
129 
130 static void
acpi_device_uninit_driver(void * cookie)131 acpi_device_uninit_driver(void *cookie)
132 {
133 	acpi_device_cookie *device = (acpi_device_cookie*)cookie;
134 
135 	free(device->path);
136 	free(device);
137 }
138 
139 
140 static status_t
acpi_device_std_ops(int32 op,...)141 acpi_device_std_ops(int32 op, ...)
142 {
143 	switch (op) {
144 		case B_MODULE_INIT:
145 		case B_MODULE_UNINIT:
146 			return B_OK;
147 	}
148 
149 	return B_BAD_VALUE;
150 }
151 
152 
153 acpi_device_module_info gACPIDeviceModule = {
154 	{
155 		{
156 			ACPI_DEVICE_MODULE_NAME,
157 			0,
158 			acpi_device_std_ops
159 		},
160 
161 		NULL,		// supports device
162 		NULL,		// register device (our parent registered us)
163 		acpi_device_init_driver,
164 		acpi_device_uninit_driver,
165 		NULL,	// register child devices
166 		NULL,	// rescan devices
167 		NULL,	// device removed
168 	},
169 	acpi_install_notify_handler,
170 	acpi_remove_notify_handler,
171 	acpi_install_address_space_handler,
172 	acpi_remove_address_space_handler,
173 	acpi_get_object_type,
174 	acpi_get_object,
175 	acpi_walk_namespace,
176 	acpi_evaluate_method,
177 	acpi_walk_resources
178 };
179