Home | History | Annotate | Line # | Download | only in acpi
acpi_util.c revision 1.33.10.1
      1  1.33.10.1  perseant /*	$NetBSD: acpi_util.c,v 1.33.10.1 2025/08/02 05:56:31 perseant Exp $ */
      2        1.1    jruoho 
      3        1.1    jruoho /*-
      4       1.20   thorpej  * Copyright (c) 2003, 2007, 2021 The NetBSD Foundation, Inc.
      5        1.1    jruoho  * All rights reserved.
      6        1.1    jruoho  *
      7        1.1    jruoho  * This code is derived from software contributed to The NetBSD Foundation
      8        1.1    jruoho  * by Charles M. Hannum of By Noon Software, Inc.
      9        1.1    jruoho  *
     10        1.1    jruoho  * Redistribution and use in source and binary forms, with or without
     11        1.1    jruoho  * modification, are permitted provided that the following conditions
     12        1.1    jruoho  * are met:
     13        1.1    jruoho  * 1. Redistributions of source code must retain the above copyright
     14        1.1    jruoho  *    notice, this list of conditions and the following disclaimer.
     15        1.1    jruoho  * 2. Redistributions in binary form must reproduce the above copyright
     16        1.1    jruoho  *    notice, this list of conditions and the following disclaimer in the
     17        1.1    jruoho  *    documentation and/or other materials provided with the distribution.
     18        1.1    jruoho  *
     19        1.1    jruoho  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20        1.1    jruoho  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21        1.1    jruoho  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22        1.1    jruoho  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23        1.1    jruoho  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24        1.1    jruoho  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25        1.1    jruoho  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26        1.1    jruoho  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27        1.1    jruoho  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28        1.1    jruoho  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29        1.1    jruoho  * POSSIBILITY OF SUCH DAMAGE.
     30        1.1    jruoho  */
     31        1.1    jruoho 
     32        1.1    jruoho /*
     33        1.1    jruoho  * Copyright 2001, 2003 Wasabi Systems, Inc.
     34        1.1    jruoho  * All rights reserved.
     35        1.1    jruoho  *
     36        1.1    jruoho  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
     37        1.1    jruoho  *
     38        1.1    jruoho  * Redistribution and use in source and binary forms, with or without
     39        1.1    jruoho  * modification, are permitted provided that the following conditions
     40        1.1    jruoho  * are met:
     41        1.1    jruoho  * 1. Redistributions of source code must retain the above copyright
     42        1.1    jruoho  *    notice, this list of conditions and the following disclaimer.
     43        1.1    jruoho  * 2. Redistributions in binary form must reproduce the above copyright
     44        1.1    jruoho  *    notice, this list of conditions and the following disclaimer in the
     45        1.1    jruoho  *    documentation and/or other materials provided with the distribution.
     46        1.1    jruoho  * 3. All advertising materials mentioning features or use of this software
     47        1.1    jruoho  *    must display the following acknowledgement:
     48        1.1    jruoho  *	This product includes software developed for the NetBSD Project by
     49        1.1    jruoho  *	Wasabi Systems, Inc.
     50        1.1    jruoho  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
     51        1.1    jruoho  *    or promote products derived from this software without specific prior
     52        1.1    jruoho  *    written permission.
     53        1.1    jruoho  *
     54        1.1    jruoho  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
     55        1.1    jruoho  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     56        1.1    jruoho  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     57        1.1    jruoho  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
     58        1.1    jruoho  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     59        1.1    jruoho  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     60        1.1    jruoho  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     61        1.1    jruoho  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     62        1.1    jruoho  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     63        1.1    jruoho  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     64        1.1    jruoho  * POSSIBILITY OF SUCH DAMAGE.
     65        1.1    jruoho  */
     66        1.1    jruoho 
     67        1.1    jruoho #include <sys/cdefs.h>
     68  1.33.10.1  perseant __KERNEL_RCSID(0, "$NetBSD: acpi_util.c,v 1.33.10.1 2025/08/02 05:56:31 perseant Exp $");
     69        1.1    jruoho 
     70        1.1    jruoho #include <sys/param.h>
     71        1.9    bouyer #include <sys/kmem.h>
     72       1.12  jmcneill #include <sys/cpu.h>
     73        1.1    jruoho 
     74        1.1    jruoho #include <dev/acpi/acpireg.h>
     75        1.1    jruoho #include <dev/acpi/acpivar.h>
     76        1.9    bouyer #include <dev/acpi/acpi_intr.h>
     77        1.1    jruoho 
     78       1.26   thorpej #include <sys/device_calls.h>
     79       1.26   thorpej 
     80       1.14  jmcneill #include <machine/acpi_machdep.h>
     81       1.14  jmcneill 
     82        1.7    jruoho #define _COMPONENT	ACPI_BUS_COMPONENT
     83        1.7    jruoho ACPI_MODULE_NAME	("acpi_util")
     84        1.1    jruoho 
     85        1.7    jruoho static void		acpi_clean_node(ACPI_HANDLE, void *);
     86       1.29  jmcneill static ACPI_STATUS	acpi_dsd_property(ACPI_HANDLE, const char *,
     87       1.29  jmcneill 			    ACPI_BUFFER *, ACPI_OBJECT_TYPE, ACPI_OBJECT **);
     88        1.7    jruoho 
     89        1.7    jruoho static const char * const acpicpu_ids[] = {
     90        1.7    jruoho 	"ACPI0007",
     91        1.7    jruoho 	NULL
     92        1.7    jruoho };
     93        1.5    jruoho 
     94       1.28  jmcneill static const struct device_compatible_entry dtlink_compat_data[] = {
     95       1.28  jmcneill 	{ .compat = "PRP0001" },
     96       1.28  jmcneill 	DEVICE_COMPAT_EOL
     97       1.28  jmcneill };
     98       1.28  jmcneill 
     99        1.1    jruoho /*
    100       1.24   thorpej  * ACPI device handle support.
    101       1.24   thorpej  */
    102       1.24   thorpej 
    103       1.24   thorpej static device_call_t
    104       1.24   thorpej acpi_devhandle_lookup_device_call(devhandle_t handle, const char *name,
    105       1.24   thorpej     devhandle_t *call_handlep)
    106       1.24   thorpej {
    107       1.24   thorpej 	__link_set_decl(acpi_device_calls, struct device_call_descriptor);
    108       1.24   thorpej 	struct device_call_descriptor * const *desc;
    109       1.24   thorpej 
    110       1.24   thorpej 	__link_set_foreach(desc, acpi_device_calls) {
    111       1.24   thorpej 		if (strcmp((*desc)->name, name) == 0) {
    112       1.24   thorpej 			return (*desc)->call;
    113       1.24   thorpej 		}
    114       1.24   thorpej 	}
    115       1.24   thorpej 	return NULL;
    116       1.24   thorpej }
    117       1.24   thorpej 
    118       1.24   thorpej static const struct devhandle_impl acpi_devhandle_impl = {
    119       1.24   thorpej 	.type = DEVHANDLE_TYPE_ACPI,
    120       1.24   thorpej 	.lookup_device_call = acpi_devhandle_lookup_device_call,
    121       1.24   thorpej };
    122       1.24   thorpej 
    123       1.24   thorpej devhandle_t
    124       1.32   thorpej devhandle_from_acpi(devhandle_t super_handle, ACPI_HANDLE const hdl)
    125       1.24   thorpej {
    126       1.32   thorpej 	devhandle_type_t super_type = devhandle_type(super_handle);
    127       1.32   thorpej 	devhandle_t handle = { 0 };
    128       1.32   thorpej 
    129       1.32   thorpej 	if (super_type == DEVHANDLE_TYPE_ACPI) {
    130       1.32   thorpej 		handle.impl = super_handle.impl;
    131       1.32   thorpej 	} else {
    132       1.32   thorpej 		KASSERT(super_type == DEVHANDLE_TYPE_INVALID);
    133       1.32   thorpej 		handle.impl = &acpi_devhandle_impl;
    134       1.32   thorpej 	}
    135       1.32   thorpej 	handle.pointer = hdl;
    136       1.24   thorpej 
    137       1.24   thorpej 	return handle;
    138       1.24   thorpej }
    139       1.24   thorpej 
    140       1.24   thorpej ACPI_HANDLE
    141       1.24   thorpej devhandle_to_acpi(devhandle_t const handle)
    142       1.24   thorpej {
    143       1.24   thorpej 	KASSERT(devhandle_type(handle) == DEVHANDLE_TYPE_ACPI);
    144       1.24   thorpej 
    145       1.24   thorpej 	return handle.pointer;
    146       1.24   thorpej }
    147       1.24   thorpej 
    148       1.24   thorpej static int
    149       1.24   thorpej acpi_device_enumerate_children(device_t dev, devhandle_t call_handle, void *v)
    150       1.24   thorpej {
    151       1.24   thorpej 	struct device_enumerate_children_args *args = v;
    152       1.24   thorpej 	ACPI_HANDLE hdl = devhandle_to_acpi(call_handle);
    153       1.24   thorpej 	struct acpi_devnode *devnode, *ad;
    154       1.24   thorpej 
    155       1.24   thorpej 	devnode = acpi_match_node(hdl);
    156       1.24   thorpej 	KASSERT(devnode != NULL);
    157       1.24   thorpej 
    158       1.24   thorpej 	SIMPLEQ_FOREACH(ad, &devnode->ad_child_head, ad_child_list) {
    159       1.24   thorpej 		if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE ||
    160       1.24   thorpej 		    !acpi_device_present(ad->ad_handle)) {
    161       1.24   thorpej 			continue;
    162       1.24   thorpej 		}
    163       1.32   thorpej 		if (!args->callback(dev, devhandle_from_acpi(call_handle,
    164       1.32   thorpej 							     ad->ad_handle),
    165       1.24   thorpej 				    args->callback_arg)) {
    166       1.24   thorpej 			break;
    167       1.24   thorpej 		}
    168       1.24   thorpej 	}
    169       1.24   thorpej 
    170       1.24   thorpej 	return 0;
    171       1.24   thorpej }
    172       1.26   thorpej ACPI_DEVICE_CALL_REGISTER(DEVICE_ENUMERATE_CHILDREN_STR,
    173       1.24   thorpej 			  acpi_device_enumerate_children)
    174       1.24   thorpej 
    175       1.24   thorpej /*
    176        1.2    jruoho  * Evaluate an integer object.
    177        1.1    jruoho  */
    178        1.1    jruoho ACPI_STATUS
    179        1.1    jruoho acpi_eval_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER *valp)
    180        1.1    jruoho {
    181        1.1    jruoho 	ACPI_OBJECT obj;
    182        1.1    jruoho 	ACPI_BUFFER buf;
    183        1.1    jruoho 	ACPI_STATUS rv;
    184        1.1    jruoho 
    185        1.1    jruoho 	if (handle == NULL)
    186        1.1    jruoho 		handle = ACPI_ROOT_OBJECT;
    187        1.1    jruoho 
    188        1.6    gsutre 	(void)memset(&obj, 0, sizeof(obj));
    189        1.1    jruoho 	buf.Pointer = &obj;
    190        1.1    jruoho 	buf.Length = sizeof(obj);
    191        1.1    jruoho 
    192        1.1    jruoho 	rv = AcpiEvaluateObject(handle, path, NULL, &buf);
    193        1.1    jruoho 
    194        1.1    jruoho 	if (ACPI_FAILURE(rv))
    195        1.1    jruoho 		return rv;
    196        1.1    jruoho 
    197        1.6    gsutre 	/* Check that evaluation produced a return value. */
    198        1.6    gsutre 	if (buf.Length == 0)
    199        1.6    gsutre 		return AE_NULL_OBJECT;
    200        1.6    gsutre 
    201        1.1    jruoho 	if (obj.Type != ACPI_TYPE_INTEGER)
    202        1.1    jruoho 		return AE_TYPE;
    203        1.1    jruoho 
    204        1.1    jruoho 	if (valp != NULL)
    205        1.1    jruoho 		*valp = obj.Integer.Value;
    206        1.1    jruoho 
    207        1.1    jruoho 	return AE_OK;
    208        1.1    jruoho }
    209        1.1    jruoho 
    210        1.1    jruoho /*
    211        1.2    jruoho  * Evaluate an integer object with a single integer input parameter.
    212        1.1    jruoho  */
    213        1.1    jruoho ACPI_STATUS
    214        1.1    jruoho acpi_eval_set_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER val)
    215        1.1    jruoho {
    216        1.1    jruoho 	ACPI_OBJECT_LIST arg;
    217        1.1    jruoho 	ACPI_OBJECT obj;
    218        1.1    jruoho 
    219        1.1    jruoho 	if (handle == NULL)
    220        1.1    jruoho 		handle = ACPI_ROOT_OBJECT;
    221        1.1    jruoho 
    222        1.1    jruoho 	obj.Type = ACPI_TYPE_INTEGER;
    223        1.1    jruoho 	obj.Integer.Value = val;
    224        1.1    jruoho 
    225        1.1    jruoho 	arg.Count = 1;
    226        1.1    jruoho 	arg.Pointer = &obj;
    227        1.1    jruoho 
    228        1.1    jruoho 	return AcpiEvaluateObject(handle, path, &arg, NULL);
    229        1.1    jruoho }
    230        1.1    jruoho 
    231        1.1    jruoho /*
    232        1.2    jruoho  * Evaluate a (Unicode) string object.
    233        1.1    jruoho  */
    234        1.1    jruoho ACPI_STATUS
    235        1.1    jruoho acpi_eval_string(ACPI_HANDLE handle, const char *path, char **stringp)
    236        1.1    jruoho {
    237        1.1    jruoho 	ACPI_OBJECT *obj;
    238        1.1    jruoho 	ACPI_BUFFER buf;
    239        1.1    jruoho 	ACPI_STATUS rv;
    240        1.1    jruoho 
    241        1.1    jruoho 	rv = acpi_eval_struct(handle, path, &buf);
    242        1.1    jruoho 
    243        1.1    jruoho 	if (ACPI_FAILURE(rv))
    244        1.1    jruoho 		return rv;
    245        1.1    jruoho 
    246        1.1    jruoho 	obj = buf.Pointer;
    247        1.1    jruoho 
    248        1.1    jruoho 	if (obj->Type != ACPI_TYPE_STRING) {
    249        1.1    jruoho 		rv = AE_TYPE;
    250        1.1    jruoho 		goto out;
    251        1.1    jruoho 	}
    252        1.1    jruoho 
    253        1.1    jruoho 	if (obj->String.Length == 0) {
    254        1.1    jruoho 		rv = AE_BAD_DATA;
    255        1.1    jruoho 		goto out;
    256        1.1    jruoho 	}
    257        1.1    jruoho 
    258        1.1    jruoho 	*stringp = ACPI_ALLOCATE(obj->String.Length + 1);
    259        1.1    jruoho 
    260        1.1    jruoho 	if (*stringp == NULL) {
    261        1.1    jruoho 		rv = AE_NO_MEMORY;
    262        1.1    jruoho 		goto out;
    263        1.1    jruoho 	}
    264        1.1    jruoho 
    265        1.1    jruoho 	(void)memcpy(*stringp, obj->String.Pointer, obj->String.Length);
    266        1.1    jruoho 
    267        1.1    jruoho 	(*stringp)[obj->String.Length] = '\0';
    268        1.1    jruoho 
    269        1.1    jruoho out:
    270        1.1    jruoho 	ACPI_FREE(buf.Pointer);
    271        1.1    jruoho 
    272        1.1    jruoho 	return rv;
    273        1.1    jruoho }
    274        1.1    jruoho 
    275        1.1    jruoho /*
    276        1.2    jruoho  * Evaluate a structure. Caller must free buf.Pointer by ACPI_FREE().
    277        1.1    jruoho  */
    278        1.1    jruoho ACPI_STATUS
    279        1.1    jruoho acpi_eval_struct(ACPI_HANDLE handle, const char *path, ACPI_BUFFER *buf)
    280        1.1    jruoho {
    281        1.1    jruoho 
    282        1.1    jruoho 	if (handle == NULL)
    283        1.1    jruoho 		handle = ACPI_ROOT_OBJECT;
    284        1.1    jruoho 
    285        1.1    jruoho 	buf->Pointer = NULL;
    286        1.1    jruoho 	buf->Length = ACPI_ALLOCATE_LOCAL_BUFFER;
    287        1.1    jruoho 
    288        1.1    jruoho 	return AcpiEvaluateObject(handle, path, NULL, buf);
    289        1.1    jruoho }
    290        1.1    jruoho 
    291        1.1    jruoho /*
    292        1.2    jruoho  * Evaluate a reference handle from an element in a package.
    293        1.1    jruoho  */
    294        1.1    jruoho ACPI_STATUS
    295        1.1    jruoho acpi_eval_reference_handle(ACPI_OBJECT *elm, ACPI_HANDLE *handle)
    296        1.1    jruoho {
    297        1.1    jruoho 
    298        1.1    jruoho 	if (elm == NULL || handle == NULL)
    299        1.1    jruoho 		return AE_BAD_PARAMETER;
    300        1.1    jruoho 
    301        1.1    jruoho 	switch (elm->Type) {
    302        1.1    jruoho 
    303        1.1    jruoho 	case ACPI_TYPE_ANY:
    304        1.1    jruoho 	case ACPI_TYPE_LOCAL_REFERENCE:
    305        1.1    jruoho 
    306        1.1    jruoho 		if (elm->Reference.Handle == NULL)
    307        1.1    jruoho 			return AE_NULL_ENTRY;
    308        1.1    jruoho 
    309        1.1    jruoho 		*handle = elm->Reference.Handle;
    310        1.1    jruoho 
    311        1.1    jruoho 		return AE_OK;
    312        1.1    jruoho 
    313        1.1    jruoho 	case ACPI_TYPE_STRING:
    314        1.1    jruoho 		return AcpiGetHandle(NULL, elm->String.Pointer, handle);
    315        1.1    jruoho 
    316        1.1    jruoho 	default:
    317        1.1    jruoho 		return AE_TYPE;
    318        1.1    jruoho 	}
    319        1.1    jruoho }
    320        1.1    jruoho 
    321        1.1    jruoho /*
    322        1.2    jruoho  * Iterate over all objects in a package, and pass them all
    323        1.2    jruoho  * to a function. If the called function returns non-AE_OK,
    324        1.2    jruoho  * the iteration is stopped and that value is returned.
    325        1.1    jruoho  */
    326        1.1    jruoho ACPI_STATUS
    327        1.1    jruoho acpi_foreach_package_object(ACPI_OBJECT *pkg,
    328        1.1    jruoho     ACPI_STATUS (*func)(ACPI_OBJECT *, void *), void *arg)
    329        1.1    jruoho {
    330        1.1    jruoho 	ACPI_STATUS rv = AE_OK;
    331        1.1    jruoho 	uint32_t i;
    332        1.1    jruoho 
    333        1.4    jruoho 	if (pkg == NULL)
    334        1.1    jruoho 		return AE_BAD_PARAMETER;
    335        1.1    jruoho 
    336        1.4    jruoho 	if (pkg->Type != ACPI_TYPE_PACKAGE)
    337        1.4    jruoho 		return AE_TYPE;
    338        1.4    jruoho 
    339        1.1    jruoho 	for (i = 0; i < pkg->Package.Count; i++) {
    340        1.1    jruoho 
    341        1.1    jruoho 		rv = (*func)(&pkg->Package.Elements[i], arg);
    342        1.1    jruoho 
    343        1.1    jruoho 		if (ACPI_FAILURE(rv))
    344        1.1    jruoho 			break;
    345        1.1    jruoho 	}
    346        1.1    jruoho 
    347        1.1    jruoho 	return rv;
    348        1.1    jruoho }
    349        1.1    jruoho 
    350        1.1    jruoho /*
    351        1.2    jruoho  * Fetch data info the specified (empty) ACPI buffer.
    352        1.2    jruoho  * Caller must free buf.Pointer by ACPI_FREE().
    353        1.1    jruoho  */
    354        1.1    jruoho ACPI_STATUS
    355        1.1    jruoho acpi_get(ACPI_HANDLE handle, ACPI_BUFFER *buf,
    356        1.1    jruoho     ACPI_STATUS (*getit)(ACPI_HANDLE, ACPI_BUFFER *))
    357        1.1    jruoho {
    358        1.1    jruoho 
    359        1.1    jruoho 	buf->Pointer = NULL;
    360        1.1    jruoho 	buf->Length = ACPI_ALLOCATE_LOCAL_BUFFER;
    361        1.1    jruoho 
    362        1.1    jruoho 	return (*getit)(handle, buf);
    363        1.1    jruoho }
    364        1.1    jruoho 
    365        1.1    jruoho /*
    366        1.2    jruoho  * Return a complete pathname from a handle.
    367        1.1    jruoho  *
    368        1.2    jruoho  * Note that the function uses static data storage;
    369        1.2    jruoho  * if the data is needed for future use, it should be
    370        1.2    jruoho  * copied before any subsequent calls overwrite it.
    371        1.1    jruoho  */
    372        1.1    jruoho const char *
    373        1.1    jruoho acpi_name(ACPI_HANDLE handle)
    374        1.1    jruoho {
    375        1.1    jruoho 	static char name[80];
    376        1.1    jruoho 	ACPI_BUFFER buf;
    377        1.1    jruoho 	ACPI_STATUS rv;
    378        1.1    jruoho 
    379        1.4    jruoho 	if (handle == NULL)
    380        1.4    jruoho 		handle = ACPI_ROOT_OBJECT;
    381        1.4    jruoho 
    382        1.1    jruoho 	buf.Pointer = name;
    383        1.1    jruoho 	buf.Length = sizeof(name);
    384        1.1    jruoho 
    385        1.1    jruoho 	rv = AcpiGetName(handle, ACPI_FULL_PATHNAME, &buf);
    386        1.1    jruoho 
    387        1.1    jruoho 	if (ACPI_FAILURE(rv))
    388        1.1    jruoho 		return "UNKNOWN";
    389        1.1    jruoho 
    390        1.1    jruoho 	return name;
    391        1.1    jruoho }
    392        1.1    jruoho 
    393        1.1    jruoho /*
    394       1.23   thorpej  * Pack _HID and _CID ID strings into an OpenFirmware-style
    395       1.20   thorpej  * string list.
    396       1.20   thorpej  */
    397       1.20   thorpej char *
    398       1.33   thorpej acpi_pack_compat_list(struct acpi_devnode *ad, size_t *sizep)
    399       1.20   thorpej {
    400       1.33   thorpej 	ACPI_DEVICE_INFO *devinfo = ad->ad_devinfo;
    401       1.33   thorpej 
    402       1.20   thorpej 	KASSERT(sizep != NULL);
    403       1.20   thorpej 
    404       1.23   thorpej 	char *sl = NULL;
    405       1.23   thorpej 	size_t slsize = 0;
    406       1.20   thorpej 	uint32_t i;
    407       1.33   thorpej 	bool dtlink = false;
    408       1.33   thorpej 
    409       1.33   thorpej 	ACPI_BUFFER buf;
    410       1.33   thorpej 	ACPI_STATUS ret;
    411       1.33   thorpej 	ACPI_OBJECT *obj;
    412       1.33   thorpej 	char *compatible;
    413       1.33   thorpej 	int n;
    414       1.33   thorpej 
    415       1.33   thorpej 	buf.Pointer = NULL;
    416       1.33   thorpej 	buf.Length = ACPI_ALLOCATE_BUFFER;
    417       1.33   thorpej 
    418       1.33   thorpej 	if ((devinfo->Valid & ACPI_VALID_HID) != 0) {
    419       1.33   thorpej 		const char *cp = devinfo->HardwareId.String;
    420       1.33   thorpej 
    421       1.33   thorpej 		if (device_compatible_pmatch_strlist(cp, strlen(cp) + 1,
    422       1.33   thorpej 						     dtlink_compat_data)) {
    423       1.33   thorpej 			dtlink = true;
    424       1.33   thorpej 		} else {
    425       1.33   thorpej 			strlist_append(&sl, &slsize, cp);
    426       1.33   thorpej 		}
    427       1.33   thorpej 	}
    428       1.20   thorpej 
    429       1.33   thorpej 	if ((devinfo->Valid & ACPI_VALID_CID) != 0) {
    430       1.33   thorpej 		for (i = 0; i < devinfo->CompatibleIdList.Count; i++) {
    431       1.33   thorpej 			const char *cp =
    432       1.33   thorpej 			    devinfo->CompatibleIdList.Ids[i].String;
    433       1.33   thorpej 
    434       1.33   thorpej 			if (device_compatible_pmatch_strlist(cp, strlen(cp) + 1,
    435       1.33   thorpej 							dtlink_compat_data)) {
    436       1.33   thorpej 				dtlink = true;
    437       1.33   thorpej 			} else {
    438       1.33   thorpej 				strlist_append(&sl, &slsize, cp);
    439       1.33   thorpej 			}
    440       1.33   thorpej 		}
    441       1.20   thorpej 	}
    442       1.20   thorpej 
    443       1.33   thorpej 	if (dtlink) {
    444       1.33   thorpej 		ret = acpi_dsd_string(ad->ad_handle, "compatible",
    445       1.33   thorpej 		    &compatible);
    446       1.33   thorpej 		if (ACPI_SUCCESS(ret)) {
    447       1.33   thorpej 			strlist_append(&sl, &slsize, compatible);
    448       1.33   thorpej 			kmem_strfree(compatible);
    449       1.33   thorpej 			goto done;
    450       1.33   thorpej 		}
    451       1.33   thorpej 
    452       1.33   thorpej 		ret = acpi_dsd_property(ad->ad_handle, "compatible", &buf,
    453       1.33   thorpej 		    ACPI_TYPE_PACKAGE, &obj);
    454       1.33   thorpej 		if (ACPI_FAILURE(ret)) {
    455       1.33   thorpej 			goto done;
    456       1.33   thorpej 		}
    457       1.33   thorpej 		if (obj->Package.Count == 0) {
    458       1.33   thorpej 			goto done;
    459       1.33   thorpej 		}
    460       1.33   thorpej 		for (n = 0; n < obj->Package.Count; n++) {
    461       1.33   thorpej 			if (obj->Package.Elements[n].Type != ACPI_TYPE_STRING) {
    462       1.33   thorpej 				continue;
    463       1.33   thorpej 			}
    464       1.23   thorpej 			strlist_append(&sl, &slsize,
    465       1.33   thorpej 			    obj->Package.Elements[n].String.Pointer);
    466       1.20   thorpej 		}
    467       1.20   thorpej 	}
    468       1.20   thorpej 
    469       1.33   thorpej  done:
    470       1.33   thorpej 	if (buf.Pointer != NULL) {
    471       1.33   thorpej 		ACPI_FREE(buf.Pointer);
    472       1.33   thorpej 	}
    473       1.23   thorpej 	*sizep = slsize;
    474       1.23   thorpej 	return sl;
    475       1.23   thorpej }
    476       1.23   thorpej 
    477       1.23   thorpej /*
    478       1.23   thorpej  * The ACPI_PNP_DEVICE_ID type is somewhat inconvenient for us to
    479       1.23   thorpej  * use.  We'll need some temporary space to pack it into an array
    480       1.23   thorpej  * of C strings.  Room for 8 should be plenty, but we can allocate
    481       1.23   thorpej  * more if necessary.
    482       1.23   thorpej  */
    483       1.23   thorpej #define	ACPI_COMPATSTR_MAX	8
    484       1.23   thorpej 
    485       1.23   thorpej static const char **
    486       1.23   thorpej acpi_compatible_alloc_strarray(ACPI_PNP_DEVICE_ID *ids,
    487       1.23   thorpej     unsigned int count, const char **buf)
    488       1.23   thorpej {
    489       1.23   thorpej 	unsigned int i;
    490       1.23   thorpej 
    491       1.23   thorpej 	buf = kmem_tmpbuf_alloc(count * sizeof(const char *),
    492       1.23   thorpej 	    buf, ACPI_COMPATSTR_MAX * sizeof(const char *), KM_SLEEP);
    493       1.23   thorpej 	for (i = 0; i < count; i++) {
    494       1.23   thorpej 		buf[i] = ids[i].String;
    495       1.23   thorpej 	}
    496       1.23   thorpej 	return buf;
    497       1.23   thorpej }
    498       1.23   thorpej 
    499       1.23   thorpej static void
    500       1.23   thorpej acpi_compatible_free_strarray(const char **cpp, unsigned int count,
    501       1.23   thorpej     const char **buf)
    502       1.23   thorpej {
    503       1.23   thorpej 	kmem_tmpbuf_free(cpp, count * sizeof(const char *), buf);
    504       1.23   thorpej }
    505       1.23   thorpej 
    506       1.29  jmcneill static int
    507       1.29  jmcneill acpi_compatible_match_dtlink(const struct acpi_attach_args * const aa,
    508       1.29  jmcneill     const struct device_compatible_entry * const dce)
    509       1.29  jmcneill {
    510       1.29  jmcneill 	const char *strings[ACPI_COMPATSTR_MAX * sizeof(const char *)];
    511       1.29  jmcneill 	ACPI_HANDLE handle = aa->aa_node->ad_handle;
    512       1.29  jmcneill 	ACPI_BUFFER buf;
    513       1.29  jmcneill 	char *compatible;
    514       1.29  jmcneill 	ACPI_STATUS ret;
    515       1.29  jmcneill 	ACPI_OBJECT *obj;
    516       1.29  jmcneill 	int rv = 0, n;
    517       1.29  jmcneill 
    518       1.29  jmcneill 	buf.Pointer = NULL;
    519       1.29  jmcneill 	buf.Length = ACPI_ALLOCATE_BUFFER;
    520       1.29  jmcneill 
    521       1.29  jmcneill 	/* Match a single string _DSD value */
    522       1.29  jmcneill 	ret = acpi_dsd_string(handle, "compatible", &compatible);
    523       1.29  jmcneill 	if (ACPI_SUCCESS(ret)) {
    524       1.29  jmcneill 		strings[0] = compatible;
    525       1.29  jmcneill 		rv = device_compatible_pmatch(strings, 1, dce);
    526       1.29  jmcneill 		kmem_strfree(compatible);
    527       1.29  jmcneill 		goto done;
    528       1.29  jmcneill 	}
    529       1.29  jmcneill 
    530       1.29  jmcneill 	/* Match from a list of strings in a _DSD value */
    531       1.29  jmcneill 	ret = acpi_dsd_property(handle, "compatible", &buf,
    532       1.29  jmcneill 	    ACPI_TYPE_PACKAGE, &obj);
    533       1.29  jmcneill 	if (ACPI_FAILURE(ret)) {
    534       1.29  jmcneill 		goto done;
    535       1.29  jmcneill 	}
    536       1.29  jmcneill 	if (obj->Package.Count == 0) {
    537       1.29  jmcneill 		goto done;
    538       1.29  jmcneill 	}
    539       1.29  jmcneill 	for (n = 0; n < imin(obj->Package.Count, ACPI_COMPATSTR_MAX); n++) {
    540       1.29  jmcneill 		if (obj->Package.Elements[n].Type != ACPI_TYPE_STRING) {
    541       1.29  jmcneill 			goto done;
    542       1.29  jmcneill 		}
    543       1.29  jmcneill 		strings[n] = obj->Package.Elements[n].String.Pointer;
    544       1.29  jmcneill 	}
    545       1.29  jmcneill 	rv = device_compatible_pmatch(strings, n, dce);
    546       1.29  jmcneill 
    547       1.29  jmcneill done:
    548       1.29  jmcneill 	if (buf.Pointer != NULL) {
    549       1.29  jmcneill 		ACPI_FREE(buf.Pointer);
    550       1.29  jmcneill 	}
    551       1.29  jmcneill 	if (rv) {
    552       1.29  jmcneill 		rv = (rv - 1) + ACPI_MATCHSCORE_CID;
    553       1.29  jmcneill 		return imin(rv, ACPI_MATCHSCORE_CID_MAX);
    554       1.29  jmcneill 	}
    555       1.29  jmcneill 	return 0;
    556       1.29  jmcneill }
    557       1.29  jmcneill 
    558       1.23   thorpej /*
    559       1.23   thorpej  * acpi_compatible_match --
    560       1.23   thorpej  *
    561       1.23   thorpej  *	Returns a weighted match value, comparing the _HID and _CID
    562       1.25    andvar  *	IDs against a driver's compatibility data.
    563       1.23   thorpej  */
    564       1.23   thorpej int
    565       1.23   thorpej acpi_compatible_match(const struct acpi_attach_args * const aa,
    566       1.23   thorpej     const struct device_compatible_entry * const dce)
    567       1.23   thorpej {
    568       1.23   thorpej 	const char *strings[ACPI_COMPATSTR_MAX * sizeof(const char *)];
    569       1.23   thorpej 	const char **cpp;
    570       1.28  jmcneill 	bool dtlink = false;
    571       1.28  jmcneill 	int rv;
    572       1.23   thorpej 
    573       1.23   thorpej 	if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) {
    574       1.23   thorpej 		return 0;
    575       1.20   thorpej 	}
    576       1.20   thorpej 
    577       1.23   thorpej 	ACPI_DEVICE_INFO *ad = aa->aa_node->ad_devinfo;
    578       1.20   thorpej 
    579       1.20   thorpej 	if ((ad->Valid & ACPI_VALID_HID) != 0) {
    580       1.23   thorpej 		strings[0] = ad->HardwareId.String;
    581       1.23   thorpej 
    582       1.23   thorpej 		/* Matching _HID wins big. */
    583       1.23   thorpej 		if (device_compatible_pmatch(strings, 1, dce) != 0) {
    584       1.23   thorpej 			return ACPI_MATCHSCORE_HID;
    585       1.23   thorpej 		}
    586       1.28  jmcneill 
    587       1.28  jmcneill 		if (device_compatible_pmatch(strings, 1,
    588       1.28  jmcneill 					     dtlink_compat_data) != 0) {
    589       1.28  jmcneill 			dtlink = true;
    590       1.28  jmcneill 		}
    591       1.20   thorpej 	}
    592       1.20   thorpej 
    593       1.20   thorpej 	if ((ad->Valid & ACPI_VALID_CID) != 0) {
    594       1.23   thorpej 		cpp = acpi_compatible_alloc_strarray(ad->CompatibleIdList.Ids,
    595       1.23   thorpej 		    ad->CompatibleIdList.Count, strings);
    596       1.23   thorpej 
    597       1.23   thorpej 		rv = device_compatible_pmatch(cpp,
    598       1.23   thorpej 		    ad->CompatibleIdList.Count, dce);
    599       1.28  jmcneill 		if (!dtlink &&
    600       1.28  jmcneill 		    device_compatible_pmatch(cpp, ad->CompatibleIdList.Count,
    601       1.28  jmcneill 					     dtlink_compat_data) != 0) {
    602       1.28  jmcneill 			dtlink = true;
    603       1.28  jmcneill 		}
    604       1.23   thorpej 		acpi_compatible_free_strarray(cpp, ad->CompatibleIdList.Count,
    605       1.23   thorpej 		    strings);
    606       1.23   thorpej 		if (rv) {
    607       1.23   thorpej 			rv = (rv - 1) + ACPI_MATCHSCORE_CID;
    608       1.28  jmcneill 			return imin(rv, ACPI_MATCHSCORE_CID_MAX);
    609       1.28  jmcneill 		}
    610       1.28  jmcneill 	}
    611       1.28  jmcneill 
    612       1.28  jmcneill 	if (dtlink) {
    613       1.29  jmcneill 		return acpi_compatible_match_dtlink(aa, dce);
    614       1.20   thorpej 	}
    615       1.20   thorpej 
    616       1.23   thorpej 	return 0;
    617       1.23   thorpej }
    618       1.23   thorpej 
    619       1.23   thorpej /*
    620       1.23   thorpej  * acpi_compatible_lookup --
    621       1.23   thorpej  *
    622       1.23   thorpej  *	Returns the device_compatible_entry that matches the _HID
    623       1.23   thorpej  *	or _CID ID.
    624       1.23   thorpej  */
    625       1.23   thorpej const struct device_compatible_entry *
    626       1.23   thorpej acpi_compatible_lookup(const struct acpi_attach_args * const aa,
    627       1.23   thorpej     const struct device_compatible_entry * const dce)
    628       1.23   thorpej {
    629       1.23   thorpej 	const struct device_compatible_entry *rv = NULL;
    630       1.23   thorpej 	const char *strings[ACPI_COMPATSTR_MAX];
    631       1.23   thorpej 	const char **cpp;
    632       1.23   thorpej 
    633       1.23   thorpej 	if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) {
    634       1.23   thorpej 		return NULL;
    635       1.23   thorpej 	}
    636       1.20   thorpej 
    637       1.23   thorpej 	ACPI_DEVICE_INFO *ad = aa->aa_node->ad_devinfo;
    638       1.23   thorpej 
    639       1.23   thorpej 	if ((ad->Valid & ACPI_VALID_HID) != 0) {
    640       1.23   thorpej 		strings[0] = ad->HardwareId.String;
    641       1.23   thorpej 
    642       1.23   thorpej 		rv = device_compatible_plookup(strings, 1, dce);
    643       1.23   thorpej 		if (rv != NULL)
    644       1.23   thorpej 			return rv;
    645       1.23   thorpej 	}
    646       1.23   thorpej 
    647       1.23   thorpej 	if ((ad->Valid & ACPI_VALID_CID) != 0) {
    648       1.23   thorpej 		cpp = acpi_compatible_alloc_strarray(ad->CompatibleIdList.Ids,
    649       1.23   thorpej 		    ad->CompatibleIdList.Count, strings);
    650       1.23   thorpej 
    651       1.23   thorpej 		rv = device_compatible_plookup(cpp,
    652       1.23   thorpej 		    ad->CompatibleIdList.Count, dce);
    653       1.23   thorpej 		acpi_compatible_free_strarray(cpp, ad->CompatibleIdList.Count,
    654       1.23   thorpej 		    strings);
    655       1.23   thorpej 	}
    656       1.23   thorpej 
    657       1.23   thorpej 	return rv;
    658       1.20   thorpej }
    659       1.20   thorpej 
    660       1.20   thorpej /*
    661        1.2    jruoho  * Match given IDs against _HID and _CIDs.
    662        1.1    jruoho  */
    663        1.1    jruoho int
    664        1.1    jruoho acpi_match_hid(ACPI_DEVICE_INFO *ad, const char * const *ids)
    665        1.1    jruoho {
    666        1.1    jruoho 	uint32_t i, n;
    667        1.1    jruoho 	char *id;
    668        1.1    jruoho 
    669        1.1    jruoho 	while (*ids) {
    670        1.1    jruoho 
    671        1.1    jruoho 		if ((ad->Valid & ACPI_VALID_HID) != 0) {
    672        1.1    jruoho 
    673        1.1    jruoho 			if (pmatch(ad->HardwareId.String, *ids, NULL) == 2)
    674        1.1    jruoho 				return 1;
    675        1.1    jruoho 		}
    676        1.1    jruoho 
    677        1.1    jruoho 		if ((ad->Valid & ACPI_VALID_CID) != 0) {
    678        1.1    jruoho 
    679        1.1    jruoho 			n = ad->CompatibleIdList.Count;
    680        1.1    jruoho 
    681        1.1    jruoho 			for (i = 0; i < n; i++) {
    682        1.1    jruoho 
    683        1.1    jruoho 				id = ad->CompatibleIdList.Ids[i].String;
    684        1.1    jruoho 
    685        1.1    jruoho 				if (pmatch(id, *ids, NULL) == 2)
    686        1.1    jruoho 					return 1;
    687        1.1    jruoho 			}
    688        1.1    jruoho 		}
    689        1.1    jruoho 
    690        1.1    jruoho 		ids++;
    691        1.1    jruoho 	}
    692        1.1    jruoho 
    693        1.1    jruoho 	return 0;
    694        1.1    jruoho }
    695        1.1    jruoho 
    696        1.7    jruoho /*
    697       1.13  jmcneill  * Match a PCI-defined bass-class, sub-class, and programming interface
    698       1.13  jmcneill  * against a handle's _CLS object.
    699       1.13  jmcneill  */
    700       1.13  jmcneill int
    701       1.13  jmcneill acpi_match_class(ACPI_HANDLE handle, uint8_t pci_class, uint8_t pci_subclass,
    702       1.13  jmcneill     uint8_t pci_interface)
    703       1.13  jmcneill {
    704       1.13  jmcneill 	ACPI_BUFFER buf;
    705       1.13  jmcneill 	ACPI_OBJECT *obj;
    706       1.13  jmcneill 	ACPI_STATUS rv;
    707       1.13  jmcneill 	int match = 0;
    708       1.13  jmcneill 
    709       1.13  jmcneill 	rv = acpi_eval_struct(handle, "_CLS", &buf);
    710       1.13  jmcneill 	if (ACPI_FAILURE(rv))
    711       1.13  jmcneill 		goto done;
    712       1.13  jmcneill 
    713       1.13  jmcneill 	obj = buf.Pointer;
    714       1.13  jmcneill 	if (obj->Type != ACPI_TYPE_PACKAGE)
    715       1.13  jmcneill 		goto done;
    716       1.13  jmcneill 	if (obj->Package.Count != 3)
    717       1.13  jmcneill 		goto done;
    718       1.13  jmcneill 	if (obj->Package.Elements[0].Type != ACPI_TYPE_INTEGER ||
    719       1.13  jmcneill 	    obj->Package.Elements[1].Type != ACPI_TYPE_INTEGER ||
    720       1.13  jmcneill 	    obj->Package.Elements[2].Type != ACPI_TYPE_INTEGER)
    721       1.13  jmcneill 		goto done;
    722       1.13  jmcneill 
    723       1.13  jmcneill 	match = obj->Package.Elements[0].Integer.Value == pci_class &&
    724       1.13  jmcneill 		obj->Package.Elements[1].Integer.Value == pci_subclass &&
    725       1.13  jmcneill 		obj->Package.Elements[2].Integer.Value == pci_interface;
    726       1.13  jmcneill 
    727       1.13  jmcneill done:
    728       1.13  jmcneill 	if (buf.Pointer)
    729       1.13  jmcneill 		ACPI_FREE(buf.Pointer);
    730       1.23   thorpej 	return match ? ACPI_MATCHSCORE_CLS : 0;
    731       1.13  jmcneill }
    732       1.13  jmcneill 
    733       1.13  jmcneill /*
    734        1.8    jruoho  * Match a device node from a handle.
    735        1.8    jruoho  */
    736        1.8    jruoho struct acpi_devnode *
    737        1.8    jruoho acpi_match_node(ACPI_HANDLE handle)
    738        1.8    jruoho {
    739        1.8    jruoho 	struct acpi_devnode *ad;
    740        1.8    jruoho 	ACPI_STATUS rv;
    741        1.8    jruoho 
    742        1.8    jruoho 	if (handle == NULL)
    743        1.8    jruoho 		return NULL;
    744        1.8    jruoho 
    745        1.8    jruoho 	rv = AcpiGetData(handle, acpi_clean_node, (void **)&ad);
    746        1.8    jruoho 
    747        1.8    jruoho 	if (ACPI_FAILURE(rv))
    748        1.8    jruoho 		return NULL;
    749        1.8    jruoho 
    750        1.8    jruoho 	return ad;
    751        1.8    jruoho }
    752        1.8    jruoho 
    753        1.8    jruoho /*
    754        1.8    jruoho  * Permanently associate a device node with a handle.
    755        1.8    jruoho  */
    756        1.8    jruoho void
    757        1.8    jruoho acpi_match_node_init(struct acpi_devnode *ad)
    758        1.8    jruoho {
    759        1.8    jruoho 	(void)AcpiAttachData(ad->ad_handle, acpi_clean_node, ad);
    760        1.8    jruoho }
    761        1.8    jruoho 
    762        1.8    jruoho static void
    763        1.8    jruoho acpi_clean_node(ACPI_HANDLE handle, void *aux)
    764        1.8    jruoho {
    765        1.8    jruoho 	/* Nothing. */
    766        1.8    jruoho }
    767        1.8    jruoho 
    768        1.8    jruoho /*
    769        1.7    jruoho  * Match a handle from a cpu_info. Returns NULL on failure.
    770        1.7    jruoho  *
    771        1.8    jruoho  * Note that acpi_match_node() can be used if the device node
    772        1.8    jruoho  * is also required.
    773        1.7    jruoho  */
    774        1.7    jruoho ACPI_HANDLE
    775        1.7    jruoho acpi_match_cpu_info(struct cpu_info *ci)
    776        1.7    jruoho {
    777        1.7    jruoho 	struct acpi_softc *sc = acpi_softc;
    778        1.7    jruoho 	struct acpi_devnode *ad;
    779        1.7    jruoho 	ACPI_INTEGER val;
    780        1.7    jruoho 	ACPI_OBJECT *obj;
    781        1.7    jruoho 	ACPI_BUFFER buf;
    782        1.7    jruoho 	ACPI_HANDLE hdl;
    783        1.7    jruoho 	ACPI_STATUS rv;
    784        1.7    jruoho 
    785  1.33.10.1  perseant 	if (sc == NULL)
    786        1.7    jruoho 		return NULL;
    787        1.7    jruoho 
    788        1.7    jruoho 	/*
    789        1.7    jruoho 	 * CPUs are declared in the ACPI namespace
    790        1.7    jruoho 	 * either as a Processor() or as a Device().
    791        1.7    jruoho 	 * In both cases the MADT entries are used
    792        1.7    jruoho 	 * for the match (see ACPI 4.0, section 8.4).
    793        1.7    jruoho 	 */
    794       1.27     skrll 	SIMPLEQ_FOREACH(ad, &sc->sc_head, ad_list) {
    795        1.7    jruoho 
    796        1.7    jruoho 		hdl = ad->ad_handle;
    797        1.7    jruoho 
    798        1.7    jruoho 		switch (ad->ad_type) {
    799        1.7    jruoho 
    800        1.7    jruoho 		case ACPI_TYPE_DEVICE:
    801        1.7    jruoho 
    802        1.7    jruoho 			if (acpi_match_hid(ad->ad_devinfo, acpicpu_ids) == 0)
    803        1.7    jruoho 				break;
    804        1.7    jruoho 
    805        1.7    jruoho 			rv = acpi_eval_integer(hdl, "_UID", &val);
    806        1.7    jruoho 
    807        1.7    jruoho 			if (ACPI_SUCCESS(rv) && val == ci->ci_acpiid)
    808        1.7    jruoho 				return hdl;
    809        1.7    jruoho 
    810        1.7    jruoho 			break;
    811        1.7    jruoho 
    812        1.7    jruoho 		case ACPI_TYPE_PROCESSOR:
    813        1.7    jruoho 
    814        1.7    jruoho 			rv = acpi_eval_struct(hdl, NULL, &buf);
    815        1.7    jruoho 
    816        1.7    jruoho 			if (ACPI_FAILURE(rv))
    817        1.7    jruoho 				break;
    818        1.7    jruoho 
    819        1.7    jruoho 			obj = buf.Pointer;
    820        1.7    jruoho 
    821        1.7    jruoho 			if (obj->Processor.ProcId == ci->ci_acpiid) {
    822        1.7    jruoho 				ACPI_FREE(buf.Pointer);
    823        1.7    jruoho 				return hdl;
    824        1.7    jruoho 			}
    825        1.7    jruoho 
    826        1.7    jruoho 			ACPI_FREE(buf.Pointer);
    827        1.7    jruoho 			break;
    828        1.7    jruoho 		}
    829        1.7    jruoho 	}
    830        1.7    jruoho 
    831        1.7    jruoho 	return NULL;
    832        1.7    jruoho }
    833        1.7    jruoho 
    834        1.7    jruoho /*
    835        1.7    jruoho  * Match a CPU from a handle. Returns NULL on failure.
    836        1.7    jruoho  */
    837        1.7    jruoho struct cpu_info *
    838        1.7    jruoho acpi_match_cpu_handle(ACPI_HANDLE hdl)
    839        1.7    jruoho {
    840        1.7    jruoho 	struct cpu_info *ci;
    841        1.7    jruoho 	ACPI_DEVICE_INFO *di;
    842        1.7    jruoho 	CPU_INFO_ITERATOR cii;
    843        1.7    jruoho 	ACPI_INTEGER val;
    844        1.7    jruoho 	ACPI_OBJECT *obj;
    845        1.7    jruoho 	ACPI_BUFFER buf;
    846        1.7    jruoho 	ACPI_STATUS rv;
    847        1.7    jruoho 
    848        1.7    jruoho 	ci = NULL;
    849        1.7    jruoho 	di = NULL;
    850        1.7    jruoho 	buf.Pointer = NULL;
    851        1.7    jruoho 
    852        1.7    jruoho 	rv = AcpiGetObjectInfo(hdl, &di);
    853        1.7    jruoho 
    854        1.7    jruoho 	if (ACPI_FAILURE(rv))
    855        1.7    jruoho 		return NULL;
    856        1.7    jruoho 
    857        1.7    jruoho 	switch (di->Type) {
    858        1.7    jruoho 
    859        1.7    jruoho 	case ACPI_TYPE_DEVICE:
    860        1.7    jruoho 
    861        1.7    jruoho 		if (acpi_match_hid(di, acpicpu_ids) == 0)
    862        1.7    jruoho 			goto out;
    863        1.7    jruoho 
    864        1.7    jruoho 		rv = acpi_eval_integer(hdl, "_UID", &val);
    865        1.7    jruoho 
    866        1.7    jruoho 		if (ACPI_FAILURE(rv))
    867        1.7    jruoho 			goto out;
    868        1.7    jruoho 
    869        1.7    jruoho 		break;
    870        1.7    jruoho 
    871        1.7    jruoho 	case ACPI_TYPE_PROCESSOR:
    872        1.7    jruoho 
    873        1.7    jruoho 		rv = acpi_eval_struct(hdl, NULL, &buf);
    874        1.7    jruoho 
    875        1.7    jruoho 		if (ACPI_FAILURE(rv))
    876        1.7    jruoho 			goto out;
    877        1.7    jruoho 
    878        1.7    jruoho 		obj = buf.Pointer;
    879        1.7    jruoho 		val = obj->Processor.ProcId;
    880        1.7    jruoho 		break;
    881        1.7    jruoho 
    882        1.7    jruoho 	default:
    883        1.7    jruoho 		goto out;
    884        1.7    jruoho 	}
    885        1.7    jruoho 
    886        1.7    jruoho 	for (CPU_INFO_FOREACH(cii, ci)) {
    887        1.7    jruoho 
    888        1.7    jruoho 		if (ci->ci_acpiid == val)
    889        1.7    jruoho 			goto out;
    890        1.7    jruoho 	}
    891        1.7    jruoho 
    892        1.7    jruoho 	ci = NULL;
    893        1.7    jruoho 
    894        1.7    jruoho out:
    895        1.7    jruoho 	if (di != NULL)
    896        1.7    jruoho 		ACPI_FREE(di);
    897        1.7    jruoho 
    898        1.7    jruoho 	if (buf.Pointer != NULL)
    899        1.7    jruoho 		ACPI_FREE(buf.Pointer);
    900        1.7    jruoho 
    901        1.7    jruoho 	return ci;
    902        1.7    jruoho }
    903        1.9    bouyer 
    904        1.9    bouyer struct acpi_irq_handler {
    905        1.9    bouyer 	uint32_t aih_irq;
    906       1.14  jmcneill 	void *aih_ih;
    907        1.9    bouyer };
    908        1.9    bouyer 
    909        1.9    bouyer void *
    910       1.14  jmcneill acpi_intr_establish(device_t dev, uint64_t c, int ipl, bool mpsafe,
    911       1.14  jmcneill     int (*intr)(void *), void *iarg, const char *xname)
    912        1.9    bouyer {
    913        1.9    bouyer 	ACPI_STATUS rv;
    914       1.10    bouyer 	ACPI_HANDLE hdl = (void *)(uintptr_t)c;
    915        1.9    bouyer 	struct acpi_resources res;
    916        1.9    bouyer 	struct acpi_irq *irq;
    917       1.19  jmcneill 	void *aih = NULL;
    918        1.9    bouyer 
    919        1.9    bouyer 	rv = acpi_resource_parse(dev, hdl, "_CRS", &res,
    920        1.9    bouyer 	    &acpi_resource_parse_ops_quiet);
    921        1.9    bouyer 	if (ACPI_FAILURE(rv))
    922        1.9    bouyer 		return NULL;
    923        1.9    bouyer 
    924        1.9    bouyer 	irq = acpi_res_irq(&res, 0);
    925        1.9    bouyer 	if (irq == NULL)
    926        1.9    bouyer 		goto end;
    927        1.9    bouyer 
    928       1.19  jmcneill 	aih = acpi_intr_establish_irq(dev, irq, ipl, mpsafe,
    929       1.19  jmcneill 	    intr, iarg, xname);
    930       1.19  jmcneill 
    931       1.19  jmcneill end:
    932       1.19  jmcneill 	acpi_resource_cleanup(&res);
    933       1.19  jmcneill 
    934       1.19  jmcneill 	return aih;
    935       1.19  jmcneill }
    936       1.19  jmcneill 
    937       1.19  jmcneill void *
    938       1.19  jmcneill acpi_intr_establish_irq(device_t dev, struct acpi_irq *irq, int ipl,
    939       1.19  jmcneill     bool mpsafe, int (*intr)(void *), void *iarg, const char *xname)
    940       1.19  jmcneill {
    941       1.19  jmcneill 	struct acpi_irq_handler *aih;
    942       1.19  jmcneill 	void *ih;
    943       1.19  jmcneill 
    944       1.14  jmcneill 	const int type = (irq->ar_type == ACPI_EDGE_SENSITIVE) ? IST_EDGE : IST_LEVEL;
    945       1.14  jmcneill 	ih = acpi_md_intr_establish(irq->ar_irq, ipl, type, intr, iarg, mpsafe, xname);
    946       1.14  jmcneill 	if (ih == NULL)
    947       1.19  jmcneill 		return NULL;
    948        1.9    bouyer 
    949       1.14  jmcneill 	aih = kmem_alloc(sizeof(struct acpi_irq_handler), KM_SLEEP);
    950        1.9    bouyer 	aih->aih_irq = irq->ar_irq;
    951       1.14  jmcneill 	aih->aih_ih = ih;
    952       1.14  jmcneill 
    953        1.9    bouyer 	return aih;
    954        1.9    bouyer }
    955        1.9    bouyer 
    956        1.9    bouyer void
    957       1.16   thorpej acpi_intr_mask(void *c)
    958       1.16   thorpej {
    959       1.16   thorpej 	struct acpi_irq_handler * const aih = c;
    960       1.16   thorpej 
    961       1.16   thorpej 	acpi_md_intr_mask(aih->aih_ih);
    962       1.16   thorpej }
    963       1.16   thorpej 
    964       1.16   thorpej void
    965       1.16   thorpej acpi_intr_unmask(void *c)
    966       1.16   thorpej {
    967       1.16   thorpej 	struct acpi_irq_handler * const aih = c;
    968       1.16   thorpej 
    969       1.16   thorpej 	acpi_md_intr_unmask(aih->aih_ih);
    970       1.16   thorpej }
    971       1.16   thorpej 
    972       1.16   thorpej void
    973       1.14  jmcneill acpi_intr_disestablish(void *c)
    974        1.9    bouyer {
    975        1.9    bouyer 	struct acpi_irq_handler *aih = c;
    976        1.9    bouyer 
    977       1.14  jmcneill 	acpi_md_intr_disestablish(aih->aih_ih);
    978        1.9    bouyer 	kmem_free(aih, sizeof(struct acpi_irq_handler));
    979        1.9    bouyer }
    980        1.9    bouyer 
    981        1.9    bouyer const char *
    982        1.9    bouyer acpi_intr_string(void *c, char *buf, size_t size)
    983        1.9    bouyer {
    984        1.9    bouyer 	struct acpi_irq_handler *aih = c;
    985        1.9    bouyer 	intr_handle_t ih = aih->aih_irq;
    986        1.9    bouyer 
    987        1.9    bouyer 	return intr_string(ih, buf, size);
    988        1.9    bouyer }
    989       1.15  jmcneill 
    990       1.15  jmcneill /*
    991       1.20   thorpej  * Device-Specific Data (_DSD) support
    992       1.15  jmcneill  */
    993       1.15  jmcneill 
    994       1.15  jmcneill static UINT8 acpi_dsd_uuid[ACPI_UUID_LENGTH] = {
    995       1.15  jmcneill 	0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d,
    996       1.15  jmcneill 	0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01
    997       1.15  jmcneill };
    998       1.15  jmcneill 
    999       1.17  jmcneill static ACPI_STATUS
   1000       1.17  jmcneill acpi_dsd_property(ACPI_HANDLE handle, const char *prop, ACPI_BUFFER *pbuf, ACPI_OBJECT_TYPE type, ACPI_OBJECT **ret)
   1001       1.15  jmcneill {
   1002       1.15  jmcneill 	ACPI_OBJECT *obj, *uuid, *props, *pobj, *propkey, *propval;
   1003       1.15  jmcneill 	ACPI_STATUS rv;
   1004       1.15  jmcneill 	int n;
   1005       1.15  jmcneill 
   1006       1.17  jmcneill 	rv = AcpiEvaluateObjectTyped(handle, "_DSD", NULL, pbuf, ACPI_TYPE_PACKAGE);
   1007       1.15  jmcneill 	if (ACPI_FAILURE(rv))
   1008       1.15  jmcneill 		return rv;
   1009       1.15  jmcneill 
   1010       1.15  jmcneill 	props = NULL;
   1011       1.17  jmcneill 	obj = (ACPI_OBJECT *)pbuf->Pointer;
   1012       1.15  jmcneill 	for (n = 0; (n + 1) < obj->Package.Count; n += 2) {
   1013       1.15  jmcneill 		uuid = &obj->Package.Elements[n];
   1014       1.15  jmcneill 		if (uuid->Buffer.Length == ACPI_UUID_LENGTH &&
   1015       1.15  jmcneill 		    memcmp(uuid->Buffer.Pointer, acpi_dsd_uuid, ACPI_UUID_LENGTH) == 0) {
   1016       1.15  jmcneill 			props = &obj->Package.Elements[n + 1];
   1017       1.15  jmcneill 			break;
   1018       1.15  jmcneill 		}
   1019       1.15  jmcneill 	}
   1020       1.17  jmcneill 	if (props == NULL)
   1021       1.17  jmcneill 		return AE_NOT_FOUND;
   1022       1.15  jmcneill 
   1023       1.15  jmcneill 	for (n = 0; n < props->Package.Count; n++) {
   1024       1.15  jmcneill 		pobj = &props->Package.Elements[n];
   1025       1.15  jmcneill 		if (pobj->Type != ACPI_TYPE_PACKAGE || pobj->Package.Count != 2)
   1026       1.15  jmcneill 			continue;
   1027       1.15  jmcneill 		propkey = (ACPI_OBJECT *)&pobj->Package.Elements[0];
   1028       1.15  jmcneill 		propval = (ACPI_OBJECT *)&pobj->Package.Elements[1];
   1029       1.15  jmcneill 		if (propkey->Type != ACPI_TYPE_STRING)
   1030       1.15  jmcneill 			continue;
   1031       1.15  jmcneill 		if (strcmp(propkey->String.Pointer, prop) != 0)
   1032       1.15  jmcneill 			continue;
   1033       1.15  jmcneill 
   1034       1.17  jmcneill 		if (propval->Type != type) {
   1035       1.17  jmcneill 			return AE_TYPE;
   1036       1.15  jmcneill 		} else {
   1037       1.17  jmcneill 			*ret = propval;
   1038       1.17  jmcneill 			return AE_OK;
   1039       1.15  jmcneill 		}
   1040       1.15  jmcneill 		break;
   1041       1.15  jmcneill 	}
   1042       1.15  jmcneill 
   1043       1.17  jmcneill 	return AE_NOT_FOUND;
   1044       1.17  jmcneill }
   1045       1.17  jmcneill 
   1046       1.17  jmcneill ACPI_STATUS
   1047       1.17  jmcneill acpi_dsd_integer(ACPI_HANDLE handle, const char *prop, ACPI_INTEGER *val)
   1048       1.17  jmcneill {
   1049       1.17  jmcneill 	ACPI_OBJECT *propval;
   1050       1.17  jmcneill 	ACPI_STATUS rv;
   1051       1.17  jmcneill 	ACPI_BUFFER buf;
   1052       1.17  jmcneill 
   1053       1.17  jmcneill 	buf.Pointer = NULL;
   1054       1.17  jmcneill 	buf.Length = ACPI_ALLOCATE_BUFFER;
   1055       1.17  jmcneill 
   1056       1.17  jmcneill 	rv = acpi_dsd_property(handle, prop, &buf, ACPI_TYPE_INTEGER, &propval);
   1057       1.17  jmcneill 	if (ACPI_SUCCESS(rv))
   1058       1.17  jmcneill 		*val = propval->Integer.Value;
   1059       1.17  jmcneill 
   1060       1.18   mlelstv 	if (buf.Pointer != NULL)
   1061       1.18   mlelstv 		ACPI_FREE(buf.Pointer);
   1062       1.17  jmcneill 	return rv;
   1063       1.17  jmcneill }
   1064       1.17  jmcneill 
   1065       1.17  jmcneill ACPI_STATUS
   1066       1.17  jmcneill acpi_dsd_string(ACPI_HANDLE handle, const char *prop, char **val)
   1067       1.17  jmcneill {
   1068       1.17  jmcneill 	ACPI_OBJECT *propval;
   1069       1.17  jmcneill 	ACPI_STATUS rv;
   1070       1.17  jmcneill 	ACPI_BUFFER buf;
   1071       1.17  jmcneill 
   1072       1.17  jmcneill 	buf.Pointer = NULL;
   1073       1.17  jmcneill 	buf.Length = ACPI_ALLOCATE_BUFFER;
   1074       1.17  jmcneill 
   1075       1.17  jmcneill 	rv = acpi_dsd_property(handle, prop, &buf, ACPI_TYPE_STRING, &propval);
   1076       1.17  jmcneill 	if (ACPI_SUCCESS(rv))
   1077       1.17  jmcneill 		*val = kmem_strdup(propval->String.Pointer, KM_SLEEP);
   1078       1.17  jmcneill 
   1079       1.18   mlelstv 	if (buf.Pointer != NULL)
   1080       1.18   mlelstv 		ACPI_FREE(buf.Pointer);
   1081       1.15  jmcneill 	return rv;
   1082       1.15  jmcneill }
   1083       1.20   thorpej 
   1084       1.30  jmcneill ACPI_STATUS
   1085       1.30  jmcneill acpi_dsd_bool(ACPI_HANDLE handle, const char *prop, bool *val)
   1086       1.30  jmcneill {
   1087       1.30  jmcneill 	ACPI_STATUS rv;
   1088       1.30  jmcneill 	ACPI_INTEGER ival;
   1089       1.30  jmcneill 
   1090       1.30  jmcneill 	rv = acpi_dsd_integer(handle, prop, &ival);
   1091       1.30  jmcneill 	if (ACPI_SUCCESS(rv)) {
   1092       1.30  jmcneill 		*val = ival != 0;
   1093       1.30  jmcneill 	}
   1094       1.30  jmcneill 
   1095       1.30  jmcneill 	return rv;
   1096       1.30  jmcneill }
   1097       1.29  jmcneill 
   1098       1.29  jmcneill 
   1099       1.20   thorpej /*
   1100       1.20   thorpej  * Device Specific Method (_DSM) support
   1101       1.20   thorpej  */
   1102       1.20   thorpej 
   1103       1.20   thorpej ACPI_STATUS
   1104       1.20   thorpej acpi_dsm_typed(ACPI_HANDLE handle, uint8_t *uuid, ACPI_INTEGER rev,
   1105       1.20   thorpej     ACPI_INTEGER func, const ACPI_OBJECT *arg3, ACPI_OBJECT_TYPE return_type,
   1106       1.20   thorpej     ACPI_OBJECT **return_obj)
   1107       1.20   thorpej {
   1108       1.20   thorpej 	ACPI_OBJECT_LIST arg;
   1109       1.20   thorpej 	ACPI_OBJECT obj[4];
   1110       1.20   thorpej 	ACPI_BUFFER buf;
   1111       1.20   thorpej 	ACPI_STATUS status;
   1112       1.20   thorpej 
   1113       1.20   thorpej 	arg.Count = 4;
   1114       1.20   thorpej 	arg.Pointer = obj;
   1115       1.20   thorpej 
   1116       1.20   thorpej 	obj[0].Type = ACPI_TYPE_BUFFER;
   1117       1.20   thorpej 	obj[0].Buffer.Length = ACPI_UUID_LENGTH;
   1118       1.20   thorpej 	obj[0].Buffer.Pointer = uuid;
   1119       1.20   thorpej 
   1120       1.20   thorpej 	obj[1].Type = ACPI_TYPE_INTEGER;
   1121       1.20   thorpej 	obj[1].Integer.Value = rev;
   1122       1.20   thorpej 
   1123       1.20   thorpej 	obj[2].Type = ACPI_TYPE_INTEGER;
   1124       1.20   thorpej 	obj[2].Integer.Value = func;
   1125       1.20   thorpej 
   1126       1.20   thorpej 	if (arg3 != NULL) {
   1127       1.20   thorpej 		obj[3] = *arg3;
   1128       1.20   thorpej 	} else {
   1129       1.20   thorpej 		obj[3].Type = ACPI_TYPE_PACKAGE;
   1130       1.20   thorpej 		obj[3].Package.Count = 0;
   1131       1.20   thorpej 		obj[3].Package.Elements = NULL;
   1132       1.20   thorpej 	}
   1133       1.20   thorpej 
   1134       1.20   thorpej 	buf.Pointer = NULL;
   1135       1.20   thorpej 	buf.Length = ACPI_ALLOCATE_BUFFER;
   1136       1.20   thorpej 
   1137       1.20   thorpej 	if (return_obj == NULL && return_type == ACPI_TYPE_ANY) {
   1138       1.20   thorpej 		status = AcpiEvaluateObject(handle, "_DSM", &arg, NULL);
   1139       1.20   thorpej 	} else {
   1140       1.20   thorpej 		*return_obj = NULL;
   1141       1.20   thorpej 		status = AcpiEvaluateObjectTyped(handle, "_DSM", &arg, &buf,
   1142       1.20   thorpej 		    return_type);
   1143       1.20   thorpej 	}
   1144       1.20   thorpej 	if (ACPI_FAILURE(status)) {
   1145       1.20   thorpej 		return status;
   1146       1.20   thorpej 	}
   1147       1.20   thorpej 	if (return_obj != NULL) {
   1148       1.20   thorpej 		*return_obj = buf.Pointer;
   1149       1.20   thorpej 	} else if (buf.Pointer != NULL) {
   1150       1.20   thorpej 		ACPI_FREE(buf.Pointer);
   1151       1.20   thorpej 	}
   1152       1.20   thorpej 	return AE_OK;
   1153       1.20   thorpej }
   1154       1.20   thorpej 
   1155       1.20   thorpej ACPI_STATUS
   1156       1.20   thorpej acpi_dsm_integer(ACPI_HANDLE handle, uint8_t *uuid, ACPI_INTEGER rev,
   1157       1.20   thorpej     ACPI_INTEGER func, const ACPI_OBJECT *arg3, ACPI_INTEGER *ret)
   1158       1.20   thorpej {
   1159       1.20   thorpej 	ACPI_OBJECT *obj;
   1160       1.20   thorpej 	ACPI_STATUS status;
   1161       1.20   thorpej 
   1162       1.20   thorpej 	status = acpi_dsm_typed(handle, uuid, rev, func, arg3,
   1163       1.20   thorpej 	    ACPI_TYPE_INTEGER, &obj);
   1164       1.20   thorpej 	if (ACPI_FAILURE(status)) {
   1165       1.20   thorpej 		return status;
   1166       1.20   thorpej 	}
   1167       1.20   thorpej 
   1168       1.20   thorpej 	*ret = obj->Integer.Value;
   1169       1.20   thorpej 	ACPI_FREE(obj);
   1170       1.20   thorpej 
   1171       1.20   thorpej 	return AE_OK;
   1172       1.20   thorpej }
   1173       1.20   thorpej 
   1174       1.20   thorpej ACPI_STATUS
   1175       1.20   thorpej acpi_dsm(ACPI_HANDLE handle, uint8_t *uuid, ACPI_INTEGER rev,
   1176       1.20   thorpej     ACPI_INTEGER func, const ACPI_OBJECT *arg3, ACPI_OBJECT **return_obj)
   1177       1.20   thorpej {
   1178       1.20   thorpej 	return acpi_dsm_typed(handle, uuid, rev, func, arg3, ACPI_TYPE_ANY,
   1179       1.20   thorpej 	    return_obj);
   1180       1.20   thorpej }
   1181       1.21  jmcneill 
   1182       1.21  jmcneill ACPI_STATUS
   1183       1.31  jmcneill acpi_dsm_query(ACPI_HANDLE handle, uint8_t *uuid, ACPI_INTEGER rev,
   1184       1.31  jmcneill     ACPI_INTEGER *ret)
   1185       1.31  jmcneill {
   1186       1.31  jmcneill 	ACPI_OBJECT *obj;
   1187       1.31  jmcneill 	ACPI_STATUS status;
   1188       1.31  jmcneill 	uint8_t *data;
   1189       1.31  jmcneill 	u_int n;
   1190       1.31  jmcneill 
   1191       1.31  jmcneill 	status = acpi_dsm(handle, uuid, rev, 0, NULL, &obj);
   1192       1.31  jmcneill 	if (ACPI_FAILURE(status)) {
   1193       1.31  jmcneill 		return status;
   1194       1.31  jmcneill 	}
   1195       1.31  jmcneill 
   1196       1.31  jmcneill 	if (obj->Type == ACPI_TYPE_INTEGER) {
   1197       1.31  jmcneill 		*ret = obj->Integer.Value;
   1198       1.31  jmcneill 	} else if (obj->Type == ACPI_TYPE_BUFFER &&
   1199       1.31  jmcneill 		   obj->Buffer.Length <= 8) {
   1200       1.31  jmcneill 		*ret = 0;
   1201       1.31  jmcneill 		data = (uint8_t *)obj->Buffer.Pointer;
   1202       1.31  jmcneill 		for (n = 0; n < obj->Buffer.Length; n++) {
   1203       1.31  jmcneill 			*ret |= (uint64_t)data[n] << (n * 8);
   1204       1.31  jmcneill 		}
   1205       1.31  jmcneill 	} else {
   1206       1.31  jmcneill 		status = AE_TYPE;
   1207       1.31  jmcneill 	}
   1208       1.31  jmcneill 
   1209       1.31  jmcneill 	ACPI_FREE(obj);
   1210       1.31  jmcneill 
   1211       1.31  jmcneill 	return status;
   1212       1.31  jmcneill }
   1213       1.31  jmcneill 
   1214       1.31  jmcneill ACPI_STATUS
   1215  1.33.10.1  perseant acpi_claim_childdevs(device_t dev, struct acpi_devnode *devnode,
   1216  1.33.10.1  perseant     const char *method)
   1217       1.21  jmcneill {
   1218       1.21  jmcneill 	struct acpi_devnode *ad;
   1219       1.21  jmcneill 
   1220       1.21  jmcneill 	SIMPLEQ_FOREACH(ad, &devnode->ad_child_head, ad_child_list) {
   1221       1.21  jmcneill 		if (ad->ad_device != NULL)
   1222       1.21  jmcneill 			continue;
   1223  1.33.10.1  perseant 
   1224  1.33.10.1  perseant 		if (method != NULL) {
   1225  1.33.10.1  perseant 			ACPI_HANDLE h;
   1226  1.33.10.1  perseant 			ACPI_STATUS rv;
   1227  1.33.10.1  perseant 
   1228  1.33.10.1  perseant 			rv = AcpiGetHandle(ad->ad_handle, method, &h);
   1229  1.33.10.1  perseant 			if (ACPI_FAILURE(rv)) {
   1230  1.33.10.1  perseant 				continue;
   1231  1.33.10.1  perseant 			}
   1232  1.33.10.1  perseant 		}
   1233  1.33.10.1  perseant 
   1234       1.22  jmcneill 		aprint_debug_dev(dev, "claiming %s\n",
   1235       1.22  jmcneill 		    acpi_name(ad->ad_handle));
   1236       1.21  jmcneill 		ad->ad_device = dev;
   1237  1.33.10.1  perseant 		acpi_claim_childdevs(dev, ad, method);
   1238       1.21  jmcneill 	}
   1239       1.21  jmcneill 
   1240       1.21  jmcneill 	return AE_OK;
   1241       1.21  jmcneill }
   1242