acpi.c revision 1.159
1/*	$NetBSD: acpi.c,v 1.159 2010/03/10 09:42:46 jruoho Exp $	*/
2
3/*-
4 * Copyright (c) 2003, 2007 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum of By Noon Software, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/*
33 * Copyright 2001, 2003 Wasabi Systems, Inc.
34 * All rights reserved.
35 *
36 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 *    notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 *    notice, this list of conditions and the following disclaimer in the
45 *    documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software
47 *    must display the following acknowledgement:
48 *	This product includes software developed for the NetBSD Project by
49 *	Wasabi Systems, Inc.
50 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
51 *    or promote products derived from this software without specific prior
52 *    written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
56 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
57 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
58 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
59 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
60 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
61 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
62 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
63 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
64 * POSSIBILITY OF SUCH DAMAGE.
65 */
66
67/*
68 * Autoconfiguration support for the Intel ACPI Component Architecture
69 * ACPI reference implementation.
70 */
71
72#include <sys/cdefs.h>
73__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.159 2010/03/10 09:42:46 jruoho Exp $");
74
75#include "opt_acpi.h"
76#include "opt_pcifixup.h"
77
78#include <sys/param.h>
79#include <sys/device.h>
80#include <sys/kernel.h>
81#include <sys/malloc.h>
82#include <sys/mutex.h>
83#include <sys/sysctl.h>
84#include <sys/systm.h>
85
86#include <dev/acpi/acpireg.h>
87#include <dev/acpi/acpivar.h>
88#include <dev/acpi/acpi_osd.h>
89#include <dev/acpi/acpi_pci.h>
90#include <dev/acpi/acpi_timer.h>
91#include <dev/acpi/acpi_wakedev.h>
92
93#ifdef ACPIVERBOSE
94#include <dev/acpi/acpidevs_data.h>
95#endif
96
97#define _COMPONENT          ACPI_TOOLS
98ACPI_MODULE_NAME            ("acpi")
99
100#if defined(ACPI_PCI_FIXUP)
101#error The option ACPI_PCI_FIXUP has been obsoleted by PCI_INTR_FIXUP_DISABLED.  Please adjust your kernel configuration file.
102#endif
103
104#ifdef PCI_INTR_FIXUP_DISABLED
105#include <dev/pci/pcidevs.h>
106#endif
107
108MALLOC_DECLARE(M_ACPI);
109
110#include <machine/acpi_machdep.h>
111
112#ifdef ACPI_DEBUGGER
113#define	ACPI_DBGR_INIT		0x01
114#define	ACPI_DBGR_TABLES	0x02
115#define	ACPI_DBGR_ENABLE	0x04
116#define	ACPI_DBGR_PROBE		0x08
117#define	ACPI_DBGR_RUNNING	0x10
118
119static int acpi_dbgr = 0x00;
120#endif
121
122static ACPI_TABLE_DESC	acpi_initial_tables[128];
123
124static int	acpi_match(device_t, cfdata_t, void *);
125static void	acpi_attach(device_t, device_t, void *);
126static void	acpi_childdet(device_t, device_t);
127static int	acpi_detach(device_t, int);
128
129static int	acpi_rescan(device_t, const char *, const int *);
130static void	acpi_rescan1(struct acpi_softc *, const char *, const int *);
131static void	acpi_rescan_nodes(struct acpi_softc *);
132
133static int	acpi_print(void *aux, const char *);
134
135static int	sysctl_hw_acpi_sleepstate(SYSCTLFN_ARGS);
136
137extern struct cfdriver acpi_cd;
138
139CFATTACH_DECL2_NEW(acpi, sizeof(struct acpi_softc),
140    acpi_match, acpi_attach, acpi_detach, NULL, acpi_rescan, acpi_childdet);
141
142/*
143 * This is a flag we set when the ACPI subsystem is active.  Machine
144 * dependent code may wish to skip other steps (such as attaching
145 * subsystems that ACPI supercedes) when ACPI is active.
146 */
147int	acpi_active;
148int	acpi_force_load;
149int	acpi_suspended = 0;
150
151/*
152 * Pointer to the ACPI subsystem's state.  There can be only
153 * one ACPI instance.
154 */
155struct acpi_softc *acpi_softc;
156
157/*
158 * Locking stuff.
159 */
160extern kmutex_t acpi_interrupt_list_mtx;
161
162/*
163 * Ignored HIDs.
164 */
165static const char * const acpi_ignored_ids[] = {
166#if defined(i386) || defined(x86_64)
167	"PNP0000",	/* AT interrupt controller is handled internally */
168	"PNP0200",	/* AT DMA controller is handled internally */
169	"PNP0A??",	/* PCI Busses are handled internally */
170	"PNP0B00",	/* AT RTC is handled internally */
171	"PNP0C01",	/* No "System Board" driver */
172	"PNP0C02",	/* No "PnP motherboard register resources" driver */
173	"PNP0C0B",	/* No need for "ACPI fan" driver */
174	"PNP0C0F",	/* ACPI PCI link devices are handled internally */
175	"INT0800",	/* Intel HW RNG is handled internally */
176#endif
177#if defined(x86_64)
178	"PNP0C04",	/* FPU is handled internally */
179#endif
180	NULL
181};
182
183/*
184 * sysctl-related information
185 */
186
187static uint64_t acpi_root_pointer;	/* found as hw.acpi.root */
188static int acpi_sleepstate = ACPI_STATE_S0;
189static char acpi_supported_states[3 * 6 + 1] = "";
190
191/*
192 * Prototypes.
193 */
194static void		acpi_build_tree(struct acpi_softc *);
195static ACPI_STATUS	acpi_make_devnode(ACPI_HANDLE, uint32_t,
196					  void *, void **);
197
198static void		acpi_enable_fixed_events(struct acpi_softc *);
199
200static ACPI_TABLE_HEADER *acpi_map_rsdt(void);
201static void		acpi_unmap_rsdt(ACPI_TABLE_HEADER *);
202static int		is_available_state(struct acpi_softc *, int);
203
204static bool		acpi_suspend(device_t, const pmf_qual_t *);
205static bool		acpi_resume(device_t, const pmf_qual_t *);
206
207#ifdef ACPI_ACTIVATE_DEV
208static void		acpi_activate_device(ACPI_HANDLE, ACPI_DEVICE_INFO **);
209static ACPI_STATUS	acpi_allocate_resources(ACPI_HANDLE);
210#endif
211
212/*
213 * acpi_probe:
214 *
215 *	Probe for ACPI support.  This is called by the
216 *	machine-dependent ACPI front-end.  All of the
217 *	actual work is done by ACPICA.
218 *
219 *	NOTE: This is not an autoconfiguration interface function.
220 */
221int
222acpi_probe(void)
223{
224	static int beenhere;
225	ACPI_TABLE_HEADER *rsdt;
226	ACPI_STATUS rv;
227
228	if (beenhere != 0)
229		panic("acpi_probe: ACPI has already been probed");
230	beenhere = 1;
231
232	mutex_init(&acpi_interrupt_list_mtx, MUTEX_DEFAULT, IPL_NONE);
233
234	/*
235	 * Start up ACPICA.
236	 */
237#ifdef ACPI_DEBUGGER
238	if (acpi_dbgr & ACPI_DBGR_INIT)
239		acpi_osd_debugger();
240#endif
241
242	AcpiGbl_AllMethodsSerialized = FALSE;
243	AcpiGbl_EnableInterpreterSlack = TRUE;
244
245	rv = AcpiInitializeSubsystem();
246	if (ACPI_FAILURE(rv)) {
247		printf("ACPI: unable to initialize ACPICA: %s\n",
248		    AcpiFormatException(rv));
249		return 0;
250	}
251
252	rv = AcpiInitializeTables(acpi_initial_tables, 128, 0);
253	if (ACPI_FAILURE(rv)) {
254#ifdef ACPI_DEBUG
255		printf("ACPI: unable to initialize ACPI tables: %s\n",
256		    AcpiFormatException(rv));
257#endif
258		AcpiTerminate();
259		return 0;
260	}
261
262	rv = AcpiReallocateRootTable();
263	if (ACPI_FAILURE(rv)) {
264		printf("ACPI: unable to reallocate root table: %s\n",
265		    AcpiFormatException(rv));
266		AcpiTerminate();
267		return 0;
268	}
269
270#ifdef ACPI_DEBUGGER
271	if (acpi_dbgr & ACPI_DBGR_TABLES)
272		acpi_osd_debugger();
273#endif
274
275	rv = AcpiLoadTables();
276	if (ACPI_FAILURE(rv)) {
277		printf("ACPI: unable to load tables: %s\n",
278		    AcpiFormatException(rv));
279		AcpiTerminate();
280		return 0;
281	}
282
283	rsdt = acpi_map_rsdt();
284	if (rsdt == NULL) {
285		printf("ACPI: unable to map RSDT\n");
286		AcpiTerminate();
287		return 0;
288	}
289
290	if (!acpi_force_load && (acpi_find_quirks() & ACPI_QUIRK_BROKEN)) {
291		printf("ACPI: BIOS implementation in listed as broken:\n");
292		printf("ACPI: X/RSDT: OemId <%6.6s,%8.8s,%08x>, "
293		       "AslId <%4.4s,%08x>\n",
294			rsdt->OemId, rsdt->OemTableId,
295		        rsdt->OemRevision,
296			rsdt->AslCompilerId,
297		        rsdt->AslCompilerRevision);
298		printf("ACPI: not used. set acpi_force_load to use anyway.\n");
299		acpi_unmap_rsdt(rsdt);
300		AcpiTerminate();
301		return 0;
302	}
303
304	acpi_unmap_rsdt(rsdt);
305
306#if notyet
307	/* Install the default address space handlers. */
308	rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
309	    ACPI_ADR_SPACE_SYSTEM_MEMORY, ACPI_DEFAULT_HANDLER, NULL, NULL);
310	if (ACPI_FAILURE(rv)) {
311		printf("ACPI: unable to initialize SystemMemory handler: %s\n",
312		    AcpiFormatException(rv));
313		AcpiTerminate();
314		return 0;
315	}
316	rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
317	    ACPI_ADR_SPACE_SYSTEM_IO, ACPI_DEFAULT_HANDLER, NULL, NULL);
318	if (ACPI_FAILURE(rv)) {
319		printf("ACPI: unable to initialize SystemIO handler: %s\n",
320		     AcpiFormatException(rv));
321		AcpiTerminate();
322		return 0;
323	}
324	rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
325	    ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
326	if (ACPI_FAILURE(rv)) {
327		printf("ACPI: unable to initialize PciConfig handler: %s\n",
328		    AcpiFormatException(rv));
329		AcpiTerminate();
330		return 0;
331	}
332#endif
333
334	rv = AcpiEnableSubsystem(~(ACPI_NO_HARDWARE_INIT|ACPI_NO_ACPI_ENABLE));
335	if (ACPI_FAILURE(rv)) {
336		printf("ACPI: unable to enable: %s\n", AcpiFormatException(rv));
337		AcpiTerminate();
338		return 0;
339	}
340
341	/*
342	 * Looks like we have ACPI!
343	 */
344
345	return 1;
346}
347
348static int
349acpi_submatch(device_t parent, cfdata_t cf, const int *locs, void *aux)
350{
351	struct cfattach *ca;
352
353	ca = config_cfattach_lookup(cf->cf_name, cf->cf_atname);
354	return (ca == &acpi_ca);
355}
356
357int
358acpi_check(device_t parent, const char *ifattr)
359{
360	return (config_search_ia(acpi_submatch, parent, ifattr, NULL) != NULL);
361}
362
363ACPI_PHYSICAL_ADDRESS
364acpi_OsGetRootPointer(void)
365{
366	ACPI_PHYSICAL_ADDRESS PhysicalAddress;
367
368	/*
369	 * IA-32: Use AcpiFindRootPointer() to locate the RSDP.
370	 *
371	 * IA-64: Use the EFI.
372	 *
373	 * We let MD code handle this since there are multiple
374	 * ways to do it.
375	 */
376
377	PhysicalAddress = acpi_md_OsGetRootPointer();
378
379	if (acpi_root_pointer == 0)
380		acpi_root_pointer = PhysicalAddress;
381
382	return PhysicalAddress;
383}
384
385/*
386 * acpi_match:
387 *
388 *	Autoconfiguration `match' routine.
389 */
390static int
391acpi_match(device_t parent, cfdata_t match, void *aux)
392{
393	/*
394	 * XXX Check other locators?  Hard to know -- machine
395	 * dependent code has already checked for the presence
396	 * of ACPI by calling acpi_probe(), so I suppose we
397	 * don't really have to do anything else.
398	 */
399	return 1;
400}
401
402/* Remove references to child devices.
403 *
404 * XXX Need to reclaim any resources?
405 */
406static void
407acpi_childdet(device_t self, device_t child)
408{
409	struct acpi_softc *sc = device_private(self);
410	struct acpi_devnode *ad;
411
412	if (sc->sc_apmbus == child)
413		sc->sc_apmbus = NULL;
414
415	SIMPLEQ_FOREACH(ad, &sc->sc_devnodes, ad_list) {
416
417		if (ad->ad_device == child)
418			ad->ad_device = NULL;
419	}
420}
421
422/*
423 * acpi_attach:
424 *
425 *	Autoconfiguration `attach' routine.  Finish initializing
426 *	ACPICA (some initialization was done in acpi_probe(),
427 *	which was required to check for the presence of ACPI),
428 *	and enable the ACPI subsystem.
429 */
430static void
431acpi_attach(device_t parent, device_t self, void *aux)
432{
433	struct acpi_softc *sc = device_private(self);
434	struct acpibus_attach_args *aa = aux;
435	ACPI_STATUS rv;
436	ACPI_TABLE_HEADER *rsdt;
437
438	aprint_naive("\n");
439	aprint_normal(": Intel ACPICA %08x\n", ACPI_CA_VERSION);
440
441	if (acpi_softc != NULL)
442		panic("acpi_attach: ACPI has already been attached");
443
444	sysmon_power_settype("acpi");
445
446	rsdt = acpi_map_rsdt();
447	if (rsdt) {
448		aprint_verbose_dev(
449		    self,
450		    "X/RSDT: OemId <%6.6s,%8.8s,%08x>, AslId <%4.4s,%08x>\n",
451		    rsdt->OemId, rsdt->OemTableId,
452		    rsdt->OemRevision,
453		    rsdt->AslCompilerId, rsdt->AslCompilerRevision);
454	} else
455		aprint_error_dev(self, "X/RSDT: Not found\n");
456
457	acpi_unmap_rsdt(rsdt);
458
459	sc->sc_dev = self;
460	sc->sc_quirks = acpi_find_quirks();
461
462	sc->sc_iot = aa->aa_iot;
463	sc->sc_memt = aa->aa_memt;
464	sc->sc_pc = aa->aa_pc;
465	sc->sc_pciflags = aa->aa_pciflags;
466	sc->sc_ic = aa->aa_ic;
467
468	SIMPLEQ_INIT(&sc->sc_devnodes);
469
470	acpi_softc = sc;
471
472	/*
473	 * Register null power management handler.
474	 */
475	if (!pmf_device_register(self, acpi_suspend, acpi_resume))
476		aprint_error_dev(self, "couldn't establish power handler\n");
477
478	/*
479	 * Bring ACPI on-line.
480	 */
481#ifdef ACPI_DEBUGGER
482	if (acpi_dbgr & ACPI_DBGR_ENABLE)
483		acpi_osd_debugger();
484#endif
485
486#define ACPI_ENABLE_PHASE1 \
487    (ACPI_NO_HANDLER_INIT | ACPI_NO_EVENT_INIT)
488#define ACPI_ENABLE_PHASE2 \
489    (ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE | \
490     ACPI_NO_ADDRESS_SPACE_INIT)
491
492	rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE1);
493	if (ACPI_FAILURE(rv)) {
494		aprint_error_dev(self, "unable to enable ACPI: %s\n",
495		    AcpiFormatException(rv));
496		return;
497	}
498
499	acpi_md_callback();
500
501	rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE2);
502	if (ACPI_FAILURE(rv)) {
503		aprint_error_dev(self, "unable to enable ACPI: %s\n",
504		    AcpiFormatException(rv));
505		return;
506	}
507
508	/* Early EC handler initialization if ECDT table is available. */
509	config_found_ia(self, "acpiecdtbus", NULL, NULL);
510
511	rv = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION);
512	if (ACPI_FAILURE(rv)) {
513		aprint_error_dev(self,
514		    "unable to initialize ACPI objects: %s\n",
515		    AcpiFormatException(rv));
516		return;
517	}
518	acpi_active = 1;
519
520	/* Our current state is "awake". */
521	sc->sc_sleepstate = ACPI_STATE_S0;
522
523	/* Show SCI interrupt. */
524	aprint_verbose_dev(self, "SCI interrupting at int %u\n",
525	    AcpiGbl_FADT.SciInterrupt);
526
527	/*
528	 * Check for fixed-hardware features.
529	 */
530	acpi_enable_fixed_events(sc);
531	acpitimer_init();
532
533	/*
534	 * Scan the namespace and build our device tree.
535	 */
536#ifdef ACPI_DEBUGGER
537	if (acpi_dbgr & ACPI_DBGR_PROBE)
538		acpi_osd_debugger();
539#endif
540	acpi_build_tree(sc);
541
542	snprintf(acpi_supported_states, sizeof(acpi_supported_states),
543	    "%s%s%s%s%s%s",
544	    is_available_state(sc, ACPI_STATE_S0) ? "S0 " : "",
545	    is_available_state(sc, ACPI_STATE_S1) ? "S1 " : "",
546	    is_available_state(sc, ACPI_STATE_S2) ? "S2 " : "",
547	    is_available_state(sc, ACPI_STATE_S3) ? "S3 " : "",
548	    is_available_state(sc, ACPI_STATE_S4) ? "S4 " : "",
549	    is_available_state(sc, ACPI_STATE_S5) ? "S5 " : "");
550
551#ifdef ACPI_DEBUGGER
552	if (acpi_dbgr & ACPI_DBGR_RUNNING)
553		acpi_osd_debugger();
554#endif
555
556#ifdef ACPI_DEBUG
557	acpi_debug_init();
558#endif
559}
560
561static int
562acpi_detach(device_t self, int flags)
563{
564	int rc;
565
566#ifdef ACPI_DEBUGGER
567	if (acpi_dbgr & ACPI_DBGR_RUNNING)
568		acpi_osd_debugger();
569#endif
570
571	if ((rc = config_detach_children(self, flags)) != 0)
572		return rc;
573
574#ifdef ACPI_DEBUGGER
575	if (acpi_dbgr & ACPI_DBGR_PROBE)
576		acpi_osd_debugger();
577#endif
578
579	if ((rc = acpitimer_detach()) != 0)
580		return rc;
581
582#if 0
583	/*
584	 * Bring ACPI on-line.
585	 */
586#ifdef ACPI_DEBUGGER
587	if (acpi_dbgr & ACPI_DBGR_ENABLE)
588		acpi_osd_debugger();
589#endif
590
591#define ACPI_ENABLE_PHASE1 \
592    (ACPI_NO_HANDLER_INIT | ACPI_NO_EVENT_INIT)
593#define ACPI_ENABLE_PHASE2 \
594    (ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE | \
595     ACPI_NO_ADDRESS_SPACE_INIT)
596
597	rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE1);
598	if (ACPI_FAILURE(rv)) {
599		aprint_error_dev(self, "unable to enable ACPI: %s\n",
600		    AcpiFormatException(rv));
601		return;
602	}
603
604	rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE2);
605	if (ACPI_FAILURE(rv)) {
606		aprint_error_dev(self, "unable to enable ACPI: %s\n",
607		    AcpiFormatException(rv));
608		return;
609	}
610
611	/* Early EC handler initialization if ECDT table is available. */
612	config_found_ia(self, "acpiecdtbus", NULL, NULL);
613
614	rv = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION);
615	if (ACPI_FAILURE(rv)) {
616		aprint_error_dev(self,
617		    "unable to initialize ACPI objects: %s\n",
618		    AcpiFormatException(rv));
619		return;
620	}
621	acpi_active = 1;
622
623	acpi_enable_fixed_events(sc);
624#endif
625
626	pmf_device_deregister(self);
627
628#if 0
629	sysmon_power_settype("acpi");
630#endif
631	acpi_softc = NULL;
632
633	return 0;
634}
635
636static bool
637acpi_suspend(device_t dv, const pmf_qual_t *qual)
638{
639	acpi_suspended = 1;
640	return true;
641}
642
643static bool
644acpi_resume(device_t dv, const pmf_qual_t *qual)
645{
646	acpi_suspended = 0;
647	return true;
648}
649
650#if 0
651/*
652 * acpi_disable:
653 *
654 *	Disable ACPI.
655 */
656static ACPI_STATUS
657acpi_disable(struct acpi_softc *sc)
658{
659	ACPI_STATUS rv = AE_OK;
660
661	if (acpi_active) {
662		rv = AcpiDisable();
663		if (ACPI_SUCCESS(rv))
664			acpi_active = 0;
665	}
666	return rv;
667}
668#endif
669
670/*
671 * acpi_build_tree:
672 *
673 *	Scan relevant portions of the ACPI namespace and attach
674 *	child devices.
675 */
676static void
677acpi_build_tree(struct acpi_softc *sc)
678{
679	static const char *scopes[] = {
680		"\\_PR_", "\\_SB_", "\\_SI_", "\\_TZ_", NULL
681	};
682
683	ACPI_HANDLE parent;
684	ACPI_STATUS rv;
685	int i;
686
687	/*
688	 * Scan the namespace and build our device tree.
689	 */
690	for (i = 0; scopes[i] != NULL; i++) {
691
692		rv = AcpiGetHandle(ACPI_ROOT_OBJECT, scopes[i], &parent);
693
694		if (ACPI_SUCCESS(rv))
695			(void)AcpiWalkNamespace(ACPI_TYPE_ANY, parent, 100,
696			    acpi_make_devnode, sc, NULL);
697	}
698
699	acpi_rescan1(sc, NULL, NULL);
700	acpi_wakedev_scan(sc);
701	acpi_pcidev_scan(sc);
702}
703
704static int
705acpi_rescan(device_t self, const char *ifattr, const int *locators)
706{
707	struct acpi_softc *sc = device_private(self);
708
709	acpi_rescan1(sc, ifattr, locators);
710	return 0;
711}
712
713static void
714acpi_rescan1(struct acpi_softc *sc, const char *ifattr, const int *locators)
715{
716	if (ifattr_match(ifattr, "acpinodebus"))
717		acpi_rescan_nodes(sc);
718
719	if (ifattr_match(ifattr, "acpiapmbus") && sc->sc_apmbus == NULL) {
720		sc->sc_apmbus = config_found_ia(sc->sc_dev, "acpiapmbus", NULL,
721		    NULL);
722	}
723}
724
725static void
726acpi_rescan_nodes(struct acpi_softc *sc)
727{
728	struct acpi_attach_args aa;
729	struct acpi_devnode *ad;
730
731	SIMPLEQ_FOREACH(ad, &sc->sc_devnodes, ad_list) {
732
733		if (ad->ad_device != NULL)
734			continue;
735
736		aa.aa_node = ad;
737		aa.aa_iot = sc->sc_iot;
738		aa.aa_memt = sc->sc_memt;
739		aa.aa_pc = sc->sc_pc;
740		aa.aa_pciflags = sc->sc_pciflags;
741		aa.aa_ic = sc->sc_ic;
742
743		if (ad->ad_devinfo->Type == ACPI_TYPE_DEVICE) {
744			/*
745			 * XXX We only attach devices which are:
746			 *
747			 *	- present
748			 *	- enabled
749			 *	- functioning properly
750			 *
751			 * However, if enabled, it's decoding resources,
752			 * so we should claim them, if possible.
753			 * Requires changes to bus_space(9).
754			 */
755			if ((ad->ad_devinfo->Valid & ACPI_VALID_STA) ==
756			    ACPI_VALID_STA &&
757			    (ad->ad_devinfo->CurrentStatus &
758			     (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|
759			      ACPI_STA_DEV_OK)) !=
760			    (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|
761			     ACPI_STA_DEV_OK))
762				continue;
763		}
764
765		/*
766		 * XXX Same problem as above...
767		 *
768		 * Do this check only for devices, as e.g.
769		 * a Thermal Zone doesn't have a HID.
770		 */
771		if (ad->ad_devinfo->Type == ACPI_TYPE_DEVICE &&
772		    (ad->ad_devinfo->Valid & ACPI_VALID_HID) == 0)
773			continue;
774
775		/*
776		 * Handled internally.
777		 */
778		if (ad->ad_devinfo->Type == ACPI_TYPE_PROCESSOR ||
779		    ad->ad_devinfo->Type == ACPI_TYPE_POWER)
780			continue;
781
782		/*
783		 * Skip ignored HIDs.
784		 */
785		if (acpi_match_hid(ad->ad_devinfo, acpi_ignored_ids))
786			continue;
787
788		ad->ad_device = config_found_ia(sc->sc_dev,
789		    "acpinodebus", &aa, acpi_print);
790	}
791}
792
793/*
794 * acpi_make_devnode:
795 *
796 *	Make an ACPI devnode.
797 */
798static ACPI_STATUS
799acpi_make_devnode(ACPI_HANDLE handle, uint32_t level,
800    void *context, void **status)
801{
802	struct acpi_softc *sc = context;
803	struct acpi_devnode *ad;
804	ACPI_DEVICE_INFO *devinfo;
805	ACPI_OBJECT_TYPE type;
806	ACPI_NAME_UNION *anu;
807	ACPI_STATUS rv;
808	int clear, i;
809
810	rv = AcpiGetType(handle, &type);
811
812	if (ACPI_FAILURE(rv))
813		return AE_OK;	/* Do not terminate the walk. */
814
815	rv = AcpiGetObjectInfo(handle, &devinfo);
816
817	if (ACPI_FAILURE(rv)) {
818		aprint_debug_dev(sc->sc_dev, "failed to get object "
819		    "information: %s\n", AcpiFormatException(rv));
820		return AE_OK;
821	}
822
823	switch (type) {
824
825	case ACPI_TYPE_DEVICE:
826
827#ifdef ACPI_ACTIVATE_DEV
828		acpi_activate_device(handle, &devinfo);
829#endif
830
831	case ACPI_TYPE_PROCESSOR:
832	case ACPI_TYPE_THERMAL:
833	case ACPI_TYPE_POWER:
834
835		ad = malloc(sizeof(*ad), M_ACPI, M_NOWAIT | M_ZERO);
836
837		if (ad == NULL)
838			return AE_NO_MEMORY;
839
840		ad->ad_parent = sc->sc_dev;
841		ad->ad_devinfo = devinfo;
842		ad->ad_handle = handle;
843		ad->ad_type = type;
844
845		anu = (ACPI_NAME_UNION *)&devinfo->Name;
846		ad->ad_name[4] = '\0';
847
848		for (i = 3, clear = 0; i >= 0; i--) {
849
850			if (clear == 0 && anu->Ascii[i] == '_')
851				ad->ad_name[i] = '\0';
852			else {
853				ad->ad_name[i] = anu->Ascii[i];
854				clear = 1;
855			}
856		}
857
858		if (ad->ad_name[0] == '\0')
859			ad->ad_name[0] = '_';
860
861		SIMPLEQ_INSERT_TAIL(&sc->sc_devnodes, ad, ad_list);
862
863#ifdef ACPIVERBOSE
864
865		if (type != ACPI_TYPE_DEVICE)
866			return AE_OK;
867
868		aprint_normal_dev(sc->sc_dev, "%-5s ", ad->ad_name);
869
870		aprint_normal("HID %-10s ",
871		    ((devinfo->Valid & ACPI_VALID_HID) != 0) ?
872		    devinfo->HardwareId.String: "-");
873
874		aprint_normal("UID %-4s ",
875		    ((devinfo->Valid & ACPI_VALID_UID) != 0) ?
876		    devinfo->UniqueId.String : "-");
877
878		if ((devinfo->Valid & ACPI_VALID_STA) != 0)
879			aprint_normal("STA 0x%08X ", devinfo->CurrentStatus);
880		else
881			aprint_normal("STA %10s ", "-");
882
883		if ((devinfo->Valid & ACPI_VALID_ADR) != 0)
884			aprint_normal("ADR 0x%016" PRIX64"",
885			    devinfo->Address);
886
887		aprint_normal("\n");
888#endif
889	}
890
891	return AE_OK;
892}
893
894/*
895 * acpi_print:
896 *
897 *	Autoconfiguration print routine for ACPI node bus.
898 */
899static int
900acpi_print(void *aux, const char *pnp)
901{
902	struct acpi_attach_args *aa = aux;
903	ACPI_STATUS rv;
904
905	if (pnp) {
906		if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_HID) {
907			char *pnpstr =
908			    aa->aa_node->ad_devinfo->HardwareId.String;
909			ACPI_BUFFER buf;
910
911			aprint_normal("%s (%s) ", aa->aa_node->ad_name,
912			    pnpstr);
913
914			rv = acpi_eval_struct(aa->aa_node->ad_handle,
915			    "_STR", &buf);
916			if (ACPI_SUCCESS(rv)) {
917				ACPI_OBJECT *obj = buf.Pointer;
918				switch (obj->Type) {
919				case ACPI_TYPE_STRING:
920					aprint_normal("[%s] ", obj->String.Pointer);
921					break;
922				case ACPI_TYPE_BUFFER:
923					aprint_normal("buffer %p ", obj->Buffer.Pointer);
924					break;
925				default:
926					aprint_normal("type %u ",obj->Type);
927					break;
928				}
929				ACPI_FREE(buf.Pointer);
930			}
931#ifdef ACPIVERBOSE
932			else {
933				int i;
934
935				for (i = 0; i < __arraycount(acpi_knowndevs);
936				    i++) {
937					if (strcmp(acpi_knowndevs[i].pnp,
938					    pnpstr) == 0) {
939						aprint_normal("[%s] ",
940						    acpi_knowndevs[i].str);
941					}
942				}
943			}
944
945#endif
946			aprint_normal("at %s", pnp);
947		} else if (aa->aa_node->ad_devinfo->Type != ACPI_TYPE_DEVICE) {
948			aprint_normal("%s (ACPI Object Type '%s' "
949			    "[0x%02x]) ", aa->aa_node->ad_name,
950			     AcpiUtGetTypeName(aa->aa_node->ad_devinfo->Type),
951			     aa->aa_node->ad_devinfo->Type);
952			aprint_normal("at %s", pnp);
953		} else
954			return 0;
955	} else {
956		aprint_normal(" (%s", aa->aa_node->ad_name);
957		if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_HID) {
958			aprint_normal(", %s", aa->aa_node->ad_devinfo->HardwareId.String);
959			if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_UID) {
960				const char *uid;
961
962				uid = aa->aa_node->ad_devinfo->UniqueId.String;
963				if (uid[0] == '\0')
964					uid = "<null>";
965				aprint_normal("-%s", uid);
966			}
967		}
968		aprint_normal(")");
969	}
970
971	return UNCONF;
972}
973
974/*****************************************************************************
975 * ACPI fixed-hardware feature handlers
976 *****************************************************************************/
977
978static UINT32	acpi_fixed_button_handler(void *);
979static void	acpi_fixed_button_pressed(void *);
980
981/*
982 * acpi_enable_fixed_events:
983 *
984 *	Enable any fixed-hardware feature handlers.
985 */
986static void
987acpi_enable_fixed_events(struct acpi_softc *sc)
988{
989	static int beenhere;
990	ACPI_STATUS rv;
991
992	KASSERT(beenhere == 0);
993	beenhere = 1;
994
995	/*
996	 * Check for fixed-hardware buttons.
997	 */
998	if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) == 0) {
999		aprint_verbose_dev(sc->sc_dev,
1000		    "fixed-feature power button present\n");
1001		sc->sc_smpsw_power.smpsw_name = device_xname(sc->sc_dev);
1002		sc->sc_smpsw_power.smpsw_type = PSWITCH_TYPE_POWER;
1003		if (sysmon_pswitch_register(&sc->sc_smpsw_power) != 0) {
1004			aprint_error_dev(sc->sc_dev,
1005			    "unable to register fixed power "
1006			    "button with sysmon\n");
1007		} else {
1008			rv = AcpiInstallFixedEventHandler(
1009			    ACPI_EVENT_POWER_BUTTON,
1010			    acpi_fixed_button_handler, &sc->sc_smpsw_power);
1011			if (ACPI_FAILURE(rv)) {
1012				aprint_error_dev(sc->sc_dev,
1013				    "unable to install handler "
1014				    "for fixed power button: %s\n",
1015				    AcpiFormatException(rv));
1016			}
1017		}
1018	}
1019
1020	if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) == 0) {
1021		aprint_verbose_dev(sc->sc_dev,
1022		    "fixed-feature sleep button present\n");
1023		sc->sc_smpsw_sleep.smpsw_name = device_xname(sc->sc_dev);
1024		sc->sc_smpsw_sleep.smpsw_type = PSWITCH_TYPE_SLEEP;
1025		if (sysmon_pswitch_register(&sc->sc_smpsw_power) != 0) {
1026			aprint_error_dev(sc->sc_dev,
1027			    "unable to register fixed sleep "
1028			    "button with sysmon\n");
1029		} else {
1030			rv = AcpiInstallFixedEventHandler(
1031			    ACPI_EVENT_SLEEP_BUTTON,
1032			    acpi_fixed_button_handler, &sc->sc_smpsw_sleep);
1033			if (ACPI_FAILURE(rv)) {
1034				aprint_error_dev(sc->sc_dev,
1035				    "unable to install handler "
1036				    "for fixed sleep button: %s\n",
1037				    AcpiFormatException(rv));
1038			}
1039		}
1040	}
1041}
1042
1043/*
1044 * acpi_fixed_button_handler:
1045 *
1046 *	Event handler for the fixed buttons.
1047 */
1048static UINT32
1049acpi_fixed_button_handler(void *context)
1050{
1051	static const int handler = OSL_NOTIFY_HANDLER;
1052	struct sysmon_pswitch *smpsw = context;
1053
1054	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s\n", __func__));
1055
1056	(void)AcpiOsExecute(handler, acpi_fixed_button_pressed, smpsw);
1057
1058	return ACPI_INTERRUPT_HANDLED;
1059}
1060
1061/*
1062 * acpi_fixed_button_pressed:
1063 *
1064 *	Deal with a fixed button being pressed.
1065 */
1066static void
1067acpi_fixed_button_pressed(void *context)
1068{
1069	struct sysmon_pswitch *smpsw = context;
1070
1071	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s: %s fixed button pressed\n",
1072		__func__, smpsw->smpsw_name));
1073
1074	sysmon_pswitch_event(smpsw, PSWITCH_EVENT_PRESSED);
1075}
1076
1077/*****************************************************************************
1078 * ACPI utility routines.
1079 *****************************************************************************/
1080
1081/*
1082 * acpi_eval_integer:
1083 *
1084 *	Evaluate an integer object.
1085 */
1086ACPI_STATUS
1087acpi_eval_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER *valp)
1088{
1089	ACPI_STATUS rv;
1090	ACPI_BUFFER buf;
1091	ACPI_OBJECT param;
1092
1093	if (handle == NULL)
1094		handle = ACPI_ROOT_OBJECT;
1095
1096	buf.Pointer = &param;
1097	buf.Length = sizeof(param);
1098
1099	rv = AcpiEvaluateObjectTyped(handle, path, NULL, &buf,
1100	    ACPI_TYPE_INTEGER);
1101	if (ACPI_SUCCESS(rv))
1102		*valp = param.Integer.Value;
1103
1104	return rv;
1105}
1106
1107/*
1108 * acpi_eval_set_integer:
1109 *
1110 *	Evaluate an integer object with a single integer input parameter.
1111 */
1112ACPI_STATUS
1113acpi_eval_set_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER arg)
1114{
1115	ACPI_OBJECT param_arg;
1116	ACPI_OBJECT_LIST param_args;
1117
1118	if (handle == NULL)
1119		handle = ACPI_ROOT_OBJECT;
1120
1121	param_arg.Type = ACPI_TYPE_INTEGER;
1122	param_arg.Integer.Value = arg;
1123
1124	param_args.Count = 1;
1125	param_args.Pointer = &param_arg;
1126
1127	return AcpiEvaluateObject(handle, path, &param_args, NULL);
1128}
1129
1130/*
1131 * acpi_eval_string:
1132 *
1133 *	Evaluate a (Unicode) string object.
1134 */
1135ACPI_STATUS
1136acpi_eval_string(ACPI_HANDLE handle, const char *path, char **stringp)
1137{
1138	ACPI_OBJECT *obj;
1139	ACPI_BUFFER buf;
1140	ACPI_STATUS rv;
1141
1142	rv = acpi_eval_struct(handle, path, &buf);
1143
1144	if (ACPI_FAILURE(rv))
1145		return rv;
1146
1147	obj = buf.Pointer;
1148
1149	if (obj->Type != ACPI_TYPE_STRING) {
1150		rv = AE_TYPE;
1151		goto out;
1152	}
1153
1154	if (obj->String.Length == 0) {
1155		rv = AE_BAD_DATA;
1156		goto out;
1157	}
1158
1159	*stringp = ACPI_ALLOCATE(obj->String.Length + 1);
1160
1161	if (*stringp == NULL) {
1162		rv = AE_NO_MEMORY;
1163		goto out;
1164	}
1165
1166	(void)memcpy(*stringp, obj->String.Pointer, obj->String.Length);
1167
1168	(*stringp)[obj->String.Length] = '\0';
1169
1170out:
1171	ACPI_FREE(buf.Pointer);
1172
1173	return rv;
1174}
1175
1176/*
1177 * acpi_eval_struct:
1178 *
1179 *	Evaluate a more complex structure.
1180 *	Caller must free buf.Pointer by ACPI_FREE().
1181 */
1182ACPI_STATUS
1183acpi_eval_struct(ACPI_HANDLE handle, const char *path, ACPI_BUFFER *bufp)
1184{
1185	ACPI_STATUS rv;
1186
1187	if (handle == NULL)
1188		handle = ACPI_ROOT_OBJECT;
1189
1190	bufp->Pointer = NULL;
1191	bufp->Length = ACPI_ALLOCATE_LOCAL_BUFFER;
1192
1193	rv = AcpiEvaluateObject(handle, path, NULL, bufp);
1194
1195	return rv;
1196}
1197
1198/*
1199 * acpi_eval_reference_handle:
1200 *
1201 *	Evaluate a reference handle from an element in a package.
1202 */
1203ACPI_STATUS
1204acpi_eval_reference_handle(ACPI_OBJECT *elm, ACPI_HANDLE *handle)
1205{
1206
1207	if (elm == NULL || handle == NULL)
1208		return AE_BAD_PARAMETER;
1209
1210	switch (elm->Type) {
1211
1212	case ACPI_TYPE_ANY:
1213	case ACPI_TYPE_LOCAL_REFERENCE:
1214
1215		if (elm->Reference.Handle == NULL)
1216			return AE_NULL_ENTRY;
1217
1218		*handle = elm->Reference.Handle;
1219
1220		return AE_OK;
1221
1222	case ACPI_TYPE_STRING:
1223		return AcpiGetHandle(NULL, elm->String.Pointer, handle);
1224
1225	default:
1226		return AE_TYPE;
1227	}
1228}
1229
1230/*
1231 * acpi_foreach_package_object:
1232 *
1233 *	Iterate over all objects in a package, and pass them all
1234 *	to a function. If the called function returns non AE_OK, the
1235 *	iteration is stopped and that value is returned.
1236 */
1237ACPI_STATUS
1238acpi_foreach_package_object(ACPI_OBJECT *pkg,
1239    ACPI_STATUS (*func)(ACPI_OBJECT *, void *),
1240    void *arg)
1241{
1242	ACPI_STATUS rv = AE_OK;
1243	int i;
1244
1245	if (pkg == NULL || pkg->Type != ACPI_TYPE_PACKAGE)
1246		return AE_BAD_PARAMETER;
1247
1248	for (i = 0; i < pkg->Package.Count; i++) {
1249		rv = (*func)(&pkg->Package.Elements[i], arg);
1250		if (ACPI_FAILURE(rv))
1251			break;
1252	}
1253
1254	return rv;
1255}
1256
1257/*
1258 * acpi_name:
1259 *
1260 *	Return a complete pathname from a handle.
1261 *
1262 *	Note that the function uses static data storage;
1263 *	if the data is needed for future use, it should be
1264 *	copied before any subsequent calls overwrite it.
1265 */
1266const char *
1267acpi_name(ACPI_HANDLE handle)
1268{
1269	static char buffer[80];
1270	ACPI_BUFFER buf;
1271	ACPI_STATUS rv;
1272
1273	buf.Length = sizeof(buffer);
1274	buf.Pointer = buffer;
1275
1276	rv = AcpiGetName(handle, ACPI_FULL_PATHNAME, &buf);
1277	if (ACPI_FAILURE(rv))
1278		return "(unknown acpi path)";
1279	return buffer;
1280}
1281
1282/*
1283 * acpi_get:
1284 *
1285 *	Fetch data info the specified (empty) ACPI buffer.
1286 *	Caller must free buf.Pointer by ACPI_FREE().
1287 */
1288ACPI_STATUS
1289acpi_get(ACPI_HANDLE handle, ACPI_BUFFER *buf,
1290    ACPI_STATUS (*getit)(ACPI_HANDLE, ACPI_BUFFER *))
1291{
1292	buf->Pointer = NULL;
1293	buf->Length = ACPI_ALLOCATE_LOCAL_BUFFER;
1294
1295	return (*getit)(handle, buf);
1296}
1297
1298
1299/*
1300 * acpi_match_hid
1301 *
1302 *	Match given ids against _HID and _CIDs.
1303 */
1304int
1305acpi_match_hid(ACPI_DEVICE_INFO *ad, const char * const *ids)
1306{
1307	int i;
1308
1309	while (*ids) {
1310		if (ad->Valid & ACPI_VALID_HID) {
1311			if (pmatch(ad->HardwareId.String, *ids, NULL) == 2)
1312				return 1;
1313		}
1314
1315		if (ad->Valid & ACPI_VALID_CID) {
1316			for (i = 0; i < ad->CompatibleIdList.Count; i++) {
1317				if (pmatch(ad->CompatibleIdList.Ids[i].String, *ids, NULL) == 2)
1318					return 1;
1319			}
1320		}
1321		ids++;
1322	}
1323
1324	return 0;
1325}
1326
1327/*
1328 * acpi_wake_gpe_helper
1329 *
1330 *	Set/unset GPE as both Runtime and Wake.
1331 */
1332static void
1333acpi_wake_gpe_helper(ACPI_HANDLE handle, bool enable)
1334{
1335	ACPI_OBJECT *elm, *obj;
1336	ACPI_INTEGER val;
1337	ACPI_BUFFER buf;
1338	ACPI_STATUS rv;
1339
1340	rv = acpi_eval_struct(handle, METHOD_NAME__PRW, &buf);
1341
1342	if (ACPI_FAILURE(rv))
1343		return;
1344
1345	obj = buf.Pointer;
1346
1347	if (obj->Type != ACPI_TYPE_PACKAGE || obj->Package.Count < 2)
1348		goto out;
1349
1350	/*
1351	 * As noted in ACPI 3.0 (section 7.2.10), the _PRW object is
1352	 * a package in which the first element is either an integer
1353	 * or again a package. In the latter case the package inside
1354	 * the package element has two elements, a reference handle
1355	 * and the GPE number.
1356	 */
1357	elm = &obj->Package.Elements[0];
1358
1359	switch (elm->Type) {
1360
1361	case ACPI_TYPE_INTEGER:
1362		val = elm->Integer.Value;
1363		break;
1364
1365	case ACPI_TYPE_PACKAGE:
1366
1367		if (elm->Package.Count < 2)
1368			goto out;
1369
1370		if (elm->Package.Elements[0].Type != ACPI_TYPE_LOCAL_REFERENCE)
1371			goto out;
1372
1373		if (elm->Package.Elements[1].Type != ACPI_TYPE_INTEGER)
1374			goto out;
1375
1376		val = elm->Package.Elements[1].Integer.Value;
1377		break;
1378
1379	default:
1380		goto out;
1381	}
1382
1383	if (enable) {
1384		(void)AcpiSetGpeType(NULL, val, ACPI_GPE_TYPE_WAKE_RUN);
1385		(void)AcpiEnableGpe(NULL, val, ACPI_NOT_ISR);
1386	} else
1387		(void)AcpiDisableGpe(NULL, val, ACPI_NOT_ISR);
1388
1389out:
1390	ACPI_FREE(buf.Pointer);
1391}
1392
1393/*
1394 * acpi_clear_wake_gpe
1395 *
1396 *	Clear GPE as both Runtime and Wake.
1397 */
1398void
1399acpi_clear_wake_gpe(ACPI_HANDLE handle)
1400{
1401	acpi_wake_gpe_helper(handle, false);
1402}
1403
1404/*
1405 * acpi_set_wake_gpe
1406 *
1407 *	Set GPE as both Runtime and Wake.
1408 */
1409void
1410acpi_set_wake_gpe(ACPI_HANDLE handle)
1411{
1412	acpi_wake_gpe_helper(handle, true);
1413}
1414
1415
1416/*****************************************************************************
1417 * ACPI sleep support.
1418 *****************************************************************************/
1419
1420static int
1421is_available_state(struct acpi_softc *sc, int state)
1422{
1423	UINT8 type_a, type_b;
1424
1425	return ACPI_SUCCESS(AcpiGetSleepTypeData((UINT8)state,
1426				&type_a, &type_b));
1427}
1428
1429/*
1430 * acpi_enter_sleep_state:
1431 *
1432 *	Enter to the specified sleep state.
1433 */
1434
1435ACPI_STATUS
1436acpi_enter_sleep_state(struct acpi_softc *sc, int state)
1437{
1438	int err;
1439	ACPI_STATUS ret = AE_OK;
1440
1441	if (state == acpi_sleepstate)
1442		return AE_OK;
1443
1444	aprint_normal_dev(sc->sc_dev, "entering state %d\n", state);
1445
1446	switch (state) {
1447	case ACPI_STATE_S0:
1448		break;
1449	case ACPI_STATE_S1:
1450	case ACPI_STATE_S2:
1451	case ACPI_STATE_S3:
1452	case ACPI_STATE_S4:
1453		if (!is_available_state(sc, state)) {
1454			aprint_error_dev(sc->sc_dev,
1455			    "ACPI S%d not available on this platform\n", state);
1456			break;
1457		}
1458
1459		acpi_wakedev_commit(sc, state);
1460
1461		if (state != ACPI_STATE_S1 && !pmf_system_suspend(PMF_Q_NONE)) {
1462			aprint_error_dev(sc->sc_dev, "aborting suspend\n");
1463			break;
1464		}
1465
1466		ret = AcpiEnterSleepStatePrep(state);
1467		if (ACPI_FAILURE(ret)) {
1468			aprint_error_dev(sc->sc_dev,
1469			    "failed preparing to sleep (%s)\n",
1470			    AcpiFormatException(ret));
1471			break;
1472		}
1473
1474		acpi_sleepstate = state;
1475		if (state == ACPI_STATE_S1) {
1476			/* just enter the state */
1477			acpi_md_OsDisableInterrupt();
1478			ret = AcpiEnterSleepState((UINT8)state);
1479			if (ACPI_FAILURE(ret))
1480				aprint_error_dev(sc->sc_dev,
1481				    "failed to enter sleep state S1: %s\n",
1482				    AcpiFormatException(ret));
1483			AcpiLeaveSleepState((UINT8)state);
1484		} else {
1485			err = acpi_md_sleep(state);
1486			if (state == ACPI_STATE_S4)
1487				AcpiEnable();
1488			pmf_system_bus_resume(PMF_Q_NONE);
1489			AcpiLeaveSleepState((UINT8)state);
1490			pmf_system_resume(PMF_Q_NONE);
1491		}
1492
1493		break;
1494	case ACPI_STATE_S5:
1495		ret = AcpiEnterSleepStatePrep(ACPI_STATE_S5);
1496		if (ACPI_FAILURE(ret)) {
1497			aprint_error_dev(sc->sc_dev,
1498			    "failed preparing to sleep (%s)\n",
1499			    AcpiFormatException(ret));
1500			break;
1501		}
1502		DELAY(1000000);
1503		acpi_sleepstate = state;
1504		acpi_md_OsDisableInterrupt();
1505		AcpiEnterSleepState(ACPI_STATE_S5);
1506		aprint_error_dev(sc->sc_dev, "WARNING powerdown failed!\n");
1507		break;
1508	}
1509
1510	acpi_sleepstate = ACPI_STATE_S0;
1511	return ret;
1512}
1513
1514#ifdef ACPI_ACTIVATE_DEV
1515
1516#define ACPI_DEV_VALID	(ACPI_VALID_STA | ACPI_VALID_HID)
1517#define ACPI_DEV_STATUS	(ACPI_STA_DEV_PRESENT | ACPI_STA_DEV_ENABLED)
1518
1519static void
1520acpi_activate_device(ACPI_HANDLE handle, ACPI_DEVICE_INFO **di)
1521{
1522	ACPI_DEVICE_INFO *newdi;
1523	ACPI_STATUS rv;
1524	uint32_t old;
1525
1526	/*
1527	 * If the device is valid and present,
1528	 * but not enabled, try to activate it.
1529	 */
1530	if (((*di)->Valid & ACPI_DEV_VALID) != ACPI_DEV_VALID)
1531		return;
1532
1533	old = (*di)->CurrentStatus;
1534
1535	if ((old & ACPI_DEV_STATUS) != ACPI_STA_DEV_PRESENT)
1536		return;
1537
1538	rv = acpi_allocate_resources(handle);
1539
1540	if (ACPI_FAILURE(rv))
1541		goto fail;
1542
1543	rv = AcpiGetObjectInfo(handle, &newdi);
1544
1545	if (ACPI_FAILURE(rv))
1546		goto fail;
1547
1548	ACPI_FREE(*di);
1549	*di = newdi;
1550
1551	aprint_verbose_dev(acpi_softc->sc_dev,
1552	    "%s activated, STA 0x%08X -> STA 0x%08X\n",
1553	    (*di)->HardwareId.String, old, (*di)->CurrentStatus);
1554
1555	return;
1556
1557fail:
1558	aprint_error_dev(acpi_softc->sc_dev, "failed to "
1559	    "activate %s\n", (*di)->HardwareId.String);
1560}
1561
1562/*
1563 * XXX: This very incomplete.
1564 */
1565ACPI_STATUS
1566acpi_allocate_resources(ACPI_HANDLE handle)
1567{
1568	ACPI_BUFFER bufp, bufc, bufn;
1569	ACPI_RESOURCE *resp, *resc, *resn;
1570	ACPI_RESOURCE_IRQ *irq;
1571	ACPI_RESOURCE_EXTENDED_IRQ *xirq;
1572	ACPI_STATUS rv;
1573	uint delta;
1574
1575	rv = acpi_get(handle, &bufp, AcpiGetPossibleResources);
1576	if (ACPI_FAILURE(rv))
1577		goto out;
1578	rv = acpi_get(handle, &bufc, AcpiGetCurrentResources);
1579	if (ACPI_FAILURE(rv)) {
1580		goto out1;
1581	}
1582
1583	bufn.Length = 1000;
1584	bufn.Pointer = resn = malloc(bufn.Length, M_ACPI, M_WAITOK);
1585	resp = bufp.Pointer;
1586	resc = bufc.Pointer;
1587	while (resc->Type != ACPI_RESOURCE_TYPE_END_TAG &&
1588	       resp->Type != ACPI_RESOURCE_TYPE_END_TAG) {
1589		while (resc->Type != resp->Type && resp->Type != ACPI_RESOURCE_TYPE_END_TAG)
1590			resp = ACPI_NEXT_RESOURCE(resp);
1591		if (resp->Type == ACPI_RESOURCE_TYPE_END_TAG)
1592			break;
1593		/* Found identical Id */
1594		resn->Type = resc->Type;
1595		switch (resc->Type) {
1596		case ACPI_RESOURCE_TYPE_IRQ:
1597			memcpy(&resn->Data, &resp->Data,
1598			       sizeof(ACPI_RESOURCE_IRQ));
1599			irq = (ACPI_RESOURCE_IRQ *)&resn->Data;
1600			irq->Interrupts[0] =
1601			    ((ACPI_RESOURCE_IRQ *)&resp->Data)->
1602			        Interrupts[irq->InterruptCount-1];
1603			irq->InterruptCount = 1;
1604			resn->Length = ACPI_RS_SIZE(ACPI_RESOURCE_IRQ);
1605			break;
1606		case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
1607			memcpy(&resn->Data, &resp->Data,
1608			       sizeof(ACPI_RESOURCE_EXTENDED_IRQ));
1609			xirq = (ACPI_RESOURCE_EXTENDED_IRQ *)&resn->Data;
1610#if 0
1611			/*
1612			 * XXX not duplicating the interrupt logic above
1613			 * because its not clear what it accomplishes.
1614			 */
1615			xirq->Interrupts[0] =
1616			    ((ACPI_RESOURCE_EXT_IRQ *)&resp->Data)->
1617			    Interrupts[irq->NumberOfInterrupts-1];
1618			xirq->NumberOfInterrupts = 1;
1619#endif
1620			resn->Length = ACPI_RS_SIZE(ACPI_RESOURCE_EXTENDED_IRQ);
1621			break;
1622		case ACPI_RESOURCE_TYPE_IO:
1623			memcpy(&resn->Data, &resp->Data,
1624			       sizeof(ACPI_RESOURCE_IO));
1625			resn->Length = resp->Length;
1626			break;
1627		default:
1628			aprint_error_dev(acpi_softc->sc_dev,
1629			    "%s: invalid type %u\n", __func__, resc->Type);
1630			rv = AE_BAD_DATA;
1631			goto out2;
1632		}
1633		resc = ACPI_NEXT_RESOURCE(resc);
1634		resn = ACPI_NEXT_RESOURCE(resn);
1635		resp = ACPI_NEXT_RESOURCE(resp);
1636		delta = (UINT8 *)resn - (UINT8 *)bufn.Pointer;
1637		if (delta >=
1638		    bufn.Length-ACPI_RS_SIZE(ACPI_RESOURCE_DATA)) {
1639			bufn.Length *= 2;
1640			bufn.Pointer = realloc(bufn.Pointer, bufn.Length,
1641					       M_ACPI, M_WAITOK);
1642			resn = (ACPI_RESOURCE *)((UINT8 *)bufn.Pointer + delta);
1643		}
1644	}
1645
1646	if (resc->Type != ACPI_RESOURCE_TYPE_END_TAG) {
1647		aprint_error_dev(acpi_softc->sc_dev,
1648		    "%s: resc not exhausted\n", __func__);
1649		rv = AE_BAD_DATA;
1650		goto out3;
1651	}
1652
1653	resn->Type = ACPI_RESOURCE_TYPE_END_TAG;
1654	rv = AcpiSetCurrentResources(handle, &bufn);
1655
1656	if (ACPI_FAILURE(rv))
1657		aprint_error_dev(acpi_softc->sc_dev, "%s: failed to set "
1658		    "resources: %s\n", __func__, AcpiFormatException(rv));
1659
1660out3:
1661	free(bufn.Pointer, M_ACPI);
1662out2:
1663	ACPI_FREE(bufc.Pointer);
1664out1:
1665	ACPI_FREE(bufp.Pointer);
1666out:
1667	return rv;
1668}
1669
1670#undef ACPI_DEV_VALID
1671#undef ACPI_DEV_STATUS
1672
1673#endif /* ACPI_ACTIVATE_DEV */
1674
1675SYSCTL_SETUP(sysctl_acpi_setup, "sysctl hw.acpi subtree setup")
1676{
1677	const struct sysctlnode *node;
1678	const struct sysctlnode *ssnode;
1679
1680	if (sysctl_createv(clog, 0, NULL, NULL,
1681	    CTLFLAG_PERMANENT,
1682	    CTLTYPE_NODE, "hw", NULL,
1683	    NULL, 0, NULL, 0,
1684	    CTL_HW, CTL_EOL) != 0)
1685		return;
1686
1687	if (sysctl_createv(clog, 0, NULL, &node,
1688	    CTLFLAG_PERMANENT,
1689	    CTLTYPE_NODE, "acpi", NULL,
1690	    NULL, 0, NULL, 0,
1691	    CTL_HW, CTL_CREATE, CTL_EOL) != 0)
1692		return;
1693
1694	sysctl_createv(NULL, 0, NULL, NULL, CTLFLAG_READONLY,
1695	    CTLTYPE_QUAD, "root",
1696	    SYSCTL_DESCR("ACPI root pointer"),
1697	    NULL, 0, &acpi_root_pointer, sizeof(acpi_root_pointer),
1698	    CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL);
1699	sysctl_createv(NULL, 0, NULL, NULL, CTLFLAG_READONLY,
1700	    CTLTYPE_STRING, "supported_states",
1701	    SYSCTL_DESCR("Supported ACPI system states"),
1702	    NULL, 0, acpi_supported_states, 0,
1703	    CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL);
1704
1705	/* ACPI sleepstate sysctl */
1706	if (sysctl_createv(NULL, 0, NULL, &node,
1707	    CTLFLAG_PERMANENT,
1708	    CTLTYPE_NODE, "machdep", NULL,
1709	    NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL) != 0)
1710		return;
1711	if (sysctl_createv(NULL, 0, &node, &ssnode,
1712	    CTLFLAG_READWRITE, CTLTYPE_INT, "sleep_state",
1713	    NULL, sysctl_hw_acpi_sleepstate, 0, NULL, 0, CTL_CREATE,
1714	    CTL_EOL) != 0)
1715		return;
1716}
1717
1718static int
1719sysctl_hw_acpi_sleepstate(SYSCTLFN_ARGS)
1720{
1721	int error, t;
1722	struct sysctlnode node;
1723
1724	node = *rnode;
1725	t = acpi_sleepstate;
1726	node.sysctl_data = &t;
1727	error = sysctl_lookup(SYSCTLFN_CALL(&node));
1728	if (error || newp == NULL)
1729		return error;
1730
1731	if (acpi_softc == NULL)
1732		return ENOSYS;
1733
1734	acpi_enter_sleep_state(acpi_softc, t);
1735
1736	return 0;
1737}
1738
1739static ACPI_TABLE_HEADER *
1740acpi_map_rsdt(void)
1741{
1742	ACPI_PHYSICAL_ADDRESS paddr;
1743	ACPI_TABLE_RSDP *rsdp;
1744
1745	paddr = AcpiOsGetRootPointer();
1746	if (paddr == 0) {
1747		printf("ACPI: couldn't get root pointer\n");
1748		return NULL;
1749	}
1750	rsdp = AcpiOsMapMemory(paddr, sizeof(ACPI_TABLE_RSDP));
1751	if (rsdp == NULL) {
1752		printf("ACPI: couldn't map RSDP\n");
1753		return NULL;
1754	}
1755	if (rsdp->Revision > 1 && rsdp->XsdtPhysicalAddress)
1756		paddr = (ACPI_PHYSICAL_ADDRESS)rsdp->XsdtPhysicalAddress;
1757	else
1758		paddr = (ACPI_PHYSICAL_ADDRESS)rsdp->RsdtPhysicalAddress;
1759	AcpiOsUnmapMemory(rsdp, sizeof(ACPI_TABLE_RSDP));
1760
1761	return AcpiOsMapMemory(paddr, sizeof(ACPI_TABLE_HEADER));
1762}
1763
1764static void
1765acpi_unmap_rsdt(ACPI_TABLE_HEADER *rsdt)
1766{
1767	if (rsdt == NULL)
1768		return;
1769
1770	AcpiOsUnmapMemory(rsdt, sizeof(ACPI_TABLE_HEADER));
1771}
1772