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