1*84b6468dSjmcneill /* $NetBSD: acpi_util.c,v 1.35 2025/01/11 11:40:43 jmcneill Exp $ */ 20c88d0e4Sjruoho 30c88d0e4Sjruoho /*- 46451a97aSthorpej * Copyright (c) 2003, 2007, 2021 The NetBSD Foundation, Inc. 50c88d0e4Sjruoho * All rights reserved. 60c88d0e4Sjruoho * 70c88d0e4Sjruoho * This code is derived from software contributed to The NetBSD Foundation 80c88d0e4Sjruoho * by Charles M. Hannum of By Noon Software, Inc. 90c88d0e4Sjruoho * 100c88d0e4Sjruoho * Redistribution and use in source and binary forms, with or without 110c88d0e4Sjruoho * modification, are permitted provided that the following conditions 120c88d0e4Sjruoho * are met: 130c88d0e4Sjruoho * 1. Redistributions of source code must retain the above copyright 140c88d0e4Sjruoho * notice, this list of conditions and the following disclaimer. 150c88d0e4Sjruoho * 2. Redistributions in binary form must reproduce the above copyright 160c88d0e4Sjruoho * notice, this list of conditions and the following disclaimer in the 170c88d0e4Sjruoho * documentation and/or other materials provided with the distribution. 180c88d0e4Sjruoho * 190c88d0e4Sjruoho * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 200c88d0e4Sjruoho * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 210c88d0e4Sjruoho * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 220c88d0e4Sjruoho * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 230c88d0e4Sjruoho * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 240c88d0e4Sjruoho * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 250c88d0e4Sjruoho * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 260c88d0e4Sjruoho * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 270c88d0e4Sjruoho * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 280c88d0e4Sjruoho * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 290c88d0e4Sjruoho * POSSIBILITY OF SUCH DAMAGE. 300c88d0e4Sjruoho */ 310c88d0e4Sjruoho 320c88d0e4Sjruoho /* 330c88d0e4Sjruoho * Copyright 2001, 2003 Wasabi Systems, Inc. 340c88d0e4Sjruoho * All rights reserved. 350c88d0e4Sjruoho * 360c88d0e4Sjruoho * Written by Jason R. Thorpe for Wasabi Systems, Inc. 370c88d0e4Sjruoho * 380c88d0e4Sjruoho * Redistribution and use in source and binary forms, with or without 390c88d0e4Sjruoho * modification, are permitted provided that the following conditions 400c88d0e4Sjruoho * are met: 410c88d0e4Sjruoho * 1. Redistributions of source code must retain the above copyright 420c88d0e4Sjruoho * notice, this list of conditions and the following disclaimer. 430c88d0e4Sjruoho * 2. Redistributions in binary form must reproduce the above copyright 440c88d0e4Sjruoho * notice, this list of conditions and the following disclaimer in the 450c88d0e4Sjruoho * documentation and/or other materials provided with the distribution. 460c88d0e4Sjruoho * 3. All advertising materials mentioning features or use of this software 470c88d0e4Sjruoho * must display the following acknowledgement: 480c88d0e4Sjruoho * This product includes software developed for the NetBSD Project by 490c88d0e4Sjruoho * Wasabi Systems, Inc. 500c88d0e4Sjruoho * 4. The name of Wasabi Systems, Inc. may not be used to endorse 510c88d0e4Sjruoho * or promote products derived from this software without specific prior 520c88d0e4Sjruoho * written permission. 530c88d0e4Sjruoho * 540c88d0e4Sjruoho * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 550c88d0e4Sjruoho * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 560c88d0e4Sjruoho * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 570c88d0e4Sjruoho * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 580c88d0e4Sjruoho * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 590c88d0e4Sjruoho * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 600c88d0e4Sjruoho * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 610c88d0e4Sjruoho * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 620c88d0e4Sjruoho * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 630c88d0e4Sjruoho * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 640c88d0e4Sjruoho * POSSIBILITY OF SUCH DAMAGE. 650c88d0e4Sjruoho */ 660c88d0e4Sjruoho 670c88d0e4Sjruoho #include <sys/cdefs.h> 68*84b6468dSjmcneill __KERNEL_RCSID(0, "$NetBSD: acpi_util.c,v 1.35 2025/01/11 11:40:43 jmcneill Exp $"); 690c88d0e4Sjruoho 700c88d0e4Sjruoho #include <sys/param.h> 71db8cbfd3Sbouyer #include <sys/kmem.h> 7253c2e439Sjmcneill #include <sys/cpu.h> 730c88d0e4Sjruoho 740c88d0e4Sjruoho #include <dev/acpi/acpireg.h> 750c88d0e4Sjruoho #include <dev/acpi/acpivar.h> 76db8cbfd3Sbouyer #include <dev/acpi/acpi_intr.h> 770c88d0e4Sjruoho 784ecce2b2Sthorpej #include <sys/device_calls.h> 794ecce2b2Sthorpej 80f62244a8Sjmcneill #include <machine/acpi_machdep.h> 81f62244a8Sjmcneill 820c88d0e4Sjruoho #define _COMPONENT ACPI_BUS_COMPONENT 830c88d0e4Sjruoho ACPI_MODULE_NAME ("acpi_util") 840c88d0e4Sjruoho 855e449c62Sjruoho static void acpi_clean_node(ACPI_HANDLE, void *); 863da31819Sjmcneill static ACPI_STATUS acpi_dsd_property(ACPI_HANDLE, const char *, 873da31819Sjmcneill ACPI_BUFFER *, ACPI_OBJECT_TYPE, ACPI_OBJECT **); 885e449c62Sjruoho 890f056e49Sjruoho static const char * const acpicpu_ids[] = { 900f056e49Sjruoho "ACPI0007", 910f056e49Sjruoho NULL 920f056e49Sjruoho }; 930f056e49Sjruoho 941ff08d8eSjmcneill static const struct device_compatible_entry dtlink_compat_data[] = { 951ff08d8eSjmcneill { .compat = "PRP0001" }, 961ff08d8eSjmcneill DEVICE_COMPAT_EOL 971ff08d8eSjmcneill }; 981ff08d8eSjmcneill 990c88d0e4Sjruoho /* 100cae7202cSthorpej * ACPI device handle support. 101cae7202cSthorpej */ 102cae7202cSthorpej 103cae7202cSthorpej static device_call_t 104cae7202cSthorpej acpi_devhandle_lookup_device_call(devhandle_t handle, const char *name, 105cae7202cSthorpej devhandle_t *call_handlep) 106cae7202cSthorpej { 107cae7202cSthorpej __link_set_decl(acpi_device_calls, struct device_call_descriptor); 108cae7202cSthorpej struct device_call_descriptor * const *desc; 109cae7202cSthorpej 110cae7202cSthorpej __link_set_foreach(desc, acpi_device_calls) { 111cae7202cSthorpej if (strcmp((*desc)->name, name) == 0) { 112cae7202cSthorpej return (*desc)->call; 113cae7202cSthorpej } 114cae7202cSthorpej } 115cae7202cSthorpej return NULL; 116cae7202cSthorpej } 117cae7202cSthorpej 118cae7202cSthorpej static const struct devhandle_impl acpi_devhandle_impl = { 119cae7202cSthorpej .type = DEVHANDLE_TYPE_ACPI, 120cae7202cSthorpej .lookup_device_call = acpi_devhandle_lookup_device_call, 121cae7202cSthorpej }; 122cae7202cSthorpej 123cae7202cSthorpej devhandle_t 1243944ff70Sthorpej devhandle_from_acpi(devhandle_t super_handle, ACPI_HANDLE const hdl) 125cae7202cSthorpej { 1263944ff70Sthorpej devhandle_type_t super_type = devhandle_type(super_handle); 1273944ff70Sthorpej devhandle_t handle = { 0 }; 1283944ff70Sthorpej 1293944ff70Sthorpej if (super_type == DEVHANDLE_TYPE_ACPI) { 1303944ff70Sthorpej handle.impl = super_handle.impl; 1313944ff70Sthorpej } else { 1323944ff70Sthorpej KASSERT(super_type == DEVHANDLE_TYPE_INVALID); 1333944ff70Sthorpej handle.impl = &acpi_devhandle_impl; 1343944ff70Sthorpej } 1353944ff70Sthorpej handle.pointer = hdl; 136cae7202cSthorpej 137cae7202cSthorpej return handle; 138cae7202cSthorpej } 139cae7202cSthorpej 140cae7202cSthorpej ACPI_HANDLE 141cae7202cSthorpej devhandle_to_acpi(devhandle_t const handle) 142cae7202cSthorpej { 143cae7202cSthorpej KASSERT(devhandle_type(handle) == DEVHANDLE_TYPE_ACPI); 144cae7202cSthorpej 145cae7202cSthorpej return handle.pointer; 146cae7202cSthorpej } 147cae7202cSthorpej 148cae7202cSthorpej static int 149cae7202cSthorpej acpi_device_enumerate_children(device_t dev, devhandle_t call_handle, void *v) 150cae7202cSthorpej { 151cae7202cSthorpej struct device_enumerate_children_args *args = v; 152cae7202cSthorpej ACPI_HANDLE hdl = devhandle_to_acpi(call_handle); 153cae7202cSthorpej struct acpi_devnode *devnode, *ad; 154cae7202cSthorpej 155cae7202cSthorpej devnode = acpi_match_node(hdl); 156cae7202cSthorpej KASSERT(devnode != NULL); 157cae7202cSthorpej 158cae7202cSthorpej SIMPLEQ_FOREACH(ad, &devnode->ad_child_head, ad_child_list) { 159cae7202cSthorpej if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE || 160cae7202cSthorpej !acpi_device_present(ad->ad_handle)) { 161cae7202cSthorpej continue; 162cae7202cSthorpej } 1633944ff70Sthorpej if (!args->callback(dev, devhandle_from_acpi(call_handle, 1643944ff70Sthorpej ad->ad_handle), 165cae7202cSthorpej args->callback_arg)) { 166cae7202cSthorpej break; 167cae7202cSthorpej } 168cae7202cSthorpej } 169cae7202cSthorpej 170cae7202cSthorpej return 0; 171cae7202cSthorpej } 1724ecce2b2Sthorpej ACPI_DEVICE_CALL_REGISTER(DEVICE_ENUMERATE_CHILDREN_STR, 173cae7202cSthorpej acpi_device_enumerate_children) 174cae7202cSthorpej 175cae7202cSthorpej /* 1760c88d0e4Sjruoho * Evaluate an integer object. 1770c88d0e4Sjruoho */ 1780c88d0e4Sjruoho ACPI_STATUS 1790c88d0e4Sjruoho acpi_eval_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER *valp) 1800c88d0e4Sjruoho { 1810c88d0e4Sjruoho ACPI_OBJECT obj; 1820c88d0e4Sjruoho ACPI_BUFFER buf; 1830c88d0e4Sjruoho ACPI_STATUS rv; 1840c88d0e4Sjruoho 1850c88d0e4Sjruoho if (handle == NULL) 1860c88d0e4Sjruoho handle = ACPI_ROOT_OBJECT; 1870c88d0e4Sjruoho 188678179dfSgsutre (void)memset(&obj, 0, sizeof(obj)); 1890c88d0e4Sjruoho buf.Pointer = &obj; 1900c88d0e4Sjruoho buf.Length = sizeof(obj); 1910c88d0e4Sjruoho 1920c88d0e4Sjruoho rv = AcpiEvaluateObject(handle, path, NULL, &buf); 1930c88d0e4Sjruoho 1940c88d0e4Sjruoho if (ACPI_FAILURE(rv)) 1950c88d0e4Sjruoho return rv; 1960c88d0e4Sjruoho 197678179dfSgsutre /* Check that evaluation produced a return value. */ 198678179dfSgsutre if (buf.Length == 0) 199678179dfSgsutre return AE_NULL_OBJECT; 200678179dfSgsutre 2010c88d0e4Sjruoho if (obj.Type != ACPI_TYPE_INTEGER) 2020c88d0e4Sjruoho return AE_TYPE; 2030c88d0e4Sjruoho 2040c88d0e4Sjruoho if (valp != NULL) 2050c88d0e4Sjruoho *valp = obj.Integer.Value; 2060c88d0e4Sjruoho 2070c88d0e4Sjruoho return AE_OK; 2080c88d0e4Sjruoho } 2090c88d0e4Sjruoho 2100c88d0e4Sjruoho /* 2110c88d0e4Sjruoho * Evaluate an integer object with a single integer input parameter. 2120c88d0e4Sjruoho */ 2130c88d0e4Sjruoho ACPI_STATUS 2140c88d0e4Sjruoho acpi_eval_set_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER val) 2150c88d0e4Sjruoho { 2160c88d0e4Sjruoho ACPI_OBJECT_LIST arg; 2170c88d0e4Sjruoho ACPI_OBJECT obj; 2180c88d0e4Sjruoho 2190c88d0e4Sjruoho if (handle == NULL) 2200c88d0e4Sjruoho handle = ACPI_ROOT_OBJECT; 2210c88d0e4Sjruoho 2220c88d0e4Sjruoho obj.Type = ACPI_TYPE_INTEGER; 2230c88d0e4Sjruoho obj.Integer.Value = val; 2240c88d0e4Sjruoho 2250c88d0e4Sjruoho arg.Count = 1; 2260c88d0e4Sjruoho arg.Pointer = &obj; 2270c88d0e4Sjruoho 2280c88d0e4Sjruoho return AcpiEvaluateObject(handle, path, &arg, NULL); 2290c88d0e4Sjruoho } 2300c88d0e4Sjruoho 2310c88d0e4Sjruoho /* 2320c88d0e4Sjruoho * Evaluate a (Unicode) string object. 2330c88d0e4Sjruoho */ 2340c88d0e4Sjruoho ACPI_STATUS 2350c88d0e4Sjruoho acpi_eval_string(ACPI_HANDLE handle, const char *path, char **stringp) 2360c88d0e4Sjruoho { 2370c88d0e4Sjruoho ACPI_OBJECT *obj; 2380c88d0e4Sjruoho ACPI_BUFFER buf; 2390c88d0e4Sjruoho ACPI_STATUS rv; 2400c88d0e4Sjruoho 2410c88d0e4Sjruoho rv = acpi_eval_struct(handle, path, &buf); 2420c88d0e4Sjruoho 2430c88d0e4Sjruoho if (ACPI_FAILURE(rv)) 2440c88d0e4Sjruoho return rv; 2450c88d0e4Sjruoho 2460c88d0e4Sjruoho obj = buf.Pointer; 2470c88d0e4Sjruoho 2480c88d0e4Sjruoho if (obj->Type != ACPI_TYPE_STRING) { 2490c88d0e4Sjruoho rv = AE_TYPE; 2500c88d0e4Sjruoho goto out; 2510c88d0e4Sjruoho } 2520c88d0e4Sjruoho 2530c88d0e4Sjruoho if (obj->String.Length == 0) { 2540c88d0e4Sjruoho rv = AE_BAD_DATA; 2550c88d0e4Sjruoho goto out; 2560c88d0e4Sjruoho } 2570c88d0e4Sjruoho 2580c88d0e4Sjruoho *stringp = ACPI_ALLOCATE(obj->String.Length + 1); 2590c88d0e4Sjruoho 2600c88d0e4Sjruoho if (*stringp == NULL) { 2610c88d0e4Sjruoho rv = AE_NO_MEMORY; 2620c88d0e4Sjruoho goto out; 2630c88d0e4Sjruoho } 2640c88d0e4Sjruoho 2650c88d0e4Sjruoho (void)memcpy(*stringp, obj->String.Pointer, obj->String.Length); 2660c88d0e4Sjruoho 2670c88d0e4Sjruoho (*stringp)[obj->String.Length] = '\0'; 2680c88d0e4Sjruoho 2690c88d0e4Sjruoho out: 2700c88d0e4Sjruoho ACPI_FREE(buf.Pointer); 2710c88d0e4Sjruoho 2720c88d0e4Sjruoho return rv; 2730c88d0e4Sjruoho } 2740c88d0e4Sjruoho 2750c88d0e4Sjruoho /* 276d6afaa44Sjruoho * Evaluate a structure. Caller must free buf.Pointer by ACPI_FREE(). 2770c88d0e4Sjruoho */ 2780c88d0e4Sjruoho ACPI_STATUS 2790c88d0e4Sjruoho acpi_eval_struct(ACPI_HANDLE handle, const char *path, ACPI_BUFFER *buf) 2800c88d0e4Sjruoho { 2810c88d0e4Sjruoho 2820c88d0e4Sjruoho if (handle == NULL) 2830c88d0e4Sjruoho handle = ACPI_ROOT_OBJECT; 2840c88d0e4Sjruoho 2850c88d0e4Sjruoho buf->Pointer = NULL; 2860c88d0e4Sjruoho buf->Length = ACPI_ALLOCATE_LOCAL_BUFFER; 2870c88d0e4Sjruoho 2880c88d0e4Sjruoho return AcpiEvaluateObject(handle, path, NULL, buf); 2890c88d0e4Sjruoho } 2900c88d0e4Sjruoho 2910c88d0e4Sjruoho /* 2920c88d0e4Sjruoho * Evaluate a reference handle from an element in a package. 2930c88d0e4Sjruoho */ 2940c88d0e4Sjruoho ACPI_STATUS 2950c88d0e4Sjruoho acpi_eval_reference_handle(ACPI_OBJECT *elm, ACPI_HANDLE *handle) 2960c88d0e4Sjruoho { 2970c88d0e4Sjruoho 2980c88d0e4Sjruoho if (elm == NULL || handle == NULL) 2990c88d0e4Sjruoho return AE_BAD_PARAMETER; 3000c88d0e4Sjruoho 3010c88d0e4Sjruoho switch (elm->Type) { 3020c88d0e4Sjruoho 3030c88d0e4Sjruoho case ACPI_TYPE_ANY: 3040c88d0e4Sjruoho case ACPI_TYPE_LOCAL_REFERENCE: 3050c88d0e4Sjruoho 3060c88d0e4Sjruoho if (elm->Reference.Handle == NULL) 3070c88d0e4Sjruoho return AE_NULL_ENTRY; 3080c88d0e4Sjruoho 3090c88d0e4Sjruoho *handle = elm->Reference.Handle; 3100c88d0e4Sjruoho 3110c88d0e4Sjruoho return AE_OK; 3120c88d0e4Sjruoho 3130c88d0e4Sjruoho case ACPI_TYPE_STRING: 3140c88d0e4Sjruoho return AcpiGetHandle(NULL, elm->String.Pointer, handle); 3150c88d0e4Sjruoho 3160c88d0e4Sjruoho default: 3170c88d0e4Sjruoho return AE_TYPE; 3180c88d0e4Sjruoho } 3190c88d0e4Sjruoho } 3200c88d0e4Sjruoho 3210c88d0e4Sjruoho /* 3220c88d0e4Sjruoho * Iterate over all objects in a package, and pass them all 3230c88d0e4Sjruoho * to a function. If the called function returns non-AE_OK, 3240c88d0e4Sjruoho * the iteration is stopped and that value is returned. 3250c88d0e4Sjruoho */ 3260c88d0e4Sjruoho ACPI_STATUS 3270c88d0e4Sjruoho acpi_foreach_package_object(ACPI_OBJECT *pkg, 3280c88d0e4Sjruoho ACPI_STATUS (*func)(ACPI_OBJECT *, void *), void *arg) 3290c88d0e4Sjruoho { 3300c88d0e4Sjruoho ACPI_STATUS rv = AE_OK; 3310c88d0e4Sjruoho uint32_t i; 3320c88d0e4Sjruoho 333e7c11148Sjruoho if (pkg == NULL) 3340c88d0e4Sjruoho return AE_BAD_PARAMETER; 3350c88d0e4Sjruoho 336e7c11148Sjruoho if (pkg->Type != ACPI_TYPE_PACKAGE) 337e7c11148Sjruoho return AE_TYPE; 338e7c11148Sjruoho 3390c88d0e4Sjruoho for (i = 0; i < pkg->Package.Count; i++) { 3400c88d0e4Sjruoho 3410c88d0e4Sjruoho rv = (*func)(&pkg->Package.Elements[i], arg); 3420c88d0e4Sjruoho 3430c88d0e4Sjruoho if (ACPI_FAILURE(rv)) 3440c88d0e4Sjruoho break; 3450c88d0e4Sjruoho } 3460c88d0e4Sjruoho 3470c88d0e4Sjruoho return rv; 3480c88d0e4Sjruoho } 3490c88d0e4Sjruoho 3500c88d0e4Sjruoho /* 3510c88d0e4Sjruoho * Fetch data info the specified (empty) ACPI buffer. 3520c88d0e4Sjruoho * Caller must free buf.Pointer by ACPI_FREE(). 3530c88d0e4Sjruoho */ 3540c88d0e4Sjruoho ACPI_STATUS 3550c88d0e4Sjruoho acpi_get(ACPI_HANDLE handle, ACPI_BUFFER *buf, 3560c88d0e4Sjruoho ACPI_STATUS (*getit)(ACPI_HANDLE, ACPI_BUFFER *)) 3570c88d0e4Sjruoho { 3580c88d0e4Sjruoho 3590c88d0e4Sjruoho buf->Pointer = NULL; 3600c88d0e4Sjruoho buf->Length = ACPI_ALLOCATE_LOCAL_BUFFER; 3610c88d0e4Sjruoho 3620c88d0e4Sjruoho return (*getit)(handle, buf); 3630c88d0e4Sjruoho } 3640c88d0e4Sjruoho 3650c88d0e4Sjruoho /* 3660c88d0e4Sjruoho * Return a complete pathname from a handle. 3670c88d0e4Sjruoho * 3680c88d0e4Sjruoho * Note that the function uses static data storage; 3690c88d0e4Sjruoho * if the data is needed for future use, it should be 3700c88d0e4Sjruoho * copied before any subsequent calls overwrite it. 3710c88d0e4Sjruoho */ 3720c88d0e4Sjruoho const char * 3730c88d0e4Sjruoho acpi_name(ACPI_HANDLE handle) 3740c88d0e4Sjruoho { 3750c88d0e4Sjruoho static char name[80]; 3760c88d0e4Sjruoho ACPI_BUFFER buf; 3770c88d0e4Sjruoho ACPI_STATUS rv; 3780c88d0e4Sjruoho 379e7c11148Sjruoho if (handle == NULL) 380e7c11148Sjruoho handle = ACPI_ROOT_OBJECT; 381e7c11148Sjruoho 3820c88d0e4Sjruoho buf.Pointer = name; 3830c88d0e4Sjruoho buf.Length = sizeof(name); 3840c88d0e4Sjruoho 3850c88d0e4Sjruoho rv = AcpiGetName(handle, ACPI_FULL_PATHNAME, &buf); 3860c88d0e4Sjruoho 3870c88d0e4Sjruoho if (ACPI_FAILURE(rv)) 3880c88d0e4Sjruoho return "UNKNOWN"; 3890c88d0e4Sjruoho 3900c88d0e4Sjruoho return name; 3910c88d0e4Sjruoho } 3920c88d0e4Sjruoho 3930c88d0e4Sjruoho /* 394660a9ad6Sthorpej * Pack _HID and _CID ID strings into an OpenFirmware-style 3956451a97aSthorpej * string list. 3966451a97aSthorpej */ 3976451a97aSthorpej char * 398568ac2aaSthorpej acpi_pack_compat_list(struct acpi_devnode *ad, size_t *sizep) 3996451a97aSthorpej { 400568ac2aaSthorpej ACPI_DEVICE_INFO *devinfo = ad->ad_devinfo; 401568ac2aaSthorpej 4026451a97aSthorpej KASSERT(sizep != NULL); 4036451a97aSthorpej 404660a9ad6Sthorpej char *sl = NULL; 405660a9ad6Sthorpej size_t slsize = 0; 4066451a97aSthorpej uint32_t i; 407568ac2aaSthorpej bool dtlink = false; 4086451a97aSthorpej 409568ac2aaSthorpej ACPI_BUFFER buf; 410568ac2aaSthorpej ACPI_STATUS ret; 411568ac2aaSthorpej ACPI_OBJECT *obj; 412568ac2aaSthorpej char *compatible; 413568ac2aaSthorpej int n; 414568ac2aaSthorpej 415568ac2aaSthorpej buf.Pointer = NULL; 416568ac2aaSthorpej buf.Length = ACPI_ALLOCATE_BUFFER; 417568ac2aaSthorpej 418568ac2aaSthorpej if ((devinfo->Valid & ACPI_VALID_HID) != 0) { 419568ac2aaSthorpej const char *cp = devinfo->HardwareId.String; 420568ac2aaSthorpej 421568ac2aaSthorpej if (device_compatible_pmatch_strlist(cp, strlen(cp) + 1, 422568ac2aaSthorpej dtlink_compat_data)) { 423568ac2aaSthorpej dtlink = true; 424568ac2aaSthorpej } else { 425568ac2aaSthorpej strlist_append(&sl, &slsize, cp); 426568ac2aaSthorpej } 4276451a97aSthorpej } 4286451a97aSthorpej 429568ac2aaSthorpej if ((devinfo->Valid & ACPI_VALID_CID) != 0) { 430568ac2aaSthorpej for (i = 0; i < devinfo->CompatibleIdList.Count; i++) { 431568ac2aaSthorpej const char *cp = 432568ac2aaSthorpej devinfo->CompatibleIdList.Ids[i].String; 433568ac2aaSthorpej 434568ac2aaSthorpej if (device_compatible_pmatch_strlist(cp, strlen(cp) + 1, 435568ac2aaSthorpej dtlink_compat_data)) { 436568ac2aaSthorpej dtlink = true; 437568ac2aaSthorpej } else { 438568ac2aaSthorpej strlist_append(&sl, &slsize, cp); 439568ac2aaSthorpej } 440568ac2aaSthorpej } 441568ac2aaSthorpej } 442568ac2aaSthorpej 443568ac2aaSthorpej if (dtlink) { 444568ac2aaSthorpej ret = acpi_dsd_string(ad->ad_handle, "compatible", 445568ac2aaSthorpej &compatible); 446568ac2aaSthorpej if (ACPI_SUCCESS(ret)) { 447568ac2aaSthorpej strlist_append(&sl, &slsize, compatible); 448568ac2aaSthorpej kmem_strfree(compatible); 449568ac2aaSthorpej goto done; 450568ac2aaSthorpej } 451568ac2aaSthorpej 452568ac2aaSthorpej ret = acpi_dsd_property(ad->ad_handle, "compatible", &buf, 453568ac2aaSthorpej ACPI_TYPE_PACKAGE, &obj); 454568ac2aaSthorpej if (ACPI_FAILURE(ret)) { 455568ac2aaSthorpej goto done; 456568ac2aaSthorpej } 457568ac2aaSthorpej if (obj->Package.Count == 0) { 458568ac2aaSthorpej goto done; 459568ac2aaSthorpej } 460568ac2aaSthorpej for (n = 0; n < obj->Package.Count; n++) { 461568ac2aaSthorpej if (obj->Package.Elements[n].Type != ACPI_TYPE_STRING) { 462568ac2aaSthorpej continue; 463568ac2aaSthorpej } 464660a9ad6Sthorpej strlist_append(&sl, &slsize, 465568ac2aaSthorpej obj->Package.Elements[n].String.Pointer); 4666451a97aSthorpej } 4676451a97aSthorpej } 4686451a97aSthorpej 469568ac2aaSthorpej done: 470568ac2aaSthorpej if (buf.Pointer != NULL) { 471568ac2aaSthorpej ACPI_FREE(buf.Pointer); 472568ac2aaSthorpej } 473660a9ad6Sthorpej *sizep = slsize; 474660a9ad6Sthorpej return sl; 475660a9ad6Sthorpej } 476660a9ad6Sthorpej 477660a9ad6Sthorpej /* 478660a9ad6Sthorpej * The ACPI_PNP_DEVICE_ID type is somewhat inconvenient for us to 479660a9ad6Sthorpej * use. We'll need some temporary space to pack it into an array 480660a9ad6Sthorpej * of C strings. Room for 8 should be plenty, but we can allocate 481660a9ad6Sthorpej * more if necessary. 482660a9ad6Sthorpej */ 483660a9ad6Sthorpej #define ACPI_COMPATSTR_MAX 8 484660a9ad6Sthorpej 485660a9ad6Sthorpej static const char ** 486660a9ad6Sthorpej acpi_compatible_alloc_strarray(ACPI_PNP_DEVICE_ID *ids, 487660a9ad6Sthorpej unsigned int count, const char **buf) 488660a9ad6Sthorpej { 489660a9ad6Sthorpej unsigned int i; 490660a9ad6Sthorpej 491660a9ad6Sthorpej buf = kmem_tmpbuf_alloc(count * sizeof(const char *), 492660a9ad6Sthorpej buf, ACPI_COMPATSTR_MAX * sizeof(const char *), KM_SLEEP); 493660a9ad6Sthorpej for (i = 0; i < count; i++) { 494660a9ad6Sthorpej buf[i] = ids[i].String; 495660a9ad6Sthorpej } 496660a9ad6Sthorpej return buf; 497660a9ad6Sthorpej } 498660a9ad6Sthorpej 499660a9ad6Sthorpej static void 500660a9ad6Sthorpej acpi_compatible_free_strarray(const char **cpp, unsigned int count, 501660a9ad6Sthorpej const char **buf) 502660a9ad6Sthorpej { 503660a9ad6Sthorpej kmem_tmpbuf_free(cpp, count * sizeof(const char *), buf); 504660a9ad6Sthorpej } 505660a9ad6Sthorpej 5063da31819Sjmcneill static int 5073da31819Sjmcneill acpi_compatible_match_dtlink(const struct acpi_attach_args * const aa, 5083da31819Sjmcneill const struct device_compatible_entry * const dce) 5093da31819Sjmcneill { 5103da31819Sjmcneill const char *strings[ACPI_COMPATSTR_MAX * sizeof(const char *)]; 5113da31819Sjmcneill ACPI_HANDLE handle = aa->aa_node->ad_handle; 5123da31819Sjmcneill ACPI_BUFFER buf; 5133da31819Sjmcneill char *compatible; 5143da31819Sjmcneill ACPI_STATUS ret; 5153da31819Sjmcneill ACPI_OBJECT *obj; 5163da31819Sjmcneill int rv = 0, n; 5173da31819Sjmcneill 5183da31819Sjmcneill buf.Pointer = NULL; 5193da31819Sjmcneill buf.Length = ACPI_ALLOCATE_BUFFER; 5203da31819Sjmcneill 5213da31819Sjmcneill /* Match a single string _DSD value */ 5223da31819Sjmcneill ret = acpi_dsd_string(handle, "compatible", &compatible); 5233da31819Sjmcneill if (ACPI_SUCCESS(ret)) { 5243da31819Sjmcneill strings[0] = compatible; 5253da31819Sjmcneill rv = device_compatible_pmatch(strings, 1, dce); 5263da31819Sjmcneill kmem_strfree(compatible); 5273da31819Sjmcneill goto done; 5283da31819Sjmcneill } 5293da31819Sjmcneill 5303da31819Sjmcneill /* Match from a list of strings in a _DSD value */ 5313da31819Sjmcneill ret = acpi_dsd_property(handle, "compatible", &buf, 5323da31819Sjmcneill ACPI_TYPE_PACKAGE, &obj); 5333da31819Sjmcneill if (ACPI_FAILURE(ret)) { 5343da31819Sjmcneill goto done; 5353da31819Sjmcneill } 5363da31819Sjmcneill if (obj->Package.Count == 0) { 5373da31819Sjmcneill goto done; 5383da31819Sjmcneill } 5393da31819Sjmcneill for (n = 0; n < imin(obj->Package.Count, ACPI_COMPATSTR_MAX); n++) { 5403da31819Sjmcneill if (obj->Package.Elements[n].Type != ACPI_TYPE_STRING) { 5413da31819Sjmcneill goto done; 5423da31819Sjmcneill } 5433da31819Sjmcneill strings[n] = obj->Package.Elements[n].String.Pointer; 5443da31819Sjmcneill } 5453da31819Sjmcneill rv = device_compatible_pmatch(strings, n, dce); 5463da31819Sjmcneill 5473da31819Sjmcneill done: 5483da31819Sjmcneill if (buf.Pointer != NULL) { 5493da31819Sjmcneill ACPI_FREE(buf.Pointer); 5503da31819Sjmcneill } 5513da31819Sjmcneill if (rv) { 5523da31819Sjmcneill rv = (rv - 1) + ACPI_MATCHSCORE_CID; 5533da31819Sjmcneill return imin(rv, ACPI_MATCHSCORE_CID_MAX); 5543da31819Sjmcneill } 5553da31819Sjmcneill return 0; 5563da31819Sjmcneill } 5573da31819Sjmcneill 558660a9ad6Sthorpej /* 559660a9ad6Sthorpej * acpi_compatible_match -- 560660a9ad6Sthorpej * 561660a9ad6Sthorpej * Returns a weighted match value, comparing the _HID and _CID 5626584ea56Sandvar * IDs against a driver's compatibility data. 563660a9ad6Sthorpej */ 564660a9ad6Sthorpej int 565660a9ad6Sthorpej acpi_compatible_match(const struct acpi_attach_args * const aa, 566660a9ad6Sthorpej const struct device_compatible_entry * const dce) 567660a9ad6Sthorpej { 568660a9ad6Sthorpej const char *strings[ACPI_COMPATSTR_MAX * sizeof(const char *)]; 569660a9ad6Sthorpej const char **cpp; 5701ff08d8eSjmcneill bool dtlink = false; 5711ff08d8eSjmcneill int rv; 572660a9ad6Sthorpej 573660a9ad6Sthorpej if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) { 574660a9ad6Sthorpej return 0; 575660a9ad6Sthorpej } 576660a9ad6Sthorpej 577660a9ad6Sthorpej ACPI_DEVICE_INFO *ad = aa->aa_node->ad_devinfo; 578660a9ad6Sthorpej 579660a9ad6Sthorpej if ((ad->Valid & ACPI_VALID_HID) != 0) { 580660a9ad6Sthorpej strings[0] = ad->HardwareId.String; 581660a9ad6Sthorpej 582660a9ad6Sthorpej /* Matching _HID wins big. */ 583660a9ad6Sthorpej if (device_compatible_pmatch(strings, 1, dce) != 0) { 584660a9ad6Sthorpej return ACPI_MATCHSCORE_HID; 585660a9ad6Sthorpej } 5861ff08d8eSjmcneill 5871ff08d8eSjmcneill if (device_compatible_pmatch(strings, 1, 5881ff08d8eSjmcneill dtlink_compat_data) != 0) { 5891ff08d8eSjmcneill dtlink = true; 5901ff08d8eSjmcneill } 591660a9ad6Sthorpej } 592660a9ad6Sthorpej 593660a9ad6Sthorpej if ((ad->Valid & ACPI_VALID_CID) != 0) { 594660a9ad6Sthorpej cpp = acpi_compatible_alloc_strarray(ad->CompatibleIdList.Ids, 595660a9ad6Sthorpej ad->CompatibleIdList.Count, strings); 596660a9ad6Sthorpej 597660a9ad6Sthorpej rv = device_compatible_pmatch(cpp, 598660a9ad6Sthorpej ad->CompatibleIdList.Count, dce); 5991ff08d8eSjmcneill if (!dtlink && 6001ff08d8eSjmcneill device_compatible_pmatch(cpp, ad->CompatibleIdList.Count, 6011ff08d8eSjmcneill dtlink_compat_data) != 0) { 6021ff08d8eSjmcneill dtlink = true; 6031ff08d8eSjmcneill } 604660a9ad6Sthorpej acpi_compatible_free_strarray(cpp, ad->CompatibleIdList.Count, 605660a9ad6Sthorpej strings); 606660a9ad6Sthorpej if (rv) { 607660a9ad6Sthorpej rv = (rv - 1) + ACPI_MATCHSCORE_CID; 6081ff08d8eSjmcneill return imin(rv, ACPI_MATCHSCORE_CID_MAX); 609660a9ad6Sthorpej } 6101ff08d8eSjmcneill } 6111ff08d8eSjmcneill 6121ff08d8eSjmcneill if (dtlink) { 6133da31819Sjmcneill return acpi_compatible_match_dtlink(aa, dce); 614660a9ad6Sthorpej } 615660a9ad6Sthorpej 616660a9ad6Sthorpej return 0; 617660a9ad6Sthorpej } 618660a9ad6Sthorpej 619660a9ad6Sthorpej /* 620660a9ad6Sthorpej * acpi_compatible_lookup -- 621660a9ad6Sthorpej * 622660a9ad6Sthorpej * Returns the device_compatible_entry that matches the _HID 623660a9ad6Sthorpej * or _CID ID. 624660a9ad6Sthorpej */ 625660a9ad6Sthorpej const struct device_compatible_entry * 626660a9ad6Sthorpej acpi_compatible_lookup(const struct acpi_attach_args * const aa, 627660a9ad6Sthorpej const struct device_compatible_entry * const dce) 628660a9ad6Sthorpej { 629660a9ad6Sthorpej const struct device_compatible_entry *rv = NULL; 630660a9ad6Sthorpej const char *strings[ACPI_COMPATSTR_MAX]; 631660a9ad6Sthorpej const char **cpp; 632660a9ad6Sthorpej 633660a9ad6Sthorpej if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) { 6346451a97aSthorpej return NULL; 6356451a97aSthorpej } 6366451a97aSthorpej 637660a9ad6Sthorpej ACPI_DEVICE_INFO *ad = aa->aa_node->ad_devinfo; 6386451a97aSthorpej 6396451a97aSthorpej if ((ad->Valid & ACPI_VALID_HID) != 0) { 640660a9ad6Sthorpej strings[0] = ad->HardwareId.String; 641660a9ad6Sthorpej 642660a9ad6Sthorpej rv = device_compatible_plookup(strings, 1, dce); 643660a9ad6Sthorpej if (rv != NULL) 644660a9ad6Sthorpej return rv; 6456451a97aSthorpej } 6466451a97aSthorpej 6476451a97aSthorpej if ((ad->Valid & ACPI_VALID_CID) != 0) { 648660a9ad6Sthorpej cpp = acpi_compatible_alloc_strarray(ad->CompatibleIdList.Ids, 649660a9ad6Sthorpej ad->CompatibleIdList.Count, strings); 650660a9ad6Sthorpej 651660a9ad6Sthorpej rv = device_compatible_plookup(cpp, 652660a9ad6Sthorpej ad->CompatibleIdList.Count, dce); 653660a9ad6Sthorpej acpi_compatible_free_strarray(cpp, ad->CompatibleIdList.Count, 654660a9ad6Sthorpej strings); 6556451a97aSthorpej } 6566451a97aSthorpej 657660a9ad6Sthorpej return rv; 6586451a97aSthorpej } 6596451a97aSthorpej 6606451a97aSthorpej /* 661d6afaa44Sjruoho * Match given IDs against _HID and _CIDs. 6620c88d0e4Sjruoho */ 6630c88d0e4Sjruoho int 6640c88d0e4Sjruoho acpi_match_hid(ACPI_DEVICE_INFO *ad, const char * const *ids) 6650c88d0e4Sjruoho { 6660c88d0e4Sjruoho uint32_t i, n; 6670c88d0e4Sjruoho char *id; 6680c88d0e4Sjruoho 6690c88d0e4Sjruoho while (*ids) { 6700c88d0e4Sjruoho 6710c88d0e4Sjruoho if ((ad->Valid & ACPI_VALID_HID) != 0) { 6720c88d0e4Sjruoho 6730c88d0e4Sjruoho if (pmatch(ad->HardwareId.String, *ids, NULL) == 2) 6740c88d0e4Sjruoho return 1; 6750c88d0e4Sjruoho } 6760c88d0e4Sjruoho 6770c88d0e4Sjruoho if ((ad->Valid & ACPI_VALID_CID) != 0) { 6780c88d0e4Sjruoho 6790c88d0e4Sjruoho n = ad->CompatibleIdList.Count; 6800c88d0e4Sjruoho 6810c88d0e4Sjruoho for (i = 0; i < n; i++) { 6820c88d0e4Sjruoho 6830c88d0e4Sjruoho id = ad->CompatibleIdList.Ids[i].String; 6840c88d0e4Sjruoho 6850c88d0e4Sjruoho if (pmatch(id, *ids, NULL) == 2) 6860c88d0e4Sjruoho return 1; 6870c88d0e4Sjruoho } 6880c88d0e4Sjruoho } 6890c88d0e4Sjruoho 6900c88d0e4Sjruoho ids++; 6910c88d0e4Sjruoho } 6920c88d0e4Sjruoho 6930c88d0e4Sjruoho return 0; 6940c88d0e4Sjruoho } 6950c88d0e4Sjruoho 6960f056e49Sjruoho /* 697d94e7e9cSjmcneill * Match a PCI-defined bass-class, sub-class, and programming interface 698d94e7e9cSjmcneill * against a handle's _CLS object. 699d94e7e9cSjmcneill */ 700d94e7e9cSjmcneill int 701d94e7e9cSjmcneill acpi_match_class(ACPI_HANDLE handle, uint8_t pci_class, uint8_t pci_subclass, 702d94e7e9cSjmcneill uint8_t pci_interface) 703d94e7e9cSjmcneill { 704d94e7e9cSjmcneill ACPI_BUFFER buf; 705d94e7e9cSjmcneill ACPI_OBJECT *obj; 706d94e7e9cSjmcneill ACPI_STATUS rv; 707d94e7e9cSjmcneill int match = 0; 708d94e7e9cSjmcneill 709d94e7e9cSjmcneill rv = acpi_eval_struct(handle, "_CLS", &buf); 710d94e7e9cSjmcneill if (ACPI_FAILURE(rv)) 711d94e7e9cSjmcneill goto done; 712d94e7e9cSjmcneill 713d94e7e9cSjmcneill obj = buf.Pointer; 714d94e7e9cSjmcneill if (obj->Type != ACPI_TYPE_PACKAGE) 715d94e7e9cSjmcneill goto done; 716d94e7e9cSjmcneill if (obj->Package.Count != 3) 717d94e7e9cSjmcneill goto done; 718d94e7e9cSjmcneill if (obj->Package.Elements[0].Type != ACPI_TYPE_INTEGER || 719d94e7e9cSjmcneill obj->Package.Elements[1].Type != ACPI_TYPE_INTEGER || 720d94e7e9cSjmcneill obj->Package.Elements[2].Type != ACPI_TYPE_INTEGER) 721d94e7e9cSjmcneill goto done; 722d94e7e9cSjmcneill 723d94e7e9cSjmcneill match = obj->Package.Elements[0].Integer.Value == pci_class && 724d94e7e9cSjmcneill obj->Package.Elements[1].Integer.Value == pci_subclass && 725d94e7e9cSjmcneill obj->Package.Elements[2].Integer.Value == pci_interface; 726d94e7e9cSjmcneill 727d94e7e9cSjmcneill done: 728d94e7e9cSjmcneill if (buf.Pointer) 729d94e7e9cSjmcneill ACPI_FREE(buf.Pointer); 730660a9ad6Sthorpej return match ? ACPI_MATCHSCORE_CLS : 0; 731d94e7e9cSjmcneill } 732d94e7e9cSjmcneill 733d94e7e9cSjmcneill /* 734a9db528eSjruoho * Match a device node from a handle. 735a9db528eSjruoho */ 736a9db528eSjruoho struct acpi_devnode * 737a9db528eSjruoho acpi_match_node(ACPI_HANDLE handle) 738a9db528eSjruoho { 739a9db528eSjruoho struct acpi_devnode *ad; 740a9db528eSjruoho ACPI_STATUS rv; 741a9db528eSjruoho 742a9db528eSjruoho if (handle == NULL) 743a9db528eSjruoho return NULL; 744a9db528eSjruoho 745a9db528eSjruoho rv = AcpiGetData(handle, acpi_clean_node, (void **)&ad); 746a9db528eSjruoho 747a9db528eSjruoho if (ACPI_FAILURE(rv)) 748a9db528eSjruoho return NULL; 749a9db528eSjruoho 750a9db528eSjruoho return ad; 751a9db528eSjruoho } 752a9db528eSjruoho 753a9db528eSjruoho /* 754a9db528eSjruoho * Permanently associate a device node with a handle. 755a9db528eSjruoho */ 756a9db528eSjruoho void 757a9db528eSjruoho acpi_match_node_init(struct acpi_devnode *ad) 758a9db528eSjruoho { 759a9db528eSjruoho (void)AcpiAttachData(ad->ad_handle, acpi_clean_node, ad); 760a9db528eSjruoho } 761a9db528eSjruoho 762a9db528eSjruoho static void 763a9db528eSjruoho acpi_clean_node(ACPI_HANDLE handle, void *aux) 764a9db528eSjruoho { 765a9db528eSjruoho /* Nothing. */ 766a9db528eSjruoho } 767a9db528eSjruoho 768a9db528eSjruoho /* 7690f056e49Sjruoho * Match a handle from a cpu_info. Returns NULL on failure. 7700f056e49Sjruoho * 771a9db528eSjruoho * Note that acpi_match_node() can be used if the device node 772a9db528eSjruoho * is also required. 7730f056e49Sjruoho */ 7740f056e49Sjruoho ACPI_HANDLE 7750f056e49Sjruoho acpi_match_cpu_info(struct cpu_info *ci) 7760f056e49Sjruoho { 7770f056e49Sjruoho struct acpi_softc *sc = acpi_softc; 7780f056e49Sjruoho struct acpi_devnode *ad; 7790f056e49Sjruoho ACPI_INTEGER val; 7800f056e49Sjruoho ACPI_OBJECT *obj; 7810f056e49Sjruoho ACPI_BUFFER buf; 7820f056e49Sjruoho ACPI_HANDLE hdl; 7830f056e49Sjruoho ACPI_STATUS rv; 7840f056e49Sjruoho 7852dd5064cSjmcneill if (sc == NULL) 7860f056e49Sjruoho return NULL; 7870f056e49Sjruoho 7880f056e49Sjruoho /* 7890f056e49Sjruoho * CPUs are declared in the ACPI namespace 7900f056e49Sjruoho * either as a Processor() or as a Device(). 7910f056e49Sjruoho * In both cases the MADT entries are used 7920f056e49Sjruoho * for the match (see ACPI 4.0, section 8.4). 7930f056e49Sjruoho */ 794de6a49e8Sskrll SIMPLEQ_FOREACH(ad, &sc->sc_head, ad_list) { 7950f056e49Sjruoho 7960f056e49Sjruoho hdl = ad->ad_handle; 7970f056e49Sjruoho 7980f056e49Sjruoho switch (ad->ad_type) { 7990f056e49Sjruoho 8000f056e49Sjruoho case ACPI_TYPE_DEVICE: 8010f056e49Sjruoho 8020f056e49Sjruoho if (acpi_match_hid(ad->ad_devinfo, acpicpu_ids) == 0) 8030f056e49Sjruoho break; 8040f056e49Sjruoho 8050f056e49Sjruoho rv = acpi_eval_integer(hdl, "_UID", &val); 8060f056e49Sjruoho 8070f056e49Sjruoho if (ACPI_SUCCESS(rv) && val == ci->ci_acpiid) 8080f056e49Sjruoho return hdl; 8090f056e49Sjruoho 8100f056e49Sjruoho break; 8110f056e49Sjruoho 8120f056e49Sjruoho case ACPI_TYPE_PROCESSOR: 8130f056e49Sjruoho 8140f056e49Sjruoho rv = acpi_eval_struct(hdl, NULL, &buf); 8150f056e49Sjruoho 8160f056e49Sjruoho if (ACPI_FAILURE(rv)) 8170f056e49Sjruoho break; 8180f056e49Sjruoho 8190f056e49Sjruoho obj = buf.Pointer; 8200f056e49Sjruoho 8210f056e49Sjruoho if (obj->Processor.ProcId == ci->ci_acpiid) { 8220f056e49Sjruoho ACPI_FREE(buf.Pointer); 8230f056e49Sjruoho return hdl; 8240f056e49Sjruoho } 8250f056e49Sjruoho 8260f056e49Sjruoho ACPI_FREE(buf.Pointer); 8270f056e49Sjruoho break; 8280f056e49Sjruoho } 8290f056e49Sjruoho } 8300f056e49Sjruoho 8310f056e49Sjruoho return NULL; 8320f056e49Sjruoho } 8330f056e49Sjruoho 8340f056e49Sjruoho /* 8350f056e49Sjruoho * Match a CPU from a handle. Returns NULL on failure. 8360f056e49Sjruoho */ 8370f056e49Sjruoho struct cpu_info * 8380f056e49Sjruoho acpi_match_cpu_handle(ACPI_HANDLE hdl) 8390f056e49Sjruoho { 8400f056e49Sjruoho struct cpu_info *ci; 8410f056e49Sjruoho ACPI_DEVICE_INFO *di; 8420f056e49Sjruoho CPU_INFO_ITERATOR cii; 8430f056e49Sjruoho ACPI_INTEGER val; 8440f056e49Sjruoho ACPI_OBJECT *obj; 8450f056e49Sjruoho ACPI_BUFFER buf; 8460f056e49Sjruoho ACPI_STATUS rv; 8470f056e49Sjruoho 8480f056e49Sjruoho ci = NULL; 8490f056e49Sjruoho di = NULL; 8500f056e49Sjruoho buf.Pointer = NULL; 8510f056e49Sjruoho 8520f056e49Sjruoho rv = AcpiGetObjectInfo(hdl, &di); 8530f056e49Sjruoho 8540f056e49Sjruoho if (ACPI_FAILURE(rv)) 8550f056e49Sjruoho return NULL; 8560f056e49Sjruoho 8570f056e49Sjruoho switch (di->Type) { 8580f056e49Sjruoho 8590f056e49Sjruoho case ACPI_TYPE_DEVICE: 8600f056e49Sjruoho 8610f056e49Sjruoho if (acpi_match_hid(di, acpicpu_ids) == 0) 8620f056e49Sjruoho goto out; 8630f056e49Sjruoho 8640f056e49Sjruoho rv = acpi_eval_integer(hdl, "_UID", &val); 8650f056e49Sjruoho 8660f056e49Sjruoho if (ACPI_FAILURE(rv)) 8670f056e49Sjruoho goto out; 8680f056e49Sjruoho 8690f056e49Sjruoho break; 8700f056e49Sjruoho 8710f056e49Sjruoho case ACPI_TYPE_PROCESSOR: 8720f056e49Sjruoho 8730f056e49Sjruoho rv = acpi_eval_struct(hdl, NULL, &buf); 8740f056e49Sjruoho 8750f056e49Sjruoho if (ACPI_FAILURE(rv)) 8760f056e49Sjruoho goto out; 8770f056e49Sjruoho 8780f056e49Sjruoho obj = buf.Pointer; 8790f056e49Sjruoho val = obj->Processor.ProcId; 8800f056e49Sjruoho break; 8810f056e49Sjruoho 8820f056e49Sjruoho default: 8830f056e49Sjruoho goto out; 8840f056e49Sjruoho } 8850f056e49Sjruoho 8860f056e49Sjruoho for (CPU_INFO_FOREACH(cii, ci)) { 8870f056e49Sjruoho 8880f056e49Sjruoho if (ci->ci_acpiid == val) 8890f056e49Sjruoho goto out; 8900f056e49Sjruoho } 8910f056e49Sjruoho 8920f056e49Sjruoho ci = NULL; 8930f056e49Sjruoho 8940f056e49Sjruoho out: 8950f056e49Sjruoho if (di != NULL) 8960f056e49Sjruoho ACPI_FREE(di); 8970f056e49Sjruoho 8980f056e49Sjruoho if (buf.Pointer != NULL) 8990f056e49Sjruoho ACPI_FREE(buf.Pointer); 9000f056e49Sjruoho 9010f056e49Sjruoho return ci; 9020f056e49Sjruoho } 903db8cbfd3Sbouyer 904db8cbfd3Sbouyer struct acpi_irq_handler { 905db8cbfd3Sbouyer uint32_t aih_irq; 906f62244a8Sjmcneill void *aih_ih; 907db8cbfd3Sbouyer }; 908db8cbfd3Sbouyer 909db8cbfd3Sbouyer void * 910f62244a8Sjmcneill acpi_intr_establish(device_t dev, uint64_t c, int ipl, bool mpsafe, 911f62244a8Sjmcneill int (*intr)(void *), void *iarg, const char *xname) 912db8cbfd3Sbouyer { 913db8cbfd3Sbouyer ACPI_STATUS rv; 91451f154a4Sbouyer ACPI_HANDLE hdl = (void *)(uintptr_t)c; 915db8cbfd3Sbouyer struct acpi_resources res; 916db8cbfd3Sbouyer struct acpi_irq *irq; 91757c57328Sjmcneill void *aih = NULL; 918db8cbfd3Sbouyer 919db8cbfd3Sbouyer rv = acpi_resource_parse(dev, hdl, "_CRS", &res, 920db8cbfd3Sbouyer &acpi_resource_parse_ops_quiet); 921db8cbfd3Sbouyer if (ACPI_FAILURE(rv)) 922db8cbfd3Sbouyer return NULL; 923db8cbfd3Sbouyer 924db8cbfd3Sbouyer irq = acpi_res_irq(&res, 0); 925db8cbfd3Sbouyer if (irq == NULL) 926db8cbfd3Sbouyer goto end; 927db8cbfd3Sbouyer 92857c57328Sjmcneill aih = acpi_intr_establish_irq(dev, irq, ipl, mpsafe, 92957c57328Sjmcneill intr, iarg, xname); 930f62244a8Sjmcneill 931db8cbfd3Sbouyer end: 932db8cbfd3Sbouyer acpi_resource_cleanup(&res); 93357c57328Sjmcneill 93457c57328Sjmcneill return aih; 93557c57328Sjmcneill } 93657c57328Sjmcneill 93757c57328Sjmcneill void * 93857c57328Sjmcneill acpi_intr_establish_irq(device_t dev, struct acpi_irq *irq, int ipl, 93957c57328Sjmcneill bool mpsafe, int (*intr)(void *), void *iarg, const char *xname) 94057c57328Sjmcneill { 94157c57328Sjmcneill struct acpi_irq_handler *aih; 94257c57328Sjmcneill void *ih; 94357c57328Sjmcneill 94457c57328Sjmcneill const int type = (irq->ar_type == ACPI_EDGE_SENSITIVE) ? IST_EDGE : IST_LEVEL; 94557c57328Sjmcneill ih = acpi_md_intr_establish(irq->ar_irq, ipl, type, intr, iarg, mpsafe, xname); 94657c57328Sjmcneill if (ih == NULL) 94757c57328Sjmcneill return NULL; 94857c57328Sjmcneill 94957c57328Sjmcneill aih = kmem_alloc(sizeof(struct acpi_irq_handler), KM_SLEEP); 95057c57328Sjmcneill aih->aih_irq = irq->ar_irq; 95157c57328Sjmcneill aih->aih_ih = ih; 95257c57328Sjmcneill 953db8cbfd3Sbouyer return aih; 954db8cbfd3Sbouyer } 955db8cbfd3Sbouyer 956db8cbfd3Sbouyer void 957659765daSthorpej acpi_intr_mask(void *c) 958659765daSthorpej { 959659765daSthorpej struct acpi_irq_handler * const aih = c; 960659765daSthorpej 961659765daSthorpej acpi_md_intr_mask(aih->aih_ih); 962659765daSthorpej } 963659765daSthorpej 964659765daSthorpej void 965659765daSthorpej acpi_intr_unmask(void *c) 966659765daSthorpej { 967659765daSthorpej struct acpi_irq_handler * const aih = c; 968659765daSthorpej 969659765daSthorpej acpi_md_intr_unmask(aih->aih_ih); 970659765daSthorpej } 971659765daSthorpej 972659765daSthorpej void 973f62244a8Sjmcneill acpi_intr_disestablish(void *c) 974db8cbfd3Sbouyer { 975db8cbfd3Sbouyer struct acpi_irq_handler *aih = c; 976db8cbfd3Sbouyer 977f62244a8Sjmcneill acpi_md_intr_disestablish(aih->aih_ih); 978db8cbfd3Sbouyer kmem_free(aih, sizeof(struct acpi_irq_handler)); 979db8cbfd3Sbouyer } 980db8cbfd3Sbouyer 981db8cbfd3Sbouyer const char * 982db8cbfd3Sbouyer acpi_intr_string(void *c, char *buf, size_t size) 983db8cbfd3Sbouyer { 984db8cbfd3Sbouyer struct acpi_irq_handler *aih = c; 985db8cbfd3Sbouyer intr_handle_t ih = aih->aih_irq; 986db8cbfd3Sbouyer 987db8cbfd3Sbouyer return intr_string(ih, buf, size); 988db8cbfd3Sbouyer } 98900639337Sjmcneill 99000639337Sjmcneill /* 9916451a97aSthorpej * Device-Specific Data (_DSD) support 99200639337Sjmcneill */ 99300639337Sjmcneill 99400639337Sjmcneill static UINT8 acpi_dsd_uuid[ACPI_UUID_LENGTH] = { 99500639337Sjmcneill 0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d, 99600639337Sjmcneill 0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01 99700639337Sjmcneill }; 99800639337Sjmcneill 9999f624f6aSjmcneill static ACPI_STATUS 10009f624f6aSjmcneill acpi_dsd_property(ACPI_HANDLE handle, const char *prop, ACPI_BUFFER *pbuf, ACPI_OBJECT_TYPE type, ACPI_OBJECT **ret) 100100639337Sjmcneill { 100200639337Sjmcneill ACPI_OBJECT *obj, *uuid, *props, *pobj, *propkey, *propval; 100300639337Sjmcneill ACPI_STATUS rv; 100400639337Sjmcneill int n; 100500639337Sjmcneill 10069f624f6aSjmcneill rv = AcpiEvaluateObjectTyped(handle, "_DSD", NULL, pbuf, ACPI_TYPE_PACKAGE); 100700639337Sjmcneill if (ACPI_FAILURE(rv)) 100800639337Sjmcneill return rv; 100900639337Sjmcneill 101000639337Sjmcneill props = NULL; 10119f624f6aSjmcneill obj = (ACPI_OBJECT *)pbuf->Pointer; 101200639337Sjmcneill for (n = 0; (n + 1) < obj->Package.Count; n += 2) { 101300639337Sjmcneill uuid = &obj->Package.Elements[n]; 101400639337Sjmcneill if (uuid->Buffer.Length == ACPI_UUID_LENGTH && 101500639337Sjmcneill memcmp(uuid->Buffer.Pointer, acpi_dsd_uuid, ACPI_UUID_LENGTH) == 0) { 101600639337Sjmcneill props = &obj->Package.Elements[n + 1]; 101700639337Sjmcneill break; 101800639337Sjmcneill } 101900639337Sjmcneill } 10209f624f6aSjmcneill if (props == NULL) 10219f624f6aSjmcneill return AE_NOT_FOUND; 102200639337Sjmcneill 102300639337Sjmcneill for (n = 0; n < props->Package.Count; n++) { 102400639337Sjmcneill pobj = &props->Package.Elements[n]; 102500639337Sjmcneill if (pobj->Type != ACPI_TYPE_PACKAGE || pobj->Package.Count != 2) 102600639337Sjmcneill continue; 102700639337Sjmcneill propkey = (ACPI_OBJECT *)&pobj->Package.Elements[0]; 102800639337Sjmcneill propval = (ACPI_OBJECT *)&pobj->Package.Elements[1]; 102900639337Sjmcneill if (propkey->Type != ACPI_TYPE_STRING) 103000639337Sjmcneill continue; 103100639337Sjmcneill if (strcmp(propkey->String.Pointer, prop) != 0) 103200639337Sjmcneill continue; 103300639337Sjmcneill 10349f624f6aSjmcneill if (propval->Type != type) { 10359f624f6aSjmcneill return AE_TYPE; 103600639337Sjmcneill } else { 10379f624f6aSjmcneill *ret = propval; 10389f624f6aSjmcneill return AE_OK; 103900639337Sjmcneill } 104000639337Sjmcneill break; 104100639337Sjmcneill } 104200639337Sjmcneill 10439f624f6aSjmcneill return AE_NOT_FOUND; 10449f624f6aSjmcneill } 10459f624f6aSjmcneill 10469f624f6aSjmcneill ACPI_STATUS 10479f624f6aSjmcneill acpi_dsd_integer(ACPI_HANDLE handle, const char *prop, ACPI_INTEGER *val) 10489f624f6aSjmcneill { 10499f624f6aSjmcneill ACPI_OBJECT *propval; 10509f624f6aSjmcneill ACPI_STATUS rv; 10519f624f6aSjmcneill ACPI_BUFFER buf; 10529f624f6aSjmcneill 10539f624f6aSjmcneill buf.Pointer = NULL; 10549f624f6aSjmcneill buf.Length = ACPI_ALLOCATE_BUFFER; 10559f624f6aSjmcneill 10569f624f6aSjmcneill rv = acpi_dsd_property(handle, prop, &buf, ACPI_TYPE_INTEGER, &propval); 10579f624f6aSjmcneill if (ACPI_SUCCESS(rv)) 10589f624f6aSjmcneill *val = propval->Integer.Value; 10599f624f6aSjmcneill 10600aac85d5Smlelstv if (buf.Pointer != NULL) 10619f624f6aSjmcneill ACPI_FREE(buf.Pointer); 10629f624f6aSjmcneill return rv; 10639f624f6aSjmcneill } 10649f624f6aSjmcneill 10659f624f6aSjmcneill ACPI_STATUS 10669f624f6aSjmcneill acpi_dsd_string(ACPI_HANDLE handle, const char *prop, char **val) 10679f624f6aSjmcneill { 10689f624f6aSjmcneill ACPI_OBJECT *propval; 10699f624f6aSjmcneill ACPI_STATUS rv; 10709f624f6aSjmcneill ACPI_BUFFER buf; 10719f624f6aSjmcneill 10729f624f6aSjmcneill buf.Pointer = NULL; 10739f624f6aSjmcneill buf.Length = ACPI_ALLOCATE_BUFFER; 10749f624f6aSjmcneill 10759f624f6aSjmcneill rv = acpi_dsd_property(handle, prop, &buf, ACPI_TYPE_STRING, &propval); 10769f624f6aSjmcneill if (ACPI_SUCCESS(rv)) 10779f624f6aSjmcneill *val = kmem_strdup(propval->String.Pointer, KM_SLEEP); 10789f624f6aSjmcneill 10790aac85d5Smlelstv if (buf.Pointer != NULL) 108000639337Sjmcneill ACPI_FREE(buf.Pointer); 108100639337Sjmcneill return rv; 108200639337Sjmcneill } 10836451a97aSthorpej 1084bf7784c0Sjmcneill ACPI_STATUS 1085bf7784c0Sjmcneill acpi_dsd_bool(ACPI_HANDLE handle, const char *prop, bool *val) 1086bf7784c0Sjmcneill { 1087bf7784c0Sjmcneill ACPI_STATUS rv; 1088bf7784c0Sjmcneill ACPI_INTEGER ival; 1089bf7784c0Sjmcneill 1090bf7784c0Sjmcneill rv = acpi_dsd_integer(handle, prop, &ival); 1091bf7784c0Sjmcneill if (ACPI_SUCCESS(rv)) { 1092bf7784c0Sjmcneill *val = ival != 0; 1093bf7784c0Sjmcneill } 1094bf7784c0Sjmcneill 1095bf7784c0Sjmcneill return rv; 1096bf7784c0Sjmcneill } 10973da31819Sjmcneill 10983da31819Sjmcneill 10996451a97aSthorpej /* 11006451a97aSthorpej * Device Specific Method (_DSM) support 11016451a97aSthorpej */ 11026451a97aSthorpej 11036451a97aSthorpej ACPI_STATUS 11046451a97aSthorpej acpi_dsm_typed(ACPI_HANDLE handle, uint8_t *uuid, ACPI_INTEGER rev, 11056451a97aSthorpej ACPI_INTEGER func, const ACPI_OBJECT *arg3, ACPI_OBJECT_TYPE return_type, 11066451a97aSthorpej ACPI_OBJECT **return_obj) 11076451a97aSthorpej { 11086451a97aSthorpej ACPI_OBJECT_LIST arg; 11096451a97aSthorpej ACPI_OBJECT obj[4]; 11106451a97aSthorpej ACPI_BUFFER buf; 11116451a97aSthorpej ACPI_STATUS status; 11126451a97aSthorpej 11136451a97aSthorpej arg.Count = 4; 11146451a97aSthorpej arg.Pointer = obj; 11156451a97aSthorpej 11166451a97aSthorpej obj[0].Type = ACPI_TYPE_BUFFER; 11176451a97aSthorpej obj[0].Buffer.Length = ACPI_UUID_LENGTH; 11186451a97aSthorpej obj[0].Buffer.Pointer = uuid; 11196451a97aSthorpej 11206451a97aSthorpej obj[1].Type = ACPI_TYPE_INTEGER; 11216451a97aSthorpej obj[1].Integer.Value = rev; 11226451a97aSthorpej 11236451a97aSthorpej obj[2].Type = ACPI_TYPE_INTEGER; 11246451a97aSthorpej obj[2].Integer.Value = func; 11256451a97aSthorpej 11266451a97aSthorpej if (arg3 != NULL) { 11276451a97aSthorpej obj[3] = *arg3; 11286451a97aSthorpej } else { 11296451a97aSthorpej obj[3].Type = ACPI_TYPE_PACKAGE; 11306451a97aSthorpej obj[3].Package.Count = 0; 11316451a97aSthorpej obj[3].Package.Elements = NULL; 11326451a97aSthorpej } 11336451a97aSthorpej 11346451a97aSthorpej buf.Pointer = NULL; 11356451a97aSthorpej buf.Length = ACPI_ALLOCATE_BUFFER; 11366451a97aSthorpej 11376451a97aSthorpej if (return_obj == NULL && return_type == ACPI_TYPE_ANY) { 11386451a97aSthorpej status = AcpiEvaluateObject(handle, "_DSM", &arg, NULL); 11396451a97aSthorpej } else { 11406451a97aSthorpej *return_obj = NULL; 11416451a97aSthorpej status = AcpiEvaluateObjectTyped(handle, "_DSM", &arg, &buf, 11426451a97aSthorpej return_type); 11436451a97aSthorpej } 11446451a97aSthorpej if (ACPI_FAILURE(status)) { 11456451a97aSthorpej return status; 11466451a97aSthorpej } 11476451a97aSthorpej if (return_obj != NULL) { 11486451a97aSthorpej *return_obj = buf.Pointer; 11496451a97aSthorpej } else if (buf.Pointer != NULL) { 11506451a97aSthorpej ACPI_FREE(buf.Pointer); 11516451a97aSthorpej } 11526451a97aSthorpej return AE_OK; 11536451a97aSthorpej } 11546451a97aSthorpej 11556451a97aSthorpej ACPI_STATUS 11566451a97aSthorpej acpi_dsm_integer(ACPI_HANDLE handle, uint8_t *uuid, ACPI_INTEGER rev, 11576451a97aSthorpej ACPI_INTEGER func, const ACPI_OBJECT *arg3, ACPI_INTEGER *ret) 11586451a97aSthorpej { 11596451a97aSthorpej ACPI_OBJECT *obj; 11606451a97aSthorpej ACPI_STATUS status; 11616451a97aSthorpej 11626451a97aSthorpej status = acpi_dsm_typed(handle, uuid, rev, func, arg3, 11636451a97aSthorpej ACPI_TYPE_INTEGER, &obj); 11646451a97aSthorpej if (ACPI_FAILURE(status)) { 11656451a97aSthorpej return status; 11666451a97aSthorpej } 11676451a97aSthorpej 11686451a97aSthorpej *ret = obj->Integer.Value; 11696451a97aSthorpej ACPI_FREE(obj); 11706451a97aSthorpej 11716451a97aSthorpej return AE_OK; 11726451a97aSthorpej } 11736451a97aSthorpej 11746451a97aSthorpej ACPI_STATUS 11756451a97aSthorpej acpi_dsm(ACPI_HANDLE handle, uint8_t *uuid, ACPI_INTEGER rev, 11766451a97aSthorpej ACPI_INTEGER func, const ACPI_OBJECT *arg3, ACPI_OBJECT **return_obj) 11776451a97aSthorpej { 11786451a97aSthorpej return acpi_dsm_typed(handle, uuid, rev, func, arg3, ACPI_TYPE_ANY, 11796451a97aSthorpej return_obj); 11806451a97aSthorpej } 1181172e088eSjmcneill 1182172e088eSjmcneill ACPI_STATUS 118348c56ea6Sjmcneill acpi_dsm_query(ACPI_HANDLE handle, uint8_t *uuid, ACPI_INTEGER rev, 118448c56ea6Sjmcneill ACPI_INTEGER *ret) 118548c56ea6Sjmcneill { 118648c56ea6Sjmcneill ACPI_OBJECT *obj; 118748c56ea6Sjmcneill ACPI_STATUS status; 118848c56ea6Sjmcneill uint8_t *data; 118948c56ea6Sjmcneill u_int n; 119048c56ea6Sjmcneill 119148c56ea6Sjmcneill status = acpi_dsm(handle, uuid, rev, 0, NULL, &obj); 119248c56ea6Sjmcneill if (ACPI_FAILURE(status)) { 119348c56ea6Sjmcneill return status; 119448c56ea6Sjmcneill } 119548c56ea6Sjmcneill 119648c56ea6Sjmcneill if (obj->Type == ACPI_TYPE_INTEGER) { 119748c56ea6Sjmcneill *ret = obj->Integer.Value; 119848c56ea6Sjmcneill } else if (obj->Type == ACPI_TYPE_BUFFER && 119948c56ea6Sjmcneill obj->Buffer.Length <= 8) { 120048c56ea6Sjmcneill *ret = 0; 120148c56ea6Sjmcneill data = (uint8_t *)obj->Buffer.Pointer; 120248c56ea6Sjmcneill for (n = 0; n < obj->Buffer.Length; n++) { 120348c56ea6Sjmcneill *ret |= (uint64_t)data[n] << (n * 8); 120448c56ea6Sjmcneill } 120548c56ea6Sjmcneill } else { 120648c56ea6Sjmcneill status = AE_TYPE; 120748c56ea6Sjmcneill } 120848c56ea6Sjmcneill 120948c56ea6Sjmcneill ACPI_FREE(obj); 121048c56ea6Sjmcneill 121148c56ea6Sjmcneill return status; 121248c56ea6Sjmcneill } 121348c56ea6Sjmcneill 121448c56ea6Sjmcneill ACPI_STATUS 1215*84b6468dSjmcneill acpi_claim_childdevs(device_t dev, struct acpi_devnode *devnode, 1216*84b6468dSjmcneill const char *method) 1217172e088eSjmcneill { 1218172e088eSjmcneill struct acpi_devnode *ad; 1219172e088eSjmcneill 1220172e088eSjmcneill SIMPLEQ_FOREACH(ad, &devnode->ad_child_head, ad_child_list) { 1221172e088eSjmcneill if (ad->ad_device != NULL) 1222172e088eSjmcneill continue; 1223*84b6468dSjmcneill 1224*84b6468dSjmcneill if (method != NULL) { 1225*84b6468dSjmcneill ACPI_HANDLE h; 1226*84b6468dSjmcneill ACPI_STATUS rv; 1227*84b6468dSjmcneill 1228*84b6468dSjmcneill rv = AcpiGetHandle(ad->ad_handle, method, &h); 1229*84b6468dSjmcneill if (ACPI_FAILURE(rv)) { 1230*84b6468dSjmcneill continue; 1231*84b6468dSjmcneill } 1232*84b6468dSjmcneill } 1233*84b6468dSjmcneill 123485dfab94Sjmcneill aprint_debug_dev(dev, "claiming %s\n", 123585dfab94Sjmcneill acpi_name(ad->ad_handle)); 1236172e088eSjmcneill ad->ad_device = dev; 1237*84b6468dSjmcneill acpi_claim_childdevs(dev, ad, method); 1238172e088eSjmcneill } 1239172e088eSjmcneill 1240172e088eSjmcneill return AE_OK; 1241172e088eSjmcneill } 1242