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