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