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