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