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