acpi_util.c revision 1.4 1 /* $NetBSD: acpi_util.c,v 1.4 2010/04/27 08:15:07 jruoho Exp $ */
2
3 /*-
4 * Copyright (c) 2003, 2007 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum of By Noon Software, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * Copyright 2001, 2003 Wasabi Systems, Inc.
34 * All rights reserved.
35 *
36 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software
47 * must display the following acknowledgement:
48 * This product includes software developed for the NetBSD Project by
49 * Wasabi Systems, Inc.
50 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
51 * or promote products derived from this software without specific prior
52 * written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
56 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
57 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
58 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
59 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
60 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
61 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
62 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
63 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
64 * POSSIBILITY OF SUCH DAMAGE.
65 */
66
67 #include <sys/cdefs.h>
68 __KERNEL_RCSID(0, "$NetBSD: acpi_util.c,v 1.4 2010/04/27 08:15:07 jruoho Exp $");
69
70 #include <sys/param.h>
71
72 #include <dev/acpi/acpireg.h>
73 #include <dev/acpi/acpivar.h>
74
75 #define _COMPONENT ACPI_BUS_COMPONENT
76 ACPI_MODULE_NAME ("acpi_util")
77
78 /*
79 * Evaluate an integer object.
80 */
81 ACPI_STATUS
82 acpi_eval_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER *valp)
83 {
84 ACPI_OBJECT obj;
85 ACPI_BUFFER buf;
86 ACPI_STATUS rv;
87
88 if (handle == NULL)
89 handle = ACPI_ROOT_OBJECT;
90
91 buf.Pointer = &obj;
92 buf.Length = sizeof(obj);
93
94 rv = AcpiEvaluateObject(handle, path, NULL, &buf);
95
96 if (ACPI_FAILURE(rv))
97 return rv;
98
99 if (obj.Type != ACPI_TYPE_INTEGER)
100 return AE_TYPE;
101
102 if (valp != NULL)
103 *valp = obj.Integer.Value;
104
105 return AE_OK;
106 }
107
108 /*
109 * Evaluate an integer object with a single integer input parameter.
110 */
111 ACPI_STATUS
112 acpi_eval_set_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER val)
113 {
114 ACPI_OBJECT_LIST arg;
115 ACPI_OBJECT obj;
116
117 if (handle == NULL)
118 handle = ACPI_ROOT_OBJECT;
119
120 obj.Type = ACPI_TYPE_INTEGER;
121 obj.Integer.Value = val;
122
123 arg.Count = 1;
124 arg.Pointer = &obj;
125
126 return AcpiEvaluateObject(handle, path, &arg, NULL);
127 }
128
129 /*
130 * Evaluate a (Unicode) string object.
131 */
132 ACPI_STATUS
133 acpi_eval_string(ACPI_HANDLE handle, const char *path, char **stringp)
134 {
135 ACPI_OBJECT *obj;
136 ACPI_BUFFER buf;
137 ACPI_STATUS rv;
138
139 rv = acpi_eval_struct(handle, path, &buf);
140
141 if (ACPI_FAILURE(rv))
142 return rv;
143
144 obj = buf.Pointer;
145
146 if (obj->Type != ACPI_TYPE_STRING) {
147 rv = AE_TYPE;
148 goto out;
149 }
150
151 if (obj->String.Length == 0) {
152 rv = AE_BAD_DATA;
153 goto out;
154 }
155
156 *stringp = ACPI_ALLOCATE(obj->String.Length + 1);
157
158 if (*stringp == NULL) {
159 rv = AE_NO_MEMORY;
160 goto out;
161 }
162
163 (void)memcpy(*stringp, obj->String.Pointer, obj->String.Length);
164
165 (*stringp)[obj->String.Length] = '\0';
166
167 out:
168 ACPI_FREE(buf.Pointer);
169
170 return rv;
171 }
172
173 /*
174 * Evaluate a structure. Caller must free buf.Pointer by ACPI_FREE().
175 */
176 ACPI_STATUS
177 acpi_eval_struct(ACPI_HANDLE handle, const char *path, ACPI_BUFFER *buf)
178 {
179
180 if (handle == NULL)
181 handle = ACPI_ROOT_OBJECT;
182
183 buf->Pointer = NULL;
184 buf->Length = ACPI_ALLOCATE_LOCAL_BUFFER;
185
186 return AcpiEvaluateObject(handle, path, NULL, buf);
187 }
188
189 /*
190 * Evaluate a reference handle from an element in a package.
191 */
192 ACPI_STATUS
193 acpi_eval_reference_handle(ACPI_OBJECT *elm, ACPI_HANDLE *handle)
194 {
195
196 if (elm == NULL || handle == NULL)
197 return AE_BAD_PARAMETER;
198
199 switch (elm->Type) {
200
201 case ACPI_TYPE_ANY:
202 case ACPI_TYPE_LOCAL_REFERENCE:
203
204 if (elm->Reference.Handle == NULL)
205 return AE_NULL_ENTRY;
206
207 *handle = elm->Reference.Handle;
208
209 return AE_OK;
210
211 case ACPI_TYPE_STRING:
212 return AcpiGetHandle(NULL, elm->String.Pointer, handle);
213
214 default:
215 return AE_TYPE;
216 }
217 }
218
219 /*
220 * Iterate over all objects in a package, and pass them all
221 * to a function. If the called function returns non-AE_OK,
222 * the iteration is stopped and that value is returned.
223 */
224 ACPI_STATUS
225 acpi_foreach_package_object(ACPI_OBJECT *pkg,
226 ACPI_STATUS (*func)(ACPI_OBJECT *, void *), void *arg)
227 {
228 ACPI_STATUS rv = AE_OK;
229 uint32_t i;
230
231 if (pkg == NULL)
232 return AE_BAD_PARAMETER;
233
234 if (pkg->Type != ACPI_TYPE_PACKAGE)
235 return AE_TYPE;
236
237 for (i = 0; i < pkg->Package.Count; i++) {
238
239 rv = (*func)(&pkg->Package.Elements[i], arg);
240
241 if (ACPI_FAILURE(rv))
242 break;
243 }
244
245 return rv;
246 }
247
248 /*
249 * Fetch data info the specified (empty) ACPI buffer.
250 * Caller must free buf.Pointer by ACPI_FREE().
251 */
252 ACPI_STATUS
253 acpi_get(ACPI_HANDLE handle, ACPI_BUFFER *buf,
254 ACPI_STATUS (*getit)(ACPI_HANDLE, ACPI_BUFFER *))
255 {
256
257 buf->Pointer = NULL;
258 buf->Length = ACPI_ALLOCATE_LOCAL_BUFFER;
259
260 return (*getit)(handle, buf);
261 }
262
263 /*
264 * Get a device node from a handle.
265 */
266 struct acpi_devnode *
267 acpi_get_node(ACPI_HANDLE handle)
268 {
269 struct acpi_softc *sc = acpi_softc; /* XXX. */
270 struct acpi_devnode *ad;
271
272 if (sc == NULL || handle == NULL)
273 return NULL;
274
275 SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) {
276
277 if (ad->ad_handle == handle)
278 return ad;
279 }
280
281 aprint_debug_dev(sc->sc_dev, "%s: failed to "
282 "find node %s\n", __func__, acpi_name(handle));
283
284 return NULL;
285 }
286
287 /*
288 * Return a complete pathname from a handle.
289 *
290 * Note that the function uses static data storage;
291 * if the data is needed for future use, it should be
292 * copied before any subsequent calls overwrite it.
293 */
294 const char *
295 acpi_name(ACPI_HANDLE handle)
296 {
297 static char name[80];
298 ACPI_BUFFER buf;
299 ACPI_STATUS rv;
300
301 if (handle == NULL)
302 handle = ACPI_ROOT_OBJECT;
303
304 buf.Pointer = name;
305 buf.Length = sizeof(name);
306
307 rv = AcpiGetName(handle, ACPI_FULL_PATHNAME, &buf);
308
309 if (ACPI_FAILURE(rv))
310 return "UNKNOWN";
311
312 return name;
313 }
314
315 /*
316 * Match given IDs against _HID and _CIDs.
317 */
318 int
319 acpi_match_hid(ACPI_DEVICE_INFO *ad, const char * const *ids)
320 {
321 uint32_t i, n;
322 char *id;
323
324 while (*ids) {
325
326 if ((ad->Valid & ACPI_VALID_HID) != 0) {
327
328 if (pmatch(ad->HardwareId.String, *ids, NULL) == 2)
329 return 1;
330 }
331
332 if ((ad->Valid & ACPI_VALID_CID) != 0) {
333
334 n = ad->CompatibleIdList.Count;
335
336 for (i = 0; i < n; i++) {
337
338 id = ad->CompatibleIdList.Ids[i].String;
339
340 if (pmatch(id, *ids, NULL) == 2)
341 return 1;
342 }
343 }
344
345 ids++;
346 }
347
348 return 0;
349 }
350
351