Deleted Added
full compact
acpi.c (78689) acpi.c (78915)
1/*-
2 * Copyright (c) 2000 Takanori Watanabe <takawata@jp.freebsd.org>
3 * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
4 * Copyright (c) 2000 Michael Smith
5 * Copyright (c) 2000 BSDi
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
1/*-
2 * Copyright (c) 2000 Takanori Watanabe <takawata@jp.freebsd.org>
3 * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
4 * Copyright (c) 2000 Michael Smith
5 * Copyright (c) 2000 BSDi
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $FreeBSD: head/sys/dev/acpica/acpi.c 78689 2001-06-24 02:37:38Z iwasaki $
29 * $FreeBSD: head/sys/dev/acpica/acpi.c 78915 2001-06-28 06:17:16Z msmith $
30 */
31
32#include "opt_acpi.h"
33#include <sys/param.h>
34#include <sys/kernel.h>
35#include <sys/proc.h>
36#include <sys/lock.h>
37#include <sys/malloc.h>
38#include <sys/mutex.h>
39#include <sys/bus.h>
40#include <sys/conf.h>
41#include <sys/ioccom.h>
42#include <sys/reboot.h>
43#include <sys/sysctl.h>
44#include <sys/ctype.h>
45
46#include <machine/clock.h>
47
48#include <machine/resource.h>
49
50#include "acpi.h"
51
52#include <dev/acpica/acpivar.h>
53#include <dev/acpica/acpiio.h>
54
55MALLOC_DEFINE(M_ACPIDEV, "acpidev", "ACPI devices");
56
57/*
58 * Hooks for the ACPI CA debugging infrastructure
59 */
60#define _COMPONENT ACPI_BUS_MANAGER
61MODULE_NAME("ACPI")
62
63/*
64 * Character device
65 */
66
67static d_open_t acpiopen;
68static d_close_t acpiclose;
69static d_ioctl_t acpiioctl;
70
71#define CDEV_MAJOR 152
72static struct cdevsw acpi_cdevsw = {
73 acpiopen,
74 acpiclose,
75 noread,
76 nowrite,
77 acpiioctl,
78 nopoll,
79 nommap,
80 nostrategy,
81 "acpi",
82 CDEV_MAJOR,
83 nodump,
84 nopsize,
85 0
86};
87
88static const char* sleep_state_names[] = {
89 "S0", "S1", "S2", "S3", "S4", "S5", "S4B" };
90
91/* this has to be static, as the softc is gone when we need it */
92static int acpi_off_state = ACPI_STATE_S5;
93
94static void acpi_identify(driver_t *driver, device_t parent);
95static int acpi_probe(device_t dev);
96static int acpi_attach(device_t dev);
97static device_t acpi_add_child(device_t bus, int order, const char *name, int unit);
98static int acpi_print_resources(struct resource_list *rl, const char *name, int type,
99 const char *format);
100static int acpi_print_child(device_t bus, device_t child);
101static int acpi_read_ivar(device_t dev, device_t child, int index, uintptr_t *result);
102static int acpi_write_ivar(device_t dev, device_t child, int index, uintptr_t value);
103static int acpi_set_resource(device_t dev, device_t child, int type, int rid, u_long start,
104 u_long count);
105static int acpi_get_resource(device_t dev, device_t child, int type, int rid, u_long *startp,
106 u_long *countp);
107static struct resource *acpi_alloc_resource(device_t bus, device_t child, int type, int *rid,
108 u_long start, u_long end, u_long count, u_int flags);
109static int acpi_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r);
110
111static void acpi_probe_children(device_t bus);
112static ACPI_STATUS acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status);
113
114static void acpi_shutdown_pre_sync(void *arg, int howto);
115static void acpi_shutdown_final(void *arg, int howto);
116
117static void acpi_enable_fixed_events(struct acpi_softc *sc);
118
119static void acpi_system_eventhandler_sleep(void *arg, int state);
120static void acpi_system_eventhandler_wakeup(void *arg, int state);
121static int acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS);
122
123static device_method_t acpi_methods[] = {
124 /* Device interface */
125 DEVMETHOD(device_identify, acpi_identify),
126 DEVMETHOD(device_probe, acpi_probe),
127 DEVMETHOD(device_attach, acpi_attach),
128 DEVMETHOD(device_shutdown, bus_generic_shutdown),
129 DEVMETHOD(device_suspend, bus_generic_suspend),
130 DEVMETHOD(device_resume, bus_generic_resume),
131
132 /* Bus interface */
133 DEVMETHOD(bus_add_child, acpi_add_child),
134 DEVMETHOD(bus_print_child, acpi_print_child),
135 DEVMETHOD(bus_read_ivar, acpi_read_ivar),
136 DEVMETHOD(bus_write_ivar, acpi_write_ivar),
137 DEVMETHOD(bus_set_resource, acpi_set_resource),
138 DEVMETHOD(bus_get_resource, acpi_get_resource),
139 DEVMETHOD(bus_alloc_resource, acpi_alloc_resource),
140 DEVMETHOD(bus_release_resource, acpi_release_resource),
141 DEVMETHOD(bus_driver_added, bus_generic_driver_added),
142 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
143 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
144 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
145 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
146
147 {0, 0}
148};
149
150static driver_t acpi_driver = {
151 "acpi",
152 acpi_methods,
153 sizeof(struct acpi_softc),
154};
155
156devclass_t acpi_devclass;
157DRIVER_MODULE(acpi, nexus, acpi_driver, acpi_devclass, 0, 0);
158
159SYSCTL_INT(_debug, OID_AUTO, acpi_debug_layer, CTLFLAG_RW, &AcpiDbgLayer, 0, "");
160SYSCTL_INT(_debug, OID_AUTO, acpi_debug_level, CTLFLAG_RW, &AcpiDbgLevel, 0, "");
161
162/*
163 * Detect ACPI, perform early initialisation
164 */
165static void
166acpi_identify(driver_t *driver, device_t parent)
167{
168 device_t child;
169 ACPI_PHYSICAL_ADDRESS rsdp;
170 int error;
171#ifdef ENABLE_DEBUGGER
172 char *debugpoint = getenv("debug.acpi.debugger");
173#endif
174
175 FUNCTION_TRACE(__func__);
176
177 if(!cold){
178 printf("Don't load this driver from userland!!\n");
179 return ;
180 }
181
182 /*
183 * Make sure we're not being doubly invoked.
184 */
185 if (device_find_child(parent, "acpi", 0) != NULL)
186 return_VOID;
187
188 /*
189 * Start up the ACPI CA subsystem.
190 */
191#ifdef ENABLE_DEBUGGER
192 if (debugpoint && !strcmp(debugpoint, "init"))
193 acpi_EnterDebugger();
194#endif
195 if ((error = AcpiInitializeSubsystem()) != AE_OK) {
196 printf("ACPI: initialisation failed: %s\n", acpi_strerror(error));
197 return_VOID;
198 }
199#ifdef ENABLE_DEBUGGER
200 if (debugpoint && !strcmp(debugpoint, "tables"))
201 acpi_EnterDebugger();
202#endif
203 if (((error = AcpiFindRootPointer(&rsdp)) != AE_OK) ||
204 ((error = AcpiLoadTables(rsdp)) != AE_OK)) {
205 printf("ACPI: table load failed: %s\n", acpi_strerror(error));
206 return_VOID;
207 }
208
209 /*
210 * Attach the actual ACPI device.
211 */
212 if ((child = BUS_ADD_CHILD(parent, 0, "acpi", 0)) == NULL) {
213 device_printf(parent, "ACPI: could not attach\n");
214 return_VOID;
215 }
216}
217
218/*
219 * Fetch some descriptive data from ACPI to put in our attach message
220 */
221static int
222acpi_probe(device_t dev)
223{
224 ACPI_TABLE_HEADER th;
225 char buf[20];
226 int error;
227
228 FUNCTION_TRACE(__func__);
229
230 if ((error = AcpiGetTableHeader(ACPI_TABLE_XSDT, 1, &th)) != AE_OK) {
231 device_printf(dev, "couldn't get XSDT header: %s\n", acpi_strerror(error));
232 return_VALUE(ENXIO);
233 }
234 sprintf(buf, "%.6s %.8s", th.OemId, th.OemTableId);
235 device_set_desc_copy(dev, buf);
236
237 return_VALUE(0);
238}
239
240static int
241acpi_attach(device_t dev)
242{
243 struct acpi_softc *sc;
244 int error;
245#ifdef ENABLE_DEBUGGER
246 char *debugpoint = getenv("debug.acpi.debugger");
247#endif
248
249 FUNCTION_TRACE(__func__);
250
251 sc = device_get_softc(dev);
252 bzero(sc, sizeof(*sc));
253 sc->acpi_dev = dev;
254
255#ifdef ENABLE_DEBUGGER
256 if (debugpoint && !strcmp(debugpoint, "spaces"))
257 acpi_EnterDebugger();
258#endif
259
260 /*
261 * Install the default address space handlers.
262 */
263 if ((error = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
264 ACPI_ADR_SPACE_SYSTEM_MEMORY,
265 ACPI_DEFAULT_HANDLER,
266 NULL, NULL)) != AE_OK) {
267 device_printf(dev, "could not initialise SystemMemory handler: %s\n", acpi_strerror(error));
268 return_VALUE(ENXIO);
269 }
270 if ((error = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
271 ACPI_ADR_SPACE_SYSTEM_IO,
272 ACPI_DEFAULT_HANDLER,
273 NULL, NULL)) != AE_OK) {
274 device_printf(dev, "could not initialise SystemIO handler: %s\n", acpi_strerror(error));
275 return_VALUE(ENXIO);
276 }
277 if ((error = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
278 ACPI_ADR_SPACE_PCI_CONFIG,
279 ACPI_DEFAULT_HANDLER,
280 NULL, NULL)) != AE_OK) {
281 device_printf(dev, "could not initialise PciConfig handler: %s\n", acpi_strerror(error));
282 return_VALUE(ENXIO);
283 }
284
285 /*
286 * Bring ACPI fully online.
287 *
288 * Note that we request that device _STA and _INI methods not be run (ACPI_NO_DEVICE_INIT)
289 * and the final object initialisation pass be skipped (ACPI_NO_OBJECT_INIT).
290 *
291 * XXX We need to arrange for the object init pass after we have attached all our
292 * child devices.
293 */
294#ifdef ENABLE_DEBUGGER
295 if (debugpoint && !strcmp(debugpoint, "enable"))
296 acpi_EnterDebugger();
297#endif
298 if ((error = AcpiEnableSubsystem(ACPI_NO_DEVICE_INIT | ACPI_NO_OBJECT_INIT)) != AE_OK) {
299 device_printf(dev, "could not enable ACPI: %s\n", acpi_strerror(error));
300 return_VALUE(ENXIO);
301 }
302
303 /*
304 * Setup our sysctl tree.
305 *
306 * XXX: This doesn't check to make sure that none of these fail.
307 */
308 sysctl_ctx_init(&sc->acpi_sysctl_ctx);
309 sc->acpi_sysctl_tree = SYSCTL_ADD_NODE(&sc->acpi_sysctl_ctx,
310 SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
311 device_get_name(dev), CTLFLAG_RD, 0, "");
312 SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
313 OID_AUTO, "power_button_state", CTLTYPE_STRING | CTLFLAG_RW,
314 &sc->acpi_power_button_sx, 0, acpi_sleep_state_sysctl, "A", "");
315 SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
316 OID_AUTO, "sleep_button_state", CTLTYPE_STRING | CTLFLAG_RW,
317 &sc->acpi_sleep_button_sx, 0, acpi_sleep_state_sysctl, "A", "");
318 SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
319 OID_AUTO, "lid_switch_state", CTLTYPE_STRING | CTLFLAG_RW,
320 &sc->acpi_lid_switch_sx, 0, acpi_sleep_state_sysctl, "A", "");
321
322 /*
323 * Dispatch the default sleep state to devices.
324 * TBD: should be configured from userland policy manager.
325 */
326 sc->acpi_power_button_sx = ACPI_POWER_BUTTON_DEFAULT_SX;
327 sc->acpi_sleep_button_sx = ACPI_SLEEP_BUTTON_DEFAULT_SX;
328 sc->acpi_lid_switch_sx = ACPI_LID_SWITCH_DEFAULT_SX;
329
330 acpi_enable_fixed_events(sc);
331
332 /*
333 * Scan the namespace and attach/initialise children.
334 */
335#ifdef ENABLE_DEBUGGER
336 if (debugpoint && !strcmp(debugpoint, "probe"))
337 acpi_EnterDebugger();
338#endif
339 if (!acpi_disabled("bus"))
340 acpi_probe_children(dev);
341
342 /*
343 * Register our shutdown handlers
344 */
345 EVENTHANDLER_REGISTER(shutdown_pre_sync, acpi_shutdown_pre_sync, sc, SHUTDOWN_PRI_LAST);
346 EVENTHANDLER_REGISTER(shutdown_final, acpi_shutdown_final, sc, SHUTDOWN_PRI_LAST);
347
348 /*
349 * Register our acpi event handlers.
350 * XXX should be configurable eg. via userland policy manager.
351 */
352 EVENTHANDLER_REGISTER(acpi_sleep_event, acpi_system_eventhandler_sleep, sc, ACPI_EVENT_PRI_LAST);
353 EVENTHANDLER_REGISTER(acpi_wakeup_event, acpi_system_eventhandler_wakeup, sc, ACPI_EVENT_PRI_LAST);
354
355 /*
356 * Flag our initial states.
357 */
358 sc->acpi_enabled = 1;
359 sc->acpi_sstate = ACPI_STATE_S0;
360
361 /*
362 * Create the control device
363 */
364 sc->acpi_dev_t = make_dev(&acpi_cdevsw, 0, 0, 5, 0660, "acpi");
365 sc->acpi_dev_t->si_drv1 = sc;
366
367#ifdef ENABLE_DEBUGGER
368 if (debugpoint && !strcmp(debugpoint, "running"))
369 acpi_EnterDebugger();
370#endif
371 return_VALUE(0);
372}
373
374/*
375 * Handle a new device being added
376 */
377static device_t
378acpi_add_child(device_t bus, int order, const char *name, int unit)
379{
380 struct acpi_device *ad;
381 device_t child;
382
383 if ((ad = malloc(sizeof(*ad), M_ACPIDEV, M_NOWAIT)) == NULL)
384 return(NULL);
385 bzero(ad, sizeof(*ad));
386
387 resource_list_init(&ad->ad_rl);
388
389 child = device_add_child_ordered(bus, order, name, unit);
390 if (child != NULL)
391 device_set_ivars(child, ad);
392 return(child);
393}
394
395/*
396 * Print child device resource usage
397 */
398static int
399acpi_print_resources(struct resource_list *rl, const char *name, int type, const char *format)
400{
401 struct resource_list_entry *rle;
402 int printed, retval;
403
404 printed = 0;
405 retval = 0;
406
407 if (!SLIST_FIRST(rl))
408 return(0);
409
410 /* Yes, this is kinda cheating */
411 SLIST_FOREACH(rle, rl, link) {
412 if (rle->type == type) {
413 if (printed == 0)
414 retval += printf(" %s ", name);
415 else if (printed > 0)
416 retval += printf(",");
417 printed++;
418 retval += printf(format, rle->start);
419 if (rle->count > 1) {
420 retval += printf("-");
421 retval += printf(format, rle->start +
422 rle->count - 1);
423 }
424 }
425 }
426 return(retval);
427}
428
429static int
430acpi_print_child(device_t bus, device_t child)
431{
432 struct acpi_device *adev = device_get_ivars(child);
433 struct resource_list *rl = &adev->ad_rl;
434 int retval = 0;
435
436 retval += bus_print_child_header(bus, child);
437 retval += acpi_print_resources(rl, "port", SYS_RES_IOPORT, "%#lx");
438 retval += acpi_print_resources(rl, "iomem", SYS_RES_MEMORY, "%#lx");
439 retval += acpi_print_resources(rl, "irq", SYS_RES_IRQ, "%ld");
440 retval += bus_print_child_footer(bus, child);
441
442 return(retval);
443}
444
445
446/*
447 * Handle per-device ivars
448 */
449static int
450acpi_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
451{
452 struct acpi_device *ad;
453
454 if ((ad = device_get_ivars(child)) == NULL) {
455 printf("device has no ivars\n");
456 return(ENOENT);
457 }
458
459 switch(index) {
460 /* ACPI ivars */
461 case ACPI_IVAR_HANDLE:
462 *(ACPI_HANDLE *)result = ad->ad_handle;
463 break;
464 case ACPI_IVAR_MAGIC:
465 *(int *)result = ad->ad_magic;
466 break;
467 case ACPI_IVAR_PRIVATE:
468 *(void **)result = ad->ad_private;
469 break;
470
471 default:
472 panic("bad ivar read request (%d)\n", index);
473 return(ENOENT);
474 }
475 return(0);
476}
477
478static int
479acpi_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
480{
481 struct acpi_device *ad;
482
483 if ((ad = device_get_ivars(child)) == NULL) {
484 printf("device has no ivars\n");
485 return(ENOENT);
486 }
487
488 switch(index) {
489 /* ACPI ivars */
490 case ACPI_IVAR_HANDLE:
491 ad->ad_handle = (ACPI_HANDLE)value;
492 break;
493 case ACPI_IVAR_MAGIC:
494 ad->ad_magic = (int )value;
495 break;
496 case ACPI_IVAR_PRIVATE:
497 ad->ad_private = (void *)value;
498 break;
499
500 default:
501 panic("bad ivar write request (%d)\n", index);
502 return(ENOENT);
503 }
504 return(0);
505}
506
507/*
508 * Handle child resource allocation/removal
509 */
510static int
511acpi_set_resource(device_t dev, device_t child, int type, int rid, u_long start, u_long count)
512{
513 struct acpi_device *ad = device_get_ivars(child);
514 struct resource_list *rl = &ad->ad_rl;
515
516 resource_list_add(rl, type, rid, start, start + count -1, count);
517
518 return(0);
519}
520
521static int
522acpi_get_resource(device_t dev, device_t child, int type, int rid, u_long *startp, u_long *countp)
523{
524 struct acpi_device *ad = device_get_ivars(child);
525 struct resource_list *rl = &ad->ad_rl;
526 struct resource_list_entry *rle;
527
528 rle = resource_list_find(rl, type, rid);
529 if (!rle)
530 return(ENOENT);
531
532 if (startp)
533 *startp = rle->start;
534 if (countp)
535 *countp = rle->count;
536
537 return(0);
538}
539
540static struct resource *
541acpi_alloc_resource(device_t bus, device_t child, int type, int *rid,
542 u_long start, u_long end, u_long count, u_int flags)
543{
544 struct acpi_device *ad = device_get_ivars(child);
545 struct resource_list *rl = &ad->ad_rl;
546
547 return(resource_list_alloc(rl, bus, child, type, rid, start, end, count, flags));
548}
549
550static int
551acpi_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r)
552{
553 struct acpi_device *ad = device_get_ivars(child);
554 struct resource_list *rl = &ad->ad_rl;
555
556 return(resource_list_release(rl, bus, child, type, rid, r));
557}
558
559/*
560 * Scan relevant portions of the ACPI namespace and attach child devices.
561 *
562 * Note that we only expect to find devices in the \_TZ_, \_SI_ and \_SB_ scopes,
563 * and \_TZ_ becomes obsolete in the ACPI 2.0 spec.
564 */
565static void
566acpi_probe_children(device_t bus)
567{
568 ACPI_HANDLE parent;
569 static char *scopes[] = {"\\_TZ_", "\\_SI", "\\_SB_", NULL};
570 int i;
571
572 FUNCTION_TRACE(__func__);
573
574 /*
575 * Create any static children by calling device identify methods.
576 */
577 DEBUG_PRINT(TRACE_OBJECTS, ("device identify routines\n"));
578 bus_generic_probe(bus);
579
580 /*
581 * Scan the namespace and insert placeholders for all the devices that
582 * we find.
583 *
584 * Note that we use AcpiWalkNamespace rather than AcpiGetDevices because
585 * we want to create nodes for all devices, not just those that are currently
586 * present. (This assumes that we don't want to create/remove devices as they
587 * appear, which might be smarter.)
588 */
589 DEBUG_PRINT(TRACE_OBJECTS, ("namespace scan\n"));
590 for (i = 0; scopes[i] != NULL; i++)
591 if ((AcpiGetHandle(ACPI_ROOT_OBJECT, scopes[i], &parent)) == AE_OK)
592 AcpiWalkNamespace(ACPI_TYPE_ANY, parent, 100, acpi_probe_child, bus, NULL);
593
594 /*
595 * Scan all of the child devices we have created and let them probe/attach.
596 */
597 DEBUG_PRINT(TRACE_OBJECTS, ("first bus_generic_attach\n"));
598 bus_generic_attach(bus);
599
600 /*
601 * Some of these children may have attached others as part of their attach
602 * process (eg. the root PCI bus driver), so rescan.
603 */
604 DEBUG_PRINT(TRACE_OBJECTS, ("second bus_generic_attach\n"));
605 bus_generic_attach(bus);
606
607 return_VOID;
608}
609
610/*
611 * Evaluate a child device and determine whether we might attach a device to
612 * it.
613 */
614static ACPI_STATUS
615acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status)
616{
617 ACPI_OBJECT_TYPE type;
618 device_t child, bus = (device_t)context;
619
620 FUNCTION_TRACE(__func__);
621
622 /*
623 * Skip this device if we think we'll have trouble with it.
624 */
625 if (acpi_avoid(handle))
626 return_ACPI_STATUS(AE_OK);
627
628 if (AcpiGetType(handle, &type) == AE_OK) {
629 switch(type) {
630 case ACPI_TYPE_DEVICE:
631 case ACPI_TYPE_PROCESSOR:
632 case ACPI_TYPE_THERMAL:
633 case ACPI_TYPE_POWER:
634 if (acpi_disabled("children"))
635 break;
636 /*
637 * Create a placeholder device for this node. Sort the placeholder
638 * so that the probe/attach passes will run breadth-first.
639 */
640 DEBUG_PRINT(TRACE_OBJECTS, ("scanning '%s'\n", acpi_name(handle)))
641 child = BUS_ADD_CHILD(bus, level * 10, NULL, -1);
642 acpi_set_handle(child, handle);
643 DEBUG_EXEC(device_probe_and_attach(child));
644 break;
645 }
646 }
647 return_ACPI_STATUS(AE_OK);
648}
649
650static void
651acpi_shutdown_pre_sync(void *arg, int howto)
652{
653 /*
654 * Disable all ACPI events before soft off, otherwise the system
655 * will be turned on again on some laptops.
656 *
657 * XXX this should probably be restricted to masking some events just
658 * before powering down, since we may still need ACPI during the
659 * shutdown process.
660 */
661 acpi_Disable((struct acpi_softc *)arg);
662}
663
664static void
665acpi_shutdown_final(void *arg, int howto)
666{
667 ACPI_STATUS status;
668
669 if (howto & RB_POWEROFF) {
670 printf("Power system off using ACPI...\n");
671 if ((status = AcpiEnterSleepState(acpi_off_state)) != AE_OK) {
672 printf("ACPI power-off failed - %s\n", acpi_strerror(status));
673 } else {
674 DELAY(1000000);
675 printf("ACPI power-off failed - timeout\n");
676 }
677 }
678}
679
680static void
681acpi_enable_fixed_events(struct acpi_softc *sc)
682{
683 static int first_time = 1;
684#define MSGFORMAT "%s button is handled as a fixed feature programming model.\n"
685
686 /* Enable and clear fixed events and install handlers. */
687 if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->PwrButton == 0) {
688 AcpiEnableEvent(ACPI_EVENT_POWER_BUTTON, ACPI_EVENT_FIXED);
689 AcpiClearEvent(ACPI_EVENT_POWER_BUTTON, ACPI_EVENT_FIXED);
690 AcpiInstallFixedEventHandler(ACPI_EVENT_POWER_BUTTON,
691 acpi_eventhandler_power_button_for_sleep, sc);
692 if (first_time) {
693 device_printf(sc->acpi_dev, MSGFORMAT, "power");
694 }
695 }
696 if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->SleepButton == 0) {
697 AcpiEnableEvent(ACPI_EVENT_SLEEP_BUTTON, ACPI_EVENT_FIXED);
698 AcpiClearEvent(ACPI_EVENT_SLEEP_BUTTON, ACPI_EVENT_FIXED);
699 AcpiInstallFixedEventHandler(ACPI_EVENT_SLEEP_BUTTON,
700 acpi_eventhandler_sleep_button_for_sleep, sc);
701 if (first_time) {
702 device_printf(sc->acpi_dev, MSGFORMAT, "sleep");
703 }
704 }
705
706 first_time = 0;
707}
708
709/*
30 */
31
32#include "opt_acpi.h"
33#include <sys/param.h>
34#include <sys/kernel.h>
35#include <sys/proc.h>
36#include <sys/lock.h>
37#include <sys/malloc.h>
38#include <sys/mutex.h>
39#include <sys/bus.h>
40#include <sys/conf.h>
41#include <sys/ioccom.h>
42#include <sys/reboot.h>
43#include <sys/sysctl.h>
44#include <sys/ctype.h>
45
46#include <machine/clock.h>
47
48#include <machine/resource.h>
49
50#include "acpi.h"
51
52#include <dev/acpica/acpivar.h>
53#include <dev/acpica/acpiio.h>
54
55MALLOC_DEFINE(M_ACPIDEV, "acpidev", "ACPI devices");
56
57/*
58 * Hooks for the ACPI CA debugging infrastructure
59 */
60#define _COMPONENT ACPI_BUS_MANAGER
61MODULE_NAME("ACPI")
62
63/*
64 * Character device
65 */
66
67static d_open_t acpiopen;
68static d_close_t acpiclose;
69static d_ioctl_t acpiioctl;
70
71#define CDEV_MAJOR 152
72static struct cdevsw acpi_cdevsw = {
73 acpiopen,
74 acpiclose,
75 noread,
76 nowrite,
77 acpiioctl,
78 nopoll,
79 nommap,
80 nostrategy,
81 "acpi",
82 CDEV_MAJOR,
83 nodump,
84 nopsize,
85 0
86};
87
88static const char* sleep_state_names[] = {
89 "S0", "S1", "S2", "S3", "S4", "S5", "S4B" };
90
91/* this has to be static, as the softc is gone when we need it */
92static int acpi_off_state = ACPI_STATE_S5;
93
94static void acpi_identify(driver_t *driver, device_t parent);
95static int acpi_probe(device_t dev);
96static int acpi_attach(device_t dev);
97static device_t acpi_add_child(device_t bus, int order, const char *name, int unit);
98static int acpi_print_resources(struct resource_list *rl, const char *name, int type,
99 const char *format);
100static int acpi_print_child(device_t bus, device_t child);
101static int acpi_read_ivar(device_t dev, device_t child, int index, uintptr_t *result);
102static int acpi_write_ivar(device_t dev, device_t child, int index, uintptr_t value);
103static int acpi_set_resource(device_t dev, device_t child, int type, int rid, u_long start,
104 u_long count);
105static int acpi_get_resource(device_t dev, device_t child, int type, int rid, u_long *startp,
106 u_long *countp);
107static struct resource *acpi_alloc_resource(device_t bus, device_t child, int type, int *rid,
108 u_long start, u_long end, u_long count, u_int flags);
109static int acpi_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r);
110
111static void acpi_probe_children(device_t bus);
112static ACPI_STATUS acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status);
113
114static void acpi_shutdown_pre_sync(void *arg, int howto);
115static void acpi_shutdown_final(void *arg, int howto);
116
117static void acpi_enable_fixed_events(struct acpi_softc *sc);
118
119static void acpi_system_eventhandler_sleep(void *arg, int state);
120static void acpi_system_eventhandler_wakeup(void *arg, int state);
121static int acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS);
122
123static device_method_t acpi_methods[] = {
124 /* Device interface */
125 DEVMETHOD(device_identify, acpi_identify),
126 DEVMETHOD(device_probe, acpi_probe),
127 DEVMETHOD(device_attach, acpi_attach),
128 DEVMETHOD(device_shutdown, bus_generic_shutdown),
129 DEVMETHOD(device_suspend, bus_generic_suspend),
130 DEVMETHOD(device_resume, bus_generic_resume),
131
132 /* Bus interface */
133 DEVMETHOD(bus_add_child, acpi_add_child),
134 DEVMETHOD(bus_print_child, acpi_print_child),
135 DEVMETHOD(bus_read_ivar, acpi_read_ivar),
136 DEVMETHOD(bus_write_ivar, acpi_write_ivar),
137 DEVMETHOD(bus_set_resource, acpi_set_resource),
138 DEVMETHOD(bus_get_resource, acpi_get_resource),
139 DEVMETHOD(bus_alloc_resource, acpi_alloc_resource),
140 DEVMETHOD(bus_release_resource, acpi_release_resource),
141 DEVMETHOD(bus_driver_added, bus_generic_driver_added),
142 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
143 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
144 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
145 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
146
147 {0, 0}
148};
149
150static driver_t acpi_driver = {
151 "acpi",
152 acpi_methods,
153 sizeof(struct acpi_softc),
154};
155
156devclass_t acpi_devclass;
157DRIVER_MODULE(acpi, nexus, acpi_driver, acpi_devclass, 0, 0);
158
159SYSCTL_INT(_debug, OID_AUTO, acpi_debug_layer, CTLFLAG_RW, &AcpiDbgLayer, 0, "");
160SYSCTL_INT(_debug, OID_AUTO, acpi_debug_level, CTLFLAG_RW, &AcpiDbgLevel, 0, "");
161
162/*
163 * Detect ACPI, perform early initialisation
164 */
165static void
166acpi_identify(driver_t *driver, device_t parent)
167{
168 device_t child;
169 ACPI_PHYSICAL_ADDRESS rsdp;
170 int error;
171#ifdef ENABLE_DEBUGGER
172 char *debugpoint = getenv("debug.acpi.debugger");
173#endif
174
175 FUNCTION_TRACE(__func__);
176
177 if(!cold){
178 printf("Don't load this driver from userland!!\n");
179 return ;
180 }
181
182 /*
183 * Make sure we're not being doubly invoked.
184 */
185 if (device_find_child(parent, "acpi", 0) != NULL)
186 return_VOID;
187
188 /*
189 * Start up the ACPI CA subsystem.
190 */
191#ifdef ENABLE_DEBUGGER
192 if (debugpoint && !strcmp(debugpoint, "init"))
193 acpi_EnterDebugger();
194#endif
195 if ((error = AcpiInitializeSubsystem()) != AE_OK) {
196 printf("ACPI: initialisation failed: %s\n", acpi_strerror(error));
197 return_VOID;
198 }
199#ifdef ENABLE_DEBUGGER
200 if (debugpoint && !strcmp(debugpoint, "tables"))
201 acpi_EnterDebugger();
202#endif
203 if (((error = AcpiFindRootPointer(&rsdp)) != AE_OK) ||
204 ((error = AcpiLoadTables(rsdp)) != AE_OK)) {
205 printf("ACPI: table load failed: %s\n", acpi_strerror(error));
206 return_VOID;
207 }
208
209 /*
210 * Attach the actual ACPI device.
211 */
212 if ((child = BUS_ADD_CHILD(parent, 0, "acpi", 0)) == NULL) {
213 device_printf(parent, "ACPI: could not attach\n");
214 return_VOID;
215 }
216}
217
218/*
219 * Fetch some descriptive data from ACPI to put in our attach message
220 */
221static int
222acpi_probe(device_t dev)
223{
224 ACPI_TABLE_HEADER th;
225 char buf[20];
226 int error;
227
228 FUNCTION_TRACE(__func__);
229
230 if ((error = AcpiGetTableHeader(ACPI_TABLE_XSDT, 1, &th)) != AE_OK) {
231 device_printf(dev, "couldn't get XSDT header: %s\n", acpi_strerror(error));
232 return_VALUE(ENXIO);
233 }
234 sprintf(buf, "%.6s %.8s", th.OemId, th.OemTableId);
235 device_set_desc_copy(dev, buf);
236
237 return_VALUE(0);
238}
239
240static int
241acpi_attach(device_t dev)
242{
243 struct acpi_softc *sc;
244 int error;
245#ifdef ENABLE_DEBUGGER
246 char *debugpoint = getenv("debug.acpi.debugger");
247#endif
248
249 FUNCTION_TRACE(__func__);
250
251 sc = device_get_softc(dev);
252 bzero(sc, sizeof(*sc));
253 sc->acpi_dev = dev;
254
255#ifdef ENABLE_DEBUGGER
256 if (debugpoint && !strcmp(debugpoint, "spaces"))
257 acpi_EnterDebugger();
258#endif
259
260 /*
261 * Install the default address space handlers.
262 */
263 if ((error = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
264 ACPI_ADR_SPACE_SYSTEM_MEMORY,
265 ACPI_DEFAULT_HANDLER,
266 NULL, NULL)) != AE_OK) {
267 device_printf(dev, "could not initialise SystemMemory handler: %s\n", acpi_strerror(error));
268 return_VALUE(ENXIO);
269 }
270 if ((error = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
271 ACPI_ADR_SPACE_SYSTEM_IO,
272 ACPI_DEFAULT_HANDLER,
273 NULL, NULL)) != AE_OK) {
274 device_printf(dev, "could not initialise SystemIO handler: %s\n", acpi_strerror(error));
275 return_VALUE(ENXIO);
276 }
277 if ((error = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
278 ACPI_ADR_SPACE_PCI_CONFIG,
279 ACPI_DEFAULT_HANDLER,
280 NULL, NULL)) != AE_OK) {
281 device_printf(dev, "could not initialise PciConfig handler: %s\n", acpi_strerror(error));
282 return_VALUE(ENXIO);
283 }
284
285 /*
286 * Bring ACPI fully online.
287 *
288 * Note that we request that device _STA and _INI methods not be run (ACPI_NO_DEVICE_INIT)
289 * and the final object initialisation pass be skipped (ACPI_NO_OBJECT_INIT).
290 *
291 * XXX We need to arrange for the object init pass after we have attached all our
292 * child devices.
293 */
294#ifdef ENABLE_DEBUGGER
295 if (debugpoint && !strcmp(debugpoint, "enable"))
296 acpi_EnterDebugger();
297#endif
298 if ((error = AcpiEnableSubsystem(ACPI_NO_DEVICE_INIT | ACPI_NO_OBJECT_INIT)) != AE_OK) {
299 device_printf(dev, "could not enable ACPI: %s\n", acpi_strerror(error));
300 return_VALUE(ENXIO);
301 }
302
303 /*
304 * Setup our sysctl tree.
305 *
306 * XXX: This doesn't check to make sure that none of these fail.
307 */
308 sysctl_ctx_init(&sc->acpi_sysctl_ctx);
309 sc->acpi_sysctl_tree = SYSCTL_ADD_NODE(&sc->acpi_sysctl_ctx,
310 SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
311 device_get_name(dev), CTLFLAG_RD, 0, "");
312 SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
313 OID_AUTO, "power_button_state", CTLTYPE_STRING | CTLFLAG_RW,
314 &sc->acpi_power_button_sx, 0, acpi_sleep_state_sysctl, "A", "");
315 SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
316 OID_AUTO, "sleep_button_state", CTLTYPE_STRING | CTLFLAG_RW,
317 &sc->acpi_sleep_button_sx, 0, acpi_sleep_state_sysctl, "A", "");
318 SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
319 OID_AUTO, "lid_switch_state", CTLTYPE_STRING | CTLFLAG_RW,
320 &sc->acpi_lid_switch_sx, 0, acpi_sleep_state_sysctl, "A", "");
321
322 /*
323 * Dispatch the default sleep state to devices.
324 * TBD: should be configured from userland policy manager.
325 */
326 sc->acpi_power_button_sx = ACPI_POWER_BUTTON_DEFAULT_SX;
327 sc->acpi_sleep_button_sx = ACPI_SLEEP_BUTTON_DEFAULT_SX;
328 sc->acpi_lid_switch_sx = ACPI_LID_SWITCH_DEFAULT_SX;
329
330 acpi_enable_fixed_events(sc);
331
332 /*
333 * Scan the namespace and attach/initialise children.
334 */
335#ifdef ENABLE_DEBUGGER
336 if (debugpoint && !strcmp(debugpoint, "probe"))
337 acpi_EnterDebugger();
338#endif
339 if (!acpi_disabled("bus"))
340 acpi_probe_children(dev);
341
342 /*
343 * Register our shutdown handlers
344 */
345 EVENTHANDLER_REGISTER(shutdown_pre_sync, acpi_shutdown_pre_sync, sc, SHUTDOWN_PRI_LAST);
346 EVENTHANDLER_REGISTER(shutdown_final, acpi_shutdown_final, sc, SHUTDOWN_PRI_LAST);
347
348 /*
349 * Register our acpi event handlers.
350 * XXX should be configurable eg. via userland policy manager.
351 */
352 EVENTHANDLER_REGISTER(acpi_sleep_event, acpi_system_eventhandler_sleep, sc, ACPI_EVENT_PRI_LAST);
353 EVENTHANDLER_REGISTER(acpi_wakeup_event, acpi_system_eventhandler_wakeup, sc, ACPI_EVENT_PRI_LAST);
354
355 /*
356 * Flag our initial states.
357 */
358 sc->acpi_enabled = 1;
359 sc->acpi_sstate = ACPI_STATE_S0;
360
361 /*
362 * Create the control device
363 */
364 sc->acpi_dev_t = make_dev(&acpi_cdevsw, 0, 0, 5, 0660, "acpi");
365 sc->acpi_dev_t->si_drv1 = sc;
366
367#ifdef ENABLE_DEBUGGER
368 if (debugpoint && !strcmp(debugpoint, "running"))
369 acpi_EnterDebugger();
370#endif
371 return_VALUE(0);
372}
373
374/*
375 * Handle a new device being added
376 */
377static device_t
378acpi_add_child(device_t bus, int order, const char *name, int unit)
379{
380 struct acpi_device *ad;
381 device_t child;
382
383 if ((ad = malloc(sizeof(*ad), M_ACPIDEV, M_NOWAIT)) == NULL)
384 return(NULL);
385 bzero(ad, sizeof(*ad));
386
387 resource_list_init(&ad->ad_rl);
388
389 child = device_add_child_ordered(bus, order, name, unit);
390 if (child != NULL)
391 device_set_ivars(child, ad);
392 return(child);
393}
394
395/*
396 * Print child device resource usage
397 */
398static int
399acpi_print_resources(struct resource_list *rl, const char *name, int type, const char *format)
400{
401 struct resource_list_entry *rle;
402 int printed, retval;
403
404 printed = 0;
405 retval = 0;
406
407 if (!SLIST_FIRST(rl))
408 return(0);
409
410 /* Yes, this is kinda cheating */
411 SLIST_FOREACH(rle, rl, link) {
412 if (rle->type == type) {
413 if (printed == 0)
414 retval += printf(" %s ", name);
415 else if (printed > 0)
416 retval += printf(",");
417 printed++;
418 retval += printf(format, rle->start);
419 if (rle->count > 1) {
420 retval += printf("-");
421 retval += printf(format, rle->start +
422 rle->count - 1);
423 }
424 }
425 }
426 return(retval);
427}
428
429static int
430acpi_print_child(device_t bus, device_t child)
431{
432 struct acpi_device *adev = device_get_ivars(child);
433 struct resource_list *rl = &adev->ad_rl;
434 int retval = 0;
435
436 retval += bus_print_child_header(bus, child);
437 retval += acpi_print_resources(rl, "port", SYS_RES_IOPORT, "%#lx");
438 retval += acpi_print_resources(rl, "iomem", SYS_RES_MEMORY, "%#lx");
439 retval += acpi_print_resources(rl, "irq", SYS_RES_IRQ, "%ld");
440 retval += bus_print_child_footer(bus, child);
441
442 return(retval);
443}
444
445
446/*
447 * Handle per-device ivars
448 */
449static int
450acpi_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
451{
452 struct acpi_device *ad;
453
454 if ((ad = device_get_ivars(child)) == NULL) {
455 printf("device has no ivars\n");
456 return(ENOENT);
457 }
458
459 switch(index) {
460 /* ACPI ivars */
461 case ACPI_IVAR_HANDLE:
462 *(ACPI_HANDLE *)result = ad->ad_handle;
463 break;
464 case ACPI_IVAR_MAGIC:
465 *(int *)result = ad->ad_magic;
466 break;
467 case ACPI_IVAR_PRIVATE:
468 *(void **)result = ad->ad_private;
469 break;
470
471 default:
472 panic("bad ivar read request (%d)\n", index);
473 return(ENOENT);
474 }
475 return(0);
476}
477
478static int
479acpi_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
480{
481 struct acpi_device *ad;
482
483 if ((ad = device_get_ivars(child)) == NULL) {
484 printf("device has no ivars\n");
485 return(ENOENT);
486 }
487
488 switch(index) {
489 /* ACPI ivars */
490 case ACPI_IVAR_HANDLE:
491 ad->ad_handle = (ACPI_HANDLE)value;
492 break;
493 case ACPI_IVAR_MAGIC:
494 ad->ad_magic = (int )value;
495 break;
496 case ACPI_IVAR_PRIVATE:
497 ad->ad_private = (void *)value;
498 break;
499
500 default:
501 panic("bad ivar write request (%d)\n", index);
502 return(ENOENT);
503 }
504 return(0);
505}
506
507/*
508 * Handle child resource allocation/removal
509 */
510static int
511acpi_set_resource(device_t dev, device_t child, int type, int rid, u_long start, u_long count)
512{
513 struct acpi_device *ad = device_get_ivars(child);
514 struct resource_list *rl = &ad->ad_rl;
515
516 resource_list_add(rl, type, rid, start, start + count -1, count);
517
518 return(0);
519}
520
521static int
522acpi_get_resource(device_t dev, device_t child, int type, int rid, u_long *startp, u_long *countp)
523{
524 struct acpi_device *ad = device_get_ivars(child);
525 struct resource_list *rl = &ad->ad_rl;
526 struct resource_list_entry *rle;
527
528 rle = resource_list_find(rl, type, rid);
529 if (!rle)
530 return(ENOENT);
531
532 if (startp)
533 *startp = rle->start;
534 if (countp)
535 *countp = rle->count;
536
537 return(0);
538}
539
540static struct resource *
541acpi_alloc_resource(device_t bus, device_t child, int type, int *rid,
542 u_long start, u_long end, u_long count, u_int flags)
543{
544 struct acpi_device *ad = device_get_ivars(child);
545 struct resource_list *rl = &ad->ad_rl;
546
547 return(resource_list_alloc(rl, bus, child, type, rid, start, end, count, flags));
548}
549
550static int
551acpi_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r)
552{
553 struct acpi_device *ad = device_get_ivars(child);
554 struct resource_list *rl = &ad->ad_rl;
555
556 return(resource_list_release(rl, bus, child, type, rid, r));
557}
558
559/*
560 * Scan relevant portions of the ACPI namespace and attach child devices.
561 *
562 * Note that we only expect to find devices in the \_TZ_, \_SI_ and \_SB_ scopes,
563 * and \_TZ_ becomes obsolete in the ACPI 2.0 spec.
564 */
565static void
566acpi_probe_children(device_t bus)
567{
568 ACPI_HANDLE parent;
569 static char *scopes[] = {"\\_TZ_", "\\_SI", "\\_SB_", NULL};
570 int i;
571
572 FUNCTION_TRACE(__func__);
573
574 /*
575 * Create any static children by calling device identify methods.
576 */
577 DEBUG_PRINT(TRACE_OBJECTS, ("device identify routines\n"));
578 bus_generic_probe(bus);
579
580 /*
581 * Scan the namespace and insert placeholders for all the devices that
582 * we find.
583 *
584 * Note that we use AcpiWalkNamespace rather than AcpiGetDevices because
585 * we want to create nodes for all devices, not just those that are currently
586 * present. (This assumes that we don't want to create/remove devices as they
587 * appear, which might be smarter.)
588 */
589 DEBUG_PRINT(TRACE_OBJECTS, ("namespace scan\n"));
590 for (i = 0; scopes[i] != NULL; i++)
591 if ((AcpiGetHandle(ACPI_ROOT_OBJECT, scopes[i], &parent)) == AE_OK)
592 AcpiWalkNamespace(ACPI_TYPE_ANY, parent, 100, acpi_probe_child, bus, NULL);
593
594 /*
595 * Scan all of the child devices we have created and let them probe/attach.
596 */
597 DEBUG_PRINT(TRACE_OBJECTS, ("first bus_generic_attach\n"));
598 bus_generic_attach(bus);
599
600 /*
601 * Some of these children may have attached others as part of their attach
602 * process (eg. the root PCI bus driver), so rescan.
603 */
604 DEBUG_PRINT(TRACE_OBJECTS, ("second bus_generic_attach\n"));
605 bus_generic_attach(bus);
606
607 return_VOID;
608}
609
610/*
611 * Evaluate a child device and determine whether we might attach a device to
612 * it.
613 */
614static ACPI_STATUS
615acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status)
616{
617 ACPI_OBJECT_TYPE type;
618 device_t child, bus = (device_t)context;
619
620 FUNCTION_TRACE(__func__);
621
622 /*
623 * Skip this device if we think we'll have trouble with it.
624 */
625 if (acpi_avoid(handle))
626 return_ACPI_STATUS(AE_OK);
627
628 if (AcpiGetType(handle, &type) == AE_OK) {
629 switch(type) {
630 case ACPI_TYPE_DEVICE:
631 case ACPI_TYPE_PROCESSOR:
632 case ACPI_TYPE_THERMAL:
633 case ACPI_TYPE_POWER:
634 if (acpi_disabled("children"))
635 break;
636 /*
637 * Create a placeholder device for this node. Sort the placeholder
638 * so that the probe/attach passes will run breadth-first.
639 */
640 DEBUG_PRINT(TRACE_OBJECTS, ("scanning '%s'\n", acpi_name(handle)))
641 child = BUS_ADD_CHILD(bus, level * 10, NULL, -1);
642 acpi_set_handle(child, handle);
643 DEBUG_EXEC(device_probe_and_attach(child));
644 break;
645 }
646 }
647 return_ACPI_STATUS(AE_OK);
648}
649
650static void
651acpi_shutdown_pre_sync(void *arg, int howto)
652{
653 /*
654 * Disable all ACPI events before soft off, otherwise the system
655 * will be turned on again on some laptops.
656 *
657 * XXX this should probably be restricted to masking some events just
658 * before powering down, since we may still need ACPI during the
659 * shutdown process.
660 */
661 acpi_Disable((struct acpi_softc *)arg);
662}
663
664static void
665acpi_shutdown_final(void *arg, int howto)
666{
667 ACPI_STATUS status;
668
669 if (howto & RB_POWEROFF) {
670 printf("Power system off using ACPI...\n");
671 if ((status = AcpiEnterSleepState(acpi_off_state)) != AE_OK) {
672 printf("ACPI power-off failed - %s\n", acpi_strerror(status));
673 } else {
674 DELAY(1000000);
675 printf("ACPI power-off failed - timeout\n");
676 }
677 }
678}
679
680static void
681acpi_enable_fixed_events(struct acpi_softc *sc)
682{
683 static int first_time = 1;
684#define MSGFORMAT "%s button is handled as a fixed feature programming model.\n"
685
686 /* Enable and clear fixed events and install handlers. */
687 if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->PwrButton == 0) {
688 AcpiEnableEvent(ACPI_EVENT_POWER_BUTTON, ACPI_EVENT_FIXED);
689 AcpiClearEvent(ACPI_EVENT_POWER_BUTTON, ACPI_EVENT_FIXED);
690 AcpiInstallFixedEventHandler(ACPI_EVENT_POWER_BUTTON,
691 acpi_eventhandler_power_button_for_sleep, sc);
692 if (first_time) {
693 device_printf(sc->acpi_dev, MSGFORMAT, "power");
694 }
695 }
696 if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->SleepButton == 0) {
697 AcpiEnableEvent(ACPI_EVENT_SLEEP_BUTTON, ACPI_EVENT_FIXED);
698 AcpiClearEvent(ACPI_EVENT_SLEEP_BUTTON, ACPI_EVENT_FIXED);
699 AcpiInstallFixedEventHandler(ACPI_EVENT_SLEEP_BUTTON,
700 acpi_eventhandler_sleep_button_for_sleep, sc);
701 if (first_time) {
702 device_printf(sc->acpi_dev, MSGFORMAT, "sleep");
703 }
704 }
705
706 first_time = 0;
707}
708
709/*
710 * Returns true if the device is actually present and should
711 * be attached to. This requires the present, enabled, UI-visible
712 * and diagnostics-passed bits to be set.
713 */
714BOOLEAN
715acpi_DeviceIsPresent(device_t dev)
716{
717 ACPI_HANDLE h;
718 ACPI_DEVICE_INFO devinfo;
719 ACPI_STATUS error;
720
721 if ((h = acpi_get_handle(dev)) == NULL)
722 return(FALSE);
723 if ((error = AcpiGetObjectInfo(h, &devinfo)) != AE_OK)
724 return(FALSE);
725 if ((devinfo.Valid & ACPI_VALID_HID) && (devinfo.CurrentStatus & 0xf))
726 return(TRUE);
727 return(FALSE);
728}
729
730/*
710 * Match a HID string against a device
711 */
712BOOLEAN
713acpi_MatchHid(device_t dev, char *hid)
714{
715 ACPI_HANDLE h;
716 ACPI_DEVICE_INFO devinfo;
717 ACPI_STATUS error;
718
719 if (hid == NULL)
720 return(FALSE);
721 if ((h = acpi_get_handle(dev)) == NULL)
722 return(FALSE);
723 if ((error = AcpiGetObjectInfo(h, &devinfo)) != AE_OK)
724 return(FALSE);
725 if ((devinfo.Valid & ACPI_VALID_HID) && !strcmp(hid, devinfo.HardwareId))
726 return(TRUE);
727 return(FALSE);
728}
729
730/*
731 * Match a HID string against a device
732 */
733BOOLEAN
734acpi_MatchHid(device_t dev, char *hid)
735{
736 ACPI_HANDLE h;
737 ACPI_DEVICE_INFO devinfo;
738 ACPI_STATUS error;
739
740 if (hid == NULL)
741 return(FALSE);
742 if ((h = acpi_get_handle(dev)) == NULL)
743 return(FALSE);
744 if ((error = AcpiGetObjectInfo(h, &devinfo)) != AE_OK)
745 return(FALSE);
746 if ((devinfo.Valid & ACPI_VALID_HID) && !strcmp(hid, devinfo.HardwareId))
747 return(TRUE);
748 return(FALSE);
749}
750
751/*
752 * Return the handle of a named object within our scope, ie. that of (parent)
753 * or one if its parents.
754 */
755ACPI_STATUS
756acpi_GetHandleInScope(ACPI_HANDLE parent, char *path, ACPI_HANDLE *result)
757{
758 ACPI_HANDLE r;
759 ACPI_STATUS status;
760
761 /* walk back up the tree to the root */
762 for (;;) {
763 status = AcpiGetHandle(parent, path, &r);
764 if (status == AE_OK) {
765 *result = r;
766 return(AE_OK);
767 }
768 if (status != AE_NOT_FOUND)
769 return(AE_OK);
770 if (AcpiGetParent(parent, &r) != AE_OK)
771 return(AE_NOT_FOUND);
772 parent = r;
773 }
774}
775
776/*
777 * Allocate a buffer with a preset data size.
778 */
779ACPI_BUFFER *
780acpi_AllocBuffer(int size)
781{
782 ACPI_BUFFER *buf;
783
784 if ((buf = malloc(size + sizeof(*buf), M_ACPIDEV, M_NOWAIT)) == NULL)
785 return(NULL);
786 buf->Length = size;
787 buf->Pointer = (void *)(buf + 1);
788 return(buf);
789}
790
791/*
731 * Perform the tedious double-get procedure required for fetching something into
732 * an ACPI_BUFFER that has not been initialised.
733 */
734ACPI_STATUS
735acpi_GetIntoBuffer(ACPI_HANDLE handle, ACPI_STATUS (*func)(ACPI_HANDLE, ACPI_BUFFER *), ACPI_BUFFER *buf)
736{
737 ACPI_STATUS status;
738
739 buf->Length = 0;
740 buf->Pointer = NULL;
741
742 if ((status = func(handle, buf)) != AE_BUFFER_OVERFLOW)
743 return(status);
744 if ((buf->Pointer = AcpiOsCallocate(buf->Length)) == NULL)
745 return(AE_NO_MEMORY);
746 return(func(handle, buf));
747}
748
749/*
792 * Perform the tedious double-get procedure required for fetching something into
793 * an ACPI_BUFFER that has not been initialised.
794 */
795ACPI_STATUS
796acpi_GetIntoBuffer(ACPI_HANDLE handle, ACPI_STATUS (*func)(ACPI_HANDLE, ACPI_BUFFER *), ACPI_BUFFER *buf)
797{
798 ACPI_STATUS status;
799
800 buf->Length = 0;
801 buf->Pointer = NULL;
802
803 if ((status = func(handle, buf)) != AE_BUFFER_OVERFLOW)
804 return(status);
805 if ((buf->Pointer = AcpiOsCallocate(buf->Length)) == NULL)
806 return(AE_NO_MEMORY);
807 return(func(handle, buf));
808}
809
810/*
750 * Allocate a buffer with a preset data size.
811 * Perform the tedious double-evaluate procedure for evaluating something into
812 * an ACPI_BUFFER that has not been initialised. Note that this evaluates
813 * twice, so avoid applying this to things that may have side-effects.
814 *
815 * This is like AcpiEvaluateObject with automatic buffer allocation.
751 */
816 */
752ACPI_BUFFER *
753acpi_AllocBuffer(int size)
817ACPI_STATUS
818acpi_EvaluateIntoBuffer(ACPI_HANDLE object, ACPI_STRING pathname, ACPI_OBJECT_LIST *params,
819 ACPI_BUFFER *buf)
754{
820{
755 ACPI_BUFFER *buf;
821 ACPI_STATUS status;
822
823 buf->Length = 0;
824 buf->Pointer = NULL;
756
825
757 if ((buf = malloc(size + sizeof(*buf), M_ACPIDEV, M_NOWAIT)) == NULL)
758 return(NULL);
759 buf->Length = size;
760 buf->Pointer = (void *)(buf + 1);
761 return(buf);
826 if ((status = AcpiEvaluateObject(object, pathname, params, buf)) != AE_BUFFER_OVERFLOW)
827 return(status);
828 if ((buf->Pointer = AcpiOsCallocate(buf->Length)) == NULL)
829 return(AE_NO_MEMORY);
830 return(AcpiEvaluateObject(object, pathname, params, buf));
762}
763
831}
832
833/*
834 * Evaluate a path that should return an integer.
835 */
836ACPI_STATUS
837acpi_EvaluateInteger(ACPI_HANDLE handle, char *path, int *number)
838{
839 ACPI_STATUS error;
840 ACPI_BUFFER buf;
841 ACPI_OBJECT param;
842
843 if (handle == NULL)
844 handle = ACPI_ROOT_OBJECT;
845 buf.Pointer = &param;
846 buf.Length = sizeof(param);
847 if ((error = AcpiEvaluateObject(handle, path, NULL, &buf)) == AE_OK) {
848 if (param.Type == ACPI_TYPE_INTEGER) {
849 *number = param.Integer.Value;
850 } else {
851 error = AE_TYPE;
852 }
853 }
854 return(error);
855}
856
857/*
858 * Iterate over the elements of an a package object, calling the supplied
859 * function for each element.
860 *
861 * XXX possible enhancement might be to abort traversal on error.
862 */
863ACPI_STATUS
864acpi_ForeachPackageObject(ACPI_OBJECT *pkg, void (* func)(ACPI_OBJECT *comp, void *arg), void *arg)
865{
866 ACPI_OBJECT *comp;
867 int i;
868
869 if ((pkg == NULL) || (pkg->Type != ACPI_TYPE_PACKAGE))
870 return(AE_BAD_PARAMETER);
871
872 /* iterate over components */
873 for (i = 0, comp = pkg->Package.Elements; i < pkg->Package.Count; i++, comp++)
874 func(comp, arg);
875
876 return(AE_OK);
877}
878
879
764static ACPI_STATUS __inline
765acpi_wakeup(UINT8 state)
766{
767 UINT16 Count;
768 ACPI_STATUS Status;
769 ACPI_OBJECT_LIST Arg_list;
770 ACPI_OBJECT Arg;
771 ACPI_OBJECT Objects[3]; /* package plus 2 number objects */
772 ACPI_BUFFER ReturnBuffer;
773
774 FUNCTION_TRACE_U32(__func__, state);
775
776 /* wait for the WAK_STS bit */
777 Count = 0;
778 while (!(AcpiHwRegisterBitAccess(ACPI_READ, ACPI_MTX_LOCK, WAK_STS))) {
779 AcpiOsSleepUsec(1000);
780 /*
781 * Some BIOSes don't set WAK_STS at all,
782 * give up waiting for wakeup if we time out.
783 */
784 if (Count > 1000) {
785 break; /* giving up */
786 }
787 Count++;
788 }
789
790 /*
791 * Evaluate the _WAK method
792 */
793 MEMSET(&Arg_list, 0, sizeof(Arg_list));
794 Arg_list.Count = 1;
795 Arg_list.Pointer = &Arg;
796
797 MEMSET(&Arg, 0, sizeof(Arg));
798 Arg.Type = ACPI_TYPE_INTEGER;
799 Arg.Integer.Value = state;
800
801 /* Set up _WAK result code buffer */
802 MEMSET(Objects, 0, sizeof(Objects));
803 ReturnBuffer.Length = sizeof(Objects);
804 ReturnBuffer.Pointer = Objects;
805
806 AcpiEvaluateObject (NULL, "\\_WAK", &Arg_list, &ReturnBuffer);
807
808 Status = AE_OK;
809 /* Check result code for _WAK */
810 if (Objects[0].Type != ACPI_TYPE_PACKAGE ||
811 Objects[1].Type != ACPI_TYPE_INTEGER ||
812 Objects[2].Type != ACPI_TYPE_INTEGER) {
813 /*
814 * In many BIOSes, _WAK doesn't return a result code.
815 * We don't need to worry about it too much :-).
816 */
817 DEBUG_PRINT (ACPI_INFO,
818 ("acpi_wakeup: _WAK result code is corrupted, "
819 "but should be OK.\n"));
820 } else {
821 /* evaluate status code */
822 switch (Objects[1].Integer.Value) {
823 case 0x00000001:
824 DEBUG_PRINT (ACPI_ERROR,
825 ("acpi_wakeup: Wake was signaled "
826 "but failed due to lack of power.\n"));
827 Status = AE_ERROR;
828 break;
829
830 case 0x00000002:
831 DEBUG_PRINT (ACPI_ERROR,
832 ("acpi_wakeup: Wake was signaled "
833 "but failed due to thermal condition.\n"));
834 Status = AE_ERROR;
835 break;
836 }
837 /* evaluate PSS code */
838 if (Objects[2].Integer.Value == 0) {
839 DEBUG_PRINT (ACPI_ERROR,
840 ("acpi_wakeup: The targeted S-state "
841 "was not entered because of too much current "
842 "being drawn from the power supply.\n"));
843 Status = AE_ERROR;
844 }
845 }
846
847 return_ACPI_STATUS(Status);
848}
849
850/*
851 * Set the system sleep state
852 *
853 * Currently we only support S1 and S5
854 */
855ACPI_STATUS
856acpi_SetSleepState(struct acpi_softc *sc, int state)
857{
858 ACPI_STATUS status = AE_OK;
859
860 FUNCTION_TRACE_U32(__func__, state);
861
862 switch (state) {
863 case ACPI_STATE_S0: /* XXX only for testing */
864 status = AcpiEnterSleepState((UINT8)state);
865 if (status != AE_OK) {
866 device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n", acpi_strerror(status));
867 }
868 break;
869
870 case ACPI_STATE_S1:
871 /*
872 * Inform all devices that we are going to sleep.
873 */
874 if (DEVICE_SUSPEND(root_bus) != 0) {
875 /*
876 * Re-wake the system.
877 *
878 * XXX note that a better two-pass approach with a 'veto' pass
879 * followed by a "real thing" pass would be better, but the
880 * current bus interface does not provide for this.
881 */
882 DEVICE_RESUME(root_bus);
883 return_ACPI_STATUS(AE_ERROR);
884 }
885 sc->acpi_sstate = state;
886 status = AcpiEnterSleepState((UINT8)state);
887 if (status != AE_OK) {
888 device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n", acpi_strerror(status));
889 break;
890 }
891 acpi_wakeup((UINT8)state);
892 DEVICE_RESUME(root_bus);
893 sc->acpi_sstate = ACPI_STATE_S0;
894 acpi_enable_fixed_events(sc);
895 break;
896
897 case ACPI_STATE_S3:
898 acpi_off_state = ACPI_STATE_S3;
899 /* FALLTHROUGH */
900 case ACPI_STATE_S5:
901 /*
902 * Shut down cleanly and power off. This will call us back through the
903 * shutdown handlers.
904 */
905 shutdown_nice(RB_POWEROFF);
906 break;
907
908 default:
909 status = AE_BAD_PARAMETER;
910 break;
911 }
912 return_ACPI_STATUS(status);
913}
914
915/*
916 * Enable/Disable ACPI
917 */
918ACPI_STATUS
919acpi_Enable(struct acpi_softc *sc)
920{
921 ACPI_STATUS status;
922 u_int32_t flags;
923
924 FUNCTION_TRACE(__func__);
925
926 flags = ACPI_NO_ADDRESS_SPACE_INIT | ACPI_NO_HARDWARE_INIT |
927 ACPI_NO_DEVICE_INIT | ACPI_NO_OBJECT_INIT;
928 if (!sc->acpi_enabled) {
929 status = AcpiEnableSubsystem(flags);
930 } else {
931 status = AE_OK;
932 }
933 if (status == AE_OK)
934 sc->acpi_enabled = 1;
935 return_ACPI_STATUS(status);
936}
937
938ACPI_STATUS
939acpi_Disable(struct acpi_softc *sc)
940{
941 ACPI_STATUS status;
942
943 FUNCTION_TRACE(__func__);
944
945 if (sc->acpi_enabled) {
946 status = AcpiDisable();
947 } else {
948 status = AE_OK;
949 }
950 if (status == AE_OK)
951 sc->acpi_enabled = 0;
952 return_ACPI_STATUS(status);
953}
954
955/*
880static ACPI_STATUS __inline
881acpi_wakeup(UINT8 state)
882{
883 UINT16 Count;
884 ACPI_STATUS Status;
885 ACPI_OBJECT_LIST Arg_list;
886 ACPI_OBJECT Arg;
887 ACPI_OBJECT Objects[3]; /* package plus 2 number objects */
888 ACPI_BUFFER ReturnBuffer;
889
890 FUNCTION_TRACE_U32(__func__, state);
891
892 /* wait for the WAK_STS bit */
893 Count = 0;
894 while (!(AcpiHwRegisterBitAccess(ACPI_READ, ACPI_MTX_LOCK, WAK_STS))) {
895 AcpiOsSleepUsec(1000);
896 /*
897 * Some BIOSes don't set WAK_STS at all,
898 * give up waiting for wakeup if we time out.
899 */
900 if (Count > 1000) {
901 break; /* giving up */
902 }
903 Count++;
904 }
905
906 /*
907 * Evaluate the _WAK method
908 */
909 MEMSET(&Arg_list, 0, sizeof(Arg_list));
910 Arg_list.Count = 1;
911 Arg_list.Pointer = &Arg;
912
913 MEMSET(&Arg, 0, sizeof(Arg));
914 Arg.Type = ACPI_TYPE_INTEGER;
915 Arg.Integer.Value = state;
916
917 /* Set up _WAK result code buffer */
918 MEMSET(Objects, 0, sizeof(Objects));
919 ReturnBuffer.Length = sizeof(Objects);
920 ReturnBuffer.Pointer = Objects;
921
922 AcpiEvaluateObject (NULL, "\\_WAK", &Arg_list, &ReturnBuffer);
923
924 Status = AE_OK;
925 /* Check result code for _WAK */
926 if (Objects[0].Type != ACPI_TYPE_PACKAGE ||
927 Objects[1].Type != ACPI_TYPE_INTEGER ||
928 Objects[2].Type != ACPI_TYPE_INTEGER) {
929 /*
930 * In many BIOSes, _WAK doesn't return a result code.
931 * We don't need to worry about it too much :-).
932 */
933 DEBUG_PRINT (ACPI_INFO,
934 ("acpi_wakeup: _WAK result code is corrupted, "
935 "but should be OK.\n"));
936 } else {
937 /* evaluate status code */
938 switch (Objects[1].Integer.Value) {
939 case 0x00000001:
940 DEBUG_PRINT (ACPI_ERROR,
941 ("acpi_wakeup: Wake was signaled "
942 "but failed due to lack of power.\n"));
943 Status = AE_ERROR;
944 break;
945
946 case 0x00000002:
947 DEBUG_PRINT (ACPI_ERROR,
948 ("acpi_wakeup: Wake was signaled "
949 "but failed due to thermal condition.\n"));
950 Status = AE_ERROR;
951 break;
952 }
953 /* evaluate PSS code */
954 if (Objects[2].Integer.Value == 0) {
955 DEBUG_PRINT (ACPI_ERROR,
956 ("acpi_wakeup: The targeted S-state "
957 "was not entered because of too much current "
958 "being drawn from the power supply.\n"));
959 Status = AE_ERROR;
960 }
961 }
962
963 return_ACPI_STATUS(Status);
964}
965
966/*
967 * Set the system sleep state
968 *
969 * Currently we only support S1 and S5
970 */
971ACPI_STATUS
972acpi_SetSleepState(struct acpi_softc *sc, int state)
973{
974 ACPI_STATUS status = AE_OK;
975
976 FUNCTION_TRACE_U32(__func__, state);
977
978 switch (state) {
979 case ACPI_STATE_S0: /* XXX only for testing */
980 status = AcpiEnterSleepState((UINT8)state);
981 if (status != AE_OK) {
982 device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n", acpi_strerror(status));
983 }
984 break;
985
986 case ACPI_STATE_S1:
987 /*
988 * Inform all devices that we are going to sleep.
989 */
990 if (DEVICE_SUSPEND(root_bus) != 0) {
991 /*
992 * Re-wake the system.
993 *
994 * XXX note that a better two-pass approach with a 'veto' pass
995 * followed by a "real thing" pass would be better, but the
996 * current bus interface does not provide for this.
997 */
998 DEVICE_RESUME(root_bus);
999 return_ACPI_STATUS(AE_ERROR);
1000 }
1001 sc->acpi_sstate = state;
1002 status = AcpiEnterSleepState((UINT8)state);
1003 if (status != AE_OK) {
1004 device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n", acpi_strerror(status));
1005 break;
1006 }
1007 acpi_wakeup((UINT8)state);
1008 DEVICE_RESUME(root_bus);
1009 sc->acpi_sstate = ACPI_STATE_S0;
1010 acpi_enable_fixed_events(sc);
1011 break;
1012
1013 case ACPI_STATE_S3:
1014 acpi_off_state = ACPI_STATE_S3;
1015 /* FALLTHROUGH */
1016 case ACPI_STATE_S5:
1017 /*
1018 * Shut down cleanly and power off. This will call us back through the
1019 * shutdown handlers.
1020 */
1021 shutdown_nice(RB_POWEROFF);
1022 break;
1023
1024 default:
1025 status = AE_BAD_PARAMETER;
1026 break;
1027 }
1028 return_ACPI_STATUS(status);
1029}
1030
1031/*
1032 * Enable/Disable ACPI
1033 */
1034ACPI_STATUS
1035acpi_Enable(struct acpi_softc *sc)
1036{
1037 ACPI_STATUS status;
1038 u_int32_t flags;
1039
1040 FUNCTION_TRACE(__func__);
1041
1042 flags = ACPI_NO_ADDRESS_SPACE_INIT | ACPI_NO_HARDWARE_INIT |
1043 ACPI_NO_DEVICE_INIT | ACPI_NO_OBJECT_INIT;
1044 if (!sc->acpi_enabled) {
1045 status = AcpiEnableSubsystem(flags);
1046 } else {
1047 status = AE_OK;
1048 }
1049 if (status == AE_OK)
1050 sc->acpi_enabled = 1;
1051 return_ACPI_STATUS(status);
1052}
1053
1054ACPI_STATUS
1055acpi_Disable(struct acpi_softc *sc)
1056{
1057 ACPI_STATUS status;
1058
1059 FUNCTION_TRACE(__func__);
1060
1061 if (sc->acpi_enabled) {
1062 status = AcpiDisable();
1063 } else {
1064 status = AE_OK;
1065 }
1066 if (status == AE_OK)
1067 sc->acpi_enabled = 0;
1068 return_ACPI_STATUS(status);
1069}
1070
1071/*
956 * Returns true if the device is actually present and should
957 * be attached to. This requires the present, enabled, UI-visible
958 * and diagnostics-passed bits to be set.
959 */
960BOOLEAN
961acpi_DeviceIsPresent(device_t dev)
962{
963 ACPI_HANDLE h;
964 ACPI_DEVICE_INFO devinfo;
965 ACPI_STATUS error;
966
967 if ((h = acpi_get_handle(dev)) == NULL)
968 return(FALSE);
969 if ((error = AcpiGetObjectInfo(h, &devinfo)) != AE_OK)
970 return(FALSE);
971 if ((devinfo.Valid & ACPI_VALID_HID) && (devinfo.CurrentStatus & 0xf))
972 return(TRUE);
973 return(FALSE);
974}
975
976/*
977 * Evaluate a path that should return an integer.
978 */
979ACPI_STATUS
980acpi_EvaluateInteger(ACPI_HANDLE handle, char *path, int *number)
981{
982 ACPI_STATUS error;
983 ACPI_BUFFER buf;
984 ACPI_OBJECT param;
985
986 if (handle == NULL)
987 handle = ACPI_ROOT_OBJECT;
988 buf.Pointer = &param;
989 buf.Length = sizeof(param);
990 if ((error = AcpiEvaluateObject(handle, path, NULL, &buf)) == AE_OK) {
991 if (param.Type == ACPI_TYPE_INTEGER) {
992 *number = param.Integer.Value;
993 } else {
994 error = AE_TYPE;
995 }
996 }
997 return(error);
998}
999
1000/*
1001 * ACPI Event Handlers
1002 */
1003
1004/* System Event Handlers (registered by EVENTHANDLER_REGISTER) */
1005
1006static void
1007acpi_system_eventhandler_sleep(void *arg, int state)
1008{
1009 FUNCTION_TRACE_U32(__func__, state);
1010
1011 if (state >= ACPI_STATE_S0 && state <= ACPI_S_STATES_MAX)
1012 acpi_SetSleepState((struct acpi_softc *)arg, state);
1013 return_VOID;
1014}
1015
1016static void
1017acpi_system_eventhandler_wakeup(void *arg, int state)
1018{
1019 FUNCTION_TRACE_U32(__func__, state);
1020
1021 /* Well, what to do? :-) */
1022
1023 return_VOID;
1024}
1025
1026/*
1027 * ACPICA Event Handlers (FixedEvent, also called from button notify handler)
1028 */
1029UINT32
1030acpi_eventhandler_power_button_for_sleep(void *context)
1031{
1032 struct acpi_softc *sc = (struct acpi_softc *)context;
1033
1034 FUNCTION_TRACE(__func__);
1035
1036 EVENTHANDLER_INVOKE(acpi_sleep_event, sc->acpi_power_button_sx);
1037
1038 return_VALUE(INTERRUPT_HANDLED);
1039}
1040
1041UINT32
1042acpi_eventhandler_power_button_for_wakeup(void *context)
1043{
1044 struct acpi_softc *sc = (struct acpi_softc *)context;
1045
1046 FUNCTION_TRACE(__func__);
1047
1048 EVENTHANDLER_INVOKE(acpi_wakeup_event, sc->acpi_power_button_sx);
1049
1050 return_VALUE(INTERRUPT_HANDLED);
1051}
1052
1053UINT32
1054acpi_eventhandler_sleep_button_for_sleep(void *context)
1055{
1056 struct acpi_softc *sc = (struct acpi_softc *)context;
1057
1058 FUNCTION_TRACE(__func__);
1059
1060 EVENTHANDLER_INVOKE(acpi_sleep_event, sc->acpi_sleep_button_sx);
1061
1062 return_VALUE(INTERRUPT_HANDLED);
1063}
1064
1065UINT32
1066acpi_eventhandler_sleep_button_for_wakeup(void *context)
1067{
1068 struct acpi_softc *sc = (struct acpi_softc *)context;
1069
1070 FUNCTION_TRACE(__func__);
1071
1072 EVENTHANDLER_INVOKE(acpi_wakeup_event, sc->acpi_sleep_button_sx);
1073
1074 return_VALUE(INTERRUPT_HANDLED);
1075}
1076
1077/*
1078 * XXX This is kinda ugly, and should not be here.
1079 */
1080struct acpi_staticbuf {
1081 ACPI_BUFFER buffer;
1082 char data[512];
1083};
1084
1085char *
1086acpi_strerror(ACPI_STATUS excep)
1087{
1088 static struct acpi_staticbuf buf;
1089
1090 buf.buffer.Length = 512;
1091 buf.buffer.Pointer = &buf.data[0];
1092
1093 if (AcpiFormatException(excep, &buf.buffer) == AE_OK)
1094 return(buf.buffer.Pointer);
1095 return("(error formatting exception)");
1096}
1097
1098char *
1099acpi_name(ACPI_HANDLE handle)
1100{
1101 static struct acpi_staticbuf buf;
1102
1103 buf.buffer.Length = 512;
1104 buf.buffer.Pointer = &buf.data[0];
1105
1106 if (AcpiGetName(handle, ACPI_FULL_PATHNAME, &buf.buffer) == AE_OK)
1107 return(buf.buffer.Pointer);
1108 return("(unknown path)");
1109}
1110
1111/*
1112 * Debugging/bug-avoidance. Avoid trying to fetch info on various
1113 * parts of the namespace.
1114 */
1115int
1116acpi_avoid(ACPI_HANDLE handle)
1117{
1118 char *cp, *np;
1119 int len;
1120
1121 np = acpi_name(handle);
1122 if (*np == '\\')
1123 np++;
1124 if ((cp = getenv("debug.acpi.avoid")) == NULL)
1125 return(0);
1126
1127 /* scan the avoid list checking for a match */
1128 for (;;) {
1129 while ((*cp != 0) && isspace(*cp))
1130 cp++;
1131 if (*cp == 0)
1132 break;
1133 len = 0;
1134 while ((cp[len] != 0) && !isspace(cp[len]))
1135 len++;
1136 if (!strncmp(cp, np, len)) {
1137 DEBUG_PRINT(TRACE_OBJECTS, ("avoiding '%s'\n", np));
1138 return(1);
1139 }
1140 cp += len;
1141 }
1142 return(0);
1143}
1144
1145/*
1146 * Debugging/bug-avoidance. Disable ACPI subsystem components.
1147 */
1148int
1149acpi_disabled(char *subsys)
1150{
1151 char *cp;
1152 int len;
1153
1154 if ((cp = getenv("debug.acpi.disable")) == NULL)
1155 return(0);
1156 if (!strcmp(cp, "all"))
1157 return(1);
1158
1159 /* scan the disable list checking for a match */
1160 for (;;) {
1161 while ((*cp != 0) && isspace(*cp))
1162 cp++;
1163 if (*cp == 0)
1164 break;
1165 len = 0;
1166 while ((cp[len] != 0) && !isspace(cp[len]))
1167 len++;
1168 if (!strncmp(cp, subsys, len)) {
1169 DEBUG_PRINT(TRACE_OBJECTS, ("disabled '%s'\n", subsys));
1170 return(1);
1171 }
1172 cp += len;
1173 }
1174 return(0);
1175}
1176
1177/*
1178 * Control interface.
1179 *
1180 * We multiplex ioctls for all participating ACPI devices here. Individual
1181 * drivers wanting to be accessible via /dev/acpi should use the register/deregister
1182 * interface to make their handlers visible.
1183 */
1184struct acpi_ioctl_hook
1185{
1186 TAILQ_ENTRY(acpi_ioctl_hook) link;
1187 u_long cmd;
1188 int (* fn)(u_long cmd, caddr_t addr, void *arg);
1189 void *arg;
1190};
1191
1192static TAILQ_HEAD(,acpi_ioctl_hook) acpi_ioctl_hooks;
1193static int acpi_ioctl_hooks_initted;
1194
1195/*
1196 * Register an ioctl handler.
1197 */
1198int
1199acpi_register_ioctl(u_long cmd, int (* fn)(u_long cmd, caddr_t addr, void *arg), void *arg)
1200{
1201 struct acpi_ioctl_hook *hp;
1202
1203 if ((hp = malloc(sizeof(*hp), M_ACPIDEV, M_NOWAIT)) == NULL)
1204 return(ENOMEM);
1205 hp->cmd = cmd;
1206 hp->fn = fn;
1207 hp->arg = arg;
1208 if (acpi_ioctl_hooks_initted == 0) {
1209 TAILQ_INIT(&acpi_ioctl_hooks);
1210 acpi_ioctl_hooks_initted = 1;
1211 }
1212 TAILQ_INSERT_TAIL(&acpi_ioctl_hooks, hp, link);
1213 return(0);
1214}
1215
1216/*
1217 * Deregister an ioctl handler.
1218 */
1219void
1220acpi_deregister_ioctl(u_long cmd, int (* fn)(u_long cmd, caddr_t addr, void *arg))
1221{
1222 struct acpi_ioctl_hook *hp;
1223
1224 TAILQ_FOREACH(hp, &acpi_ioctl_hooks, link)
1225 if ((hp->cmd == cmd) && (hp->fn == fn))
1226 break;
1227
1228 if (hp != NULL) {
1229 TAILQ_REMOVE(&acpi_ioctl_hooks, hp, link);
1230 free(hp, M_ACPIDEV);
1231 }
1232}
1233
1234static int
1235acpiopen(dev_t dev, int flag, int fmt, struct proc *p)
1236{
1237 return(0);
1238}
1239
1240static int
1241acpiclose(dev_t dev, int flag, int fmt, struct proc *p)
1242{
1243 return(0);
1244}
1245
1246static int
1247acpiioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
1248{
1249 struct acpi_softc *sc;
1250 struct acpi_ioctl_hook *hp;
1251 int error, xerror, state;
1252
1253 error = state = 0;
1254 sc = dev->si_drv1;
1255
1256 /*
1257 * Scan the list of registered ioctls, looking for handlers.
1258 */
1259 if (acpi_ioctl_hooks_initted) {
1260 TAILQ_FOREACH(hp, &acpi_ioctl_hooks, link) {
1261 if (hp->cmd == cmd) {
1262 xerror = hp->fn(cmd, addr, hp->arg);
1263 if (xerror != 0)
1264 error = xerror;
1265 goto out;
1266 }
1267 }
1268 }
1269
1270 /*
1271 * Core system ioctls.
1272 */
1273 switch (cmd) {
1274 case ACPIIO_ENABLE:
1275 if (ACPI_FAILURE(acpi_Enable(sc)))
1276 error = ENXIO;
1277 break;
1278
1279 case ACPIIO_DISABLE:
1280 if (ACPI_FAILURE(acpi_Disable(sc)))
1281 error = ENXIO;
1282 break;
1283
1284 case ACPIIO_SETSLPSTATE:
1285 if (!sc->acpi_enabled) {
1286 error = ENXIO;
1287 break;
1288 }
1289 state = *(int *)addr;
1290 if (state >= ACPI_STATE_S0 && state <= ACPI_S_STATES_MAX) {
1291 acpi_SetSleepState(sc, state);
1292 } else {
1293 error = EINVAL;
1294 }
1295 break;
1296
1297 default:
1298 if (error == 0)
1299 error = EINVAL;
1300 break;
1301 }
1302
1303out:
1304 return(error);
1305}
1306
1307static int
1308acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS)
1309{
1310 char sleep_state[10];
1311 int error;
1312 u_int new_state, old_state;
1313
1314 old_state = *(u_int *)oidp->oid_arg1;
1315 if (old_state > ACPI_S_STATES_MAX)
1316 strcpy(sleep_state, "unknown");
1317 else
1318 strncpy(sleep_state, sleep_state_names[old_state],
1319 sizeof(sleep_state_names[old_state]));
1320 error = sysctl_handle_string(oidp, sleep_state, sizeof(sleep_state), req);
1321 if (error == 0 && req->newptr != NULL) {
1322 for (new_state = ACPI_STATE_S0; new_state <= ACPI_S_STATES_MAX; new_state++)
1323 if (strncmp(sleep_state, sleep_state_names[new_state],
1324 sizeof(sleep_state)) == 0)
1325 break;
1326 if (new_state != old_state && new_state <= ACPI_S_STATES_MAX)
1327 *(u_int *)oidp->oid_arg1 = new_state;
1328 else
1329 error = EINVAL;
1330 }
1331 return(error);
1332}
1333
1334#ifdef ACPI_DEBUG
1335/*
1336 * Support for parsing debug options from the kernel environment.
1337 *
1338 * Bits may be set in the AcpiDbgLayer and AcpiDbgLevel debug registers
1339 * by specifying the names of the bits in the debug.acpi.layer and
1340 * debug.acpi.level environment variables. Bits may be unset by
1341 * prefixing the bit name with !.
1342 */
1343struct debugtag
1344{
1345 char *name;
1346 UINT32 value;
1347};
1348
1349static struct debugtag dbg_layer[] = {
1072 * ACPI Event Handlers
1073 */
1074
1075/* System Event Handlers (registered by EVENTHANDLER_REGISTER) */
1076
1077static void
1078acpi_system_eventhandler_sleep(void *arg, int state)
1079{
1080 FUNCTION_TRACE_U32(__func__, state);
1081
1082 if (state >= ACPI_STATE_S0 && state <= ACPI_S_STATES_MAX)
1083 acpi_SetSleepState((struct acpi_softc *)arg, state);
1084 return_VOID;
1085}
1086
1087static void
1088acpi_system_eventhandler_wakeup(void *arg, int state)
1089{
1090 FUNCTION_TRACE_U32(__func__, state);
1091
1092 /* Well, what to do? :-) */
1093
1094 return_VOID;
1095}
1096
1097/*
1098 * ACPICA Event Handlers (FixedEvent, also called from button notify handler)
1099 */
1100UINT32
1101acpi_eventhandler_power_button_for_sleep(void *context)
1102{
1103 struct acpi_softc *sc = (struct acpi_softc *)context;
1104
1105 FUNCTION_TRACE(__func__);
1106
1107 EVENTHANDLER_INVOKE(acpi_sleep_event, sc->acpi_power_button_sx);
1108
1109 return_VALUE(INTERRUPT_HANDLED);
1110}
1111
1112UINT32
1113acpi_eventhandler_power_button_for_wakeup(void *context)
1114{
1115 struct acpi_softc *sc = (struct acpi_softc *)context;
1116
1117 FUNCTION_TRACE(__func__);
1118
1119 EVENTHANDLER_INVOKE(acpi_wakeup_event, sc->acpi_power_button_sx);
1120
1121 return_VALUE(INTERRUPT_HANDLED);
1122}
1123
1124UINT32
1125acpi_eventhandler_sleep_button_for_sleep(void *context)
1126{
1127 struct acpi_softc *sc = (struct acpi_softc *)context;
1128
1129 FUNCTION_TRACE(__func__);
1130
1131 EVENTHANDLER_INVOKE(acpi_sleep_event, sc->acpi_sleep_button_sx);
1132
1133 return_VALUE(INTERRUPT_HANDLED);
1134}
1135
1136UINT32
1137acpi_eventhandler_sleep_button_for_wakeup(void *context)
1138{
1139 struct acpi_softc *sc = (struct acpi_softc *)context;
1140
1141 FUNCTION_TRACE(__func__);
1142
1143 EVENTHANDLER_INVOKE(acpi_wakeup_event, sc->acpi_sleep_button_sx);
1144
1145 return_VALUE(INTERRUPT_HANDLED);
1146}
1147
1148/*
1149 * XXX This is kinda ugly, and should not be here.
1150 */
1151struct acpi_staticbuf {
1152 ACPI_BUFFER buffer;
1153 char data[512];
1154};
1155
1156char *
1157acpi_strerror(ACPI_STATUS excep)
1158{
1159 static struct acpi_staticbuf buf;
1160
1161 buf.buffer.Length = 512;
1162 buf.buffer.Pointer = &buf.data[0];
1163
1164 if (AcpiFormatException(excep, &buf.buffer) == AE_OK)
1165 return(buf.buffer.Pointer);
1166 return("(error formatting exception)");
1167}
1168
1169char *
1170acpi_name(ACPI_HANDLE handle)
1171{
1172 static struct acpi_staticbuf buf;
1173
1174 buf.buffer.Length = 512;
1175 buf.buffer.Pointer = &buf.data[0];
1176
1177 if (AcpiGetName(handle, ACPI_FULL_PATHNAME, &buf.buffer) == AE_OK)
1178 return(buf.buffer.Pointer);
1179 return("(unknown path)");
1180}
1181
1182/*
1183 * Debugging/bug-avoidance. Avoid trying to fetch info on various
1184 * parts of the namespace.
1185 */
1186int
1187acpi_avoid(ACPI_HANDLE handle)
1188{
1189 char *cp, *np;
1190 int len;
1191
1192 np = acpi_name(handle);
1193 if (*np == '\\')
1194 np++;
1195 if ((cp = getenv("debug.acpi.avoid")) == NULL)
1196 return(0);
1197
1198 /* scan the avoid list checking for a match */
1199 for (;;) {
1200 while ((*cp != 0) && isspace(*cp))
1201 cp++;
1202 if (*cp == 0)
1203 break;
1204 len = 0;
1205 while ((cp[len] != 0) && !isspace(cp[len]))
1206 len++;
1207 if (!strncmp(cp, np, len)) {
1208 DEBUG_PRINT(TRACE_OBJECTS, ("avoiding '%s'\n", np));
1209 return(1);
1210 }
1211 cp += len;
1212 }
1213 return(0);
1214}
1215
1216/*
1217 * Debugging/bug-avoidance. Disable ACPI subsystem components.
1218 */
1219int
1220acpi_disabled(char *subsys)
1221{
1222 char *cp;
1223 int len;
1224
1225 if ((cp = getenv("debug.acpi.disable")) == NULL)
1226 return(0);
1227 if (!strcmp(cp, "all"))
1228 return(1);
1229
1230 /* scan the disable list checking for a match */
1231 for (;;) {
1232 while ((*cp != 0) && isspace(*cp))
1233 cp++;
1234 if (*cp == 0)
1235 break;
1236 len = 0;
1237 while ((cp[len] != 0) && !isspace(cp[len]))
1238 len++;
1239 if (!strncmp(cp, subsys, len)) {
1240 DEBUG_PRINT(TRACE_OBJECTS, ("disabled '%s'\n", subsys));
1241 return(1);
1242 }
1243 cp += len;
1244 }
1245 return(0);
1246}
1247
1248/*
1249 * Control interface.
1250 *
1251 * We multiplex ioctls for all participating ACPI devices here. Individual
1252 * drivers wanting to be accessible via /dev/acpi should use the register/deregister
1253 * interface to make their handlers visible.
1254 */
1255struct acpi_ioctl_hook
1256{
1257 TAILQ_ENTRY(acpi_ioctl_hook) link;
1258 u_long cmd;
1259 int (* fn)(u_long cmd, caddr_t addr, void *arg);
1260 void *arg;
1261};
1262
1263static TAILQ_HEAD(,acpi_ioctl_hook) acpi_ioctl_hooks;
1264static int acpi_ioctl_hooks_initted;
1265
1266/*
1267 * Register an ioctl handler.
1268 */
1269int
1270acpi_register_ioctl(u_long cmd, int (* fn)(u_long cmd, caddr_t addr, void *arg), void *arg)
1271{
1272 struct acpi_ioctl_hook *hp;
1273
1274 if ((hp = malloc(sizeof(*hp), M_ACPIDEV, M_NOWAIT)) == NULL)
1275 return(ENOMEM);
1276 hp->cmd = cmd;
1277 hp->fn = fn;
1278 hp->arg = arg;
1279 if (acpi_ioctl_hooks_initted == 0) {
1280 TAILQ_INIT(&acpi_ioctl_hooks);
1281 acpi_ioctl_hooks_initted = 1;
1282 }
1283 TAILQ_INSERT_TAIL(&acpi_ioctl_hooks, hp, link);
1284 return(0);
1285}
1286
1287/*
1288 * Deregister an ioctl handler.
1289 */
1290void
1291acpi_deregister_ioctl(u_long cmd, int (* fn)(u_long cmd, caddr_t addr, void *arg))
1292{
1293 struct acpi_ioctl_hook *hp;
1294
1295 TAILQ_FOREACH(hp, &acpi_ioctl_hooks, link)
1296 if ((hp->cmd == cmd) && (hp->fn == fn))
1297 break;
1298
1299 if (hp != NULL) {
1300 TAILQ_REMOVE(&acpi_ioctl_hooks, hp, link);
1301 free(hp, M_ACPIDEV);
1302 }
1303}
1304
1305static int
1306acpiopen(dev_t dev, int flag, int fmt, struct proc *p)
1307{
1308 return(0);
1309}
1310
1311static int
1312acpiclose(dev_t dev, int flag, int fmt, struct proc *p)
1313{
1314 return(0);
1315}
1316
1317static int
1318acpiioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
1319{
1320 struct acpi_softc *sc;
1321 struct acpi_ioctl_hook *hp;
1322 int error, xerror, state;
1323
1324 error = state = 0;
1325 sc = dev->si_drv1;
1326
1327 /*
1328 * Scan the list of registered ioctls, looking for handlers.
1329 */
1330 if (acpi_ioctl_hooks_initted) {
1331 TAILQ_FOREACH(hp, &acpi_ioctl_hooks, link) {
1332 if (hp->cmd == cmd) {
1333 xerror = hp->fn(cmd, addr, hp->arg);
1334 if (xerror != 0)
1335 error = xerror;
1336 goto out;
1337 }
1338 }
1339 }
1340
1341 /*
1342 * Core system ioctls.
1343 */
1344 switch (cmd) {
1345 case ACPIIO_ENABLE:
1346 if (ACPI_FAILURE(acpi_Enable(sc)))
1347 error = ENXIO;
1348 break;
1349
1350 case ACPIIO_DISABLE:
1351 if (ACPI_FAILURE(acpi_Disable(sc)))
1352 error = ENXIO;
1353 break;
1354
1355 case ACPIIO_SETSLPSTATE:
1356 if (!sc->acpi_enabled) {
1357 error = ENXIO;
1358 break;
1359 }
1360 state = *(int *)addr;
1361 if (state >= ACPI_STATE_S0 && state <= ACPI_S_STATES_MAX) {
1362 acpi_SetSleepState(sc, state);
1363 } else {
1364 error = EINVAL;
1365 }
1366 break;
1367
1368 default:
1369 if (error == 0)
1370 error = EINVAL;
1371 break;
1372 }
1373
1374out:
1375 return(error);
1376}
1377
1378static int
1379acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS)
1380{
1381 char sleep_state[10];
1382 int error;
1383 u_int new_state, old_state;
1384
1385 old_state = *(u_int *)oidp->oid_arg1;
1386 if (old_state > ACPI_S_STATES_MAX)
1387 strcpy(sleep_state, "unknown");
1388 else
1389 strncpy(sleep_state, sleep_state_names[old_state],
1390 sizeof(sleep_state_names[old_state]));
1391 error = sysctl_handle_string(oidp, sleep_state, sizeof(sleep_state), req);
1392 if (error == 0 && req->newptr != NULL) {
1393 for (new_state = ACPI_STATE_S0; new_state <= ACPI_S_STATES_MAX; new_state++)
1394 if (strncmp(sleep_state, sleep_state_names[new_state],
1395 sizeof(sleep_state)) == 0)
1396 break;
1397 if (new_state != old_state && new_state <= ACPI_S_STATES_MAX)
1398 *(u_int *)oidp->oid_arg1 = new_state;
1399 else
1400 error = EINVAL;
1401 }
1402 return(error);
1403}
1404
1405#ifdef ACPI_DEBUG
1406/*
1407 * Support for parsing debug options from the kernel environment.
1408 *
1409 * Bits may be set in the AcpiDbgLayer and AcpiDbgLevel debug registers
1410 * by specifying the names of the bits in the debug.acpi.layer and
1411 * debug.acpi.level environment variables. Bits may be unset by
1412 * prefixing the bit name with !.
1413 */
1414struct debugtag
1415{
1416 char *name;
1417 UINT32 value;
1418};
1419
1420static struct debugtag dbg_layer[] = {
1350 {"GLOBAL", 0x00000001},
1351 {"COMMON", 0x00000002},
1352 {"PARSER", 0x00000004},
1353 {"DISPATCHER", 0x00000008},
1354 {"INTERPRETER", 0x00000010},
1355 {"NAMESPACE", 0x00000020},
1356 {"RESOURCE_MANAGER", 0x00000040},
1357 {"TABLE_MANAGER", 0x00000080},
1358 {"EVENT_HANDLING", 0x00000100},
1359 {"HARDWARE", 0x00000200},
1360 {"MISCELLANEOUS", 0x00000400},
1361 {"OS_DEPENDENT", 0x00000800},
1362 {"BUS_MANAGER", 0x00001000},
1363 {"PROCESSOR_CONTROL", 0x00002000},
1364 {"SYSTEM_CONTROL", 0x00004000},
1365 {"THERMAL_CONTROL", 0x00008000},
1366 {"POWER_CONTROL", 0x00010000},
1367 {"EMBEDDED_CONTROLLER", 0x00020000},
1368 {"BATTERY", 0x00040000},
1369 {"DEBUGGER", 0x00100000},
1370 {"ALL_COMPONENTS", 0x001FFFFF},
1421 {"ACPI_UTILITIES", ACPI_UTILITIES},
1422 {"ACPI_HARDWARE", ACPI_HARDWARE},
1423 {"ACPI_EVENTS", ACPI_EVENTS},
1424 {"ACPI_TABLES", ACPI_TABLES},
1425 {"ACPI_NAMESPACE", ACPI_NAMESPACE},
1426 {"ACPI_PARSER", ACPI_PARSER},
1427 {"ACPI_DISPATCHER", ACPI_DISPATCHER},
1428 {"ACPI_EXECUTER", ACPI_EXECUTER},
1429 {"ACPI_RESOURCES", ACPI_RESOURCES},
1430 {"ACPI_DEVICES", ACPI_DEVICES},
1431 {"ACPI_POWER", ACPI_POWER},
1432 {"ACPI_BUS_MANAGER", ACPI_BUS_MANAGER},
1433 {"ACPI_POWER_CONTROL", ACPI_POWER_CONTROL},
1434 {"ACPI_EMBEDDED_CONTROLLER", ACPI_EMBEDDED_CONTROLLER},
1435 {"ACPI_PROCESSOR_CONTROL", ACPI_PROCESSOR_CONTROL},
1436 {"ACPI_AC_ADAPTER", ACPI_AC_ADAPTER},
1437 {"ACPI_BATTERY", ACPI_BATTERY},
1438 {"ACPI_BUTTON", ACPI_BUTTON},
1439 {"ACPI_SYSTEM", ACPI_SYSTEM},
1440 {"ACPI_THERMAL_ZONE", ACPI_THERMAL_ZONE},
1441 {"ACPI_DEBUGGER", ACPI_DEBUGGER},
1442 {"ACPI_OS_SERVICES", ACPI_OS_SERVICES},
1443 {"ACPI_ALL_COMPONENTS", ACPI_ALL_COMPONENTS},
1371 {NULL, 0}
1372};
1373
1374static struct debugtag dbg_level[] = {
1444 {NULL, 0}
1445};
1446
1447static struct debugtag dbg_level[] = {
1375 {"ACPI_OK", 0x00000001},
1376 {"ACPI_INFO", 0x00000002},
1377 {"ACPI_WARN", 0x00000004},
1378 {"ACPI_ERROR", 0x00000008},
1379 {"ACPI_FATAL", 0x00000010},
1380 {"ACPI_DEBUG_OBJECT", 0x00000020},
1381 {"ACPI_ALL", 0x0000003F},
1382 {"TRACE_PARSE", 0x00000100},
1383 {"TRACE_DISPATCH", 0x00000200},
1384 {"TRACE_LOAD", 0x00000400},
1385 {"TRACE_EXEC", 0x00000800},
1386 {"TRACE_NAMES", 0x00001000},
1387 {"TRACE_OPREGION", 0x00002000},
1388 {"TRACE_BFIELD", 0x00004000},
1389 {"TRACE_TRASH", 0x00008000},
1390 {"TRACE_TABLES", 0x00010000},
1391 {"TRACE_FUNCTIONS", 0x00020000},
1392 {"TRACE_VALUES", 0x00040000},
1393 {"TRACE_OBJECTS", 0x00080000},
1394 {"TRACE_ALLOCATIONS", 0x00100000},
1395 {"TRACE_RESOURCES", 0x00200000},
1396 {"TRACE_IO", 0x00400000},
1397 {"TRACE_INTERRUPTS", 0x00800000},
1398 {"TRACE_USER_REQUESTS", 0x01000000},
1399 {"TRACE_PACKAGE", 0x02000000},
1400 {"TRACE_MUTEX", 0x04000000},
1401 {"TRACE_ALL", 0x0FFFFF00},
1402 {"VERBOSE_AML_DISASSEMBLE", 0x10000000},
1403 {"VERBOSE_INFO", 0x20000000},
1404 {"VERBOSE_TABLES", 0x40000000},
1405 {"VERBOSE_EVENTS", 0x80000000},
1406 {"VERBOSE_ALL", 0xF0000000},
1448 {"ACPI_OK", ACPI_OK},
1449 {"ACPI_INFO", ACPI_INFO},
1450 {"ACPI_WARN", ACPI_WARN},
1451 {"ACPI_ERROR", ACPI_ERROR},
1452 {"ACPI_FATAL", ACPI_FATAL},
1453 {"ACPI_DEBUG_OBJECT", ACPI_DEBUG_OBJECT},
1454 {"ACPI_ALL", ACPI_ALL},
1455 {"TRACE_THREADS", TRACE_THREADS},
1456 {"TRACE_PARSE", TRACE_PARSE},
1457 {"TRACE_DISPATCH", TRACE_DISPATCH},
1458 {"TRACE_LOAD", TRACE_LOAD},
1459 {"TRACE_EXEC", TRACE_EXEC},
1460 {"TRACE_NAMES", TRACE_NAMES},
1461 {"TRACE_OPREGION", TRACE_OPREGION},
1462 {"TRACE_BFIELD", TRACE_BFIELD},
1463 {"TRACE_TRASH", TRACE_TRASH},
1464 {"TRACE_TABLES", TRACE_TABLES},
1465 {"TRACE_FUNCTIONS", TRACE_FUNCTIONS},
1466 {"TRACE_VALUES", TRACE_VALUES},
1467 {"TRACE_OBJECTS", TRACE_OBJECTS},
1468 {"TRACE_ALLOCATIONS", TRACE_ALLOCATIONS},
1469 {"TRACE_RESOURCES", TRACE_RESOURCES},
1470 {"TRACE_IO", TRACE_IO},
1471 {"TRACE_INTERRUPTS", TRACE_INTERRUPTS},
1472 {"TRACE_USER_REQUESTS", TRACE_USER_REQUESTS},
1473 {"TRACE_PACKAGE", TRACE_PACKAGE},
1474 {"TRACE_MUTEX", TRACE_MUTEX},
1475 {"TRACE_INIT", TRACE_INIT},
1476 {"TRACE_ALL", TRACE_ALL},
1477 {"VERBOSE_AML_DISASSEMBLE", VERBOSE_AML_DISASSEMBLE},
1478 {"VERBOSE_INFO", VERBOSE_INFO},
1479 {"VERBOSE_TABLES", VERBOSE_TABLES},
1480 {"VERBOSE_EVENTS", VERBOSE_EVENTS},
1481 {"VERBOSE_ALL", VERBOSE_ALL},
1407 {NULL, 0}
1408};
1409
1410static void
1411acpi_parse_debug(char *cp, struct debugtag *tag, UINT32 *flag)
1412{
1413 char *ep;
1414 int i, l;
1415 int set;
1416
1417 while (*cp) {
1418 if (isspace(*cp)) {
1419 cp++;
1420 continue;
1421 }
1422 ep = cp;
1423 while (*ep && !isspace(*ep))
1424 ep++;
1425 if (*cp == '!') {
1426 set = 0;
1427 cp++;
1428 if (cp == ep)
1429 continue;
1430 } else {
1431 set = 1;
1432 }
1433 l = ep - cp;
1434 for (i = 0; tag[i].name != NULL; i++) {
1435 if (!strncmp(cp, tag[i].name, l)) {
1436 if (set) {
1437 *flag |= tag[i].value;
1438 } else {
1439 *flag &= ~tag[i].value;
1440 }
1441 printf("ACPI_DEBUG: set '%s'\n", tag[i].name);
1442 }
1443 }
1444 cp = ep;
1445 }
1446}
1447
1448static void
1449acpi_set_debugging(void *junk)
1450{
1451 char *cp;
1452
1453 AcpiDbgLayer = 0;
1454 AcpiDbgLevel = 0;
1455 if ((cp = getenv("debug.acpi.layer")) != NULL)
1456 acpi_parse_debug(cp, &dbg_layer[0], &AcpiDbgLayer);
1457 if ((cp = getenv("debug.acpi.level")) != NULL)
1458 acpi_parse_debug(cp, &dbg_level[0], &AcpiDbgLevel);
1459
1460 printf("ACPI debug layer 0x%x debug level 0x%x\n", AcpiDbgLayer, AcpiDbgLevel);
1461}
1462SYSINIT(acpi_debugging, SI_SUB_TUNABLES, SI_ORDER_ANY, acpi_set_debugging, NULL);
1463#endif
1464
1465/*
1466 * ACPI Battery Abstruction Layer
1467 */
1468
1469struct acpi_batteries {
1470 TAILQ_ENTRY(acpi_batteries) link;
1471 struct acpi_battdesc battdesc;
1472};
1473
1474static TAILQ_HEAD(,acpi_batteries) acpi_batteries;
1475static int acpi_batteries_initted = 0;
1476static int acpi_batteries_units = 0;
1477static struct acpi_battinfo acpi_battery_battinfo;
1478
1479static int
1480acpi_battery_get_units(void)
1481{
1482
1483 return (acpi_batteries_units);
1484}
1485
1486static int
1487acpi_battery_get_battdesc(int logical_unit, struct acpi_battdesc *battdesc)
1488{
1489 int i;
1490 struct acpi_batteries *bp;
1491
1492 if (logical_unit < 0 || logical_unit >= acpi_batteries_units) {
1493 return (ENXIO);
1494 }
1495
1496 i = 0;
1497 TAILQ_FOREACH(bp, &acpi_batteries, link) {
1498 if (logical_unit == i) {
1499 battdesc->type = bp->battdesc.type;
1500 battdesc->phys_unit = bp->battdesc.phys_unit;
1501 return (0);
1502 }
1503 i++;
1504 }
1505
1506 return (ENXIO);
1507}
1508
1509static int
1510acpi_battery_get_battinfo(int unit, struct acpi_battinfo *battinfo)
1511{
1512 int error;
1513 struct acpi_battdesc battdesc;
1514
1515 error = 0;
1516 if (unit == -1) {
1517 error = acpi_cmbat_get_battinfo(-1, battinfo);
1518 goto out;
1519 } else {
1520 if ((error = acpi_battery_get_battdesc(unit, &battdesc)) != 0) {
1521 goto out;
1522 }
1523 switch (battdesc.type) {
1524 case ACPI_BATT_TYPE_CMBAT:
1525 error = acpi_cmbat_get_battinfo(battdesc.phys_unit,
1526 battinfo);
1527 break;
1528 default:
1529 error = ENXIO;
1530 break;
1531 }
1532 }
1533out:
1534 return (error);
1535}
1536
1537static int
1538acpi_battery_ioctl(u_long cmd, caddr_t addr, void *arg)
1539{
1540 int error;
1541 int logical_unit;
1542 union acpi_battery_ioctl_arg *ioctl_arg;
1543
1544 ioctl_arg = (union acpi_battery_ioctl_arg *)addr;
1545 error = 0;
1546 switch (cmd) {
1547 case ACPIIO_BATT_GET_UNITS:
1548 *(int *)addr = acpi_battery_get_units();
1549 break;
1550
1551 case ACPIIO_BATT_GET_BATTDESC:
1552 logical_unit = ioctl_arg->unit;
1553 error = acpi_battery_get_battdesc(logical_unit, &ioctl_arg->battdesc);
1554 break;
1555
1556 case ACPIIO_BATT_GET_BATTINFO:
1557 logical_unit = ioctl_arg->unit;
1558 error = acpi_battery_get_battinfo(logical_unit,
1559 &ioctl_arg->battinfo);
1560 break;
1561
1562 default:
1563 error = EINVAL;
1564 break;
1565 }
1566
1567 return (error);
1568}
1569
1570static int
1571acpi_battery_sysctl(SYSCTL_HANDLER_ARGS)
1572{
1573 int val;
1574 int error;
1575
1576 acpi_battery_get_battinfo(-1, &acpi_battery_battinfo);
1577 val = *(u_int *)oidp->oid_arg1;
1578 error = sysctl_handle_int(oidp, &val, 0, req);
1579 return (error);
1580}
1581
1582static int
1583acpi_battery_init(void)
1584{
1585 device_t dev;
1586 struct acpi_softc *sc;
1587 int error;
1588
1589 if ((dev = devclass_get_device(acpi_devclass, 0)) == NULL) {
1590 return (ENXIO);
1591 }
1592 if ((sc = device_get_softc(dev)) == NULL) {
1593 return (ENXIO);
1594 }
1595
1596 error = 0;
1597
1598 TAILQ_INIT(&acpi_batteries);
1599 acpi_batteries_initted = 1;
1600
1601 if ((error = acpi_register_ioctl(ACPIIO_BATT_GET_UNITS,
1602 acpi_battery_ioctl, NULL)) != 0) {
1603 return (error);
1604 }
1605 if ((error = acpi_register_ioctl(ACPIIO_BATT_GET_BATTDESC,
1606 acpi_battery_ioctl, NULL)) != 0) {
1607 return (error);
1608 }
1609 if ((error = acpi_register_ioctl(ACPIIO_BATT_GET_BATTINFO,
1610 acpi_battery_ioctl, NULL)) != 0) {
1611 return (error);
1612 }
1613
1614 sysctl_ctx_init(&sc->acpi_battery_sysctl_ctx);
1615 sc->acpi_battery_sysctl_tree = SYSCTL_ADD_NODE(&sc->acpi_battery_sysctl_ctx,
1616 SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
1617 OID_AUTO, "battery", CTLFLAG_RD, 0, "");
1618 SYSCTL_ADD_PROC(&sc->acpi_battery_sysctl_ctx,
1619 SYSCTL_CHILDREN(sc->acpi_battery_sysctl_tree),
1620 OID_AUTO, "life", CTLTYPE_INT | CTLFLAG_RD,
1621 &acpi_battery_battinfo.cap, 0, acpi_battery_sysctl, "I", "");
1622 SYSCTL_ADD_PROC(&sc->acpi_battery_sysctl_ctx,
1623 SYSCTL_CHILDREN(sc->acpi_battery_sysctl_tree),
1624 OID_AUTO, "time", CTLTYPE_INT | CTLFLAG_RD,
1625 &acpi_battery_battinfo.min, 0, acpi_battery_sysctl, "I", "");
1626 SYSCTL_ADD_PROC(&sc->acpi_battery_sysctl_ctx,
1627 SYSCTL_CHILDREN(sc->acpi_battery_sysctl_tree),
1628 OID_AUTO, "state", CTLTYPE_INT | CTLFLAG_RD,
1629 &acpi_battery_battinfo.state, 0, acpi_battery_sysctl, "I", "");
1630 SYSCTL_ADD_INT(&sc->acpi_battery_sysctl_ctx,
1631 SYSCTL_CHILDREN(sc->acpi_battery_sysctl_tree),
1632 OID_AUTO, "units", CTLFLAG_RD, &acpi_batteries_units, 0, "");
1633
1634 return (error);
1635}
1636
1637int
1638acpi_battery_register(int type, int phys_unit)
1639{
1640 int error;
1641 struct acpi_batteries *bp;
1642
1643 error = 0;
1644 if ((bp = malloc(sizeof(*bp), M_ACPIDEV, M_NOWAIT)) == NULL) {
1645 return(ENOMEM);
1646 }
1647
1648 bp->battdesc.type = type;
1649 bp->battdesc.phys_unit = phys_unit;
1650 if (acpi_batteries_initted == 0) {
1651 if ((error = acpi_battery_init()) != 0) {
1652 free(bp, M_ACPIDEV);
1653 return(error);
1654 }
1655 }
1656
1657 TAILQ_INSERT_TAIL(&acpi_batteries, bp, link);
1658 acpi_batteries_units++;
1659
1660 return(0);
1661}
1662
1482 {NULL, 0}
1483};
1484
1485static void
1486acpi_parse_debug(char *cp, struct debugtag *tag, UINT32 *flag)
1487{
1488 char *ep;
1489 int i, l;
1490 int set;
1491
1492 while (*cp) {
1493 if (isspace(*cp)) {
1494 cp++;
1495 continue;
1496 }
1497 ep = cp;
1498 while (*ep && !isspace(*ep))
1499 ep++;
1500 if (*cp == '!') {
1501 set = 0;
1502 cp++;
1503 if (cp == ep)
1504 continue;
1505 } else {
1506 set = 1;
1507 }
1508 l = ep - cp;
1509 for (i = 0; tag[i].name != NULL; i++) {
1510 if (!strncmp(cp, tag[i].name, l)) {
1511 if (set) {
1512 *flag |= tag[i].value;
1513 } else {
1514 *flag &= ~tag[i].value;
1515 }
1516 printf("ACPI_DEBUG: set '%s'\n", tag[i].name);
1517 }
1518 }
1519 cp = ep;
1520 }
1521}
1522
1523static void
1524acpi_set_debugging(void *junk)
1525{
1526 char *cp;
1527
1528 AcpiDbgLayer = 0;
1529 AcpiDbgLevel = 0;
1530 if ((cp = getenv("debug.acpi.layer")) != NULL)
1531 acpi_parse_debug(cp, &dbg_layer[0], &AcpiDbgLayer);
1532 if ((cp = getenv("debug.acpi.level")) != NULL)
1533 acpi_parse_debug(cp, &dbg_level[0], &AcpiDbgLevel);
1534
1535 printf("ACPI debug layer 0x%x debug level 0x%x\n", AcpiDbgLayer, AcpiDbgLevel);
1536}
1537SYSINIT(acpi_debugging, SI_SUB_TUNABLES, SI_ORDER_ANY, acpi_set_debugging, NULL);
1538#endif
1539
1540/*
1541 * ACPI Battery Abstruction Layer
1542 */
1543
1544struct acpi_batteries {
1545 TAILQ_ENTRY(acpi_batteries) link;
1546 struct acpi_battdesc battdesc;
1547};
1548
1549static TAILQ_HEAD(,acpi_batteries) acpi_batteries;
1550static int acpi_batteries_initted = 0;
1551static int acpi_batteries_units = 0;
1552static struct acpi_battinfo acpi_battery_battinfo;
1553
1554static int
1555acpi_battery_get_units(void)
1556{
1557
1558 return (acpi_batteries_units);
1559}
1560
1561static int
1562acpi_battery_get_battdesc(int logical_unit, struct acpi_battdesc *battdesc)
1563{
1564 int i;
1565 struct acpi_batteries *bp;
1566
1567 if (logical_unit < 0 || logical_unit >= acpi_batteries_units) {
1568 return (ENXIO);
1569 }
1570
1571 i = 0;
1572 TAILQ_FOREACH(bp, &acpi_batteries, link) {
1573 if (logical_unit == i) {
1574 battdesc->type = bp->battdesc.type;
1575 battdesc->phys_unit = bp->battdesc.phys_unit;
1576 return (0);
1577 }
1578 i++;
1579 }
1580
1581 return (ENXIO);
1582}
1583
1584static int
1585acpi_battery_get_battinfo(int unit, struct acpi_battinfo *battinfo)
1586{
1587 int error;
1588 struct acpi_battdesc battdesc;
1589
1590 error = 0;
1591 if (unit == -1) {
1592 error = acpi_cmbat_get_battinfo(-1, battinfo);
1593 goto out;
1594 } else {
1595 if ((error = acpi_battery_get_battdesc(unit, &battdesc)) != 0) {
1596 goto out;
1597 }
1598 switch (battdesc.type) {
1599 case ACPI_BATT_TYPE_CMBAT:
1600 error = acpi_cmbat_get_battinfo(battdesc.phys_unit,
1601 battinfo);
1602 break;
1603 default:
1604 error = ENXIO;
1605 break;
1606 }
1607 }
1608out:
1609 return (error);
1610}
1611
1612static int
1613acpi_battery_ioctl(u_long cmd, caddr_t addr, void *arg)
1614{
1615 int error;
1616 int logical_unit;
1617 union acpi_battery_ioctl_arg *ioctl_arg;
1618
1619 ioctl_arg = (union acpi_battery_ioctl_arg *)addr;
1620 error = 0;
1621 switch (cmd) {
1622 case ACPIIO_BATT_GET_UNITS:
1623 *(int *)addr = acpi_battery_get_units();
1624 break;
1625
1626 case ACPIIO_BATT_GET_BATTDESC:
1627 logical_unit = ioctl_arg->unit;
1628 error = acpi_battery_get_battdesc(logical_unit, &ioctl_arg->battdesc);
1629 break;
1630
1631 case ACPIIO_BATT_GET_BATTINFO:
1632 logical_unit = ioctl_arg->unit;
1633 error = acpi_battery_get_battinfo(logical_unit,
1634 &ioctl_arg->battinfo);
1635 break;
1636
1637 default:
1638 error = EINVAL;
1639 break;
1640 }
1641
1642 return (error);
1643}
1644
1645static int
1646acpi_battery_sysctl(SYSCTL_HANDLER_ARGS)
1647{
1648 int val;
1649 int error;
1650
1651 acpi_battery_get_battinfo(-1, &acpi_battery_battinfo);
1652 val = *(u_int *)oidp->oid_arg1;
1653 error = sysctl_handle_int(oidp, &val, 0, req);
1654 return (error);
1655}
1656
1657static int
1658acpi_battery_init(void)
1659{
1660 device_t dev;
1661 struct acpi_softc *sc;
1662 int error;
1663
1664 if ((dev = devclass_get_device(acpi_devclass, 0)) == NULL) {
1665 return (ENXIO);
1666 }
1667 if ((sc = device_get_softc(dev)) == NULL) {
1668 return (ENXIO);
1669 }
1670
1671 error = 0;
1672
1673 TAILQ_INIT(&acpi_batteries);
1674 acpi_batteries_initted = 1;
1675
1676 if ((error = acpi_register_ioctl(ACPIIO_BATT_GET_UNITS,
1677 acpi_battery_ioctl, NULL)) != 0) {
1678 return (error);
1679 }
1680 if ((error = acpi_register_ioctl(ACPIIO_BATT_GET_BATTDESC,
1681 acpi_battery_ioctl, NULL)) != 0) {
1682 return (error);
1683 }
1684 if ((error = acpi_register_ioctl(ACPIIO_BATT_GET_BATTINFO,
1685 acpi_battery_ioctl, NULL)) != 0) {
1686 return (error);
1687 }
1688
1689 sysctl_ctx_init(&sc->acpi_battery_sysctl_ctx);
1690 sc->acpi_battery_sysctl_tree = SYSCTL_ADD_NODE(&sc->acpi_battery_sysctl_ctx,
1691 SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
1692 OID_AUTO, "battery", CTLFLAG_RD, 0, "");
1693 SYSCTL_ADD_PROC(&sc->acpi_battery_sysctl_ctx,
1694 SYSCTL_CHILDREN(sc->acpi_battery_sysctl_tree),
1695 OID_AUTO, "life", CTLTYPE_INT | CTLFLAG_RD,
1696 &acpi_battery_battinfo.cap, 0, acpi_battery_sysctl, "I", "");
1697 SYSCTL_ADD_PROC(&sc->acpi_battery_sysctl_ctx,
1698 SYSCTL_CHILDREN(sc->acpi_battery_sysctl_tree),
1699 OID_AUTO, "time", CTLTYPE_INT | CTLFLAG_RD,
1700 &acpi_battery_battinfo.min, 0, acpi_battery_sysctl, "I", "");
1701 SYSCTL_ADD_PROC(&sc->acpi_battery_sysctl_ctx,
1702 SYSCTL_CHILDREN(sc->acpi_battery_sysctl_tree),
1703 OID_AUTO, "state", CTLTYPE_INT | CTLFLAG_RD,
1704 &acpi_battery_battinfo.state, 0, acpi_battery_sysctl, "I", "");
1705 SYSCTL_ADD_INT(&sc->acpi_battery_sysctl_ctx,
1706 SYSCTL_CHILDREN(sc->acpi_battery_sysctl_tree),
1707 OID_AUTO, "units", CTLFLAG_RD, &acpi_batteries_units, 0, "");
1708
1709 return (error);
1710}
1711
1712int
1713acpi_battery_register(int type, int phys_unit)
1714{
1715 int error;
1716 struct acpi_batteries *bp;
1717
1718 error = 0;
1719 if ((bp = malloc(sizeof(*bp), M_ACPIDEV, M_NOWAIT)) == NULL) {
1720 return(ENOMEM);
1721 }
1722
1723 bp->battdesc.type = type;
1724 bp->battdesc.phys_unit = phys_unit;
1725 if (acpi_batteries_initted == 0) {
1726 if ((error = acpi_battery_init()) != 0) {
1727 free(bp, M_ACPIDEV);
1728 return(error);
1729 }
1730 }
1731
1732 TAILQ_INSERT_TAIL(&acpi_batteries, bp, link);
1733 acpi_batteries_units++;
1734
1735 return(0);
1736}
1737