acpi.c revision 1.106
1/*	$NetBSD: acpi.c,v 1.106 2007/12/14 01:29:29 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 * 3. All advertising materials mentioning features or use of this software
19 *    must display the following acknowledgement:
20 *	This product includes software developed by the NetBSD
21 *	Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 *    contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39/*
40 * Copyright 2001, 2003 Wasabi Systems, Inc.
41 * All rights reserved.
42 *
43 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
44 *
45 * Redistribution and use in source and binary forms, with or without
46 * modification, are permitted provided that the following conditions
47 * are met:
48 * 1. Redistributions of source code must retain the above copyright
49 *    notice, this list of conditions and the following disclaimer.
50 * 2. Redistributions in binary form must reproduce the above copyright
51 *    notice, this list of conditions and the following disclaimer in the
52 *    documentation and/or other materials provided with the distribution.
53 * 3. All advertising materials mentioning features or use of this software
54 *    must display the following acknowledgement:
55 *	This product includes software developed for the NetBSD Project by
56 *	Wasabi Systems, Inc.
57 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
58 *    or promote products derived from this software without specific prior
59 *    written permission.
60 *
61 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
62 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
63 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
64 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
65 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
66 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
67 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
68 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
69 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
70 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
71 * POSSIBILITY OF SUCH DAMAGE.
72 */
73
74/*
75 * Autoconfiguration support for the Intel ACPI Component Architecture
76 * ACPI reference implementation.
77 */
78
79#include <sys/cdefs.h>
80__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.106 2007/12/14 01:29:29 jmcneill Exp $");
81
82#include "opt_acpi.h"
83#include "opt_pcifixup.h"
84
85#include <sys/param.h>
86#include <sys/systm.h>
87#include <sys/device.h>
88#include <sys/malloc.h>
89#include <sys/mutex.h>
90#include <sys/kernel.h>
91#include <sys/proc.h>
92#include <sys/sysctl.h>
93
94#include <dev/acpi/acpica.h>
95#include <dev/acpi/acpireg.h>
96#include <dev/acpi/acpivar.h>
97#include <dev/acpi/acpi_osd.h>
98#include <dev/acpi/acpi_timer.h>
99#ifdef ACPIVERBOSE
100#include <dev/acpi/acpidevs_data.h>
101#endif
102
103#if defined(ACPI_PCI_FIXUP)
104#error The option ACPI_PCI_FIXUP has been obsoleted by PCI_INTR_FIXUP_DISABLED.  Please adjust your kernel configuration file.
105#endif
106
107#ifdef PCI_INTR_FIXUP_DISABLED
108#include <dev/pci/pcidevs.h>
109#endif
110
111MALLOC_DECLARE(M_ACPI);
112
113#include <machine/acpi_machdep.h>
114
115#ifdef ACPI_DEBUGGER
116#define	ACPI_DBGR_INIT		0x01
117#define	ACPI_DBGR_TABLES	0x02
118#define	ACPI_DBGR_ENABLE	0x04
119#define	ACPI_DBGR_PROBE		0x08
120#define	ACPI_DBGR_RUNNING	0x10
121
122static int acpi_dbgr = 0x00;
123#endif
124
125static ACPI_TABLE_DESC	acpi_initial_tables[128];
126
127static int	acpi_match(struct device *, struct cfdata *, void *);
128static void	acpi_attach(struct device *, struct device *, void *);
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_DECL(acpi, sizeof(struct acpi_softc),
137    acpi_match, acpi_attach, NULL, NULL);
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;
146
147/*
148 * Pointer to the ACPI subsystem's state.  There can be only
149 * one ACPI instance.
150 */
151struct acpi_softc *acpi_softc;
152
153/*
154 * Locking stuff.
155 */
156static kmutex_t acpi_slock;
157static int acpi_locked;
158extern kmutex_t acpi_interrupt_list_mtx;
159
160/*
161 * sysctl-related information
162 */
163
164static int acpi_node = CTL_EOL;
165static uint64_t acpi_root_pointer;	/* found as hw.acpi.root */
166static int acpi_sleepstate = ACPI_STATE_S0;
167
168/*
169 * Prototypes.
170 */
171static void		acpi_shutdown(void *);
172static void		acpi_build_tree(struct acpi_softc *);
173static ACPI_STATUS	acpi_make_devnode(ACPI_HANDLE, UINT32, void *, void **);
174
175static void		acpi_enable_fixed_events(struct acpi_softc *);
176
177/*
178 * acpi_probe:
179 *
180 *	Probe for ACPI support.  This is called by the
181 *	machine-dependent ACPI front-end.  All of the
182 *	actual work is done by ACPICA.
183 *
184 *	NOTE: This is not an autoconfiguration interface function.
185 */
186int
187acpi_probe(void)
188{
189	static int beenhere;
190	ACPI_STATUS rv;
191
192	if (beenhere != 0)
193		panic("acpi_probe: ACPI has already been probed");
194	beenhere = 1;
195
196	mutex_init(&acpi_slock, MUTEX_DEFAULT, IPL_NONE);
197	mutex_init(&acpi_interrupt_list_mtx, MUTEX_DEFAULT, IPL_NONE);
198	acpi_locked = 0;
199
200	/*
201	 * Start up ACPICA.
202	 */
203#ifdef ACPI_DEBUGGER
204	if (acpi_dbgr & ACPI_DBGR_INIT)
205		acpi_osd_debugger();
206#endif
207
208	AcpiGbl_AllMethodsSerialized = FALSE;
209	AcpiGbl_EnableInterpreterSlack = TRUE;
210
211	rv = AcpiInitializeSubsystem();
212	if (ACPI_FAILURE(rv)) {
213		printf("ACPI: unable to initialize ACPICA: %s\n",
214		    AcpiFormatException(rv));
215		return 0;
216	}
217
218	rv = AcpiInitializeTables(acpi_initial_tables, 128, 0);
219	if (ACPI_FAILURE(rv)) {
220		printf("ACPI: unable to initialize ACPI tables: %s\n",
221		    AcpiFormatException(rv));
222		return 0;
223	}
224
225	rv = AcpiReallocateRootTable();
226	if (ACPI_FAILURE(rv)) {
227		printf("ACPI: unable to reallocate root table: %s\n",
228		    AcpiFormatException(rv));
229		return 0;
230	}
231
232#ifdef ACPI_DEBUGGER
233	if (acpi_dbgr & ACPI_DBGR_TABLES)
234		acpi_osd_debugger();
235#endif
236
237	rv = AcpiLoadTables();
238	if (ACPI_FAILURE(rv)) {
239		printf("ACPI: unable to load tables: %s\n",
240		    AcpiFormatException(rv));
241		return 0;
242	}
243
244#if notyet
245	if (!acpi_force_load && (acpi_find_quirks() & ACPI_QUIRK_BROKEN)) {
246		printf("ACPI: BIOS implementation in listed as broken:\n");
247		printf("ACPI: X/RSDT: OemId <%6.6s,%8.8s,%08x>, "
248		       "AslId <%4.4s,%08x>\n",
249			AcpiGbl_XSDT->OemId, AcpiGbl_XSDT->OemTableId,
250		        AcpiGbl_XSDT->OemRevision,
251			AcpiGbl_XSDT->AslCompilerId,
252		        AcpiGbl_XSDT->AslCompilerRevision);
253		printf("ACPI: not used. set acpi_force_load to use anyway.\n");
254		return 0;
255	}
256
257	/* Install the default address space handlers. */
258	rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
259	    ACPI_ADR_SPACE_SYSTEM_MEMORY, ACPI_DEFAULT_HANDLER, NULL, NULL);
260	if (ACPI_FAILURE(rv)) {
261		printf("ACPI: unable to initialise SystemMemory handler: %s\n",
262		    AcpiFormatException(rv));
263		return 0;
264	}
265	rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
266	    ACPI_ADR_SPACE_SYSTEM_IO, ACPI_DEFAULT_HANDLER, NULL, NULL);
267	if (ACPI_FAILURE(rv)) {
268		printf("ACPI: unable to initialise SystemIO handler: %s\n",
269		     AcpiFormatException(rv));
270		return 0;
271	}
272	rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
273	    ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
274	if (ACPI_FAILURE(rv)) {
275		printf("ACPI: unabled to initialise PciConfig handler: %s\n",
276		    AcpiFormatException(rv));
277		return 0;
278	}
279#endif
280
281	rv = AcpiEnableSubsystem(~(ACPI_NO_HARDWARE_INIT|ACPI_NO_ACPI_ENABLE));
282	if (ACPI_FAILURE(rv)) {
283		printf("ACPI: unable to enable: %s\n", AcpiFormatException(rv));
284		return 0;
285	}
286
287	/*
288	 * Looks like we have ACPI!
289	 */
290
291	return 1;
292}
293
294static int
295acpi_submatch(device_t parent, cfdata_t cf, const int *locs, void *aux)
296{
297	struct cfattach *ca;
298
299	ca = config_cfattach_lookup(cf->cf_name, cf->cf_atname);
300	return (ca == &acpi_ca);
301}
302
303int
304acpi_check(device_t parent, const char *ifattr)
305{
306	return (config_search_ia(acpi_submatch, parent, ifattr, NULL) != NULL);
307}
308
309ACPI_PHYSICAL_ADDRESS
310acpi_OsGetRootPointer(void)
311{
312	ACPI_PHYSICAL_ADDRESS PhysicalAddress;
313
314	/*
315	 * IA-32: Use AcpiFindRootPointer() to locate the RSDP.
316	 *
317	 * IA-64: Use the EFI.
318	 *
319	 * We let MD code handle this since there are multiple
320	 * ways to do it.
321	 */
322
323	PhysicalAddress = acpi_md_OsGetRootPointer();
324
325	if (acpi_root_pointer == 0)
326		acpi_root_pointer = PhysicalAddress;
327
328	return PhysicalAddress;
329}
330
331/*
332 * acpi_match:
333 *
334 *	Autoconfiguration `match' routine.
335 */
336static int
337acpi_match(struct device *parent, struct cfdata *match,
338    void *aux)
339{
340	/*
341	 * XXX Check other locators?  Hard to know -- machine
342	 * dependent code has already checked for the presence
343	 * of ACPI by calling acpi_probe(), so I suppose we
344	 * don't really have to do anything else.
345	 */
346	return 1;
347}
348
349/*
350 * acpi_attach:
351 *
352 *	Autoconfiguration `attach' routine.  Finish initializing
353 *	ACPICA (some initialization was done in acpi_probe(),
354 *	which was required to check for the presence of ACPI),
355 *	and enable the ACPI subsystem.
356 */
357static void
358acpi_attach(struct device *parent, struct device *self, void *aux)
359{
360	struct acpi_softc *sc = (void *) self;
361	struct acpibus_attach_args *aa = aux;
362	ACPI_STATUS rv;
363
364	aprint_naive(": Advanced Configuration and Power Interface\n");
365	aprint_normal(": Advanced Configuration and Power Interface\n");
366
367	if (acpi_softc != NULL)
368		panic("acpi_attach: ACPI has already been attached");
369
370	sysmon_power_settype("acpi");
371
372	aprint_verbose("%s: using Intel ACPI CA subsystem version %08x\n",
373	    sc->sc_dev.dv_xname, ACPI_CA_VERSION);
374
375#if 0
376	aprint_verbose("%s: X/RSDT: OemId <%6.6s,%8.8s,%08x>, AslId <%4.4s,%08x>\n",
377	    sc->sc_dev.dv_xname,
378	    AcpiGbl_XSDT->OemId, AcpiGbl_XSDT->OemTableId,
379	    AcpiGbl_XSDT->OemRevision,
380	    AcpiGbl_XSDT->AslCompilerId, AcpiGbl_XSDT->AslCompilerRevision);
381#endif
382
383	sc->sc_quirks = acpi_find_quirks();
384
385	sc->sc_iot = aa->aa_iot;
386	sc->sc_memt = aa->aa_memt;
387	sc->sc_pc = aa->aa_pc;
388	sc->sc_pciflags = aa->aa_pciflags;
389	sc->sc_ic = aa->aa_ic;
390
391	acpi_softc = sc;
392
393	/*
394	 * Register null power management handler
395	 */
396	if (!pmf_device_register(self, NULL, NULL))
397		aprint_error_dev(self, "couldn't establish power handler\n");
398
399	/*
400	 * Bring ACPI on-line.
401	 */
402#ifdef ACPI_DEBUGGER
403	if (acpi_dbgr & ACPI_DBGR_ENABLE)
404		acpi_osd_debugger();
405#endif
406
407#define ACPI_ENABLE_PHASE1 \
408    (ACPI_NO_HANDLER_INIT | ACPI_NO_EVENT_INIT)
409#define ACPI_ENABLE_PHASE2 \
410    (ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE | \
411     ACPI_NO_ADDRESS_SPACE_INIT)
412
413	rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE1);
414	if (ACPI_FAILURE(rv)) {
415		aprint_error("%s: unable to enable ACPI: %s\n",
416		    sc->sc_dev.dv_xname, AcpiFormatException(rv));
417		return;
418	}
419
420	acpi_md_callback();
421
422	rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE2);
423	if (ACPI_FAILURE(rv)) {
424		aprint_error("%s: unable to enable ACPI: %s\n",
425		    sc->sc_dev.dv_xname, AcpiFormatException(rv));
426		return;
427	}
428
429	/* early EC handler initialization if ECDT table is available */
430	config_found_ia(&sc->sc_dev, "acpiecdtbus", NULL, NULL);
431
432	rv = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION);
433	if (ACPI_FAILURE(rv)) {
434		aprint_error("%s: unable to initialize ACPI objects: %s\n",
435		    sc->sc_dev.dv_xname, AcpiFormatException(rv));
436		return;
437	}
438	acpi_active = 1;
439
440	/* Our current state is "awake". */
441	sc->sc_sleepstate = ACPI_STATE_S0;
442
443	/* Show SCI interrupt. */
444	aprint_verbose("%s: SCI interrupting at int %d\n",
445	    sc->sc_dev.dv_xname, AcpiGbl_FADT.SciInterrupt);
446
447	/*
448	 * Check for fixed-hardware features.
449	 */
450	acpi_enable_fixed_events(sc);
451	acpitimer_init();
452
453	/*
454	 * Scan the namespace and build our device tree.
455	 */
456#ifdef ACPI_DEBUGGER
457	if (acpi_dbgr & ACPI_DBGR_PROBE)
458		acpi_osd_debugger();
459#endif
460	acpi_build_tree(sc);
461
462	if (acpi_root_pointer != 0 && acpi_node != CTL_EOL) {
463		(void)sysctl_createv(NULL, 0, NULL, NULL,
464		    CTLFLAG_IMMEDIATE,
465		    CTLTYPE_QUAD, "root", NULL, NULL,
466		    acpi_root_pointer, NULL, 0,
467		    CTL_HW, acpi_node, CTL_CREATE, CTL_EOL);
468	}
469
470
471	/*
472	 * Register a shutdown hook that disables certain ACPI
473	 * events that might happen and confuse us while we're
474	 * trying to shut down.
475	 */
476	sc->sc_sdhook = shutdownhook_establish(acpi_shutdown, sc);
477	if (sc->sc_sdhook == NULL)
478		aprint_error("%s: WARNING: unable to register shutdown hook\n",
479		    sc->sc_dev.dv_xname);
480
481#ifdef ACPI_DEBUGGER
482	if (acpi_dbgr & ACPI_DBGR_RUNNING)
483		acpi_osd_debugger();
484#endif
485}
486
487/*
488 * acpi_shutdown:
489 *
490 *	Shutdown hook for ACPI -- disable some events that
491 *	might confuse us.
492 */
493static void
494acpi_shutdown(void *arg)
495{
496	/* nothing */
497}
498
499#if 0
500/*
501 * acpi_disable:
502 *
503 *	Disable ACPI.
504 */
505static ACPI_STATUS
506acpi_disable(struct acpi_softc *sc)
507{
508	ACPI_STATUS rv = AE_OK;
509
510	if (acpi_active) {
511		rv = AcpiDisable();
512		if (ACPI_SUCCESS(rv))
513			acpi_active = 0;
514	}
515	return rv;
516}
517#endif
518
519struct acpi_make_devnode_state {
520	struct acpi_softc *softc;
521	struct acpi_scope *scope;
522};
523
524/*
525 * acpi_build_tree:
526 *
527 *	Scan relevant portions of the ACPI namespace and attach
528 *	child devices.
529 */
530static void
531acpi_build_tree(struct acpi_softc *sc)
532{
533	static const char *scopes[] = {
534		"\\_PR_",	/* ACPI 1.0 processor namespace */
535		"\\_SB_",	/* system bus namespace */
536		"\\_SI_",	/* system indicator namespace */
537		"\\_TZ_",	/* ACPI 1.0 thermal zone namespace */
538		NULL,
539	};
540	struct acpi_attach_args aa;
541	struct acpi_make_devnode_state state;
542	struct acpi_scope *as;
543	struct acpi_devnode *ad;
544	ACPI_HANDLE parent;
545	ACPI_STATUS rv;
546	int i;
547
548	TAILQ_INIT(&sc->sc_scopes);
549
550	state.softc = sc;
551
552	/*
553	 * Scan the namespace and build our tree.
554	 */
555	for (i = 0; scopes[i] != NULL; i++) {
556		as = malloc(sizeof(*as), M_ACPI, M_WAITOK);
557		as->as_name = scopes[i];
558		TAILQ_INIT(&as->as_devnodes);
559
560		TAILQ_INSERT_TAIL(&sc->sc_scopes, as, as_list);
561
562		state.scope = as;
563
564		rv = AcpiGetHandle(ACPI_ROOT_OBJECT, scopes[i],
565		    &parent);
566		if (ACPI_SUCCESS(rv)) {
567			AcpiWalkNamespace(ACPI_TYPE_ANY, parent, 100,
568			    acpi_make_devnode, &state, NULL);
569		}
570
571		/* Now, for this namespace, try and attach the devices. */
572		TAILQ_FOREACH(ad, &as->as_devnodes, ad_list) {
573			aa.aa_node = ad;
574			aa.aa_iot = sc->sc_iot;
575			aa.aa_memt = sc->sc_memt;
576			aa.aa_pc = sc->sc_pc;
577			aa.aa_pciflags = sc->sc_pciflags;
578			aa.aa_ic = sc->sc_ic;
579
580			if (ad->ad_devinfo->Type == ACPI_TYPE_DEVICE) {
581				/*
582				 * XXX We only attach devices which are:
583				 *
584				 *	- present
585				 *	- enabled
586				 *	- functioning properly
587				 *
588				 * However, if enabled, it's decoding resources,
589				 * so we should claim them, if possible.
590				 * Requires changes to bus_space(9).
591				 */
592				if ((ad->ad_devinfo->Valid & ACPI_VALID_STA) ==
593				    ACPI_VALID_STA &&
594				    (ad->ad_devinfo->CurrentStatus &
595				     (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|
596				      ACPI_STA_DEV_OK)) !=
597				    (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|
598				     ACPI_STA_DEV_OK))
599					continue;
600			}
601
602			/*
603			 * XXX Same problem as above...
604			 *
605			 * Do this check only for devices, as e.g.
606			 * a Thermal Zone doesn't have a HID.
607			 */
608			if (ad->ad_devinfo->Type == ACPI_TYPE_DEVICE &&
609			    (ad->ad_devinfo->Valid & ACPI_VALID_HID) == 0)
610				continue;
611
612			ad->ad_device = config_found_ia(&sc->sc_dev,
613			    "acpinodebus", &aa, acpi_print);
614		}
615	}
616	config_found_ia(&sc->sc_dev, "acpiapmbus", NULL, NULL);
617}
618
619#ifdef ACPI_ACTIVATE_DEV
620static void
621acpi_activate_device(ACPI_HANDLE handle, ACPI_DEVICE_INFO **di)
622{
623	ACPI_STATUS rv;
624	ACPI_BUFFER buf;
625
626	buf.Pointer = NULL;
627	buf.Length = ACPI_ALLOCATE_BUFFER;
628
629#ifdef ACPI_DEBUG
630	aprint_normal("acpi_activate_device: %s, old status=%x\n",
631	       (*di)->HardwareId.Value, (*di)->CurrentStatus);
632#endif
633
634	rv = acpi_allocate_resources(handle);
635	if (ACPI_FAILURE(rv)) {
636		aprint_error("acpi: activate failed for %s\n",
637		       (*di)->HardwareId.Value);
638	} else {
639		aprint_verbose("acpi: activated %s\n",
640		    (*di)->HardwareId.Value);
641	}
642
643	(void)AcpiGetObjectInfo(handle, &buf);
644	AcpiOsFree(*di);
645	*di = buf.Pointer;
646
647#ifdef ACPI_DEBUG
648	aprint_normal("acpi_activate_device: %s, new status=%x\n",
649	       (*di)->HardwareId.Value, (*di)->CurrentStatus);
650#endif
651}
652#endif /* ACPI_ACTIVATE_DEV */
653
654/*
655 * acpi_make_devnode:
656 *
657 *	Make an ACPI devnode.
658 */
659static ACPI_STATUS
660acpi_make_devnode(ACPI_HANDLE handle, UINT32 level, void *context,
661    void **status)
662{
663	struct acpi_make_devnode_state *state = context;
664#if defined(ACPI_DEBUG) || defined(ACPI_EXTRA_DEBUG)
665	struct acpi_softc *sc = state->softc;
666#endif
667	struct acpi_scope *as = state->scope;
668	struct acpi_devnode *ad;
669	ACPI_OBJECT_TYPE type;
670	ACPI_BUFFER buf;
671	ACPI_DEVICE_INFO *devinfo;
672	ACPI_STATUS rv;
673	ACPI_NAME_UNION *anu;
674	int i, clear = 0;
675
676	rv = AcpiGetType(handle, &type);
677	if (ACPI_SUCCESS(rv)) {
678		buf.Pointer = NULL;
679		buf.Length = ACPI_ALLOCATE_BUFFER;
680		rv = AcpiGetObjectInfo(handle, &buf);
681		if (ACPI_FAILURE(rv)) {
682#ifdef ACPI_DEBUG
683			aprint_normal("%s: AcpiGetObjectInfo failed: %s\n",
684			    sc->sc_dev.dv_xname, AcpiFormatException(rv));
685#endif
686			goto out; /* XXX why return OK */
687		}
688
689		devinfo = buf.Pointer;
690
691		switch (type) {
692		case ACPI_TYPE_DEVICE:
693#ifdef ACPI_ACTIVATE_DEV
694			if ((devinfo->Valid & (ACPI_VALID_STA|ACPI_VALID_HID)) ==
695			    (ACPI_VALID_STA|ACPI_VALID_HID) &&
696			    (devinfo->CurrentStatus &
697			     (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED)) ==
698			    ACPI_STA_DEV_PRESENT)
699				acpi_activate_device(handle, &devinfo);
700
701			/* FALLTHROUGH */
702#endif
703
704		case ACPI_TYPE_PROCESSOR:
705		case ACPI_TYPE_THERMAL:
706		case ACPI_TYPE_POWER:
707			ad = malloc(sizeof(*ad), M_ACPI, M_NOWAIT|M_ZERO);
708			if (ad == NULL)
709				return AE_NO_MEMORY;
710
711			ad->ad_devinfo = devinfo;
712			ad->ad_handle = handle;
713			ad->ad_level = level;
714			ad->ad_scope = as;
715			ad->ad_type = type;
716
717			anu = (ACPI_NAME_UNION *)&devinfo->Name;
718			ad->ad_name[4] = '\0';
719			for (i = 3, clear = 0; i >= 0; i--) {
720				if (!clear && anu->Ascii[i] == '_')
721					ad->ad_name[i] = '\0';
722				else {
723					ad->ad_name[i] = anu->Ascii[i];
724					clear = 1;
725				}
726			}
727			if (ad->ad_name[0] == '\0')
728				ad->ad_name[0] = '_';
729
730			TAILQ_INSERT_TAIL(&as->as_devnodes, ad, ad_list);
731
732			if (type == ACPI_TYPE_DEVICE &&
733			    (ad->ad_devinfo->Valid & ACPI_VALID_HID) == 0)
734				goto out;
735
736#ifdef ACPI_EXTRA_DEBUG
737			aprint_normal("%s: HID %s found in scope %s level %d\n",
738			    sc->sc_dev.dv_xname,
739			    ad->ad_devinfo->HardwareId.Value,
740			    as->as_name, ad->ad_level);
741			if (ad->ad_devinfo->Valid & ACPI_VALID_UID)
742				aprint_normal("       UID %s\n",
743				    ad->ad_devinfo->UniqueId.Value);
744			if (ad->ad_devinfo->Valid & ACPI_VALID_ADR)
745				aprint_normal("       ADR 0x%016qx\n",
746				    ad->ad_devinfo->Address);
747			if (ad->ad_devinfo->Valid & ACPI_VALID_STA)
748				aprint_normal("       STA 0x%08x\n",
749				    ad->ad_devinfo->CurrentStatus);
750#endif
751		}
752	}
753 out:
754	return AE_OK;
755}
756
757/*
758 * acpi_print:
759 *
760 *	Autoconfiguration print routine for ACPI node bus.
761 */
762static int
763acpi_print(void *aux, const char *pnp)
764{
765	struct acpi_attach_args *aa = aux;
766	ACPI_STATUS rv;
767
768	if (pnp) {
769		if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_HID) {
770			char *pnpstr =
771			    aa->aa_node->ad_devinfo->HardwareId.Value;
772			char *str;
773
774			aprint_normal("%s (%s) ", aa->aa_node->ad_name,
775			    pnpstr);
776			rv = acpi_eval_string(aa->aa_node->ad_handle,
777			    "_STR", &str);
778			if (ACPI_SUCCESS(rv)) {
779				aprint_normal("[%s] ", str);
780				AcpiOsFree(str);
781			}
782#ifdef ACPIVERBOSE
783			else {
784				int i;
785
786				for (i = 0; i < sizeof(acpi_knowndevs) /
787				    sizeof(acpi_knowndevs[0]); i++) {
788					if (strcmp(acpi_knowndevs[i].pnp,
789					    pnpstr) == 0) {
790						aprint_normal("[%s] ",
791						    acpi_knowndevs[i].str);
792					}
793				}
794			}
795
796#endif
797			aprint_normal("at %s", pnp);
798		} else if (aa->aa_node->ad_devinfo->Type != ACPI_TYPE_DEVICE) {
799			aprint_normal("%s (ACPI Object Type '%s' "
800			    "[0x%02x]) ", aa->aa_node->ad_name,
801			     AcpiUtGetTypeName(aa->aa_node->ad_devinfo->Type),
802			     aa->aa_node->ad_devinfo->Type);
803			aprint_normal("at %s", pnp);
804		} else
805			return 0;
806	} else {
807		aprint_normal(" (%s", aa->aa_node->ad_name);
808		if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_HID) {
809			aprint_normal(", %s", aa->aa_node->ad_devinfo->HardwareId.Value);
810			if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_UID) {
811				const char *uid;
812
813				uid = aa->aa_node->ad_devinfo->UniqueId.Value;
814				if (uid[0] == '\0')
815					uid = "<null>";
816				aprint_normal("-%s", uid);
817			}
818		}
819		aprint_normal(")");
820	}
821
822	return UNCONF;
823}
824
825/*****************************************************************************
826 * ACPI fixed-hardware feature handlers
827 *****************************************************************************/
828
829static UINT32	acpi_fixed_button_handler(void *);
830static void	acpi_fixed_button_pressed(void *);
831
832/*
833 * acpi_enable_fixed_events:
834 *
835 *	Enable any fixed-hardware feature handlers.
836 */
837static void
838acpi_enable_fixed_events(struct acpi_softc *sc)
839{
840	static int beenhere;
841	ACPI_STATUS rv;
842
843	KASSERT(beenhere == 0);
844	beenhere = 1;
845
846	/*
847	 * Check for fixed-hardware buttons.
848	 */
849
850	if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) == 0) {
851		aprint_verbose("%s: fixed-feature power button present\n",
852		    sc->sc_dev.dv_xname);
853		sc->sc_smpsw_power.smpsw_name = sc->sc_dev.dv_xname;
854		sc->sc_smpsw_power.smpsw_type = PSWITCH_TYPE_POWER;
855		if (sysmon_pswitch_register(&sc->sc_smpsw_power) != 0) {
856			aprint_error("%s: unable to register fixed power "
857			    "button with sysmon\n", sc->sc_dev.dv_xname);
858		} else {
859			rv = AcpiInstallFixedEventHandler(
860			    ACPI_EVENT_POWER_BUTTON,
861			    acpi_fixed_button_handler, &sc->sc_smpsw_power);
862			if (ACPI_FAILURE(rv)) {
863				aprint_error("%s: unable to install handler "
864				    "for fixed power button: %s\n",
865				    sc->sc_dev.dv_xname,
866				    AcpiFormatException(rv));
867			}
868		}
869	}
870
871	if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) == 0) {
872		aprint_verbose("%s: fixed-feature sleep button present\n",
873		    sc->sc_dev.dv_xname);
874		sc->sc_smpsw_sleep.smpsw_name = sc->sc_dev.dv_xname;
875		sc->sc_smpsw_sleep.smpsw_type = PSWITCH_TYPE_SLEEP;
876		if (sysmon_pswitch_register(&sc->sc_smpsw_power) != 0) {
877			aprint_error("%s: unable to register fixed sleep "
878			    "button with sysmon\n", sc->sc_dev.dv_xname);
879		} else {
880			rv = AcpiInstallFixedEventHandler(
881			    ACPI_EVENT_SLEEP_BUTTON,
882			    acpi_fixed_button_handler, &sc->sc_smpsw_sleep);
883			if (ACPI_FAILURE(rv)) {
884				aprint_error("%s: unable to install handler "
885				    "for fixed sleep button: %s\n",
886				    sc->sc_dev.dv_xname,
887				    AcpiFormatException(rv));
888			}
889		}
890	}
891}
892
893/*
894 * acpi_fixed_button_handler:
895 *
896 *	Event handler for the fixed buttons.
897 */
898static UINT32
899acpi_fixed_button_handler(void *context)
900{
901	struct sysmon_pswitch *smpsw = context;
902	int rv;
903
904#ifdef ACPI_BUT_DEBUG
905	printf("%s: fixed button handler\n", smpsw->smpsw_name);
906#endif
907
908	rv = AcpiOsExecute(OSL_NOTIFY_HANDLER,
909	    acpi_fixed_button_pressed, smpsw);
910	if (ACPI_FAILURE(rv))
911		printf("%s: WARNING: unable to queue fixed button pressed "
912		    "callback: %s\n", smpsw->smpsw_name,
913		    AcpiFormatException(rv));
914
915	return ACPI_INTERRUPT_HANDLED;
916}
917
918/*
919 * acpi_fixed_button_pressed:
920 *
921 *	Deal with a fixed button being pressed.
922 */
923static void
924acpi_fixed_button_pressed(void *context)
925{
926	struct sysmon_pswitch *smpsw = context;
927
928#ifdef ACPI_BUT_DEBUG
929	printf("%s: fixed button pressed, calling sysmon\n",
930	    smpsw->smpsw_name);
931#endif
932
933	sysmon_pswitch_event(smpsw, PSWITCH_EVENT_PRESSED);
934}
935
936/*****************************************************************************
937 * ACPI utility routines.
938 *****************************************************************************/
939
940/*
941 * acpi_eval_integer:
942 *
943 *	Evaluate an integer object.
944 */
945ACPI_STATUS
946acpi_eval_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER *valp)
947{
948	ACPI_STATUS rv;
949	ACPI_BUFFER buf;
950	ACPI_OBJECT param;
951
952	if (handle == NULL)
953		handle = ACPI_ROOT_OBJECT;
954
955	buf.Pointer = &param;
956	buf.Length = sizeof(param);
957
958	rv = AcpiEvaluateObjectTyped(handle, path, NULL, &buf, ACPI_TYPE_INTEGER);
959	if (ACPI_SUCCESS(rv))
960		*valp = param.Integer.Value;
961
962	return rv;
963}
964
965/*
966 * acpi_eval_string:
967 *
968 *	Evaluate a (Unicode) string object.
969 */
970ACPI_STATUS
971acpi_eval_string(ACPI_HANDLE handle, const char *path, char **stringp)
972{
973	ACPI_STATUS rv;
974	ACPI_BUFFER buf;
975
976	if (handle == NULL)
977		handle = ACPI_ROOT_OBJECT;
978
979	buf.Pointer = NULL;
980	buf.Length = ACPI_ALLOCATE_BUFFER;
981
982	rv = AcpiEvaluateObjectTyped(handle, path, NULL, &buf, ACPI_TYPE_STRING);
983	if (ACPI_SUCCESS(rv)) {
984		ACPI_OBJECT *param = buf.Pointer;
985		const char *ptr = param->String.Pointer;
986		size_t len = param->String.Length;
987		if ((*stringp = AcpiOsAllocate(len)) == NULL)
988			rv = AE_NO_MEMORY;
989		else
990			(void)memcpy(*stringp, ptr, len);
991		AcpiOsFree(param);
992	}
993
994	return rv;
995}
996
997
998/*
999 * acpi_eval_struct:
1000 *
1001 *	Evaluate a more complex structure.
1002 *	Caller must free buf.Pointer by AcpiOsFree().
1003 */
1004ACPI_STATUS
1005acpi_eval_struct(ACPI_HANDLE handle, const char *path, ACPI_BUFFER *bufp)
1006{
1007	ACPI_STATUS rv;
1008
1009	if (handle == NULL)
1010		handle = ACPI_ROOT_OBJECT;
1011
1012	bufp->Pointer = NULL;
1013	bufp->Length = ACPI_ALLOCATE_BUFFER;
1014
1015	rv = AcpiEvaluateObject(handle, path, NULL, bufp);
1016
1017	return rv;
1018}
1019
1020/*
1021 * acpi_foreach_package_object:
1022 *
1023 *	Iterate over all objects in a in a packages and pass then all
1024 *	to a function. If the called function returns non AE_OK, the
1025 *	iteration is stopped and that value is returned.
1026 */
1027
1028ACPI_STATUS
1029acpi_foreach_package_object(ACPI_OBJECT *pkg,
1030    ACPI_STATUS (*func)(ACPI_OBJECT *, void *),
1031    void *arg)
1032{
1033	ACPI_STATUS rv = AE_OK;
1034	int i;
1035
1036	if (pkg == NULL || pkg->Type != ACPI_TYPE_PACKAGE)
1037		return AE_BAD_PARAMETER;
1038
1039	for (i = 0; i < pkg->Package.Count; i++) {
1040		rv = (*func)(&pkg->Package.Elements[i], arg);
1041		if (ACPI_FAILURE(rv))
1042			break;
1043	}
1044
1045	return rv;
1046}
1047
1048const char *
1049acpi_name(ACPI_HANDLE handle)
1050{
1051	static char buffer[80];
1052	ACPI_BUFFER buf;
1053	ACPI_STATUS rv;
1054
1055	buf.Length = sizeof(buffer);
1056	buf.Pointer = buffer;
1057
1058	rv = AcpiGetName(handle, ACPI_FULL_PATHNAME, &buf);
1059	if (ACPI_FAILURE(rv))
1060		return "(unknown acpi path)";
1061	return buffer;
1062}
1063
1064/*
1065 * acpi_get:
1066 *
1067 *	Fetch data info the specified (empty) ACPI buffer.
1068 *	Caller must free buf.Pointer by AcpiOsFree().
1069 */
1070ACPI_STATUS
1071acpi_get(ACPI_HANDLE handle, ACPI_BUFFER *buf,
1072    ACPI_STATUS (*getit)(ACPI_HANDLE, ACPI_BUFFER *))
1073{
1074	buf->Pointer = NULL;
1075	buf->Length = ACPI_ALLOCATE_BUFFER;
1076
1077	return (*getit)(handle, buf);
1078}
1079
1080
1081/*
1082 * acpi_match_hid
1083 *
1084 *	Match given ids against _HID and _CIDs
1085 */
1086int
1087acpi_match_hid(ACPI_DEVICE_INFO *ad, const char * const *ids)
1088{
1089	int i;
1090
1091	while (*ids) {
1092		if (ad->Valid & ACPI_VALID_HID) {
1093			if (pmatch(ad->HardwareId.Value, *ids, NULL) == 2)
1094				return 1;
1095		}
1096
1097		if (ad->Valid & ACPI_VALID_CID) {
1098			for (i = 0; i < ad->CompatibilityId.Count; i++) {
1099				if (pmatch(ad->CompatibilityId.Id[i].Value, *ids, NULL) == 2)
1100					return 1;
1101			}
1102		}
1103		ids++;
1104	}
1105
1106	return 0;
1107}
1108
1109/*
1110 * acpi_set_wake_gpe
1111 *
1112 *	Set GPE as both Runtime and Wake
1113 */
1114void
1115acpi_set_wake_gpe(ACPI_HANDLE handle)
1116{
1117	ACPI_BUFFER buf;
1118	ACPI_STATUS rv;
1119	ACPI_OBJECT *p, *elt;
1120
1121	rv = acpi_eval_struct(handle, METHOD_NAME__PRW, &buf);
1122	if (ACPI_FAILURE(rv))
1123		return;			/* just ignore */
1124
1125	p = buf.Pointer;
1126	if (p->Type != ACPI_TYPE_PACKAGE || p->Package.Count < 2)
1127		goto out;		/* just ignore */
1128
1129	elt = p->Package.Elements;
1130
1131	/* TBD: package support */
1132	AcpiSetGpeType(NULL, elt[0].Integer.Value, ACPI_GPE_TYPE_WAKE_RUN);
1133	AcpiEnableGpe(NULL, elt[0].Integer.Value, ACPI_NOT_ISR);
1134
1135 out:
1136	AcpiOsFree(buf.Pointer);
1137}
1138
1139
1140/*****************************************************************************
1141 * ACPI sleep support.
1142 *****************************************************************************/
1143
1144static int
1145is_available_state(struct acpi_softc *sc, int state)
1146{
1147	UINT8 type_a, type_b;
1148
1149	return ACPI_SUCCESS(AcpiGetSleepTypeData((UINT8)state,
1150				&type_a, &type_b));
1151}
1152
1153/*
1154 * acpi_enter_sleep_state:
1155 *
1156 *	enter to the specified sleep state.
1157 */
1158
1159ACPI_STATUS
1160acpi_enter_sleep_state(struct acpi_softc *sc, int state)
1161{
1162	int err;
1163	ACPI_STATUS ret = AE_OK;
1164
1165	if (state == acpi_sleepstate)
1166		return AE_OK;
1167
1168	aprint_normal("%s: entering state %d\n", sc->sc_dev.dv_xname, state);
1169
1170	switch (state) {
1171	case ACPI_STATE_S0:
1172		break;
1173	case ACPI_STATE_S1:
1174	case ACPI_STATE_S2:
1175	case ACPI_STATE_S3:
1176	case ACPI_STATE_S4:
1177		if (!is_available_state(sc, state)) {
1178			aprint_error("%s: cannot enter the sleep state (%d)\n",
1179			    sc->sc_dev.dv_xname, state);
1180			break;
1181		}
1182
1183		if (state != ACPI_STATE_S1 && !pmf_system_suspend()) {
1184			aprint_error_dev(&sc->sc_dev, "aborting suspend\n");
1185			break;
1186		}
1187
1188		ret = AcpiEnterSleepStatePrep(state);
1189		if (ACPI_FAILURE(ret)) {
1190			aprint_error("%s: failed preparing to sleep (%s)\n",
1191			    sc->sc_dev.dv_xname, AcpiFormatException(ret));
1192			break;
1193		}
1194
1195		acpi_sleepstate = state;
1196		if (state == ACPI_STATE_S1) {
1197			/* just enter the state */
1198			acpi_md_OsDisableInterrupt();
1199			AcpiEnterSleepState((UINT8)state);
1200			AcpiLeaveSleepState((UINT8)state);
1201		} else {
1202			err = acpi_md_sleep(state);
1203			if (state == ACPI_STATE_S4)
1204				AcpiEnable();
1205			pmf_system_bus_resume();
1206			AcpiLeaveSleepState((UINT8)state);
1207			pmf_system_resume();
1208		}
1209
1210		break;
1211	case ACPI_STATE_S5:
1212		ret = AcpiEnterSleepStatePrep(ACPI_STATE_S5);
1213		if (ACPI_FAILURE(ret)) {
1214			aprint_error("%s: failed preparing to sleep (%s)\n",
1215			       sc->sc_dev.dv_xname, AcpiFormatException(ret));
1216			break;
1217		}
1218		DELAY(1000000);
1219		acpi_sleepstate = state;
1220		acpi_md_OsDisableInterrupt();
1221		AcpiEnterSleepState(ACPI_STATE_S5);
1222		aprint_error("%s: WARNING powerdown failed!\n",
1223		    sc->sc_dev.dv_xname);
1224		break;
1225	}
1226
1227	acpi_sleepstate = ACPI_STATE_S0;
1228	return ret;
1229}
1230
1231#if defined(ACPI_ACTIVATE_DEV)
1232/* XXX This very incomplete */
1233ACPI_STATUS
1234acpi_allocate_resources(ACPI_HANDLE handle)
1235{
1236	ACPI_BUFFER bufp, bufc, bufn;
1237	ACPI_RESOURCE *resp, *resc, *resn;
1238	ACPI_RESOURCE_IRQ *irq;
1239	ACPI_RESOURCE_EXTENDED_IRQ *xirq;
1240	ACPI_STATUS rv;
1241	uint delta;
1242
1243	rv = acpi_get(handle, &bufp, AcpiGetPossibleResources);
1244	if (ACPI_FAILURE(rv))
1245		goto out;
1246	rv = acpi_get(handle, &bufc, AcpiGetCurrentResources);
1247	if (ACPI_FAILURE(rv)) {
1248		goto out1;
1249	}
1250
1251	bufn.Length = 1000;
1252	bufn.Pointer = resn = malloc(bufn.Length, M_ACPI, M_WAITOK);
1253	resp = bufp.Pointer;
1254	resc = bufc.Pointer;
1255	while (resc->Type != ACPI_RESOURCE_TYPE_END_TAG &&
1256	       resp->Type != ACPI_RESOURCE_TYPE_END_TAG) {
1257		while (resc->Type != resp->Type && resp->Type != ACPI_RESOURCE_TYPE_END_TAG)
1258			resp = ACPI_NEXT_RESOURCE(resp);
1259		if (resp->Type == ACPI_RESOURCE_TYPE_END_TAG)
1260			break;
1261		/* Found identical Id */
1262		resn->Type = resc->Type;
1263		switch (resc->Type) {
1264		case ACPI_RESOURCE_TYPE_IRQ:
1265			memcpy(&resn->Data, &resp->Data,
1266			       sizeof(ACPI_RESOURCE_IRQ));
1267			irq = (ACPI_RESOURCE_IRQ *)&resn->Data;
1268			irq->Interrupts[0] =
1269			    ((ACPI_RESOURCE_IRQ *)&resp->Data)->
1270			        Interrupts[irq->InterruptCount-1];
1271			irq->InterruptCount = 1;
1272			resn->Length = ACPI_RS_SIZE(ACPI_RESOURCE_IRQ);
1273			break;
1274		case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
1275			memcpy(&resn->Data, &resp->Data,
1276			       sizeof(ACPI_RESOURCE_EXTENDED_IRQ));
1277			xirq = (ACPI_RESOURCE_EXTENDED_IRQ *)&resn->Data;
1278#if 0
1279			/*
1280			 * XXX not duplicating the interrupt logic above
1281			 * because its not clear what it accomplishes.
1282			 */
1283			xirq->Interrupts[0] =
1284			    ((ACPI_RESOURCE_EXT_IRQ *)&resp->Data)->
1285			    Interrupts[irq->NumberOfInterrupts-1];
1286			xirq->NumberOfInterrupts = 1;
1287#endif
1288			resn->Length = ACPI_RS_SIZE(ACPI_RESOURCE_EXTENDED_IRQ);
1289			break;
1290		case ACPI_RESOURCE_TYPE_IO:
1291			memcpy(&resn->Data, &resp->Data,
1292			       sizeof(ACPI_RESOURCE_IO));
1293			resn->Length = resp->Length;
1294			break;
1295		default:
1296			printf("acpi_allocate_resources: res=%d\n", resc->Type);
1297			rv = AE_BAD_DATA;
1298			goto out2;
1299		}
1300		resc = ACPI_NEXT_RESOURCE(resc);
1301		resn = ACPI_NEXT_RESOURCE(resn);
1302		resp = ACPI_NEXT_RESOURCE(resp);
1303		delta = (UINT8 *)resn - (UINT8 *)bufn.Pointer;
1304		if (delta >=
1305		    bufn.Length-ACPI_RS_SIZE(ACPI_RESOURCE_DATA)) {
1306			bufn.Length *= 2;
1307			bufn.Pointer = realloc(bufn.Pointer, bufn.Length,
1308					       M_ACPI, M_WAITOK);
1309			resn = (ACPI_RESOURCE *)((UINT8 *)bufn.Pointer + delta);
1310		}
1311	}
1312	if (resc->Type != ACPI_RESOURCE_TYPE_END_TAG) {
1313		printf("acpi_allocate_resources: resc not exhausted\n");
1314		rv = AE_BAD_DATA;
1315		goto out3;
1316	}
1317
1318	resn->Type = ACPI_RESOURCE_TYPE_END_TAG;
1319	rv = AcpiSetCurrentResources(handle, &bufn);
1320	if (ACPI_FAILURE(rv)) {
1321		printf("acpi_allocate_resources: AcpiSetCurrentResources %s\n",
1322		       AcpiFormatException(rv));
1323	}
1324
1325out3:
1326	free(bufn.Pointer, M_ACPI);
1327out2:
1328	AcpiOsFree(bufc.Pointer);
1329out1:
1330	AcpiOsFree(bufp.Pointer);
1331out:
1332	return rv;
1333}
1334#endif /* ACPI_ACTIVATE_DEV */
1335
1336SYSCTL_SETUP(sysctl_acpi_setup, "sysctl hw.acpi subtree setup")
1337{
1338	const struct sysctlnode *node;
1339	const struct sysctlnode *ssnode;
1340
1341	if (sysctl_createv(clog, 0, NULL, NULL,
1342	    CTLFLAG_PERMANENT,
1343	    CTLTYPE_NODE, "hw", NULL,
1344	    NULL, 0, NULL, 0,
1345	    CTL_HW, CTL_EOL) != 0)
1346		return;
1347
1348	if (sysctl_createv(clog, 0, NULL, &node,
1349	    CTLFLAG_PERMANENT,
1350	    CTLTYPE_NODE, "acpi", NULL,
1351	    NULL, 0, NULL, 0,
1352	    CTL_HW, CTL_CREATE, CTL_EOL) != 0)
1353		return;
1354
1355	acpi_node = node->sysctl_num;
1356
1357	/* ACPI sleepstate sysctl */
1358	if (sysctl_createv(NULL, 0, NULL, &node,
1359	    CTLFLAG_PERMANENT,
1360	    CTLTYPE_NODE, "machdep", NULL,
1361	    NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL) != 0)
1362		return;
1363	if (sysctl_createv(NULL, 0, &node, &ssnode,
1364	    CTLFLAG_READWRITE, CTLTYPE_INT, "sleep_state",
1365	    NULL, sysctl_hw_acpi_sleepstate, 0, NULL, 0, CTL_CREATE,
1366	    CTL_EOL) != 0)
1367		return;
1368}
1369
1370static int
1371sysctl_hw_acpi_sleepstate(SYSCTLFN_ARGS)
1372{
1373	int error, t;
1374	struct sysctlnode node;
1375
1376	node = *rnode;
1377	t = acpi_sleepstate;
1378	node.sysctl_data = &t;
1379	error = sysctl_lookup(SYSCTLFN_CALL(&node));
1380	if (error || newp == NULL)
1381		return error;
1382
1383	if (acpi_softc == NULL)
1384		return ENOSYS;
1385
1386	acpi_enter_sleep_state(acpi_softc, t);
1387
1388	return 0;
1389}
1390