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