1*b61b358aSthorpej /* $NetBSD: acpi_util.c,v 1.33 2022/07/23 03:08:17 thorpej Exp $ */
20c88d0e4Sjruoho
30c88d0e4Sjruoho /*-
433af1b8eSthorpej * 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*b61b358aSthorpej __KERNEL_RCSID(0, "$NetBSD: acpi_util.c,v 1.33 2022/07/23 03:08:17 thorpej Exp $");
690c88d0e4Sjruoho
700c88d0e4Sjruoho #include <sys/param.h>
7127ab5385Sbouyer #include <sys/kmem.h>
72c3ae344aSjmcneill #include <sys/cpu.h>
730c88d0e4Sjruoho
740c88d0e4Sjruoho #include <dev/acpi/acpireg.h>
750c88d0e4Sjruoho #include <dev/acpi/acpivar.h>
7627ab5385Sbouyer #include <dev/acpi/acpi_intr.h>
770c88d0e4Sjruoho
786ed8e091Sthorpej #include <sys/device_calls.h>
796ed8e091Sthorpej
80488c5b15Sjmcneill #include <machine/acpi_machdep.h>
81488c5b15Sjmcneill
820c88d0e4Sjruoho #define _COMPONENT ACPI_BUS_COMPONENT
830c88d0e4Sjruoho ACPI_MODULE_NAME ("acpi_util")
840c88d0e4Sjruoho
855e449c62Sjruoho static void acpi_clean_node(ACPI_HANDLE, void *);
86312915a9Sjmcneill static ACPI_STATUS acpi_dsd_property(ACPI_HANDLE, const char *,
87312915a9Sjmcneill ACPI_BUFFER *, ACPI_OBJECT_TYPE, ACPI_OBJECT **);
885e449c62Sjruoho
894bd16782Sjruoho static const char * const acpicpu_ids[] = {
904bd16782Sjruoho "ACPI0007",
914bd16782Sjruoho NULL
924bd16782Sjruoho };
934bd16782Sjruoho
948b25d0adSjmcneill static const struct device_compatible_entry dtlink_compat_data[] = {
958b25d0adSjmcneill { .compat = "PRP0001" },
968b25d0adSjmcneill DEVICE_COMPAT_EOL
978b25d0adSjmcneill };
988b25d0adSjmcneill
990c88d0e4Sjruoho /*
10037aee2b1Sthorpej * ACPI device handle support.
10137aee2b1Sthorpej */
10237aee2b1Sthorpej
10337aee2b1Sthorpej static device_call_t
acpi_devhandle_lookup_device_call(devhandle_t handle,const char * name,devhandle_t * call_handlep)10437aee2b1Sthorpej acpi_devhandle_lookup_device_call(devhandle_t handle, const char *name,
10537aee2b1Sthorpej devhandle_t *call_handlep)
10637aee2b1Sthorpej {
10737aee2b1Sthorpej __link_set_decl(acpi_device_calls, struct device_call_descriptor);
10837aee2b1Sthorpej struct device_call_descriptor * const *desc;
10937aee2b1Sthorpej
11037aee2b1Sthorpej __link_set_foreach(desc, acpi_device_calls) {
11137aee2b1Sthorpej if (strcmp((*desc)->name, name) == 0) {
11237aee2b1Sthorpej return (*desc)->call;
11337aee2b1Sthorpej }
11437aee2b1Sthorpej }
11537aee2b1Sthorpej return NULL;
11637aee2b1Sthorpej }
11737aee2b1Sthorpej
11837aee2b1Sthorpej static const struct devhandle_impl acpi_devhandle_impl = {
11937aee2b1Sthorpej .type = DEVHANDLE_TYPE_ACPI,
12037aee2b1Sthorpej .lookup_device_call = acpi_devhandle_lookup_device_call,
12137aee2b1Sthorpej };
12237aee2b1Sthorpej
12337aee2b1Sthorpej devhandle_t
devhandle_from_acpi(devhandle_t super_handle,ACPI_HANDLE const hdl)12409eb5c43Sthorpej devhandle_from_acpi(devhandle_t super_handle, ACPI_HANDLE const hdl)
12537aee2b1Sthorpej {
12609eb5c43Sthorpej devhandle_type_t super_type = devhandle_type(super_handle);
12709eb5c43Sthorpej devhandle_t handle = { 0 };
12809eb5c43Sthorpej
12909eb5c43Sthorpej if (super_type == DEVHANDLE_TYPE_ACPI) {
13009eb5c43Sthorpej handle.impl = super_handle.impl;
13109eb5c43Sthorpej } else {
13209eb5c43Sthorpej KASSERT(super_type == DEVHANDLE_TYPE_INVALID);
13309eb5c43Sthorpej handle.impl = &acpi_devhandle_impl;
13409eb5c43Sthorpej }
13509eb5c43Sthorpej handle.pointer = hdl;
13637aee2b1Sthorpej
13737aee2b1Sthorpej return handle;
13837aee2b1Sthorpej }
13937aee2b1Sthorpej
14037aee2b1Sthorpej ACPI_HANDLE
devhandle_to_acpi(devhandle_t const handle)14137aee2b1Sthorpej devhandle_to_acpi(devhandle_t const handle)
14237aee2b1Sthorpej {
14337aee2b1Sthorpej KASSERT(devhandle_type(handle) == DEVHANDLE_TYPE_ACPI);
14437aee2b1Sthorpej
14537aee2b1Sthorpej return handle.pointer;
14637aee2b1Sthorpej }
14737aee2b1Sthorpej
14837aee2b1Sthorpej static int
acpi_device_enumerate_children(device_t dev,devhandle_t call_handle,void * v)14937aee2b1Sthorpej acpi_device_enumerate_children(device_t dev, devhandle_t call_handle, void *v)
15037aee2b1Sthorpej {
15137aee2b1Sthorpej struct device_enumerate_children_args *args = v;
15237aee2b1Sthorpej ACPI_HANDLE hdl = devhandle_to_acpi(call_handle);
15337aee2b1Sthorpej struct acpi_devnode *devnode, *ad;
15437aee2b1Sthorpej
15537aee2b1Sthorpej devnode = acpi_match_node(hdl);
15637aee2b1Sthorpej KASSERT(devnode != NULL);
15737aee2b1Sthorpej
15837aee2b1Sthorpej SIMPLEQ_FOREACH(ad, &devnode->ad_child_head, ad_child_list) {
15937aee2b1Sthorpej if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE ||
16037aee2b1Sthorpej !acpi_device_present(ad->ad_handle)) {
16137aee2b1Sthorpej continue;
16237aee2b1Sthorpej }
16309eb5c43Sthorpej if (!args->callback(dev, devhandle_from_acpi(call_handle,
16409eb5c43Sthorpej ad->ad_handle),
16537aee2b1Sthorpej args->callback_arg)) {
16637aee2b1Sthorpej break;
16737aee2b1Sthorpej }
16837aee2b1Sthorpej }
16937aee2b1Sthorpej
17037aee2b1Sthorpej return 0;
17137aee2b1Sthorpej }
ACPI_DEVICE_CALL_REGISTER(DEVICE_ENUMERATE_CHILDREN_STR,acpi_device_enumerate_children)1726ed8e091Sthorpej ACPI_DEVICE_CALL_REGISTER(DEVICE_ENUMERATE_CHILDREN_STR,
17337aee2b1Sthorpej acpi_device_enumerate_children)
17437aee2b1Sthorpej
17537aee2b1Sthorpej /*
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
acpi_eval_set_integer(ACPI_HANDLE handle,const char * path,ACPI_INTEGER val)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
acpi_eval_string(ACPI_HANDLE handle,const char * path,char ** stringp)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
acpi_eval_struct(ACPI_HANDLE handle,const char * path,ACPI_BUFFER * buf)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
acpi_eval_reference_handle(ACPI_OBJECT * elm,ACPI_HANDLE * handle)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
acpi_foreach_package_object(ACPI_OBJECT * pkg,ACPI_STATUS (* func)(ACPI_OBJECT *,void *),void * arg)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
acpi_get(ACPI_HANDLE handle,ACPI_BUFFER * buf,ACPI_STATUS (* getit)(ACPI_HANDLE,ACPI_BUFFER *))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 *
acpi_name(ACPI_HANDLE handle)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 /*
394537afe45Sthorpej * Pack _HID and _CID ID strings into an OpenFirmware-style
39533af1b8eSthorpej * string list.
39633af1b8eSthorpej */
39733af1b8eSthorpej char *
acpi_pack_compat_list(struct acpi_devnode * ad,size_t * sizep)398*b61b358aSthorpej acpi_pack_compat_list(struct acpi_devnode *ad, size_t *sizep)
39933af1b8eSthorpej {
400*b61b358aSthorpej ACPI_DEVICE_INFO *devinfo = ad->ad_devinfo;
401*b61b358aSthorpej
40233af1b8eSthorpej KASSERT(sizep != NULL);
40333af1b8eSthorpej
404537afe45Sthorpej char *sl = NULL;
405537afe45Sthorpej size_t slsize = 0;
40633af1b8eSthorpej uint32_t i;
407*b61b358aSthorpej bool dtlink = false;
40833af1b8eSthorpej
409*b61b358aSthorpej ACPI_BUFFER buf;
410*b61b358aSthorpej ACPI_STATUS ret;
411*b61b358aSthorpej ACPI_OBJECT *obj;
412*b61b358aSthorpej char *compatible;
413*b61b358aSthorpej int n;
414*b61b358aSthorpej
415*b61b358aSthorpej buf.Pointer = NULL;
416*b61b358aSthorpej buf.Length = ACPI_ALLOCATE_BUFFER;
417*b61b358aSthorpej
418*b61b358aSthorpej if ((devinfo->Valid & ACPI_VALID_HID) != 0) {
419*b61b358aSthorpej const char *cp = devinfo->HardwareId.String;
420*b61b358aSthorpej
421*b61b358aSthorpej if (device_compatible_pmatch_strlist(cp, strlen(cp) + 1,
422*b61b358aSthorpej dtlink_compat_data)) {
423*b61b358aSthorpej dtlink = true;
424*b61b358aSthorpej } else {
425*b61b358aSthorpej strlist_append(&sl, &slsize, cp);
426*b61b358aSthorpej }
42733af1b8eSthorpej }
42833af1b8eSthorpej
429*b61b358aSthorpej if ((devinfo->Valid & ACPI_VALID_CID) != 0) {
430*b61b358aSthorpej for (i = 0; i < devinfo->CompatibleIdList.Count; i++) {
431*b61b358aSthorpej const char *cp =
432*b61b358aSthorpej devinfo->CompatibleIdList.Ids[i].String;
433*b61b358aSthorpej
434*b61b358aSthorpej if (device_compatible_pmatch_strlist(cp, strlen(cp) + 1,
435*b61b358aSthorpej dtlink_compat_data)) {
436*b61b358aSthorpej dtlink = true;
437*b61b358aSthorpej } else {
438*b61b358aSthorpej strlist_append(&sl, &slsize, cp);
439*b61b358aSthorpej }
440*b61b358aSthorpej }
441*b61b358aSthorpej }
442*b61b358aSthorpej
443*b61b358aSthorpej if (dtlink) {
444*b61b358aSthorpej ret = acpi_dsd_string(ad->ad_handle, "compatible",
445*b61b358aSthorpej &compatible);
446*b61b358aSthorpej if (ACPI_SUCCESS(ret)) {
447*b61b358aSthorpej strlist_append(&sl, &slsize, compatible);
448*b61b358aSthorpej kmem_strfree(compatible);
449*b61b358aSthorpej goto done;
450*b61b358aSthorpej }
451*b61b358aSthorpej
452*b61b358aSthorpej ret = acpi_dsd_property(ad->ad_handle, "compatible", &buf,
453*b61b358aSthorpej ACPI_TYPE_PACKAGE, &obj);
454*b61b358aSthorpej if (ACPI_FAILURE(ret)) {
455*b61b358aSthorpej goto done;
456*b61b358aSthorpej }
457*b61b358aSthorpej if (obj->Package.Count == 0) {
458*b61b358aSthorpej goto done;
459*b61b358aSthorpej }
460*b61b358aSthorpej for (n = 0; n < obj->Package.Count; n++) {
461*b61b358aSthorpej if (obj->Package.Elements[n].Type != ACPI_TYPE_STRING) {
462*b61b358aSthorpej continue;
463*b61b358aSthorpej }
464537afe45Sthorpej strlist_append(&sl, &slsize,
465*b61b358aSthorpej obj->Package.Elements[n].String.Pointer);
46633af1b8eSthorpej }
46733af1b8eSthorpej }
46833af1b8eSthorpej
469*b61b358aSthorpej done:
470*b61b358aSthorpej if (buf.Pointer != NULL) {
471*b61b358aSthorpej ACPI_FREE(buf.Pointer);
472*b61b358aSthorpej }
473537afe45Sthorpej *sizep = slsize;
474537afe45Sthorpej return sl;
475537afe45Sthorpej }
476537afe45Sthorpej
477537afe45Sthorpej /*
478537afe45Sthorpej * The ACPI_PNP_DEVICE_ID type is somewhat inconvenient for us to
479537afe45Sthorpej * use. We'll need some temporary space to pack it into an array
480537afe45Sthorpej * of C strings. Room for 8 should be plenty, but we can allocate
481537afe45Sthorpej * more if necessary.
482537afe45Sthorpej */
483537afe45Sthorpej #define ACPI_COMPATSTR_MAX 8
484537afe45Sthorpej
485537afe45Sthorpej static const char **
acpi_compatible_alloc_strarray(ACPI_PNP_DEVICE_ID * ids,unsigned int count,const char ** buf)486537afe45Sthorpej acpi_compatible_alloc_strarray(ACPI_PNP_DEVICE_ID *ids,
487537afe45Sthorpej unsigned int count, const char **buf)
488537afe45Sthorpej {
489537afe45Sthorpej unsigned int i;
490537afe45Sthorpej
491537afe45Sthorpej buf = kmem_tmpbuf_alloc(count * sizeof(const char *),
492537afe45Sthorpej buf, ACPI_COMPATSTR_MAX * sizeof(const char *), KM_SLEEP);
493537afe45Sthorpej for (i = 0; i < count; i++) {
494537afe45Sthorpej buf[i] = ids[i].String;
495537afe45Sthorpej }
496537afe45Sthorpej return buf;
497537afe45Sthorpej }
498537afe45Sthorpej
499537afe45Sthorpej static void
acpi_compatible_free_strarray(const char ** cpp,unsigned int count,const char ** buf)500537afe45Sthorpej acpi_compatible_free_strarray(const char **cpp, unsigned int count,
501537afe45Sthorpej const char **buf)
502537afe45Sthorpej {
503537afe45Sthorpej kmem_tmpbuf_free(cpp, count * sizeof(const char *), buf);
504537afe45Sthorpej }
505537afe45Sthorpej
506312915a9Sjmcneill static int
acpi_compatible_match_dtlink(const struct acpi_attach_args * const aa,const struct device_compatible_entry * const dce)507312915a9Sjmcneill acpi_compatible_match_dtlink(const struct acpi_attach_args * const aa,
508312915a9Sjmcneill const struct device_compatible_entry * const dce)
509312915a9Sjmcneill {
510312915a9Sjmcneill const char *strings[ACPI_COMPATSTR_MAX * sizeof(const char *)];
511312915a9Sjmcneill ACPI_HANDLE handle = aa->aa_node->ad_handle;
512312915a9Sjmcneill ACPI_BUFFER buf;
513312915a9Sjmcneill char *compatible;
514312915a9Sjmcneill ACPI_STATUS ret;
515312915a9Sjmcneill ACPI_OBJECT *obj;
516312915a9Sjmcneill int rv = 0, n;
517312915a9Sjmcneill
518312915a9Sjmcneill buf.Pointer = NULL;
519312915a9Sjmcneill buf.Length = ACPI_ALLOCATE_BUFFER;
520312915a9Sjmcneill
521312915a9Sjmcneill /* Match a single string _DSD value */
522312915a9Sjmcneill ret = acpi_dsd_string(handle, "compatible", &compatible);
523312915a9Sjmcneill if (ACPI_SUCCESS(ret)) {
524312915a9Sjmcneill strings[0] = compatible;
525312915a9Sjmcneill rv = device_compatible_pmatch(strings, 1, dce);
526312915a9Sjmcneill kmem_strfree(compatible);
527312915a9Sjmcneill goto done;
528312915a9Sjmcneill }
529312915a9Sjmcneill
530312915a9Sjmcneill /* Match from a list of strings in a _DSD value */
531312915a9Sjmcneill ret = acpi_dsd_property(handle, "compatible", &buf,
532312915a9Sjmcneill ACPI_TYPE_PACKAGE, &obj);
533312915a9Sjmcneill if (ACPI_FAILURE(ret)) {
534312915a9Sjmcneill goto done;
535312915a9Sjmcneill }
536312915a9Sjmcneill if (obj->Package.Count == 0) {
537312915a9Sjmcneill goto done;
538312915a9Sjmcneill }
539312915a9Sjmcneill for (n = 0; n < imin(obj->Package.Count, ACPI_COMPATSTR_MAX); n++) {
540312915a9Sjmcneill if (obj->Package.Elements[n].Type != ACPI_TYPE_STRING) {
541312915a9Sjmcneill goto done;
542312915a9Sjmcneill }
543312915a9Sjmcneill strings[n] = obj->Package.Elements[n].String.Pointer;
544312915a9Sjmcneill }
545312915a9Sjmcneill rv = device_compatible_pmatch(strings, n, dce);
546312915a9Sjmcneill
547312915a9Sjmcneill done:
548312915a9Sjmcneill if (buf.Pointer != NULL) {
549312915a9Sjmcneill ACPI_FREE(buf.Pointer);
550312915a9Sjmcneill }
551312915a9Sjmcneill if (rv) {
552312915a9Sjmcneill rv = (rv - 1) + ACPI_MATCHSCORE_CID;
553312915a9Sjmcneill return imin(rv, ACPI_MATCHSCORE_CID_MAX);
554312915a9Sjmcneill }
555312915a9Sjmcneill return 0;
556312915a9Sjmcneill }
557312915a9Sjmcneill
558537afe45Sthorpej /*
559537afe45Sthorpej * acpi_compatible_match --
560537afe45Sthorpej *
561537afe45Sthorpej * Returns a weighted match value, comparing the _HID and _CID
562a0b1e536Sandvar * IDs against a driver's compatibility data.
563537afe45Sthorpej */
564537afe45Sthorpej int
acpi_compatible_match(const struct acpi_attach_args * const aa,const struct device_compatible_entry * const dce)565537afe45Sthorpej acpi_compatible_match(const struct acpi_attach_args * const aa,
566537afe45Sthorpej const struct device_compatible_entry * const dce)
567537afe45Sthorpej {
568537afe45Sthorpej const char *strings[ACPI_COMPATSTR_MAX * sizeof(const char *)];
569537afe45Sthorpej const char **cpp;
5708b25d0adSjmcneill bool dtlink = false;
5718b25d0adSjmcneill int rv;
572537afe45Sthorpej
573537afe45Sthorpej if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) {
574537afe45Sthorpej return 0;
575537afe45Sthorpej }
576537afe45Sthorpej
577537afe45Sthorpej ACPI_DEVICE_INFO *ad = aa->aa_node->ad_devinfo;
578537afe45Sthorpej
579537afe45Sthorpej if ((ad->Valid & ACPI_VALID_HID) != 0) {
580537afe45Sthorpej strings[0] = ad->HardwareId.String;
581537afe45Sthorpej
582537afe45Sthorpej /* Matching _HID wins big. */
583537afe45Sthorpej if (device_compatible_pmatch(strings, 1, dce) != 0) {
584537afe45Sthorpej return ACPI_MATCHSCORE_HID;
585537afe45Sthorpej }
5868b25d0adSjmcneill
5878b25d0adSjmcneill if (device_compatible_pmatch(strings, 1,
5888b25d0adSjmcneill dtlink_compat_data) != 0) {
5898b25d0adSjmcneill dtlink = true;
5908b25d0adSjmcneill }
591537afe45Sthorpej }
592537afe45Sthorpej
593537afe45Sthorpej if ((ad->Valid & ACPI_VALID_CID) != 0) {
594537afe45Sthorpej cpp = acpi_compatible_alloc_strarray(ad->CompatibleIdList.Ids,
595537afe45Sthorpej ad->CompatibleIdList.Count, strings);
596537afe45Sthorpej
597537afe45Sthorpej rv = device_compatible_pmatch(cpp,
598537afe45Sthorpej ad->CompatibleIdList.Count, dce);
5998b25d0adSjmcneill if (!dtlink &&
6008b25d0adSjmcneill device_compatible_pmatch(cpp, ad->CompatibleIdList.Count,
6018b25d0adSjmcneill dtlink_compat_data) != 0) {
6028b25d0adSjmcneill dtlink = true;
6038b25d0adSjmcneill }
604537afe45Sthorpej acpi_compatible_free_strarray(cpp, ad->CompatibleIdList.Count,
605537afe45Sthorpej strings);
606537afe45Sthorpej if (rv) {
607537afe45Sthorpej rv = (rv - 1) + ACPI_MATCHSCORE_CID;
6088b25d0adSjmcneill return imin(rv, ACPI_MATCHSCORE_CID_MAX);
609537afe45Sthorpej }
6108b25d0adSjmcneill }
6118b25d0adSjmcneill
6128b25d0adSjmcneill if (dtlink) {
613312915a9Sjmcneill return acpi_compatible_match_dtlink(aa, dce);
614537afe45Sthorpej }
615537afe45Sthorpej
616537afe45Sthorpej return 0;
617537afe45Sthorpej }
618537afe45Sthorpej
619537afe45Sthorpej /*
620537afe45Sthorpej * acpi_compatible_lookup --
621537afe45Sthorpej *
622537afe45Sthorpej * Returns the device_compatible_entry that matches the _HID
623537afe45Sthorpej * or _CID ID.
624537afe45Sthorpej */
625537afe45Sthorpej const struct device_compatible_entry *
acpi_compatible_lookup(const struct acpi_attach_args * const aa,const struct device_compatible_entry * const dce)626537afe45Sthorpej acpi_compatible_lookup(const struct acpi_attach_args * const aa,
627537afe45Sthorpej const struct device_compatible_entry * const dce)
628537afe45Sthorpej {
629537afe45Sthorpej const struct device_compatible_entry *rv = NULL;
630537afe45Sthorpej const char *strings[ACPI_COMPATSTR_MAX];
631537afe45Sthorpej const char **cpp;
632537afe45Sthorpej
633537afe45Sthorpej if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) {
63433af1b8eSthorpej return NULL;
63533af1b8eSthorpej }
63633af1b8eSthorpej
637537afe45Sthorpej ACPI_DEVICE_INFO *ad = aa->aa_node->ad_devinfo;
63833af1b8eSthorpej
63933af1b8eSthorpej if ((ad->Valid & ACPI_VALID_HID) != 0) {
640537afe45Sthorpej strings[0] = ad->HardwareId.String;
641537afe45Sthorpej
642537afe45Sthorpej rv = device_compatible_plookup(strings, 1, dce);
643537afe45Sthorpej if (rv != NULL)
644537afe45Sthorpej return rv;
64533af1b8eSthorpej }
64633af1b8eSthorpej
64733af1b8eSthorpej if ((ad->Valid & ACPI_VALID_CID) != 0) {
648537afe45Sthorpej cpp = acpi_compatible_alloc_strarray(ad->CompatibleIdList.Ids,
649537afe45Sthorpej ad->CompatibleIdList.Count, strings);
650537afe45Sthorpej
651537afe45Sthorpej rv = device_compatible_plookup(cpp,
652537afe45Sthorpej ad->CompatibleIdList.Count, dce);
653537afe45Sthorpej acpi_compatible_free_strarray(cpp, ad->CompatibleIdList.Count,
654537afe45Sthorpej strings);
65533af1b8eSthorpej }
65633af1b8eSthorpej
657537afe45Sthorpej return rv;
65833af1b8eSthorpej }
65933af1b8eSthorpej
66033af1b8eSthorpej /*
661d6afaa44Sjruoho * Match given IDs against _HID and _CIDs.
6620c88d0e4Sjruoho */
6630c88d0e4Sjruoho int
acpi_match_hid(ACPI_DEVICE_INFO * ad,const char * const * ids)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
6964bd16782Sjruoho /*
697560c4949Sjmcneill * Match a PCI-defined bass-class, sub-class, and programming interface
698560c4949Sjmcneill * against a handle's _CLS object.
699560c4949Sjmcneill */
700560c4949Sjmcneill int
acpi_match_class(ACPI_HANDLE handle,uint8_t pci_class,uint8_t pci_subclass,uint8_t pci_interface)701560c4949Sjmcneill acpi_match_class(ACPI_HANDLE handle, uint8_t pci_class, uint8_t pci_subclass,
702560c4949Sjmcneill uint8_t pci_interface)
703560c4949Sjmcneill {
704560c4949Sjmcneill ACPI_BUFFER buf;
705560c4949Sjmcneill ACPI_OBJECT *obj;
706560c4949Sjmcneill ACPI_STATUS rv;
707560c4949Sjmcneill int match = 0;
708560c4949Sjmcneill
709560c4949Sjmcneill rv = acpi_eval_struct(handle, "_CLS", &buf);
710560c4949Sjmcneill if (ACPI_FAILURE(rv))
711560c4949Sjmcneill goto done;
712560c4949Sjmcneill
713560c4949Sjmcneill obj = buf.Pointer;
714560c4949Sjmcneill if (obj->Type != ACPI_TYPE_PACKAGE)
715560c4949Sjmcneill goto done;
716560c4949Sjmcneill if (obj->Package.Count != 3)
717560c4949Sjmcneill goto done;
718560c4949Sjmcneill if (obj->Package.Elements[0].Type != ACPI_TYPE_INTEGER ||
719560c4949Sjmcneill obj->Package.Elements[1].Type != ACPI_TYPE_INTEGER ||
720560c4949Sjmcneill obj->Package.Elements[2].Type != ACPI_TYPE_INTEGER)
721560c4949Sjmcneill goto done;
722560c4949Sjmcneill
723560c4949Sjmcneill match = obj->Package.Elements[0].Integer.Value == pci_class &&
724560c4949Sjmcneill obj->Package.Elements[1].Integer.Value == pci_subclass &&
725560c4949Sjmcneill obj->Package.Elements[2].Integer.Value == pci_interface;
726560c4949Sjmcneill
727560c4949Sjmcneill done:
728560c4949Sjmcneill if (buf.Pointer)
729560c4949Sjmcneill ACPI_FREE(buf.Pointer);
730537afe45Sthorpej return match ? ACPI_MATCHSCORE_CLS : 0;
731560c4949Sjmcneill }
732560c4949Sjmcneill
733560c4949Sjmcneill /*
7342d023696Sjruoho * Match a device node from a handle.
7352d023696Sjruoho */
7362d023696Sjruoho struct acpi_devnode *
acpi_match_node(ACPI_HANDLE handle)7372d023696Sjruoho acpi_match_node(ACPI_HANDLE handle)
7382d023696Sjruoho {
7392d023696Sjruoho struct acpi_devnode *ad;
7402d023696Sjruoho ACPI_STATUS rv;
7412d023696Sjruoho
7422d023696Sjruoho if (handle == NULL)
7432d023696Sjruoho return NULL;
7442d023696Sjruoho
7452d023696Sjruoho rv = AcpiGetData(handle, acpi_clean_node, (void **)&ad);
7462d023696Sjruoho
7472d023696Sjruoho if (ACPI_FAILURE(rv))
7482d023696Sjruoho return NULL;
7492d023696Sjruoho
7502d023696Sjruoho return ad;
7512d023696Sjruoho }
7522d023696Sjruoho
7532d023696Sjruoho /*
7542d023696Sjruoho * Permanently associate a device node with a handle.
7552d023696Sjruoho */
7562d023696Sjruoho void
acpi_match_node_init(struct acpi_devnode * ad)7572d023696Sjruoho acpi_match_node_init(struct acpi_devnode *ad)
7582d023696Sjruoho {
7592d023696Sjruoho (void)AcpiAttachData(ad->ad_handle, acpi_clean_node, ad);
7602d023696Sjruoho }
7612d023696Sjruoho
7622d023696Sjruoho static void
acpi_clean_node(ACPI_HANDLE handle,void * aux)7632d023696Sjruoho acpi_clean_node(ACPI_HANDLE handle, void *aux)
7642d023696Sjruoho {
7652d023696Sjruoho /* Nothing. */
7662d023696Sjruoho }
7672d023696Sjruoho
7682d023696Sjruoho /*
7694bd16782Sjruoho * Match a handle from a cpu_info. Returns NULL on failure.
7704bd16782Sjruoho *
7712d023696Sjruoho * Note that acpi_match_node() can be used if the device node
7722d023696Sjruoho * is also required.
7734bd16782Sjruoho */
7744bd16782Sjruoho ACPI_HANDLE
acpi_match_cpu_info(struct cpu_info * ci)7754bd16782Sjruoho acpi_match_cpu_info(struct cpu_info *ci)
7764bd16782Sjruoho {
7774bd16782Sjruoho struct acpi_softc *sc = acpi_softc;
7784bd16782Sjruoho struct acpi_devnode *ad;
7794bd16782Sjruoho ACPI_INTEGER val;
7804bd16782Sjruoho ACPI_OBJECT *obj;
7814bd16782Sjruoho ACPI_BUFFER buf;
7824bd16782Sjruoho ACPI_HANDLE hdl;
7834bd16782Sjruoho ACPI_STATUS rv;
7844bd16782Sjruoho
7854bd16782Sjruoho if (sc == NULL || acpi_active == 0)
7864bd16782Sjruoho return NULL;
7874bd16782Sjruoho
7884bd16782Sjruoho /*
7894bd16782Sjruoho * CPUs are declared in the ACPI namespace
7904bd16782Sjruoho * either as a Processor() or as a Device().
7914bd16782Sjruoho * In both cases the MADT entries are used
7924bd16782Sjruoho * for the match (see ACPI 4.0, section 8.4).
7934bd16782Sjruoho */
794ac3c40c2Sskrll SIMPLEQ_FOREACH(ad, &sc->sc_head, ad_list) {
7954bd16782Sjruoho
7964bd16782Sjruoho hdl = ad->ad_handle;
7974bd16782Sjruoho
7984bd16782Sjruoho switch (ad->ad_type) {
7994bd16782Sjruoho
8004bd16782Sjruoho case ACPI_TYPE_DEVICE:
8014bd16782Sjruoho
8024bd16782Sjruoho if (acpi_match_hid(ad->ad_devinfo, acpicpu_ids) == 0)
8034bd16782Sjruoho break;
8044bd16782Sjruoho
8054bd16782Sjruoho rv = acpi_eval_integer(hdl, "_UID", &val);
8064bd16782Sjruoho
8074bd16782Sjruoho if (ACPI_SUCCESS(rv) && val == ci->ci_acpiid)
8084bd16782Sjruoho return hdl;
8094bd16782Sjruoho
8104bd16782Sjruoho break;
8114bd16782Sjruoho
8124bd16782Sjruoho case ACPI_TYPE_PROCESSOR:
8134bd16782Sjruoho
8144bd16782Sjruoho rv = acpi_eval_struct(hdl, NULL, &buf);
8154bd16782Sjruoho
8164bd16782Sjruoho if (ACPI_FAILURE(rv))
8174bd16782Sjruoho break;
8184bd16782Sjruoho
8194bd16782Sjruoho obj = buf.Pointer;
8204bd16782Sjruoho
8214bd16782Sjruoho if (obj->Processor.ProcId == ci->ci_acpiid) {
8224bd16782Sjruoho ACPI_FREE(buf.Pointer);
8234bd16782Sjruoho return hdl;
8244bd16782Sjruoho }
8254bd16782Sjruoho
8264bd16782Sjruoho ACPI_FREE(buf.Pointer);
8274bd16782Sjruoho break;
8284bd16782Sjruoho }
8294bd16782Sjruoho }
8304bd16782Sjruoho
8314bd16782Sjruoho return NULL;
8324bd16782Sjruoho }
8334bd16782Sjruoho
8344bd16782Sjruoho /*
8354bd16782Sjruoho * Match a CPU from a handle. Returns NULL on failure.
8364bd16782Sjruoho */
8374bd16782Sjruoho struct cpu_info *
acpi_match_cpu_handle(ACPI_HANDLE hdl)8384bd16782Sjruoho acpi_match_cpu_handle(ACPI_HANDLE hdl)
8394bd16782Sjruoho {
8404bd16782Sjruoho struct cpu_info *ci;
8414bd16782Sjruoho ACPI_DEVICE_INFO *di;
8424bd16782Sjruoho CPU_INFO_ITERATOR cii;
8434bd16782Sjruoho ACPI_INTEGER val;
8444bd16782Sjruoho ACPI_OBJECT *obj;
8454bd16782Sjruoho ACPI_BUFFER buf;
8464bd16782Sjruoho ACPI_STATUS rv;
8474bd16782Sjruoho
8484bd16782Sjruoho ci = NULL;
8494bd16782Sjruoho di = NULL;
8504bd16782Sjruoho buf.Pointer = NULL;
8514bd16782Sjruoho
8524bd16782Sjruoho rv = AcpiGetObjectInfo(hdl, &di);
8534bd16782Sjruoho
8544bd16782Sjruoho if (ACPI_FAILURE(rv))
8554bd16782Sjruoho return NULL;
8564bd16782Sjruoho
8574bd16782Sjruoho switch (di->Type) {
8584bd16782Sjruoho
8594bd16782Sjruoho case ACPI_TYPE_DEVICE:
8604bd16782Sjruoho
8614bd16782Sjruoho if (acpi_match_hid(di, acpicpu_ids) == 0)
8624bd16782Sjruoho goto out;
8634bd16782Sjruoho
8644bd16782Sjruoho rv = acpi_eval_integer(hdl, "_UID", &val);
8654bd16782Sjruoho
8664bd16782Sjruoho if (ACPI_FAILURE(rv))
8674bd16782Sjruoho goto out;
8684bd16782Sjruoho
8694bd16782Sjruoho break;
8704bd16782Sjruoho
8714bd16782Sjruoho case ACPI_TYPE_PROCESSOR:
8724bd16782Sjruoho
8734bd16782Sjruoho rv = acpi_eval_struct(hdl, NULL, &buf);
8744bd16782Sjruoho
8754bd16782Sjruoho if (ACPI_FAILURE(rv))
8764bd16782Sjruoho goto out;
8774bd16782Sjruoho
8784bd16782Sjruoho obj = buf.Pointer;
8794bd16782Sjruoho val = obj->Processor.ProcId;
8804bd16782Sjruoho break;
8814bd16782Sjruoho
8824bd16782Sjruoho default:
8834bd16782Sjruoho goto out;
8844bd16782Sjruoho }
8854bd16782Sjruoho
8864bd16782Sjruoho for (CPU_INFO_FOREACH(cii, ci)) {
8874bd16782Sjruoho
8884bd16782Sjruoho if (ci->ci_acpiid == val)
8894bd16782Sjruoho goto out;
8904bd16782Sjruoho }
8914bd16782Sjruoho
8924bd16782Sjruoho ci = NULL;
8934bd16782Sjruoho
8944bd16782Sjruoho out:
8954bd16782Sjruoho if (di != NULL)
8964bd16782Sjruoho ACPI_FREE(di);
8974bd16782Sjruoho
8984bd16782Sjruoho if (buf.Pointer != NULL)
8994bd16782Sjruoho ACPI_FREE(buf.Pointer);
9004bd16782Sjruoho
9014bd16782Sjruoho return ci;
9024bd16782Sjruoho }
90327ab5385Sbouyer
90427ab5385Sbouyer struct acpi_irq_handler {
90527ab5385Sbouyer uint32_t aih_irq;
906488c5b15Sjmcneill void *aih_ih;
90727ab5385Sbouyer };
90827ab5385Sbouyer
90927ab5385Sbouyer void *
acpi_intr_establish(device_t dev,uint64_t c,int ipl,bool mpsafe,int (* intr)(void *),void * iarg,const char * xname)910488c5b15Sjmcneill acpi_intr_establish(device_t dev, uint64_t c, int ipl, bool mpsafe,
911488c5b15Sjmcneill int (*intr)(void *), void *iarg, const char *xname)
91227ab5385Sbouyer {
91327ab5385Sbouyer ACPI_STATUS rv;
914b4014e03Sbouyer ACPI_HANDLE hdl = (void *)(uintptr_t)c;
91527ab5385Sbouyer struct acpi_resources res;
91627ab5385Sbouyer struct acpi_irq *irq;
91753eb8527Sjmcneill void *aih = NULL;
91827ab5385Sbouyer
91927ab5385Sbouyer rv = acpi_resource_parse(dev, hdl, "_CRS", &res,
92027ab5385Sbouyer &acpi_resource_parse_ops_quiet);
92127ab5385Sbouyer if (ACPI_FAILURE(rv))
92227ab5385Sbouyer return NULL;
92327ab5385Sbouyer
92427ab5385Sbouyer irq = acpi_res_irq(&res, 0);
92527ab5385Sbouyer if (irq == NULL)
92627ab5385Sbouyer goto end;
92727ab5385Sbouyer
92853eb8527Sjmcneill aih = acpi_intr_establish_irq(dev, irq, ipl, mpsafe,
92953eb8527Sjmcneill intr, iarg, xname);
930488c5b15Sjmcneill
93127ab5385Sbouyer end:
93227ab5385Sbouyer acpi_resource_cleanup(&res);
93353eb8527Sjmcneill
93453eb8527Sjmcneill return aih;
93553eb8527Sjmcneill }
93653eb8527Sjmcneill
93753eb8527Sjmcneill void *
acpi_intr_establish_irq(device_t dev,struct acpi_irq * irq,int ipl,bool mpsafe,int (* intr)(void *),void * iarg,const char * xname)93853eb8527Sjmcneill acpi_intr_establish_irq(device_t dev, struct acpi_irq *irq, int ipl,
93953eb8527Sjmcneill bool mpsafe, int (*intr)(void *), void *iarg, const char *xname)
94053eb8527Sjmcneill {
94153eb8527Sjmcneill struct acpi_irq_handler *aih;
94253eb8527Sjmcneill void *ih;
94353eb8527Sjmcneill
94453eb8527Sjmcneill const int type = (irq->ar_type == ACPI_EDGE_SENSITIVE) ? IST_EDGE : IST_LEVEL;
94553eb8527Sjmcneill ih = acpi_md_intr_establish(irq->ar_irq, ipl, type, intr, iarg, mpsafe, xname);
94653eb8527Sjmcneill if (ih == NULL)
94753eb8527Sjmcneill return NULL;
94853eb8527Sjmcneill
94953eb8527Sjmcneill aih = kmem_alloc(sizeof(struct acpi_irq_handler), KM_SLEEP);
95053eb8527Sjmcneill aih->aih_irq = irq->ar_irq;
95153eb8527Sjmcneill aih->aih_ih = ih;
95253eb8527Sjmcneill
95327ab5385Sbouyer return aih;
95427ab5385Sbouyer }
95527ab5385Sbouyer
95627ab5385Sbouyer void
acpi_intr_mask(void * c)95797faf389Sthorpej acpi_intr_mask(void *c)
95897faf389Sthorpej {
95997faf389Sthorpej struct acpi_irq_handler * const aih = c;
96097faf389Sthorpej
96197faf389Sthorpej acpi_md_intr_mask(aih->aih_ih);
96297faf389Sthorpej }
96397faf389Sthorpej
96497faf389Sthorpej void
acpi_intr_unmask(void * c)96597faf389Sthorpej acpi_intr_unmask(void *c)
96697faf389Sthorpej {
96797faf389Sthorpej struct acpi_irq_handler * const aih = c;
96897faf389Sthorpej
96997faf389Sthorpej acpi_md_intr_unmask(aih->aih_ih);
97097faf389Sthorpej }
97197faf389Sthorpej
97297faf389Sthorpej void
acpi_intr_disestablish(void * c)973488c5b15Sjmcneill acpi_intr_disestablish(void *c)
97427ab5385Sbouyer {
97527ab5385Sbouyer struct acpi_irq_handler *aih = c;
97627ab5385Sbouyer
977488c5b15Sjmcneill acpi_md_intr_disestablish(aih->aih_ih);
97827ab5385Sbouyer kmem_free(aih, sizeof(struct acpi_irq_handler));
97927ab5385Sbouyer }
98027ab5385Sbouyer
98127ab5385Sbouyer const char *
acpi_intr_string(void * c,char * buf,size_t size)98227ab5385Sbouyer acpi_intr_string(void *c, char *buf, size_t size)
98327ab5385Sbouyer {
98427ab5385Sbouyer struct acpi_irq_handler *aih = c;
98527ab5385Sbouyer intr_handle_t ih = aih->aih_irq;
98627ab5385Sbouyer
98727ab5385Sbouyer return intr_string(ih, buf, size);
98827ab5385Sbouyer }
989ee3102aaSjmcneill
990ee3102aaSjmcneill /*
99133af1b8eSthorpej * Device-Specific Data (_DSD) support
992ee3102aaSjmcneill */
993ee3102aaSjmcneill
994ee3102aaSjmcneill static UINT8 acpi_dsd_uuid[ACPI_UUID_LENGTH] = {
995ee3102aaSjmcneill 0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d,
996ee3102aaSjmcneill 0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01
997ee3102aaSjmcneill };
998ee3102aaSjmcneill
99901fc4962Sjmcneill static ACPI_STATUS
acpi_dsd_property(ACPI_HANDLE handle,const char * prop,ACPI_BUFFER * pbuf,ACPI_OBJECT_TYPE type,ACPI_OBJECT ** ret)100001fc4962Sjmcneill acpi_dsd_property(ACPI_HANDLE handle, const char *prop, ACPI_BUFFER *pbuf, ACPI_OBJECT_TYPE type, ACPI_OBJECT **ret)
1001ee3102aaSjmcneill {
1002ee3102aaSjmcneill ACPI_OBJECT *obj, *uuid, *props, *pobj, *propkey, *propval;
1003ee3102aaSjmcneill ACPI_STATUS rv;
1004ee3102aaSjmcneill int n;
1005ee3102aaSjmcneill
100601fc4962Sjmcneill rv = AcpiEvaluateObjectTyped(handle, "_DSD", NULL, pbuf, ACPI_TYPE_PACKAGE);
1007ee3102aaSjmcneill if (ACPI_FAILURE(rv))
1008ee3102aaSjmcneill return rv;
1009ee3102aaSjmcneill
1010ee3102aaSjmcneill props = NULL;
101101fc4962Sjmcneill obj = (ACPI_OBJECT *)pbuf->Pointer;
1012ee3102aaSjmcneill for (n = 0; (n + 1) < obj->Package.Count; n += 2) {
1013ee3102aaSjmcneill uuid = &obj->Package.Elements[n];
1014ee3102aaSjmcneill if (uuid->Buffer.Length == ACPI_UUID_LENGTH &&
1015ee3102aaSjmcneill memcmp(uuid->Buffer.Pointer, acpi_dsd_uuid, ACPI_UUID_LENGTH) == 0) {
1016ee3102aaSjmcneill props = &obj->Package.Elements[n + 1];
1017ee3102aaSjmcneill break;
1018ee3102aaSjmcneill }
1019ee3102aaSjmcneill }
102001fc4962Sjmcneill if (props == NULL)
102101fc4962Sjmcneill return AE_NOT_FOUND;
1022ee3102aaSjmcneill
1023ee3102aaSjmcneill for (n = 0; n < props->Package.Count; n++) {
1024ee3102aaSjmcneill pobj = &props->Package.Elements[n];
1025ee3102aaSjmcneill if (pobj->Type != ACPI_TYPE_PACKAGE || pobj->Package.Count != 2)
1026ee3102aaSjmcneill continue;
1027ee3102aaSjmcneill propkey = (ACPI_OBJECT *)&pobj->Package.Elements[0];
1028ee3102aaSjmcneill propval = (ACPI_OBJECT *)&pobj->Package.Elements[1];
1029ee3102aaSjmcneill if (propkey->Type != ACPI_TYPE_STRING)
1030ee3102aaSjmcneill continue;
1031ee3102aaSjmcneill if (strcmp(propkey->String.Pointer, prop) != 0)
1032ee3102aaSjmcneill continue;
1033ee3102aaSjmcneill
103401fc4962Sjmcneill if (propval->Type != type) {
103501fc4962Sjmcneill return AE_TYPE;
1036ee3102aaSjmcneill } else {
103701fc4962Sjmcneill *ret = propval;
103801fc4962Sjmcneill return AE_OK;
1039ee3102aaSjmcneill }
1040ee3102aaSjmcneill break;
1041ee3102aaSjmcneill }
1042ee3102aaSjmcneill
104301fc4962Sjmcneill return AE_NOT_FOUND;
104401fc4962Sjmcneill }
104501fc4962Sjmcneill
104601fc4962Sjmcneill ACPI_STATUS
acpi_dsd_integer(ACPI_HANDLE handle,const char * prop,ACPI_INTEGER * val)104701fc4962Sjmcneill acpi_dsd_integer(ACPI_HANDLE handle, const char *prop, ACPI_INTEGER *val)
104801fc4962Sjmcneill {
104901fc4962Sjmcneill ACPI_OBJECT *propval;
105001fc4962Sjmcneill ACPI_STATUS rv;
105101fc4962Sjmcneill ACPI_BUFFER buf;
105201fc4962Sjmcneill
105301fc4962Sjmcneill buf.Pointer = NULL;
105401fc4962Sjmcneill buf.Length = ACPI_ALLOCATE_BUFFER;
105501fc4962Sjmcneill
105601fc4962Sjmcneill rv = acpi_dsd_property(handle, prop, &buf, ACPI_TYPE_INTEGER, &propval);
105701fc4962Sjmcneill if (ACPI_SUCCESS(rv))
105801fc4962Sjmcneill *val = propval->Integer.Value;
105901fc4962Sjmcneill
10601fd42d68Smlelstv if (buf.Pointer != NULL)
106101fc4962Sjmcneill ACPI_FREE(buf.Pointer);
106201fc4962Sjmcneill return rv;
106301fc4962Sjmcneill }
106401fc4962Sjmcneill
106501fc4962Sjmcneill ACPI_STATUS
acpi_dsd_string(ACPI_HANDLE handle,const char * prop,char ** val)106601fc4962Sjmcneill acpi_dsd_string(ACPI_HANDLE handle, const char *prop, char **val)
106701fc4962Sjmcneill {
106801fc4962Sjmcneill ACPI_OBJECT *propval;
106901fc4962Sjmcneill ACPI_STATUS rv;
107001fc4962Sjmcneill ACPI_BUFFER buf;
107101fc4962Sjmcneill
107201fc4962Sjmcneill buf.Pointer = NULL;
107301fc4962Sjmcneill buf.Length = ACPI_ALLOCATE_BUFFER;
107401fc4962Sjmcneill
107501fc4962Sjmcneill rv = acpi_dsd_property(handle, prop, &buf, ACPI_TYPE_STRING, &propval);
107601fc4962Sjmcneill if (ACPI_SUCCESS(rv))
107701fc4962Sjmcneill *val = kmem_strdup(propval->String.Pointer, KM_SLEEP);
107801fc4962Sjmcneill
10791fd42d68Smlelstv if (buf.Pointer != NULL)
1080ee3102aaSjmcneill ACPI_FREE(buf.Pointer);
1081ee3102aaSjmcneill return rv;
1082ee3102aaSjmcneill }
108333af1b8eSthorpej
10848430034eSjmcneill ACPI_STATUS
acpi_dsd_bool(ACPI_HANDLE handle,const char * prop,bool * val)10858430034eSjmcneill acpi_dsd_bool(ACPI_HANDLE handle, const char *prop, bool *val)
10868430034eSjmcneill {
10878430034eSjmcneill ACPI_STATUS rv;
10888430034eSjmcneill ACPI_INTEGER ival;
10898430034eSjmcneill
10908430034eSjmcneill rv = acpi_dsd_integer(handle, prop, &ival);
10918430034eSjmcneill if (ACPI_SUCCESS(rv)) {
10928430034eSjmcneill *val = ival != 0;
10938430034eSjmcneill }
10948430034eSjmcneill
10958430034eSjmcneill return rv;
10968430034eSjmcneill }
1097312915a9Sjmcneill
1098312915a9Sjmcneill
109933af1b8eSthorpej /*
110033af1b8eSthorpej * Device Specific Method (_DSM) support
110133af1b8eSthorpej */
110233af1b8eSthorpej
110333af1b8eSthorpej ACPI_STATUS
acpi_dsm_typed(ACPI_HANDLE handle,uint8_t * uuid,ACPI_INTEGER rev,ACPI_INTEGER func,const ACPI_OBJECT * arg3,ACPI_OBJECT_TYPE return_type,ACPI_OBJECT ** return_obj)110433af1b8eSthorpej acpi_dsm_typed(ACPI_HANDLE handle, uint8_t *uuid, ACPI_INTEGER rev,
110533af1b8eSthorpej ACPI_INTEGER func, const ACPI_OBJECT *arg3, ACPI_OBJECT_TYPE return_type,
110633af1b8eSthorpej ACPI_OBJECT **return_obj)
110733af1b8eSthorpej {
110833af1b8eSthorpej ACPI_OBJECT_LIST arg;
110933af1b8eSthorpej ACPI_OBJECT obj[4];
111033af1b8eSthorpej ACPI_BUFFER buf;
111133af1b8eSthorpej ACPI_STATUS status;
111233af1b8eSthorpej
111333af1b8eSthorpej arg.Count = 4;
111433af1b8eSthorpej arg.Pointer = obj;
111533af1b8eSthorpej
111633af1b8eSthorpej obj[0].Type = ACPI_TYPE_BUFFER;
111733af1b8eSthorpej obj[0].Buffer.Length = ACPI_UUID_LENGTH;
111833af1b8eSthorpej obj[0].Buffer.Pointer = uuid;
111933af1b8eSthorpej
112033af1b8eSthorpej obj[1].Type = ACPI_TYPE_INTEGER;
112133af1b8eSthorpej obj[1].Integer.Value = rev;
112233af1b8eSthorpej
112333af1b8eSthorpej obj[2].Type = ACPI_TYPE_INTEGER;
112433af1b8eSthorpej obj[2].Integer.Value = func;
112533af1b8eSthorpej
112633af1b8eSthorpej if (arg3 != NULL) {
112733af1b8eSthorpej obj[3] = *arg3;
112833af1b8eSthorpej } else {
112933af1b8eSthorpej obj[3].Type = ACPI_TYPE_PACKAGE;
113033af1b8eSthorpej obj[3].Package.Count = 0;
113133af1b8eSthorpej obj[3].Package.Elements = NULL;
113233af1b8eSthorpej }
113333af1b8eSthorpej
113433af1b8eSthorpej buf.Pointer = NULL;
113533af1b8eSthorpej buf.Length = ACPI_ALLOCATE_BUFFER;
113633af1b8eSthorpej
113733af1b8eSthorpej if (return_obj == NULL && return_type == ACPI_TYPE_ANY) {
113833af1b8eSthorpej status = AcpiEvaluateObject(handle, "_DSM", &arg, NULL);
113933af1b8eSthorpej } else {
114033af1b8eSthorpej *return_obj = NULL;
114133af1b8eSthorpej status = AcpiEvaluateObjectTyped(handle, "_DSM", &arg, &buf,
114233af1b8eSthorpej return_type);
114333af1b8eSthorpej }
114433af1b8eSthorpej if (ACPI_FAILURE(status)) {
114533af1b8eSthorpej return status;
114633af1b8eSthorpej }
114733af1b8eSthorpej if (return_obj != NULL) {
114833af1b8eSthorpej *return_obj = buf.Pointer;
114933af1b8eSthorpej } else if (buf.Pointer != NULL) {
115033af1b8eSthorpej ACPI_FREE(buf.Pointer);
115133af1b8eSthorpej }
115233af1b8eSthorpej return AE_OK;
115333af1b8eSthorpej }
115433af1b8eSthorpej
115533af1b8eSthorpej ACPI_STATUS
acpi_dsm_integer(ACPI_HANDLE handle,uint8_t * uuid,ACPI_INTEGER rev,ACPI_INTEGER func,const ACPI_OBJECT * arg3,ACPI_INTEGER * ret)115633af1b8eSthorpej acpi_dsm_integer(ACPI_HANDLE handle, uint8_t *uuid, ACPI_INTEGER rev,
115733af1b8eSthorpej ACPI_INTEGER func, const ACPI_OBJECT *arg3, ACPI_INTEGER *ret)
115833af1b8eSthorpej {
115933af1b8eSthorpej ACPI_OBJECT *obj;
116033af1b8eSthorpej ACPI_STATUS status;
116133af1b8eSthorpej
116233af1b8eSthorpej status = acpi_dsm_typed(handle, uuid, rev, func, arg3,
116333af1b8eSthorpej ACPI_TYPE_INTEGER, &obj);
116433af1b8eSthorpej if (ACPI_FAILURE(status)) {
116533af1b8eSthorpej return status;
116633af1b8eSthorpej }
116733af1b8eSthorpej
116833af1b8eSthorpej *ret = obj->Integer.Value;
116933af1b8eSthorpej ACPI_FREE(obj);
117033af1b8eSthorpej
117133af1b8eSthorpej return AE_OK;
117233af1b8eSthorpej }
117333af1b8eSthorpej
117433af1b8eSthorpej ACPI_STATUS
acpi_dsm(ACPI_HANDLE handle,uint8_t * uuid,ACPI_INTEGER rev,ACPI_INTEGER func,const ACPI_OBJECT * arg3,ACPI_OBJECT ** return_obj)117533af1b8eSthorpej acpi_dsm(ACPI_HANDLE handle, uint8_t *uuid, ACPI_INTEGER rev,
117633af1b8eSthorpej ACPI_INTEGER func, const ACPI_OBJECT *arg3, ACPI_OBJECT **return_obj)
117733af1b8eSthorpej {
117833af1b8eSthorpej return acpi_dsm_typed(handle, uuid, rev, func, arg3, ACPI_TYPE_ANY,
117933af1b8eSthorpej return_obj);
118033af1b8eSthorpej }
11812ae5b509Sjmcneill
11822ae5b509Sjmcneill ACPI_STATUS
acpi_dsm_query(ACPI_HANDLE handle,uint8_t * uuid,ACPI_INTEGER rev,ACPI_INTEGER * ret)1183ae008ef2Sjmcneill acpi_dsm_query(ACPI_HANDLE handle, uint8_t *uuid, ACPI_INTEGER rev,
1184ae008ef2Sjmcneill ACPI_INTEGER *ret)
1185ae008ef2Sjmcneill {
1186ae008ef2Sjmcneill ACPI_OBJECT *obj;
1187ae008ef2Sjmcneill ACPI_STATUS status;
1188ae008ef2Sjmcneill uint8_t *data;
1189ae008ef2Sjmcneill u_int n;
1190ae008ef2Sjmcneill
1191ae008ef2Sjmcneill status = acpi_dsm(handle, uuid, rev, 0, NULL, &obj);
1192ae008ef2Sjmcneill if (ACPI_FAILURE(status)) {
1193ae008ef2Sjmcneill return status;
1194ae008ef2Sjmcneill }
1195ae008ef2Sjmcneill
1196ae008ef2Sjmcneill if (obj->Type == ACPI_TYPE_INTEGER) {
1197ae008ef2Sjmcneill *ret = obj->Integer.Value;
1198ae008ef2Sjmcneill } else if (obj->Type == ACPI_TYPE_BUFFER &&
1199ae008ef2Sjmcneill obj->Buffer.Length <= 8) {
1200ae008ef2Sjmcneill *ret = 0;
1201ae008ef2Sjmcneill data = (uint8_t *)obj->Buffer.Pointer;
1202ae008ef2Sjmcneill for (n = 0; n < obj->Buffer.Length; n++) {
1203ae008ef2Sjmcneill *ret |= (uint64_t)data[n] << (n * 8);
1204ae008ef2Sjmcneill }
1205ae008ef2Sjmcneill } else {
1206ae008ef2Sjmcneill status = AE_TYPE;
1207ae008ef2Sjmcneill }
1208ae008ef2Sjmcneill
1209ae008ef2Sjmcneill ACPI_FREE(obj);
1210ae008ef2Sjmcneill
1211ae008ef2Sjmcneill return status;
1212ae008ef2Sjmcneill }
1213ae008ef2Sjmcneill
1214ae008ef2Sjmcneill ACPI_STATUS
acpi_claim_childdevs(device_t dev,struct acpi_devnode * devnode)12152ae5b509Sjmcneill acpi_claim_childdevs(device_t dev, struct acpi_devnode *devnode)
12162ae5b509Sjmcneill {
12172ae5b509Sjmcneill struct acpi_devnode *ad;
12182ae5b509Sjmcneill
12192ae5b509Sjmcneill SIMPLEQ_FOREACH(ad, &devnode->ad_child_head, ad_child_list) {
12202ae5b509Sjmcneill if (ad->ad_device != NULL)
12212ae5b509Sjmcneill continue;
12226a1f27f6Sjmcneill aprint_debug_dev(dev, "claiming %s\n",
12236a1f27f6Sjmcneill acpi_name(ad->ad_handle));
12242ae5b509Sjmcneill ad->ad_device = dev;
12252ae5b509Sjmcneill acpi_claim_childdevs(dev, ad);
12262ae5b509Sjmcneill }
12272ae5b509Sjmcneill
12282ae5b509Sjmcneill return AE_OK;
12292ae5b509Sjmcneill }
1230