acpi.c revision 1.286
1/*	$NetBSD: acpi.c,v 1.286 2020/11/08 14:16:59 jmcneill Exp $	*/
2
3/*-
4 * Copyright (c) 2003, 2007 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum of By Noon Software, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/*
33 * Copyright (c) 2003 Wasabi Systems, Inc.
34 * All rights reserved.
35 *
36 * Written by Frank van der Linden for Wasabi Systems, Inc.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 *    notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 *    notice, this list of conditions and the following disclaimer in the
45 *    documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software
47 *    must display the following acknowledgement:
48 *      This product includes software developed for the NetBSD Project by
49 *      Wasabi Systems, Inc.
50 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
51 *    or promote products derived from this software without specific prior
52 *    written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
56 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
57 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
58 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
59 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
60 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
61 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
62 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
63 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
64 * POSSIBILITY OF SUCH DAMAGE.
65 */
66
67/*
68 * Copyright 2001, 2003 Wasabi Systems, Inc.
69 * All rights reserved.
70 *
71 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
72 *
73 * Redistribution and use in source and binary forms, with or without
74 * modification, are permitted provided that the following conditions
75 * are met:
76 * 1. Redistributions of source code must retain the above copyright
77 *    notice, this list of conditions and the following disclaimer.
78 * 2. Redistributions in binary form must reproduce the above copyright
79 *    notice, this list of conditions and the following disclaimer in the
80 *    documentation and/or other materials provided with the distribution.
81 * 3. All advertising materials mentioning features or use of this software
82 *    must display the following acknowledgement:
83 *	This product includes software developed for the NetBSD Project by
84 *	Wasabi Systems, Inc.
85 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
86 *    or promote products derived from this software without specific prior
87 *    written permission.
88 *
89 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
90 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
91 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
92 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
93 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
94 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
95 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
96 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
97 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
98 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
99 * POSSIBILITY OF SUCH DAMAGE.
100 */
101
102#include <sys/cdefs.h>
103__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.286 2020/11/08 14:16:59 jmcneill Exp $");
104
105#include "pci.h"
106#include "opt_acpi.h"
107#include "opt_pcifixup.h"
108
109#include <sys/param.h>
110#include <sys/device.h>
111#include <sys/kernel.h>
112#include <sys/kmem.h>
113#include <sys/malloc.h>
114#include <sys/module.h>
115#include <sys/mutex.h>
116#include <sys/sysctl.h>
117#include <sys/systm.h>
118#include <sys/timetc.h>
119
120#include <dev/acpi/acpireg.h>
121#include <dev/acpi/acpivar.h>
122#include <dev/acpi/acpi_mcfg.h>
123#include <dev/acpi/acpi_osd.h>
124#include <dev/acpi/acpi_pci.h>
125#include <dev/acpi/acpi_power.h>
126#include <dev/acpi/acpi_timer.h>
127#include <dev/acpi/acpi_wakedev.h>
128
129#include <machine/acpi_machdep.h>
130
131#include "ioconf.h"
132
133#define _COMPONENT	ACPI_BUS_COMPONENT
134ACPI_MODULE_NAME	("acpi")
135
136/*
137 * The acpi_active variable is set when the ACPI subsystem is active.
138 * Machine-dependent code may wish to skip other steps (such as attaching
139 * subsystems that ACPI supercedes) when ACPI is active.
140 */
141int		acpi_active = 0;
142int		acpi_suspended = 0;
143int		acpi_force_load = 0;
144int		acpi_verbose_loaded = 0;
145
146struct acpi_softc	*acpi_softc = NULL;
147static uint64_t		 acpi_root_pointer;
148extern kmutex_t		 acpi_interrupt_list_mtx;
149static ACPI_HANDLE	 acpi_scopes[4];
150ACPI_TABLE_HEADER	*madt_header;
151ACPI_TABLE_HEADER	*gtdt_header;
152
153/*
154 * This structure provides a context for the ACPI
155 * namespace walk performed in acpi_build_tree().
156 */
157struct acpi_walkcontext {
158	struct acpi_softc	*aw_sc;
159	struct acpi_devnode	*aw_parent;
160};
161
162/*
163 * Ignored HIDs.
164 */
165static const char * const acpi_ignored_ids[] = {
166#if defined(i386) || defined(x86_64)
167	"ACPI0007",	/* ACPI CPUs do not attach to acpi(4) */
168	"PNP0000",	/* AT interrupt controller is handled internally */
169	"PNP0001",	/* EISA interrupt controller is handled internally */
170	"PNP0200",	/* AT DMA controller is handled internally */
171	"PNP0A??",	/* PCI Busses are handled internally */
172	"PNP0B00",	/* AT RTC is handled internally */
173	"PNP0C02",	/* PnP motherboard resources */
174	"PNP0C0F",	/* ACPI PCI link devices are handled internally */
175#endif
176#if defined(x86_64)
177	"PNP0C04",	/* FPU is handled internally */
178#endif
179#if defined(__aarch64__)
180	"ACPI0004",	/* ACPI module devices are handled internally */
181	"ACPI0007",	/* ACPI CPUs are attached via MADT GICC subtables */
182	"PNP0C0F",	/* ACPI PCI link devices are handled internally */
183#endif
184	NULL
185};
186
187/*
188 * Devices that should be attached early.
189 */
190static const char * const acpi_early_ids[] = {
191	"PNP0C09",	/* acpiec(4) */
192	NULL
193};
194
195static int		acpi_match(device_t, cfdata_t, void *);
196static int		acpi_submatch(device_t, cfdata_t, const int *, void *);
197static void		acpi_attach(device_t, device_t, void *);
198static int		acpi_detach(device_t, int);
199static void		acpi_childdet(device_t, device_t);
200static bool		acpi_suspend(device_t, const pmf_qual_t *);
201static bool		acpi_resume(device_t, const pmf_qual_t *);
202
203static void		acpi_build_tree(struct acpi_softc *);
204static void		acpi_config_tree(struct acpi_softc *);
205static void		acpi_config_dma(struct acpi_softc *);
206static ACPI_STATUS	acpi_make_devnode(ACPI_HANDLE, uint32_t,
207					  void *, void **);
208static ACPI_STATUS	acpi_make_devnode_post(ACPI_HANDLE, uint32_t,
209					       void *, void **);
210static void		acpi_make_name(struct acpi_devnode *, uint32_t);
211
212static int		acpi_rescan(device_t, const char *, const int *);
213static void		acpi_rescan_early(struct acpi_softc *);
214static void		acpi_rescan_nodes(struct acpi_softc *);
215static void		acpi_rescan_capabilities(device_t);
216static int		acpi_print(void *aux, const char *);
217
218static void		acpi_notify_handler(ACPI_HANDLE, uint32_t, void *);
219
220static void		acpi_register_fixed_button(struct acpi_softc *, int);
221static void		acpi_deregister_fixed_button(struct acpi_softc *, int);
222static uint32_t		acpi_fixed_button_handler(void *);
223static void		acpi_fixed_button_pressed(void *);
224
225static void		acpi_sleep_init(struct acpi_softc *);
226
227static int		sysctl_hw_acpi_fixedstats(SYSCTLFN_PROTO);
228static int		sysctl_hw_acpi_sleepstate(SYSCTLFN_PROTO);
229static int		sysctl_hw_acpi_sleepstates(SYSCTLFN_PROTO);
230
231static bool		  acpi_is_scope(struct acpi_devnode *);
232static ACPI_TABLE_HEADER *acpi_map_rsdt(void);
233static void		  acpi_unmap_rsdt(ACPI_TABLE_HEADER *);
234
235void			acpi_print_verbose_stub(struct acpi_softc *);
236void			acpi_print_dev_stub(const char *);
237
238static void		acpi_activate_device(ACPI_HANDLE, ACPI_DEVICE_INFO **);
239ACPI_STATUS		acpi_allocate_resources(ACPI_HANDLE);
240
241void (*acpi_print_verbose)(struct acpi_softc *) = acpi_print_verbose_stub;
242void (*acpi_print_dev)(const char *) = acpi_print_dev_stub;
243
244bus_dma_tag_t		acpi_default_dma_tag(struct acpi_softc *, struct acpi_devnode *);
245bus_dma_tag_t		acpi_default_dma64_tag(struct acpi_softc *, struct acpi_devnode *);
246pci_chipset_tag_t	acpi_default_pci_chipset_tag(struct acpi_softc *, int, int);
247
248CFATTACH_DECL2_NEW(acpi, sizeof(struct acpi_softc),
249    acpi_match, acpi_attach, acpi_detach, NULL, acpi_rescan, acpi_childdet);
250
251/*
252 * Probe for ACPI support.
253 *
254 * This is called by the machine-dependent ACPI front-end.
255 * Note: this is not an autoconfiguration interface function.
256 */
257int
258acpi_probe(void)
259{
260	ACPI_TABLE_HEADER *rsdt;
261	ACPI_STATUS rv;
262	int quirks;
263
264	if (acpi_softc != NULL)
265		panic("%s: already probed", __func__);
266
267	mutex_init(&acpi_interrupt_list_mtx, MUTEX_DEFAULT, IPL_NONE);
268
269	/*
270	 * Start up ACPICA.
271	 */
272	AcpiGbl_EnableInterpreterSlack = true;
273
274	rv = AcpiInitializeSubsystem();
275
276	if (ACPI_FAILURE(rv)) {
277		aprint_error("%s: failed to initialize subsystem\n", __func__);
278		return 0;
279	}
280
281	/*
282	 * Allocate space for RSDT/XSDT and DSDT,
283	 * but allow resizing if more tables exist.
284	 */
285	rv = AcpiInitializeTables(NULL, 2, true);
286
287	if (ACPI_FAILURE(rv)) {
288		aprint_error("%s: failed to initialize tables\n", __func__);
289		goto fail;
290	}
291
292	rv = AcpiLoadTables();
293
294	if (ACPI_FAILURE(rv)) {
295		aprint_error("%s: failed to load tables\n", __func__);
296		goto fail;
297	}
298
299	rsdt = acpi_map_rsdt();
300
301	if (rsdt == NULL) {
302		aprint_error("%s: failed to map RSDT\n", __func__);
303		goto fail;
304	}
305
306	quirks = acpi_find_quirks();
307
308	if (acpi_force_load == 0 && (quirks & ACPI_QUIRK_BROKEN) != 0) {
309
310		aprint_normal("ACPI: BIOS is listed as broken:\n");
311		aprint_normal("ACPI: X/RSDT: OemId <%6.6s,%8.8s,%08x>, "
312		       "AslId <%4.4s,%08x>\n", rsdt->OemId, rsdt->OemTableId,
313		        rsdt->OemRevision, rsdt->AslCompilerId,
314		        rsdt->AslCompilerRevision);
315		aprint_normal("ACPI: Not used. Set acpi_force_load to use.\n");
316
317		acpi_unmap_rsdt(rsdt);
318		goto fail;
319	}
320
321	if (acpi_force_load == 0 && (quirks & ACPI_QUIRK_OLDBIOS) != 0) {
322
323		aprint_normal("ACPI: BIOS is too old (%s). "
324		    "Set acpi_force_load to use.\n",
325		    pmf_get_platform("bios-date"));
326
327		acpi_unmap_rsdt(rsdt);
328		goto fail;
329	}
330
331	acpi_unmap_rsdt(rsdt);
332
333	rv = AcpiEnableSubsystem(~(ACPI_NO_HARDWARE_INIT|ACPI_NO_ACPI_ENABLE));
334
335	if (ACPI_FAILURE(rv)) {
336		aprint_error("%s: failed to enable subsystem\n", __func__);
337		goto fail;
338	}
339
340	return 1;
341
342fail:
343	(void)AcpiTerminate();
344
345	return 0;
346}
347
348void
349acpi_disable(void)
350{
351
352	if (acpi_softc == NULL)
353		return;
354
355	KASSERT(acpi_active != 0);
356
357	if (AcpiGbl_FADT.SmiCommand != 0)
358		AcpiDisable();
359}
360
361int
362acpi_check(device_t parent, const char *ifattr)
363{
364	return (config_search_ia(acpi_submatch, parent, ifattr, NULL) != NULL);
365}
366
367int
368acpi_reset(void)
369{
370	struct acpi_softc *sc = acpi_softc;
371	ACPI_GENERIC_ADDRESS *ResetReg;
372	ACPI_PCI_ID PciId;
373	ACPI_STATUS status;
374
375	if (sc == NULL)
376		return ENXIO;
377
378	ResetReg = &AcpiGbl_FADT.ResetRegister;
379
380	/* Check if the reset register is supported */
381	if (!(AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER) ||
382	    !ResetReg->Address) {
383		return ENOENT;
384	}
385
386	switch (ResetReg->SpaceId) {
387	case ACPI_ADR_SPACE_PCI_CONFIG:
388		PciId.Segment = PciId.Bus = 0;
389		PciId.Device = ACPI_GAS_PCI_DEV(ResetReg->Address);
390		PciId.Function = ACPI_GAS_PCI_FUNC(ResetReg->Address);
391		status = AcpiOsWritePciConfiguration(&PciId,
392		    ACPI_GAS_PCI_REGOFF(ResetReg->Address),
393		    AcpiGbl_FADT.ResetValue, ResetReg->BitWidth);
394		break;
395	case ACPI_ADR_SPACE_SYSTEM_IO:
396	case ACPI_ADR_SPACE_SYSTEM_MEMORY:
397		status = AcpiReset();
398		break;
399	default:
400		status = AE_TYPE;
401		break;
402	}
403
404	return ACPI_FAILURE(status) ? EIO : 0;
405}
406
407/*
408 * Autoconfiguration.
409 */
410static int
411acpi_match(device_t parent, cfdata_t match, void *aux)
412{
413	/*
414	 * XXX: Nada; MD code has called acpi_probe().
415	 */
416	return 1;
417}
418
419static int
420acpi_submatch(device_t parent, cfdata_t cf, const int *locs, void *aux)
421{
422	struct cfattach *ca;
423
424	ca = config_cfattach_lookup(cf->cf_name, cf->cf_atname);
425
426	return (ca == &acpi_ca);
427}
428
429static void
430acpi_attach(device_t parent, device_t self, void *aux)
431{
432	struct acpi_softc *sc = device_private(self);
433	struct acpibus_attach_args *aa = aux;
434	ACPI_TABLE_HEADER *rsdt;
435	ACPI_STATUS rv;
436
437	aprint_naive("\n");
438	aprint_normal(": Intel ACPICA %08x\n", ACPI_CA_VERSION);
439
440	if (acpi_softc != NULL)
441		panic("%s: already attached", __func__);
442
443	rsdt = acpi_map_rsdt();
444
445	if (rsdt == NULL)
446		aprint_error_dev(self, "X/RSDT: Not found\n");
447	else {
448		aprint_verbose_dev(self,
449		    "X/RSDT: OemId <%6.6s,%8.8s,%08x>, AslId <%4.4s,%08x>\n",
450		    rsdt->OemId, rsdt->OemTableId,
451		    rsdt->OemRevision,
452		    rsdt->AslCompilerId, rsdt->AslCompilerRevision);
453	}
454
455	acpi_unmap_rsdt(rsdt);
456
457	sc->sc_dev = self;
458	sc->sc_root = NULL;
459
460	sc->sc_sleepstate = ACPI_STATE_S0;
461	sc->sc_quirks = acpi_find_quirks();
462
463	sysmon_power_settype("acpi");
464
465	sc->sc_iot = aa->aa_iot;
466	sc->sc_memt = aa->aa_memt;
467	sc->sc_pciflags = aa->aa_pciflags;
468	sc->sc_ic = aa->aa_ic;
469	sc->sc_dmat = aa->aa_dmat;
470	sc->sc_dmat64 = aa->aa_dmat64;
471
472	SIMPLEQ_INIT(&sc->ad_head);
473
474	acpi_softc = sc;
475
476	if (pmf_device_register(self, acpi_suspend, acpi_resume) != true)
477		aprint_error_dev(self, "couldn't establish power handler\n");
478
479	/*
480	 * Bring ACPICA on-line.
481	 */
482
483	rv = AcpiEnableSubsystem(ACPI_FULL_INITIALIZATION);
484
485	if (ACPI_FAILURE(rv))
486		goto fail;
487
488	/*
489	 * Early initialization of acpiec(4) via ECDT.
490	 */
491	(void)config_found_ia(self, "acpiecdtbus", aa, NULL);
492
493	rv = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION);
494
495	if (ACPI_FAILURE(rv))
496		goto fail;
497
498	/*
499	 * Scan the namespace and build our device tree.
500	 */
501	acpi_build_tree(sc);
502
503#if NPCI > 0
504	/*
505	 * Probe MCFG table
506	 */
507	acpimcfg_probe(sc);
508#endif
509
510	acpi_md_callback(sc);
511
512	/*
513	 * Early initialization of the _PDC control method
514	 * that may load additional SSDT tables dynamically.
515	 */
516	(void)acpi_md_pdc();
517
518	/*
519	 * Install global notify handlers.
520	 */
521	rv = AcpiInstallNotifyHandler(ACPI_ROOT_OBJECT,
522	    ACPI_SYSTEM_NOTIFY, acpi_notify_handler, NULL);
523
524	if (ACPI_FAILURE(rv))
525		goto fail;
526
527	rv = AcpiInstallNotifyHandler(ACPI_ROOT_OBJECT,
528	    ACPI_DEVICE_NOTIFY, acpi_notify_handler, NULL);
529
530	if (ACPI_FAILURE(rv))
531		goto fail;
532
533	acpi_active = 1;
534
535	if (!AcpiGbl_ReducedHardware) {
536		/* Show SCI interrupt. */
537		aprint_verbose_dev(self, "SCI interrupting at int %u\n",
538		    AcpiGbl_FADT.SciInterrupt);
539
540		/*
541		 * Install fixed-event handlers.
542		 */
543		acpi_register_fixed_button(sc, ACPI_EVENT_POWER_BUTTON);
544		acpi_register_fixed_button(sc, ACPI_EVENT_SLEEP_BUTTON);
545	}
546
547	acpitimer_init(sc);
548	acpi_config_tree(sc);
549	acpi_sleep_init(sc);
550
551#ifdef ACPI_DEBUG
552	acpi_debug_init();
553#endif
554
555	/*
556	 * Print debug information.
557	 */
558	acpi_print_verbose(sc);
559
560	return;
561
562fail:
563	aprint_error("%s: failed to initialize ACPI: %s\n",
564	    __func__, AcpiFormatException(rv));
565}
566
567/*
568 * XXX: This is incomplete.
569 */
570static int
571acpi_detach(device_t self, int flags)
572{
573	struct acpi_softc *sc = device_private(self);
574	ACPI_STATUS rv;
575	int rc;
576
577	rv = AcpiRemoveNotifyHandler(ACPI_ROOT_OBJECT,
578	    ACPI_SYSTEM_NOTIFY, acpi_notify_handler);
579
580	if (ACPI_FAILURE(rv))
581		return EBUSY;
582
583	rv = AcpiRemoveNotifyHandler(ACPI_ROOT_OBJECT,
584	    ACPI_DEVICE_NOTIFY, acpi_notify_handler);
585
586	if (ACPI_FAILURE(rv))
587		return EBUSY;
588
589	if ((rc = config_detach_children(self, flags)) != 0)
590		return rc;
591
592	if ((rc = acpitimer_detach()) != 0)
593		return rc;
594
595	if (!AcpiGbl_ReducedHardware) {
596		acpi_deregister_fixed_button(sc, ACPI_EVENT_POWER_BUTTON);
597		acpi_deregister_fixed_button(sc, ACPI_EVENT_SLEEP_BUTTON);
598	}
599
600	pmf_device_deregister(self);
601
602	acpi_softc = NULL;
603
604	return 0;
605}
606
607static void
608acpi_childdet(device_t self, device_t child)
609{
610	struct acpi_softc *sc = device_private(self);
611	struct acpi_devnode *ad;
612
613	if (sc->sc_apmbus == child)
614		sc->sc_apmbus = NULL;
615
616	if (sc->sc_hpet == child)
617		sc->sc_hpet = NULL;
618
619	if (sc->sc_wdrt == child)
620		sc->sc_wdrt = NULL;
621
622	SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) {
623
624		if (ad->ad_device == child)
625			ad->ad_device = NULL;
626	}
627}
628
629static bool
630acpi_suspend(device_t dv, const pmf_qual_t *qual)
631{
632
633	acpi_suspended = 1;
634
635	return true;
636}
637
638static bool
639acpi_resume(device_t dv, const pmf_qual_t *qual)
640{
641
642	acpi_suspended = 0;
643
644	return true;
645}
646
647/*
648 * Namespace scan.
649 */
650static void
651acpi_build_tree(struct acpi_softc *sc)
652{
653	struct acpi_walkcontext awc;
654
655	/*
656	 * Get the root scope handles.
657	 */
658	KASSERT(__arraycount(acpi_scopes) == 4);
659
660	(void)AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_PR_", &acpi_scopes[0]);
661	(void)AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SB_", &acpi_scopes[1]);
662	(void)AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SI_", &acpi_scopes[2]);
663	(void)AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_TZ_", &acpi_scopes[3]);
664
665	/*
666	 * Make the root node.
667	 */
668	awc.aw_sc = sc;
669	awc.aw_parent = NULL;
670
671	(void)acpi_make_devnode(ACPI_ROOT_OBJECT, 0, &awc, NULL);
672
673	KASSERT(sc->sc_root == NULL);
674	KASSERT(awc.aw_parent != NULL);
675
676	sc->sc_root = awc.aw_parent;
677
678	/*
679	 * Build the internal namespace.
680	 */
681	(void)AcpiWalkNamespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, UINT32_MAX,
682	    acpi_make_devnode, acpi_make_devnode_post, &awc, NULL);
683
684	/*
685	 * Scan the internal namespace.
686	 */
687	(void)acpi_pcidev_scan(sc->sc_root);
688}
689
690static void
691acpi_config_tree(struct acpi_softc *sc)
692{
693	/*
694	 * Assign bus_dma resources
695	 */
696	acpi_config_dma(sc);
697
698	/*
699	 * Configure all everything found "at acpi?".
700	 */
701	(void)acpi_rescan(sc->sc_dev, NULL, NULL);
702
703	/*
704	 * Update GPE information.
705	 *
706	 * Note that this must be called after
707	 * all GPE handlers have been installed.
708	 */
709	(void)AcpiUpdateAllGpes();
710
711	/*
712	 * Defer rest of the configuration.
713	 */
714	(void)config_defer(sc->sc_dev, acpi_rescan_capabilities);
715}
716
717static void
718acpi_config_dma(struct acpi_softc *sc)
719{
720	struct acpi_devnode *ad;
721
722	SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) {
723
724		if (ad->ad_device != NULL)
725			continue;
726
727		if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE)
728			continue;
729
730		ad->ad_dmat = acpi_get_dma_tag(sc, ad);
731		ad->ad_dmat64 = acpi_get_dma64_tag(sc, ad);
732	}
733}
734
735static ACPI_STATUS
736acpi_make_devnode(ACPI_HANDLE handle, uint32_t level,
737    void *context, void **status)
738{
739	struct acpi_walkcontext *awc = context;
740	struct acpi_softc *sc = awc->aw_sc;
741	struct acpi_devnode *ad;
742	ACPI_DEVICE_INFO *devinfo;
743	ACPI_OBJECT_TYPE type;
744	ACPI_STATUS rv;
745
746	rv = AcpiGetObjectInfo(handle, &devinfo);
747
748	if (ACPI_FAILURE(rv))
749		return AE_OK;	/* Do not terminate the walk. */
750
751	type = devinfo->Type;
752
753	switch (type) {
754
755	case ACPI_TYPE_DEVICE:
756		acpi_activate_device(handle, &devinfo);
757		/* FALLTHROUGH */
758
759	case ACPI_TYPE_PROCESSOR:
760	case ACPI_TYPE_THERMAL:
761	case ACPI_TYPE_POWER:
762
763		ad = kmem_zalloc(sizeof(*ad), KM_SLEEP);
764
765		ad->ad_device = NULL;
766		ad->ad_notify = NULL;
767		ad->ad_pciinfo = NULL;
768		ad->ad_wakedev = NULL;
769
770		ad->ad_type = type;
771		ad->ad_handle = handle;
772		ad->ad_devinfo = devinfo;
773
774		ad->ad_root = sc->sc_dev;
775		ad->ad_parent = awc->aw_parent;
776
777		acpi_match_node_init(ad);
778		acpi_make_name(ad, devinfo->Name);
779
780		/*
781		 * Identify wake GPEs from the _PRW. Note that
782		 * AcpiUpdateAllGpes() must be called afterwards.
783		 */
784		if (ad->ad_devinfo->Type == ACPI_TYPE_DEVICE)
785			acpi_wakedev_init(ad);
786
787		SIMPLEQ_INIT(&ad->ad_child_head);
788		SIMPLEQ_INSERT_TAIL(&sc->ad_head, ad, ad_list);
789
790		if (ad->ad_parent != NULL) {
791
792			SIMPLEQ_INSERT_TAIL(&ad->ad_parent->ad_child_head,
793			    ad, ad_child_list);
794		}
795
796		awc->aw_parent = ad;
797		break;
798
799	default:
800		ACPI_FREE(devinfo);
801		break;
802	}
803
804	return AE_OK;
805}
806
807static ACPI_STATUS
808acpi_make_devnode_post(ACPI_HANDLE handle, uint32_t level,
809    void *context, void **status)
810{
811	struct acpi_walkcontext *awc = context;
812
813	KASSERT(awc != NULL);
814	KASSERT(awc->aw_parent != NULL);
815
816	if (handle == awc->aw_parent->ad_handle)
817		awc->aw_parent = awc->aw_parent->ad_parent;
818
819	return AE_OK;
820}
821
822static void
823acpi_make_name(struct acpi_devnode *ad, uint32_t name)
824{
825	ACPI_NAME_UNION *anu;
826	int clear, i;
827
828	anu = (ACPI_NAME_UNION *)&name;
829	ad->ad_name[4] = '\0';
830
831	for (i = 3, clear = 0; i >= 0; i--) {
832
833		if (clear == 0 && anu->Ascii[i] == '_')
834			ad->ad_name[i] = '\0';
835		else {
836			ad->ad_name[i] = anu->Ascii[i];
837			clear = 1;
838		}
839	}
840
841	if (ad->ad_name[0] == '\0')
842		ad->ad_name[0] = '_';
843}
844
845bus_dma_tag_t
846acpi_default_dma_tag(struct acpi_softc *sc, struct acpi_devnode *ad)
847{
848	return sc->sc_dmat;
849}
850__weak_alias(acpi_get_dma_tag,acpi_default_dma_tag);
851
852bus_dma_tag_t
853acpi_default_dma64_tag(struct acpi_softc *sc, struct acpi_devnode *ad)
854{
855	return sc->sc_dmat64;
856}
857__weak_alias(acpi_get_dma64_tag,acpi_default_dma64_tag);
858
859pci_chipset_tag_t
860acpi_default_pci_chipset_tag(struct acpi_softc *sc, int seg, int bbn)
861{
862	return NULL;
863}
864__weak_alias(acpi_get_pci_chipset_tag,acpi_default_pci_chipset_tag);
865
866/*
867 * Device attachment.
868 */
869static int
870acpi_rescan(device_t self, const char *ifattr, const int *locators)
871{
872	struct acpi_softc *sc = device_private(self);
873	struct acpi_attach_args aa;
874
875	/*
876	 * Try to attach hpet(4) first via a specific table.
877	 */
878	aa.aa_memt = sc->sc_memt;
879
880	if (ifattr_match(ifattr, "acpihpetbus") && sc->sc_hpet == NULL)
881		sc->sc_hpet = config_found_ia(sc->sc_dev,
882		    "acpihpetbus", &aa, NULL);
883
884	/*
885	 * A two-pass scan for acpinodebus.
886	 */
887	if (ifattr_match(ifattr, "acpinodebus")) {
888		acpi_rescan_early(sc);
889		acpi_rescan_nodes(sc);
890	}
891
892	/*
893	 * Attach APM emulation and acpiwdrt(4).
894	 */
895	if (ifattr_match(ifattr, "acpiapmbus") && sc->sc_apmbus == NULL)
896		sc->sc_apmbus = config_found_ia(sc->sc_dev,
897		    "acpiapmbus", NULL, NULL);
898
899	if (ifattr_match(ifattr, "acpiwdrtbus") && sc->sc_wdrt == NULL)
900		sc->sc_wdrt = config_found_ia(sc->sc_dev,
901		    "acpiwdrtbus", NULL, NULL);
902
903	return 0;
904}
905
906static void
907acpi_rescan_early(struct acpi_softc *sc)
908{
909	struct acpi_attach_args aa;
910	struct acpi_devnode *ad;
911
912	/*
913	 * First scan for devices such as acpiec(4) that
914	 * should be always attached before anything else.
915	 * We want these devices to attach regardless of
916	 * the device status and other restrictions.
917	 */
918	SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) {
919
920		if (ad->ad_device != NULL)
921			continue;
922
923		if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE)
924			continue;
925
926		if (acpi_match_hid(ad->ad_devinfo, acpi_early_ids) == 0)
927			continue;
928
929		aa.aa_node = ad;
930		aa.aa_iot = sc->sc_iot;
931		aa.aa_memt = sc->sc_memt;
932		if (ad->ad_pciinfo != NULL) {
933			aa.aa_pc = ad->ad_pciinfo->ap_pc;
934			aa.aa_pciflags = sc->sc_pciflags;
935		}
936		aa.aa_ic = sc->sc_ic;
937		aa.aa_dmat = ad->ad_dmat;
938		aa.aa_dmat64 = ad->ad_dmat64;
939
940		ad->ad_device = config_found_ia(sc->sc_dev,
941		    "acpinodebus", &aa, acpi_print);
942	}
943}
944
945static void
946acpi_rescan_nodes(struct acpi_softc *sc)
947{
948	const char * const hpet_ids[] = { "PNP0103", NULL };
949	struct acpi_attach_args aa;
950	struct acpi_devnode *ad;
951	ACPI_DEVICE_INFO *di;
952
953	SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) {
954
955		if (ad->ad_device != NULL)
956			continue;
957
958		/*
959		 * There is a bug in ACPICA: it defines the type
960		 * of the scopes incorrectly for its own reasons.
961		 */
962		if (acpi_is_scope(ad) != false)
963			continue;
964
965		di = ad->ad_devinfo;
966
967		/*
968		 * We only attach devices which are present, enabled, and
969		 * functioning properly. However, if a device is enabled,
970		 * it is decoding resources and we should claim these,
971		 * if possible. This requires changes to bus_space(9).
972		 */
973		if (di->Type == ACPI_TYPE_DEVICE &&
974		    !acpi_device_present(ad->ad_handle)) {
975			continue;
976		}
977
978		if (di->Type == ACPI_TYPE_POWER)
979			continue;
980
981		if (di->Type == ACPI_TYPE_PROCESSOR)
982			continue;
983
984		if (acpi_match_hid(di, acpi_early_ids) != 0)
985			continue;
986
987		if (acpi_match_hid(di, acpi_ignored_ids) != 0)
988			continue;
989
990		if (acpi_match_hid(di, hpet_ids) != 0 && sc->sc_hpet != NULL)
991			continue;
992
993		aa.aa_node = ad;
994		aa.aa_iot = sc->sc_iot;
995		aa.aa_memt = sc->sc_memt;
996		if (ad->ad_pciinfo != NULL) {
997			aa.aa_pc = ad->ad_pciinfo->ap_pc;
998			aa.aa_pciflags = sc->sc_pciflags;
999		}
1000		aa.aa_ic = sc->sc_ic;
1001		aa.aa_dmat = ad->ad_dmat;
1002		aa.aa_dmat64 = ad->ad_dmat64;
1003
1004		ad->ad_device = config_found_ia(sc->sc_dev,
1005		    "acpinodebus", &aa, acpi_print);
1006	}
1007}
1008
1009static void
1010acpi_rescan_capabilities(device_t self)
1011{
1012	struct acpi_softc *sc = device_private(self);
1013	struct acpi_devnode *ad;
1014	ACPI_HANDLE tmp;
1015	ACPI_STATUS rv;
1016
1017	SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) {
1018
1019		if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE)
1020			continue;
1021
1022		/*
1023		 * Scan power resource capabilities.
1024		 *
1025		 * If any power states are supported,
1026		 * at least _PR0 and _PR3 must be present.
1027		 */
1028		rv = AcpiGetHandle(ad->ad_handle, "_PR0", &tmp);
1029
1030		if (ACPI_SUCCESS(rv)) {
1031			ad->ad_flags |= ACPI_DEVICE_POWER;
1032			acpi_power_add(ad);
1033		}
1034
1035		/*
1036		 * Scan wake-up capabilities.
1037		 */
1038		if (ad->ad_wakedev != NULL) {
1039			ad->ad_flags |= ACPI_DEVICE_WAKEUP;
1040			acpi_wakedev_add(ad);
1041		}
1042
1043		/*
1044		 * Scan docking stations.
1045		 */
1046		rv = AcpiGetHandle(ad->ad_handle, "_DCK", &tmp);
1047
1048		if (ACPI_SUCCESS(rv))
1049			ad->ad_flags |= ACPI_DEVICE_DOCK;
1050
1051		/*
1052		 * Scan devices that are ejectable.
1053		 */
1054		rv = AcpiGetHandle(ad->ad_handle, "_EJ0", &tmp);
1055
1056		if (ACPI_SUCCESS(rv))
1057			ad->ad_flags |= ACPI_DEVICE_EJECT;
1058	}
1059}
1060
1061static int
1062acpi_print(void *aux, const char *pnp)
1063{
1064	struct acpi_attach_args *aa = aux;
1065	struct acpi_devnode *ad;
1066	const char *hid, *uid;
1067	ACPI_DEVICE_INFO *di;
1068
1069	ad = aa->aa_node;
1070	di = ad->ad_devinfo;
1071
1072	hid = di->HardwareId.String;
1073	uid = di->UniqueId.String;
1074
1075	if (pnp != NULL) {
1076
1077		if (di->Type != ACPI_TYPE_DEVICE) {
1078
1079			aprint_normal("%s (ACPI Object Type '%s') at %s",
1080			    ad->ad_name, AcpiUtGetTypeName(ad->ad_type), pnp);
1081
1082			return UNCONF;
1083		}
1084
1085		if ((di->Valid & ACPI_VALID_HID) == 0 || hid == NULL)
1086			return 0;
1087
1088		aprint_normal("%s (%s) ", ad->ad_name, hid);
1089		acpi_print_dev(hid);
1090		aprint_normal("at %s", pnp);
1091
1092		return UNCONF;
1093	}
1094
1095	aprint_normal(" (%s", ad->ad_name);
1096
1097	if ((di->Valid & ACPI_VALID_HID) != 0 && hid != NULL) {
1098
1099		aprint_normal(", %s", hid);
1100
1101		if ((di->Valid & ACPI_VALID_UID) != 0 && uid != NULL) {
1102
1103			if (uid[0] == '\0')
1104				uid = "<null>";
1105
1106			aprint_normal("-%s", uid);
1107		}
1108	}
1109
1110	aprint_normal(")");
1111
1112	return UNCONF;
1113}
1114
1115/*
1116 * Notify.
1117 */
1118static void
1119acpi_notify_handler(ACPI_HANDLE handle, uint32_t event, void *aux)
1120{
1121	struct acpi_softc *sc = acpi_softc;
1122	struct acpi_devnode *ad;
1123
1124	KASSERT(sc != NULL);
1125	KASSERT(aux == NULL);
1126	KASSERT(acpi_active != 0);
1127
1128	if (acpi_suspended != 0)
1129		return;
1130
1131	/*
1132	 *  System: 0x00 - 0x7F.
1133	 *  Device: 0x80 - 0xFF.
1134	 */
1135	switch (event) {
1136
1137	case ACPI_NOTIFY_BUS_CHECK:
1138	case ACPI_NOTIFY_DEVICE_CHECK:
1139	case ACPI_NOTIFY_DEVICE_WAKE:
1140	case ACPI_NOTIFY_EJECT_REQUEST:
1141	case ACPI_NOTIFY_DEVICE_CHECK_LIGHT:
1142	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
1143	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
1144	case ACPI_NOTIFY_POWER_FAULT:
1145	case ACPI_NOTIFY_CAPABILITIES_CHECK:
1146	case ACPI_NOTIFY_DEVICE_PLD_CHECK:
1147	case ACPI_NOTIFY_RESERVED:
1148	case ACPI_NOTIFY_LOCALITY_UPDATE:
1149		break;
1150	}
1151
1152	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "notification 0x%02X for "
1153		"%s (%p)\n", event, acpi_name(handle), handle));
1154
1155	/*
1156	 * We deliver notifications only to drivers
1157	 * that have been successfully attached and
1158	 * that have registered a handler with us.
1159	 * The opaque pointer is always the device_t.
1160	 */
1161	SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) {
1162
1163		if (ad->ad_device == NULL)
1164			continue;
1165
1166		if (ad->ad_notify == NULL)
1167			continue;
1168
1169		if (ad->ad_handle != handle)
1170			continue;
1171
1172		(*ad->ad_notify)(ad->ad_handle, event, ad->ad_device);
1173
1174		return;
1175	}
1176
1177	aprint_debug_dev(sc->sc_dev, "unhandled notify 0x%02X "
1178	    "for %s (%p)\n", event, acpi_name(handle), handle);
1179}
1180
1181bool
1182acpi_register_notify(struct acpi_devnode *ad, ACPI_NOTIFY_HANDLER notify)
1183{
1184	struct acpi_softc *sc = acpi_softc;
1185
1186	KASSERT(sc != NULL);
1187	KASSERT(acpi_active != 0);
1188
1189	if (acpi_suspended != 0)
1190		goto fail;
1191
1192	if (ad == NULL || notify == NULL)
1193		goto fail;
1194
1195	ad->ad_notify = notify;
1196
1197	return true;
1198
1199fail:
1200	aprint_error_dev(sc->sc_dev, "failed to register notify "
1201	    "handler for %s (%p)\n", ad->ad_name, ad->ad_handle);
1202
1203	return false;
1204}
1205
1206void
1207acpi_deregister_notify(struct acpi_devnode *ad)
1208{
1209
1210	ad->ad_notify = NULL;
1211}
1212
1213/*
1214 * Fixed buttons.
1215 */
1216static void
1217acpi_register_fixed_button(struct acpi_softc *sc, int event)
1218{
1219	struct sysmon_pswitch *smpsw;
1220	ACPI_STATUS rv;
1221	int type;
1222
1223	switch (event) {
1224
1225	case ACPI_EVENT_POWER_BUTTON:
1226
1227		if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) != 0)
1228			return;
1229
1230		type = PSWITCH_TYPE_POWER;
1231		smpsw = &sc->sc_smpsw_power;
1232		break;
1233
1234	case ACPI_EVENT_SLEEP_BUTTON:
1235
1236		if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) != 0)
1237			return;
1238
1239		type = PSWITCH_TYPE_SLEEP;
1240		smpsw = &sc->sc_smpsw_sleep;
1241		break;
1242
1243	default:
1244		rv = AE_TYPE;
1245		goto fail;
1246	}
1247
1248	smpsw->smpsw_type = type;
1249	smpsw->smpsw_name = device_xname(sc->sc_dev);
1250
1251	if (sysmon_pswitch_register(smpsw) != 0) {
1252		rv = AE_ERROR;
1253		goto fail;
1254	}
1255
1256	AcpiClearEvent(event);
1257
1258	rv = AcpiInstallFixedEventHandler(event,
1259	    acpi_fixed_button_handler, smpsw);
1260
1261	if (ACPI_FAILURE(rv)) {
1262		sysmon_pswitch_unregister(smpsw);
1263		goto fail;
1264	}
1265
1266	aprint_normal_dev(sc->sc_dev, "fixed %s button present\n",
1267	    (type != PSWITCH_TYPE_SLEEP) ? "power" : "sleep");
1268
1269	return;
1270
1271fail:
1272	aprint_error_dev(sc->sc_dev, "failed to register "
1273	    "fixed event %d: %s\n", event, AcpiFormatException(rv));
1274}
1275
1276static void
1277acpi_deregister_fixed_button(struct acpi_softc *sc, int event)
1278{
1279	struct sysmon_pswitch *smpsw;
1280	ACPI_STATUS rv;
1281
1282	switch (event) {
1283
1284	case ACPI_EVENT_POWER_BUTTON:
1285		smpsw = &sc->sc_smpsw_power;
1286
1287		if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) != 0) {
1288			KASSERT(smpsw->smpsw_type != PSWITCH_TYPE_POWER);
1289			return;
1290		}
1291
1292		break;
1293
1294	case ACPI_EVENT_SLEEP_BUTTON:
1295		smpsw = &sc->sc_smpsw_sleep;
1296
1297		if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) != 0) {
1298			KASSERT(smpsw->smpsw_type != PSWITCH_TYPE_SLEEP);
1299			return;
1300		}
1301
1302		break;
1303
1304	default:
1305		rv = AE_TYPE;
1306		goto fail;
1307	}
1308
1309	rv = AcpiRemoveFixedEventHandler(event, acpi_fixed_button_handler);
1310
1311	if (ACPI_SUCCESS(rv)) {
1312		sysmon_pswitch_unregister(smpsw);
1313		return;
1314	}
1315
1316fail:
1317	aprint_error_dev(sc->sc_dev, "failed to deregister "
1318	    "fixed event: %s\n", AcpiFormatException(rv));
1319}
1320
1321static uint32_t
1322acpi_fixed_button_handler(void *context)
1323{
1324	static const int handler = OSL_NOTIFY_HANDLER;
1325	struct sysmon_pswitch *smpsw = context;
1326
1327	(void)AcpiOsExecute(handler, acpi_fixed_button_pressed, smpsw);
1328
1329	return ACPI_INTERRUPT_HANDLED;
1330}
1331
1332static void
1333acpi_fixed_button_pressed(void *context)
1334{
1335	struct sysmon_pswitch *smpsw = context;
1336
1337	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s fixed button pressed\n",
1338		(smpsw->smpsw_type != ACPI_EVENT_SLEEP_BUTTON) ?
1339		"power" : "sleep"));
1340
1341	sysmon_pswitch_event(smpsw, PSWITCH_EVENT_PRESSED);
1342}
1343
1344/*
1345 * Sleep.
1346 */
1347static void
1348acpi_sleep_init(struct acpi_softc *sc)
1349{
1350	uint8_t a, b, i;
1351	ACPI_STATUS rv;
1352
1353	CTASSERT(ACPI_STATE_S0 == 0 && ACPI_STATE_S1 == 1);
1354	CTASSERT(ACPI_STATE_S2 == 2 && ACPI_STATE_S3 == 3);
1355	CTASSERT(ACPI_STATE_S4 == 4 && ACPI_STATE_S5 == 5);
1356
1357	/*
1358	 * Evaluate supported sleep states.
1359	 */
1360	for (i = ACPI_STATE_S0; i <= ACPI_STATE_S5; i++) {
1361
1362		rv = AcpiGetSleepTypeData(i, &a, &b);
1363
1364		if (ACPI_SUCCESS(rv))
1365			sc->sc_sleepstates |= __BIT(i);
1366	}
1367}
1368
1369/*
1370 * Must be called with interrupts enabled.
1371 */
1372void
1373acpi_enter_sleep_state(int state)
1374{
1375	struct acpi_softc *sc = acpi_softc;
1376	ACPI_STATUS rv;
1377
1378	if (acpi_softc == NULL)
1379		return;
1380
1381	if (state == sc->sc_sleepstate)
1382		return;
1383
1384	if (state < ACPI_STATE_S0 || state > ACPI_STATE_S5)
1385		return;
1386
1387	aprint_normal_dev(sc->sc_dev, "entering state S%d\n", state);
1388
1389	switch (state) {
1390
1391	case ACPI_STATE_S0:
1392		sc->sc_sleepstate = ACPI_STATE_S0;
1393		return;
1394
1395	case ACPI_STATE_S1:
1396	case ACPI_STATE_S2:
1397	case ACPI_STATE_S3:
1398	case ACPI_STATE_S4:
1399
1400		if ((sc->sc_sleepstates & __BIT(state)) == 0) {
1401			aprint_error_dev(sc->sc_dev, "sleep state "
1402			    "S%d is not available\n", state);
1403			return;
1404		}
1405
1406		/*
1407		 * Evaluate the _TTS method. This should be done before
1408		 * pmf_system_suspend(9) and the evaluation of _PTS.
1409		 * We should also re-evaluate this once we return to
1410		 * S0 or if we abort the sleep state transition in the
1411		 * middle (see ACPI 3.0, section 7.3.6). In reality,
1412		 * however, the _TTS method is seldom seen in the field.
1413		 */
1414		rv = acpi_eval_set_integer(NULL, "\\_TTS", state);
1415
1416		if (ACPI_SUCCESS(rv))
1417			aprint_debug_dev(sc->sc_dev, "evaluated _TTS\n");
1418
1419		if (state != ACPI_STATE_S1 &&
1420		    pmf_system_suspend(PMF_Q_NONE) != true) {
1421			aprint_error_dev(sc->sc_dev, "aborting suspend\n");
1422			break;
1423		}
1424
1425		/*
1426		 * This will evaluate the  _PTS and _SST methods,
1427		 * but unlike the documentation claims, not _GTS,
1428		 * which is evaluated in AcpiEnterSleepState().
1429		 * This must be called with interrupts enabled.
1430		 */
1431		rv = AcpiEnterSleepStatePrep(state);
1432
1433		if (ACPI_FAILURE(rv)) {
1434			aprint_error_dev(sc->sc_dev, "failed to prepare "
1435			    "S%d: %s\n", state, AcpiFormatException(rv));
1436			break;
1437		}
1438
1439		/*
1440		 * After the _PTS method has been evaluated, we can
1441		 * enable wake and evaluate _PSW (ACPI 4.0, p. 284).
1442		 */
1443		acpi_wakedev_commit(sc, state);
1444
1445		sc->sc_sleepstate = state;
1446
1447		if (state == ACPI_STATE_S1) {
1448
1449			/*
1450			 * Before the transition to S1, CPU caches
1451			 * must be flushed (see ACPI 4.0, 7.3.4.2).
1452			 *
1453			 * Note that interrupts must be off before
1454			 * calling AcpiEnterSleepState(). Conversely,
1455			 * AcpiLeaveSleepState() should always be
1456			 * called with interrupts enabled.
1457			 */
1458			acpi_md_OsDisableInterrupt();
1459
1460			ACPI_FLUSH_CPU_CACHE();
1461			rv = AcpiEnterSleepState(state);
1462
1463			if (ACPI_FAILURE(rv))
1464				aprint_error_dev(sc->sc_dev, "failed to "
1465				    "enter S1: %s\n", AcpiFormatException(rv));
1466
1467			/*
1468			 * Clear fixed events and disable all GPEs before
1469			 * interrupts are enabled.
1470			 */
1471			AcpiClearEvent(ACPI_EVENT_PMTIMER);
1472			AcpiClearEvent(ACPI_EVENT_GLOBAL);
1473			AcpiClearEvent(ACPI_EVENT_POWER_BUTTON);
1474			AcpiClearEvent(ACPI_EVENT_SLEEP_BUTTON);
1475			AcpiClearEvent(ACPI_EVENT_RTC);
1476#if (!ACPI_REDUCED_HARDWARE)
1477			AcpiHwDisableAllGpes();
1478#endif
1479
1480			acpi_md_OsEnableInterrupt();
1481			rv = AcpiLeaveSleepState(state);
1482
1483		} else {
1484
1485			(void)acpi_md_sleep(state);
1486
1487			if (state == ACPI_STATE_S4)
1488				AcpiEnable();
1489
1490			(void)pmf_system_bus_resume(PMF_Q_NONE);
1491			(void)AcpiLeaveSleepState(state);
1492			(void)AcpiSetFirmwareWakingVector(0, 0);
1493			(void)pmf_system_resume(PMF_Q_NONE);
1494		}
1495
1496		/*
1497		 * No wake GPEs should be enabled at runtime.
1498		 */
1499		acpi_wakedev_commit(sc, ACPI_STATE_S0);
1500		break;
1501
1502	case ACPI_STATE_S5:
1503
1504		(void)acpi_eval_set_integer(NULL, "\\_TTS", ACPI_STATE_S5);
1505
1506		rv = AcpiEnterSleepStatePrep(ACPI_STATE_S5);
1507
1508		if (ACPI_FAILURE(rv)) {
1509			aprint_error_dev(sc->sc_dev, "failed to prepare "
1510			    "S%d: %s\n", state, AcpiFormatException(rv));
1511			break;
1512		}
1513
1514		(void)AcpiDisableAllGpes();
1515
1516		DELAY(1000000);
1517
1518		sc->sc_sleepstate = state;
1519		acpi_md_OsDisableInterrupt();
1520
1521		(void)AcpiEnterSleepState(ACPI_STATE_S5);
1522
1523		aprint_error_dev(sc->sc_dev, "WARNING: powerdown failed!\n");
1524
1525		break;
1526	}
1527
1528	sc->sc_sleepstate = ACPI_STATE_S0;
1529
1530	(void)acpi_eval_set_integer(NULL, "\\_TTS", ACPI_STATE_S0);
1531}
1532
1533/*
1534 * Sysctl.
1535 */
1536SYSCTL_SETUP(sysctl_acpi_setup, "sysctl hw.acpi subtree setup")
1537{
1538	const struct sysctlnode *rnode, *snode;
1539	int err;
1540
1541	err = sysctl_createv(clog, 0, NULL, &rnode,
1542	    CTLFLAG_PERMANENT, CTLTYPE_NODE,
1543	    "acpi", SYSCTL_DESCR("ACPI subsystem parameters"),
1544	    NULL, 0, NULL, 0,
1545	    CTL_HW, CTL_CREATE, CTL_EOL);
1546
1547	if (err != 0)
1548		return;
1549
1550	(void)sysctl_createv(NULL, 0, &rnode, NULL,
1551	    CTLFLAG_PERMANENT | CTLFLAG_READONLY, CTLTYPE_QUAD,
1552	    "root", SYSCTL_DESCR("ACPI root pointer"),
1553	    NULL, 0, &acpi_root_pointer, sizeof(acpi_root_pointer),
1554	    CTL_CREATE, CTL_EOL);
1555
1556	err = sysctl_createv(clog, 0, &rnode, &snode,
1557	    CTLFLAG_PERMANENT, CTLTYPE_NODE,
1558	    "sleep", SYSCTL_DESCR("ACPI sleep"),
1559	    NULL, 0, NULL, 0,
1560	    CTL_CREATE, CTL_EOL);
1561
1562	if (err != 0)
1563		return;
1564
1565	(void)sysctl_createv(NULL, 0, &snode, NULL,
1566	    CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT,
1567	    "state", SYSCTL_DESCR("System sleep state"),
1568	    sysctl_hw_acpi_sleepstate, 0, NULL, 0,
1569	    CTL_CREATE, CTL_EOL);
1570
1571	(void)sysctl_createv(NULL, 0, &snode, NULL,
1572	    CTLFLAG_PERMANENT | CTLFLAG_READONLY, CTLTYPE_STRING,
1573	    "states", SYSCTL_DESCR("Supported sleep states"),
1574	    sysctl_hw_acpi_sleepstates, 0, NULL, 0,
1575	    CTL_CREATE, CTL_EOL);
1576
1577	err = sysctl_createv(clog, 0, &rnode, &rnode,
1578	    CTLFLAG_PERMANENT, CTLTYPE_NODE,
1579	    "stat", SYSCTL_DESCR("ACPI statistics"),
1580	    NULL, 0, NULL, 0,
1581	    CTL_CREATE, CTL_EOL);
1582
1583	if (err != 0)
1584		return;
1585
1586	(void)sysctl_createv(clog, 0, &rnode, NULL,
1587	    CTLFLAG_PERMANENT | CTLFLAG_READONLY, CTLTYPE_QUAD,
1588	    "gpe", SYSCTL_DESCR("Number of dispatched GPEs"),
1589	    NULL, 0, &AcpiGpeCount, sizeof(AcpiGpeCount),
1590	    CTL_CREATE, CTL_EOL);
1591
1592	(void)sysctl_createv(clog, 0, &rnode, NULL,
1593	    CTLFLAG_PERMANENT | CTLFLAG_READONLY, CTLTYPE_QUAD,
1594	    "sci", SYSCTL_DESCR("Number of SCI interrupts"),
1595	    NULL, 0, &AcpiSciCount, sizeof(AcpiSciCount),
1596	    CTL_CREATE, CTL_EOL);
1597
1598	(void)sysctl_createv(clog, 0, &rnode, NULL,
1599	    CTLFLAG_PERMANENT | CTLFLAG_READONLY, CTLTYPE_QUAD,
1600	    "fixed", SYSCTL_DESCR("Number of fixed events"),
1601	    sysctl_hw_acpi_fixedstats, 0, NULL, 0,
1602	    CTL_CREATE, CTL_EOL);
1603
1604	(void)sysctl_createv(clog, 0, &rnode, NULL,
1605	    CTLFLAG_PERMANENT | CTLFLAG_READONLY, CTLTYPE_QUAD,
1606	    "method", SYSCTL_DESCR("Number of methods executed"),
1607	    NULL, 0, &AcpiMethodCount, sizeof(AcpiMethodCount),
1608	    CTL_CREATE, CTL_EOL);
1609
1610	CTASSERT(sizeof(AcpiGpeCount) == sizeof(uint64_t));
1611	CTASSERT(sizeof(AcpiSciCount) == sizeof(uint64_t));
1612}
1613
1614static int
1615sysctl_hw_acpi_fixedstats(SYSCTLFN_ARGS)
1616{
1617	struct sysctlnode node;
1618	uint64_t t;
1619	int err, i;
1620
1621	for (i = t = 0; i < __arraycount(AcpiFixedEventCount); i++)
1622		t += AcpiFixedEventCount[i];
1623
1624	node = *rnode;
1625	node.sysctl_data = &t;
1626
1627	err = sysctl_lookup(SYSCTLFN_CALL(&node));
1628
1629	if (err || newp == NULL)
1630		return err;
1631
1632	return 0;
1633}
1634
1635static int
1636sysctl_hw_acpi_sleepstate(SYSCTLFN_ARGS)
1637{
1638	struct acpi_softc *sc = acpi_softc;
1639	struct sysctlnode node;
1640	int err, t;
1641
1642	if (acpi_softc == NULL)
1643		return ENOSYS;
1644
1645	node = *rnode;
1646	t = sc->sc_sleepstate;
1647	node.sysctl_data = &t;
1648
1649	err = sysctl_lookup(SYSCTLFN_CALL(&node));
1650
1651	if (err || newp == NULL)
1652		return err;
1653
1654	if (t < ACPI_STATE_S0 || t > ACPI_STATE_S5)
1655		return EINVAL;
1656
1657	acpi_enter_sleep_state(t);
1658
1659	return 0;
1660}
1661
1662static int
1663sysctl_hw_acpi_sleepstates(SYSCTLFN_ARGS)
1664{
1665	struct acpi_softc *sc = acpi_softc;
1666	struct sysctlnode node;
1667	char t[3 * 6 + 1];
1668	int err;
1669
1670	if (acpi_softc == NULL)
1671		return ENOSYS;
1672
1673	(void)memset(t, '\0', sizeof(t));
1674
1675	(void)snprintf(t, sizeof(t), "%s%s%s%s%s%s",
1676	    ((sc->sc_sleepstates & __BIT(0)) != 0) ? "S0 " : "",
1677	    ((sc->sc_sleepstates & __BIT(1)) != 0) ? "S1 " : "",
1678	    ((sc->sc_sleepstates & __BIT(2)) != 0) ? "S2 " : "",
1679	    ((sc->sc_sleepstates & __BIT(3)) != 0) ? "S3 " : "",
1680	    ((sc->sc_sleepstates & __BIT(4)) != 0) ? "S4 " : "",
1681	    ((sc->sc_sleepstates & __BIT(5)) != 0) ? "S5 " : "");
1682
1683	node = *rnode;
1684	node.sysctl_data = &t;
1685
1686	err = sysctl_lookup(SYSCTLFN_CALL(&node));
1687
1688	if (err || newp == NULL)
1689		return err;
1690
1691	return 0;
1692}
1693
1694/*
1695 * Tables.
1696 */
1697ACPI_PHYSICAL_ADDRESS
1698acpi_OsGetRootPointer(void)
1699{
1700	ACPI_PHYSICAL_ADDRESS PhysicalAddress;
1701
1702	/*
1703	 * We let MD code handle this since there are multiple ways to do it:
1704	 *
1705	 *	IA-32: Use AcpiFindRootPointer() to locate the RSDP.
1706	 *
1707	 *	IA-64: Use the EFI.
1708	 */
1709	PhysicalAddress = acpi_md_OsGetRootPointer();
1710
1711	if (acpi_root_pointer == 0)
1712		acpi_root_pointer = PhysicalAddress;
1713
1714	return PhysicalAddress;
1715}
1716
1717static ACPI_TABLE_HEADER *
1718acpi_map_rsdt(void)
1719{
1720	ACPI_PHYSICAL_ADDRESS paddr;
1721	ACPI_TABLE_RSDP *rsdp;
1722
1723	paddr = AcpiOsGetRootPointer();
1724
1725	if (paddr == 0)
1726		return NULL;
1727
1728	rsdp = AcpiOsMapMemory(paddr, sizeof(ACPI_TABLE_RSDP));
1729
1730	if (rsdp == NULL)
1731		return NULL;
1732
1733	if (rsdp->Revision > 1 && rsdp->XsdtPhysicalAddress)
1734		paddr = rsdp->XsdtPhysicalAddress;
1735	else
1736		paddr = rsdp->RsdtPhysicalAddress;
1737
1738	AcpiOsUnmapMemory(rsdp, sizeof(ACPI_TABLE_RSDP));
1739
1740	return AcpiOsMapMemory(paddr, sizeof(ACPI_TABLE_HEADER));
1741}
1742
1743/*
1744 * XXX: Refactor to be a generic function that unmaps tables.
1745 */
1746static void
1747acpi_unmap_rsdt(ACPI_TABLE_HEADER *rsdt)
1748{
1749
1750	if (rsdt == NULL)
1751		return;
1752
1753	AcpiOsUnmapMemory(rsdt, sizeof(ACPI_TABLE_HEADER));
1754}
1755
1756/*
1757 * XXX: Refactor to be a generic function that maps tables.
1758 */
1759ACPI_STATUS
1760acpi_madt_map(void)
1761{
1762	ACPI_STATUS  rv;
1763
1764	if (madt_header != NULL)
1765		return AE_ALREADY_EXISTS;
1766
1767	rv = AcpiGetTable(ACPI_SIG_MADT, 1, &madt_header);
1768
1769	if (ACPI_FAILURE(rv))
1770		return rv;
1771
1772	return AE_OK;
1773}
1774
1775void
1776acpi_madt_unmap(void)
1777{
1778	madt_header = NULL;
1779}
1780
1781ACPI_STATUS
1782acpi_gtdt_map(void)
1783{
1784	ACPI_STATUS  rv;
1785
1786	if (gtdt_header != NULL)
1787		return AE_ALREADY_EXISTS;
1788
1789	rv = AcpiGetTable(ACPI_SIG_GTDT, 1, &gtdt_header);
1790
1791	if (ACPI_FAILURE(rv))
1792		return rv;
1793
1794	return AE_OK;
1795}
1796
1797void
1798acpi_gtdt_unmap(void)
1799{
1800	gtdt_header = NULL;
1801}
1802
1803/*
1804 * XXX: Refactor to be a generic function that walks tables.
1805 */
1806void
1807acpi_madt_walk(ACPI_STATUS (*func)(ACPI_SUBTABLE_HEADER *, void *), void *aux)
1808{
1809	ACPI_SUBTABLE_HEADER *hdrp;
1810	char *madtend, *where;
1811
1812	madtend = (char *)madt_header + madt_header->Length;
1813	where = (char *)madt_header + sizeof (ACPI_TABLE_MADT);
1814
1815	while (where < madtend) {
1816
1817		hdrp = (ACPI_SUBTABLE_HEADER *)where;
1818
1819		if (hdrp->Length == 0 || ACPI_FAILURE(func(hdrp, aux)))
1820			break;
1821
1822		where += hdrp->Length;
1823	}
1824}
1825
1826void
1827acpi_gtdt_walk(ACPI_STATUS (*func)(ACPI_GTDT_HEADER *, void *), void *aux)
1828{
1829	ACPI_GTDT_HEADER *hdrp;
1830	char *gtdtend, *where;
1831
1832	gtdtend = (char *)gtdt_header + gtdt_header->Length;
1833	where = (char *)gtdt_header + sizeof (ACPI_TABLE_GTDT);
1834
1835	while (where < gtdtend) {
1836
1837		hdrp = (ACPI_GTDT_HEADER *)where;
1838
1839		if (hdrp->Length == 0 || ACPI_FAILURE(func(hdrp, aux)))
1840			break;
1841
1842		where += hdrp->Length;
1843	}
1844}
1845
1846/*
1847 * Miscellaneous.
1848 */
1849static bool
1850acpi_is_scope(struct acpi_devnode *ad)
1851{
1852	int i;
1853
1854	/*
1855	 * Return true if the node is a root scope.
1856	 */
1857	if (ad->ad_parent == NULL)
1858		return false;
1859
1860	if (ad->ad_parent->ad_handle != ACPI_ROOT_OBJECT)
1861		return false;
1862
1863	for (i = 0; i < __arraycount(acpi_scopes); i++) {
1864
1865		if (acpi_scopes[i] == NULL)
1866			continue;
1867
1868		if (ad->ad_handle == acpi_scopes[i])
1869			return true;
1870	}
1871
1872	return false;
1873}
1874
1875bool
1876acpi_device_present(ACPI_HANDLE handle)
1877{
1878	ACPI_STATUS rv;
1879	ACPI_INTEGER sta;
1880
1881	rv = acpi_eval_integer(handle, "_STA", &sta);
1882
1883	if (ACPI_FAILURE(rv)) {
1884		/* No _STA method -> must be there */
1885		return rv == AE_NOT_FOUND;
1886	}
1887
1888	return (sta & ACPI_STA_OK) == ACPI_STA_OK;
1889}
1890
1891/*
1892 * ACPIVERBOSE.
1893 */
1894void
1895acpi_load_verbose(void)
1896{
1897
1898	if (acpi_verbose_loaded == 0)
1899		module_autoload("acpiverbose", MODULE_CLASS_MISC);
1900}
1901
1902void
1903acpi_print_verbose_stub(struct acpi_softc *sc)
1904{
1905
1906	acpi_load_verbose();
1907
1908	if (acpi_verbose_loaded != 0)
1909		acpi_print_verbose(sc);
1910}
1911
1912void
1913acpi_print_dev_stub(const char *pnpstr)
1914{
1915
1916	acpi_load_verbose();
1917
1918	if (acpi_verbose_loaded != 0)
1919		acpi_print_dev(pnpstr);
1920}
1921
1922MALLOC_DECLARE(M_ACPI); /* XXX: ACPI_ACTIVATE_DEV should use kmem(9). */
1923
1924/*
1925 * ACPI_ACTIVATE_DEV.
1926 */
1927static void
1928acpi_activate_device(ACPI_HANDLE handle, ACPI_DEVICE_INFO **di)
1929{
1930
1931#ifndef ACPI_ACTIVATE_DEV
1932	return;
1933}
1934#else
1935	static const int valid = ACPI_VALID_HID;
1936	ACPI_DEVICE_INFO *newdi;
1937	ACPI_STATUS rv;
1938
1939
1940	/*
1941	 * If the device is valid and present,
1942	 * but not enabled, try to activate it.
1943	 */
1944	if (((*di)->Valid & valid) != valid)
1945		return;
1946
1947	if (!acpi_device_present(handle))
1948		return;
1949
1950	rv = acpi_allocate_resources(handle);
1951
1952	if (ACPI_FAILURE(rv))
1953		goto fail;
1954
1955	rv = AcpiGetObjectInfo(handle, &newdi);
1956
1957	if (ACPI_FAILURE(rv))
1958		goto fail;
1959
1960	ACPI_FREE(*di);
1961	*di = newdi;
1962
1963	aprint_verbose_dev(acpi_softc->sc_dev,
1964	    "%s activated\n", (*di)->HardwareId.String);
1965
1966	return;
1967
1968fail:
1969	aprint_error_dev(acpi_softc->sc_dev, "failed to "
1970	    "activate %s\n", (*di)->HardwareId.String);
1971}
1972
1973/*
1974 * XXX: This very incomplete.
1975 */
1976ACPI_STATUS
1977acpi_allocate_resources(ACPI_HANDLE handle)
1978{
1979	ACPI_BUFFER bufp, bufc, bufn;
1980	ACPI_RESOURCE *resp, *resc, *resn;
1981	ACPI_RESOURCE_IRQ *irq;
1982#if 0
1983	ACPI_RESOURCE_EXTENDED_IRQ *xirq;
1984#endif
1985	ACPI_STATUS rv;
1986	uint delta;
1987
1988	rv = acpi_get(handle, &bufp, AcpiGetPossibleResources);
1989	if (ACPI_FAILURE(rv))
1990		goto out;
1991	rv = acpi_get(handle, &bufc, AcpiGetCurrentResources);
1992	if (ACPI_FAILURE(rv)) {
1993		goto out1;
1994	}
1995
1996	bufn.Length = 1000;
1997	bufn.Pointer = resn = malloc(bufn.Length, M_ACPI, M_WAITOK);
1998	resp = bufp.Pointer;
1999	resc = bufc.Pointer;
2000	while (resc->Type != ACPI_RESOURCE_TYPE_END_TAG &&
2001	       resp->Type != ACPI_RESOURCE_TYPE_END_TAG) {
2002		while (resc->Type != resp->Type && resp->Type != ACPI_RESOURCE_TYPE_END_TAG)
2003			resp = ACPI_NEXT_RESOURCE(resp);
2004		if (resp->Type == ACPI_RESOURCE_TYPE_END_TAG)
2005			break;
2006		/* Found identical Id */
2007		resn->Type = resc->Type;
2008		switch (resc->Type) {
2009		case ACPI_RESOURCE_TYPE_IRQ:
2010			memcpy(&resn->Data, &resp->Data,
2011			       sizeof(ACPI_RESOURCE_IRQ));
2012			irq = (ACPI_RESOURCE_IRQ *)&resn->Data;
2013			irq->Interrupts[0] =
2014			    ((ACPI_RESOURCE_IRQ *)&resp->Data)->
2015			        Interrupts[irq->InterruptCount-1];
2016			irq->InterruptCount = 1;
2017			resn->Length = ACPI_RS_SIZE(ACPI_RESOURCE_IRQ);
2018			break;
2019		case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
2020			memcpy(&resn->Data, &resp->Data,
2021			       sizeof(ACPI_RESOURCE_EXTENDED_IRQ));
2022#if 0
2023			xirq = (ACPI_RESOURCE_EXTENDED_IRQ *)&resn->Data;
2024			/*
2025			 * XXX:	Not duplicating the interrupt logic above
2026			 *	because its not clear what it accomplishes.
2027			 */
2028			xirq->Interrupts[0] =
2029			    ((ACPI_RESOURCE_EXT_IRQ *)&resp->Data)->
2030			    Interrupts[irq->NumberOfInterrupts-1];
2031			xirq->NumberOfInterrupts = 1;
2032#endif
2033			resn->Length = ACPI_RS_SIZE(ACPI_RESOURCE_EXTENDED_IRQ);
2034			break;
2035		case ACPI_RESOURCE_TYPE_IO:
2036			memcpy(&resn->Data, &resp->Data,
2037			       sizeof(ACPI_RESOURCE_IO));
2038			resn->Length = resp->Length;
2039			break;
2040		default:
2041			aprint_error_dev(acpi_softc->sc_dev,
2042			    "%s: invalid type %u\n", __func__, resc->Type);
2043			rv = AE_BAD_DATA;
2044			goto out2;
2045		}
2046		resc = ACPI_NEXT_RESOURCE(resc);
2047		resn = ACPI_NEXT_RESOURCE(resn);
2048		resp = ACPI_NEXT_RESOURCE(resp);
2049		delta = (uint8_t *)resn - (uint8_t *)bufn.Pointer;
2050		if (delta >=
2051		    bufn.Length-ACPI_RS_SIZE(ACPI_RESOURCE_DATA)) {
2052			bufn.Length *= 2;
2053			bufn.Pointer = realloc(bufn.Pointer, bufn.Length,
2054					       M_ACPI, M_WAITOK);
2055			resn = (ACPI_RESOURCE *)((uint8_t *)bufn.Pointer +
2056			    delta);
2057		}
2058	}
2059
2060	if (resc->Type != ACPI_RESOURCE_TYPE_END_TAG) {
2061		aprint_error_dev(acpi_softc->sc_dev,
2062		    "%s: resc not exhausted\n", __func__);
2063		rv = AE_BAD_DATA;
2064		goto out3;
2065	}
2066
2067	resn->Type = ACPI_RESOURCE_TYPE_END_TAG;
2068	rv = AcpiSetCurrentResources(handle, &bufn);
2069
2070	if (ACPI_FAILURE(rv))
2071		aprint_error_dev(acpi_softc->sc_dev, "%s: failed to set "
2072		    "resources: %s\n", __func__, AcpiFormatException(rv));
2073
2074out3:
2075	free(bufn.Pointer, M_ACPI);
2076out2:
2077	ACPI_FREE(bufc.Pointer);
2078out1:
2079	ACPI_FREE(bufp.Pointer);
2080out:
2081	return rv;
2082}
2083
2084#endif	/* ACPI_ACTIVATE_DEV */
2085