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$ 30 */ 31 32 #include "opt_acpi.h" 33 #include <sys/param.h> 34 #include <sys/kernel.h> 35 #include <sys/malloc.h> 36 #include <sys/mutex.h> 37 #include <sys/bus.h> 38 #include <sys/conf.h> 39 #include <sys/ioccom.h> 40 #include <sys/reboot.h> 41 #include <sys/sysctl.h> 42 #include <sys/ctype.h> 43 44 #include <machine/clock.h> 45 46 #include <machine/resource.h> 47 48 #include "acpi.h" 49 50 #include <dev/acpica/acpivar.h> 51 #include <dev/acpica/acpiio.h> 52 53 MALLOC_DEFINE(M_ACPIDEV, "acpidev", "ACPI devices"); 54 55 /* 56 * Hooks for the ACPI CA debugging infrastructure 57 */ 58 #define _COMPONENT BUS_MANAGER 59 MODULE_NAME("ACPI") 60 61 /* 62 * Character device 63 */ 64 65 static d_open_t acpiopen; 66 static d_close_t acpiclose; 67 static d_ioctl_t acpiioctl; 68 69 #define CDEV_MAJOR 152 70 static struct cdevsw acpi_cdevsw = { 71 acpiopen, 72 acpiclose, 73 noread, 74 nowrite, 75 acpiioctl, 76 nopoll, 77 nommap, 78 nostrategy, 79 "acpi", 80 CDEV_MAJOR, 81 nodump, 82 nopsize, 83 0, 84 -1 85 }; 86 87 static const char* sleep_state_names[] = { 88 "S0", "S1", "S2", "S3", "S4", "S4B", "S5" }; 89 90 static void acpi_identify(driver_t *driver, device_t parent); 91 static int acpi_probe(device_t dev); 92 static int acpi_attach(device_t dev); 93 static device_t acpi_add_child(device_t bus, int order, const char *name, int unit); 94 static int acpi_print_resources(struct resource_list *rl, const char *name, int type, 95 const char *format); 96 static int acpi_print_child(device_t bus, device_t child); 97 static int acpi_read_ivar(device_t dev, device_t child, int index, uintptr_t *result); 98 static int acpi_write_ivar(device_t dev, device_t child, int index, uintptr_t value); 99 static int acpi_set_resource(device_t dev, device_t child, int type, int rid, u_long start, 100 u_long count); 101 static int acpi_get_resource(device_t dev, device_t child, int type, int rid, u_long *startp, 102 u_long *countp); 103 static struct resource *acpi_alloc_resource(device_t bus, device_t child, int type, int *rid, 104 u_long start, u_long end, u_long count, u_int flags); 105 static int acpi_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r); 106 107 static void acpi_probe_children(device_t bus); 108 static ACPI_STATUS acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status); 109 110 static void acpi_shutdown_pre_sync(void *arg, int howto); 111 static void acpi_shutdown_final(void *arg, int howto); 112 113 static void acpi_enable_fixed_events(struct acpi_softc *sc); 114 115 #ifdef ACPI_DEBUG 116 static void acpi_set_debugging(void); 117 #endif 118 119 static void acpi_system_eventhandler_sleep(void *arg, int state); 120 static void acpi_system_eventhandler_wakeup(void *arg, int state); 121 static int acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS); 122 123 static 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 150 static driver_t acpi_driver = { 151 "acpi", 152 acpi_methods, 153 sizeof(struct acpi_softc), 154 }; 155 156 devclass_t acpi_devclass; 157 DRIVER_MODULE(acpi, nexus, acpi_driver, acpi_devclass, 0, 0); 158 159 SYSCTL_INT(_debug, OID_AUTO, acpi_debug_layer, CTLFLAG_RW, &AcpiDbgLayer, 0, ""); 160 SYSCTL_INT(_debug, OID_AUTO, acpi_debug_level, CTLFLAG_RW, &AcpiDbgLevel, 0, ""); 161 162 /* 163 * Detect ACPI, perform early initialisation 164 */ 165 static void 166 acpi_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(__FUNCTION__); 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 #ifdef ACPI_DEBUG 189 acpi_set_debugging(); 190 #endif 191 192 /* 193 * Start up ACPICA 194 */ 195 #ifdef ENABLE_DEBUGGER 196 if (debugpoint && !strcmp(debugpoint, "init")) 197 acpi_EnterDebugger(); 198 #endif 199 if ((error = AcpiInitializeSubsystem()) != AE_OK) { 200 printf("ACPI: initialisation failed: %s\n", acpi_strerror(error)); 201 return_VOID; 202 } 203 #ifdef ENABLE_DEBUGGER 204 if (debugpoint && !strcmp(debugpoint, "tables")) 205 acpi_EnterDebugger(); 206 #endif 207 if (((error = AcpiFindRootPointer(&rsdp)) != AE_OK) || 208 ((error = AcpiLoadTables(rsdp)) != AE_OK)) { 209 printf("ACPI: table load failed: %s\n", acpi_strerror(error)); 210 return_VOID; 211 } 212 213 /* 214 * Attach the actual ACPI device. 215 */ 216 if ((child = BUS_ADD_CHILD(parent, 0, "acpi", 0)) == NULL) { 217 device_printf(parent, "ACPI: could not attach\n"); 218 return_VOID; 219 } 220 } 221 222 /* 223 * Fetch some descriptive data from ACPI to put in our attach message 224 */ 225 static int 226 acpi_probe(device_t dev) 227 { 228 ACPI_TABLE_HEADER th; 229 char buf[20]; 230 int error; 231 232 FUNCTION_TRACE(__FUNCTION__); 233 234 if ((error = AcpiGetTableHeader(ACPI_TABLE_XSDT, 1, &th)) != AE_OK) { 235 device_printf(dev, "couldn't get XSDT header: %s\n", acpi_strerror(error)); 236 return_VALUE(ENXIO); 237 } 238 sprintf(buf, "%.6s %.8s", th.OemId, th.OemTableId); 239 device_set_desc_copy(dev, buf); 240 241 return_VALUE(0); 242 } 243 244 static int 245 acpi_attach(device_t dev) 246 { 247 struct acpi_softc *sc; 248 int error; 249 #ifdef ENABLE_DEBUGGER 250 char *debugpoint = getenv("debug.acpi.debugger"); 251 #endif 252 253 FUNCTION_TRACE(__FUNCTION__); 254 255 sc = device_get_softc(dev); 256 bzero(sc, sizeof(*sc)); 257 sc->acpi_dev = dev; 258 259 #ifdef ENABLE_DEBUGGER 260 if (debugpoint && !strcmp(debugpoint, "spaces")) 261 acpi_EnterDebugger(); 262 #endif 263 264 /* 265 * Install the default address space handlers. 266 */ 267 if ((error = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT, 268 ADDRESS_SPACE_SYSTEM_MEMORY, 269 ACPI_DEFAULT_HANDLER, 270 NULL, NULL)) != AE_OK) { 271 device_printf(dev, "could not initialise SystemMemory handler: %s\n", acpi_strerror(error)); 272 return_VALUE(ENXIO); 273 } 274 if ((error = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT, 275 ADDRESS_SPACE_SYSTEM_IO, 276 ACPI_DEFAULT_HANDLER, 277 NULL, NULL)) != AE_OK) { 278 device_printf(dev, "could not initialise SystemIO handler: %s\n", acpi_strerror(error)); 279 return_VALUE(ENXIO); 280 } 281 if ((error = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT, 282 ADDRESS_SPACE_PCI_CONFIG, 283 ACPI_DEFAULT_HANDLER, 284 NULL, NULL)) != AE_OK) { 285 device_printf(dev, "could not initialise PciConfig handler: %s\n", acpi_strerror(error)); 286 return_VALUE(ENXIO); 287 } 288 289 /* 290 * Bring ACPI fully online. 291 * 292 * Note that we request that device _STA and _INI methods not be run (ACPI_NO_DEVICE_INIT) 293 * and the final object initialisation pass be skipped (ACPI_NO_OBJECT_INIT). 294 * 295 * XXX We need to arrange for the object init pass after we have attached all our 296 * child devices. 297 */ 298 #ifdef ENABLE_DEBUGGER 299 if (debugpoint && !strcmp(debugpoint, "enable")) 300 acpi_EnterDebugger(); 301 #endif 302 if ((error = AcpiEnableSubsystem(ACPI_NO_DEVICE_INIT | ACPI_NO_OBJECT_INIT)) != AE_OK) { 303 device_printf(dev, "could not enable ACPI: %s\n", acpi_strerror(error)); 304 return_VALUE(ENXIO); 305 } 306 307 /* 308 * Setup our sysctl tree. 309 * 310 * XXX: This doesn't check to make sure that none of these fail. 311 */ 312 sysctl_ctx_init(&sc->acpi_sysctl_ctx); 313 sc->acpi_sysctl_tree = SYSCTL_ADD_NODE(&sc->acpi_sysctl_ctx, 314 SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, 315 device_get_name(dev), CTLFLAG_RD, 0, ""); 316 SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), 317 OID_AUTO, "power_button_state", CTLTYPE_STRING | CTLFLAG_RW, 318 &sc->acpi_power_button_sx, 0, acpi_sleep_state_sysctl, "A", ""); 319 SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), 320 OID_AUTO, "sleep_button_state", CTLTYPE_STRING | CTLFLAG_RW, 321 &sc->acpi_sleep_button_sx, 0, acpi_sleep_state_sysctl, "A", ""); 322 SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), 323 OID_AUTO, "lid_switch_state", CTLTYPE_STRING | CTLFLAG_RW, 324 &sc->acpi_lid_switch_sx, 0, acpi_sleep_state_sysctl, "A", ""); 325 326 /* 327 * Dispatch the default sleep state to devices. 328 * TBD: should be configured from userland policy manager. 329 */ 330 sc->acpi_power_button_sx = ACPI_POWER_BUTTON_DEFAULT_SX; 331 sc->acpi_sleep_button_sx = ACPI_SLEEP_BUTTON_DEFAULT_SX; 332 sc->acpi_lid_switch_sx = ACPI_LID_SWITCH_DEFAULT_SX; 333 334 acpi_enable_fixed_events(sc); 335 336 /* 337 * Scan the namespace and attach/initialise children. 338 */ 339 #ifdef ENABLE_DEBUGGER 340 if (debugpoint && !strcmp(debugpoint, "probe")) 341 acpi_EnterDebugger(); 342 #endif 343 if (!acpi_disabled("bus")) 344 acpi_probe_children(dev); 345 346 /* 347 * Register our shutdown handlers 348 */ 349 EVENTHANDLER_REGISTER(shutdown_pre_sync, acpi_shutdown_pre_sync, sc, SHUTDOWN_PRI_LAST); 350 EVENTHANDLER_REGISTER(shutdown_final, acpi_shutdown_final, sc, SHUTDOWN_PRI_LAST); 351 352 /* 353 * Register our acpi event handlers. 354 * XXX should be configurable eg. via userland policy manager. 355 */ 356 EVENTHANDLER_REGISTER(acpi_sleep_event, acpi_system_eventhandler_sleep, sc, ACPI_EVENT_PRI_LAST); 357 EVENTHANDLER_REGISTER(acpi_wakeup_event, acpi_system_eventhandler_wakeup, sc, ACPI_EVENT_PRI_LAST); 358 359 /* 360 * Flag our initial states. 361 */ 362 sc->acpi_enabled = 1; 363 sc->acpi_sstate = ACPI_STATE_S0; 364 365 /* 366 * Create the control device 367 */ 368 sc->acpi_dev_t = make_dev(&acpi_cdevsw, 0, 0, 5, 0660, "acpi"); 369 sc->acpi_dev_t->si_drv1 = sc; 370 371 #ifdef ENABLE_DEBUGGER 372 if (debugpoint && !strcmp(debugpoint, "running")) 373 acpi_EnterDebugger(); 374 #endif 375 return_VALUE(0); 376 } 377 378 /* 379 * Handle a new device being added 380 */ 381 static device_t 382 acpi_add_child(device_t bus, int order, const char *name, int unit) 383 { 384 struct acpi_device *ad; 385 device_t child; 386 387 if ((ad = malloc(sizeof(*ad), M_ACPIDEV, M_NOWAIT)) == NULL) 388 return(NULL); 389 bzero(ad, sizeof(*ad)); 390 391 resource_list_init(&ad->ad_rl); 392 393 child = device_add_child_ordered(bus, order, name, unit); 394 if (child != NULL) 395 device_set_ivars(child, ad); 396 return(child); 397 } 398 399 /* 400 * Print child device resource usage 401 */ 402 static int 403 acpi_print_resources(struct resource_list *rl, const char *name, int type, const char *format) 404 { 405 struct resource_list_entry *rle; 406 int printed, retval; 407 408 printed = 0; 409 retval = 0; 410 411 if (!SLIST_FIRST(rl)) 412 return(0); 413 414 /* Yes, this is kinda cheating */ 415 SLIST_FOREACH(rle, rl, link) { 416 if (rle->type == type) { 417 if (printed == 0) 418 retval += printf(" %s ", name); 419 else if (printed > 0) 420 retval += printf(","); 421 printed++; 422 retval += printf(format, rle->start); 423 if (rle->count > 1) { 424 retval += printf("-"); 425 retval += printf(format, rle->start + 426 rle->count - 1); 427 } 428 } 429 } 430 return(retval); 431 } 432 433 static int 434 acpi_print_child(device_t bus, device_t child) 435 { 436 struct acpi_device *adev = device_get_ivars(child); 437 struct resource_list *rl = &adev->ad_rl; 438 int retval = 0; 439 440 retval += bus_print_child_header(bus, child); 441 retval += acpi_print_resources(rl, "port", SYS_RES_IOPORT, "%#lx"); 442 retval += acpi_print_resources(rl, "iomem", SYS_RES_MEMORY, "%#lx"); 443 retval += acpi_print_resources(rl, "irq", SYS_RES_IRQ, "%ld"); 444 retval += bus_print_child_footer(bus, child); 445 446 return(retval); 447 } 448 449 450 /* 451 * Handle per-device ivars 452 */ 453 static int 454 acpi_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) 455 { 456 struct acpi_device *ad; 457 458 if ((ad = device_get_ivars(child)) == NULL) { 459 printf("device has no ivars\n"); 460 return(ENOENT); 461 } 462 463 switch(index) { 464 /* ACPI ivars */ 465 case ACPI_IVAR_HANDLE: 466 *(ACPI_HANDLE *)result = ad->ad_handle; 467 break; 468 case ACPI_IVAR_MAGIC: 469 *(int *)result = ad->ad_magic; 470 break; 471 case ACPI_IVAR_PRIVATE: 472 *(void **)result = ad->ad_private; 473 break; 474 475 default: 476 panic("bad ivar read request (%d)\n", index); 477 return(ENOENT); 478 } 479 return(0); 480 } 481 482 static int 483 acpi_write_ivar(device_t dev, device_t child, int index, uintptr_t value) 484 { 485 struct acpi_device *ad; 486 487 if ((ad = device_get_ivars(child)) == NULL) { 488 printf("device has no ivars\n"); 489 return(ENOENT); 490 } 491 492 switch(index) { 493 /* ACPI ivars */ 494 case ACPI_IVAR_HANDLE: 495 ad->ad_handle = (ACPI_HANDLE)value; 496 break; 497 case ACPI_IVAR_MAGIC: 498 ad->ad_magic = (int )value; 499 break; 500 case ACPI_IVAR_PRIVATE: 501 ad->ad_private = (void *)value; 502 break; 503 504 default: 505 panic("bad ivar write request (%d)\n", index); 506 return(ENOENT); 507 } 508 return(0); 509 } 510 511 /* 512 * Handle child resource allocation/removal 513 */ 514 static int 515 acpi_set_resource(device_t dev, device_t child, int type, int rid, u_long start, u_long count) 516 { 517 struct acpi_device *ad = device_get_ivars(child); 518 struct resource_list *rl = &ad->ad_rl; 519 520 resource_list_add(rl, type, rid, start, start + count -1, count); 521 522 return(0); 523 } 524 525 static int 526 acpi_get_resource(device_t dev, device_t child, int type, int rid, u_long *startp, u_long *countp) 527 { 528 struct acpi_device *ad = device_get_ivars(child); 529 struct resource_list *rl = &ad->ad_rl; 530 struct resource_list_entry *rle; 531 532 rle = resource_list_find(rl, type, rid); 533 if (!rle) 534 return(ENOENT); 535 536 if (startp) 537 *startp = rle->start; 538 if (countp) 539 *countp = rle->count; 540 541 return(0); 542 } 543 544 static struct resource * 545 acpi_alloc_resource(device_t bus, device_t child, int type, int *rid, 546 u_long start, u_long end, u_long count, u_int flags) 547 { 548 struct acpi_device *ad = device_get_ivars(child); 549 struct resource_list *rl = &ad->ad_rl; 550 551 return(resource_list_alloc(rl, bus, child, type, rid, start, end, count, flags)); 552 } 553 554 static int 555 acpi_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r) 556 { 557 struct acpi_device *ad = device_get_ivars(child); 558 struct resource_list *rl = &ad->ad_rl; 559 560 return(resource_list_release(rl, bus, child, type, rid, r)); 561 } 562 563 /* 564 * Scan relevant portions of the ACPI namespace and attach child devices. 565 * 566 * Note that we only expect to find devices in the \_TZ_, \_SI_ and \_SB_ scopes, 567 * and \_TZ_ becomes obsolete in the ACPI 2.0 spec. 568 */ 569 static void 570 acpi_probe_children(device_t bus) 571 { 572 ACPI_HANDLE parent; 573 static char *scopes[] = {"\\_TZ_", "\\_SI", "\\_SB_", NULL}; 574 int i; 575 576 FUNCTION_TRACE(__FUNCTION__); 577 578 /* 579 * Create any static children by calling device identify methods. 580 */ 581 DEBUG_PRINT(TRACE_OBJECTS, ("device identify routines\n")); 582 bus_generic_probe(bus); 583 584 /* 585 * Scan the namespace and insert placeholders for all the devices that 586 * we find. 587 * 588 * Note that we use AcpiWalkNamespace rather than AcpiGetDevices because 589 * we want to create nodes for all devices, not just those that are currently 590 * present. (This assumes that we don't want to create/remove devices as they 591 * appear, which might be smarter.) 592 */ 593 DEBUG_PRINT(TRACE_OBJECTS, ("namespace scan\n")); 594 for (i = 0; scopes[i] != NULL; i++) 595 if ((AcpiGetHandle(ACPI_ROOT_OBJECT, scopes[i], &parent)) == AE_OK) 596 AcpiWalkNamespace(ACPI_TYPE_ANY, parent, 100, acpi_probe_child, bus, NULL); 597 598 /* 599 * Scan all of the child devices we have created and let them probe/attach. 600 */ 601 DEBUG_PRINT(TRACE_OBJECTS, ("first bus_generic_attach\n")); 602 bus_generic_attach(bus); 603 604 /* 605 * Some of these children may have attached others as part of their attach 606 * process (eg. the root PCI bus driver), so rescan. 607 */ 608 DEBUG_PRINT(TRACE_OBJECTS, ("second bus_generic_attach\n")); 609 bus_generic_attach(bus); 610 611 return_VOID; 612 } 613 614 /* 615 * Evaluate a child device and determine whether we might attach a device to 616 * it. 617 */ 618 static ACPI_STATUS 619 acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status) 620 { 621 ACPI_OBJECT_TYPE type; 622 device_t child, bus = (device_t)context; 623 624 FUNCTION_TRACE(__FUNCTION__); 625 626 /* 627 * Skip this device if we think we'll have trouble with it. 628 */ 629 if (acpi_avoid(handle)) 630 return_ACPI_STATUS(AE_OK); 631 632 if (AcpiGetType(handle, &type) == AE_OK) { 633 switch(type) { 634 case ACPI_TYPE_DEVICE: 635 case ACPI_TYPE_PROCESSOR: 636 case ACPI_TYPE_THERMAL: 637 case ACPI_TYPE_POWER: 638 if (acpi_disabled("children")) 639 break; 640 /* 641 * Create a placeholder device for this node. Sort the placeholder 642 * so that the probe/attach passes will run breadth-first. 643 */ 644 DEBUG_PRINT(TRACE_OBJECTS, ("scanning '%s'\n", acpi_name(handle))) 645 child = BUS_ADD_CHILD(bus, level * 10, NULL, -1); 646 acpi_set_handle(child, handle); 647 DEBUG_EXEC(device_probe_and_attach(child)); 648 break; 649 } 650 } 651 return_ACPI_STATUS(AE_OK); 652 } 653 654 static void 655 acpi_shutdown_pre_sync(void *arg, int howto) 656 { 657 /* 658 * Disable all ACPI events before soft off, otherwise the system 659 * will be turned on again on some laptops. 660 * 661 * XXX this should probably be restricted to masking some events just 662 * before powering down, since we may still need ACPI during the 663 * shutdown process. 664 */ 665 acpi_Disable((struct acpi_softc *)arg); 666 } 667 668 static void 669 acpi_shutdown_final(void *arg, int howto) 670 { 671 ACPI_STATUS status; 672 673 if (howto & RB_POWEROFF) { 674 printf("Power system off using ACPI...\n"); 675 if ((status = AcpiEnterSleepState(ACPI_STATE_S5)) != AE_OK) { 676 printf("ACPI power-off failed - %s\n", acpi_strerror(status)); 677 } else { 678 DELAY(1000000); 679 printf("ACPI power-off failed - timeout\n"); 680 } 681 } 682 } 683 684 static void 685 acpi_enable_fixed_events(struct acpi_softc *sc) 686 { 687 static int first_time = 1; 688 #define MSGFORMAT "%s button is handled as a fixed feature programming model.\n" 689 690 /* Enable and clear fixed events and install handlers. */ 691 if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->PwrButton == 0) { 692 AcpiEnableEvent(ACPI_EVENT_POWER_BUTTON, ACPI_EVENT_FIXED); 693 AcpiClearEvent(ACPI_EVENT_POWER_BUTTON, ACPI_EVENT_FIXED); 694 AcpiInstallFixedEventHandler(ACPI_EVENT_POWER_BUTTON, 695 acpi_eventhandler_power_button_for_sleep, sc); 696 if (first_time) { 697 device_printf(sc->acpi_dev, MSGFORMAT, "power"); 698 } 699 } 700 if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->SleepButton == 0) { 701 AcpiEnableEvent(ACPI_EVENT_SLEEP_BUTTON, ACPI_EVENT_FIXED); 702 AcpiClearEvent(ACPI_EVENT_SLEEP_BUTTON, ACPI_EVENT_FIXED); 703 AcpiInstallFixedEventHandler(ACPI_EVENT_SLEEP_BUTTON, 704 acpi_eventhandler_sleep_button_for_sleep, sc); 705 if (first_time) { 706 device_printf(sc->acpi_dev, MSGFORMAT, "sleep"); 707 } 708 } 709 710 first_time = 0; 711 } 712 713 /* 714 * Match a HID string against a device 715 */ 716 BOOLEAN 717 acpi_MatchHid(device_t dev, char *hid) 718 { 719 ACPI_HANDLE h; 720 ACPI_DEVICE_INFO devinfo; 721 ACPI_STATUS error; 722 723 if (hid == NULL) 724 return(FALSE); 725 if ((h = acpi_get_handle(dev)) == NULL) 726 return(FALSE); 727 if ((error = AcpiGetObjectInfo(h, &devinfo)) != AE_OK) 728 return(FALSE); 729 if ((devinfo.Valid & ACPI_VALID_HID) && !strcmp(hid, devinfo.HardwareId)) 730 return(TRUE); 731 return(FALSE); 732 } 733 734 /* 735 * Perform the tedious double-get procedure required for fetching something into 736 * an ACPI_BUFFER that has not been initialised. 737 */ 738 ACPI_STATUS 739 acpi_GetIntoBuffer(ACPI_HANDLE handle, ACPI_STATUS (*func)(ACPI_HANDLE, ACPI_BUFFER *), ACPI_BUFFER *buf) 740 { 741 ACPI_STATUS status; 742 743 buf->Length = 0; 744 buf->Pointer = NULL; 745 746 if ((status = func(handle, buf)) != AE_BUFFER_OVERFLOW) 747 return(status); 748 if ((buf->Pointer = AcpiOsCallocate(buf->Length)) == NULL) 749 return(AE_NO_MEMORY); 750 return(func(handle, buf)); 751 } 752 753 /* 754 * Allocate a buffer with a preset data size. 755 */ 756 ACPI_BUFFER * 757 acpi_AllocBuffer(int size) 758 { 759 ACPI_BUFFER *buf; 760 761 if ((buf = malloc(size + sizeof(*buf), M_ACPIDEV, M_NOWAIT)) == NULL) 762 return(NULL); 763 buf->Length = size; 764 buf->Pointer = (void *)(buf + 1); 765 return(buf); 766 } 767 768 /* 769 * Set the system sleep state 770 * 771 * Currently we only support S1 and S5 772 */ 773 ACPI_STATUS 774 acpi_SetSleepState(struct acpi_softc *sc, int state) 775 { 776 ACPI_STATUS status = AE_OK; 777 778 FUNCTION_TRACE_U32(__FUNCTION__, state); 779 780 switch (state) { 781 case ACPI_STATE_S0: /* XXX only for testing */ 782 status = AcpiEnterSleepState((UINT8)state); 783 if (status != AE_OK) { 784 device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n", acpi_strerror(status)); 785 } 786 break; 787 788 case ACPI_STATE_S1: 789 /* 790 * Inform all devices that we are going to sleep. 791 */ 792 if (DEVICE_SUSPEND(root_bus) != 0) { 793 /* 794 * Re-wake the system. 795 * 796 * XXX note that a better two-pass approach with a 'veto' pass 797 * followed by a "real thing" pass would be better, but the 798 * current bus interface does not provide for this. 799 */ 800 DEVICE_RESUME(root_bus); 801 return_ACPI_STATUS(AE_ERROR); 802 } 803 sc->acpi_sstate = state; 804 status = AcpiEnterSleepState((UINT8)state); 805 if (status != AE_OK) { 806 device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n", acpi_strerror(status)); 807 } 808 DEVICE_RESUME(root_bus); 809 sc->acpi_sstate = ACPI_STATE_S0; 810 acpi_enable_fixed_events(sc); 811 break; 812 813 case ACPI_STATE_S5: 814 /* 815 * Shut down cleanly and power off. This will call us back through the 816 * shutdown handlers. 817 */ 818 shutdown_nice(RB_POWEROFF); 819 break; 820 821 default: 822 status = AE_BAD_PARAMETER; 823 break; 824 } 825 return_ACPI_STATUS(status); 826 } 827 828 /* 829 * Enable/Disable ACPI 830 */ 831 ACPI_STATUS 832 acpi_Enable(struct acpi_softc *sc) 833 { 834 ACPI_STATUS status; 835 u_int32_t flags; 836 837 FUNCTION_TRACE(__FUNCTION__); 838 839 flags = ACPI_NO_ADDRESS_SPACE_INIT | ACPI_NO_HARDWARE_INIT | 840 ACPI_NO_DEVICE_INIT | ACPI_NO_OBJECT_INIT; 841 if (!sc->acpi_enabled) { 842 status = AcpiEnableSubsystem(flags); 843 } else { 844 status = AE_OK; 845 } 846 if (status == AE_OK) 847 sc->acpi_enabled = 1; 848 return_ACPI_STATUS(status); 849 } 850 851 ACPI_STATUS 852 acpi_Disable(struct acpi_softc *sc) 853 { 854 ACPI_STATUS status; 855 856 FUNCTION_TRACE(__FUNCTION__); 857 858 if (sc->acpi_enabled) { 859 status = AcpiDisable(); 860 } else { 861 status = AE_OK; 862 } 863 if (status == AE_OK) 864 sc->acpi_enabled = 0; 865 return_ACPI_STATUS(status); 866 } 867 868 /* 869 * Returns true if the device is actually present and should 870 * be attached to. This requires the present, enabled, UI-visible 871 * and diagnostics-passed bits to be set. 872 */ 873 BOOLEAN 874 acpi_DeviceIsPresent(device_t dev) 875 { 876 ACPI_HANDLE h; 877 ACPI_DEVICE_INFO devinfo; 878 ACPI_STATUS error; 879 880 if ((h = acpi_get_handle(dev)) == NULL) 881 return(FALSE); 882 if ((error = AcpiGetObjectInfo(h, &devinfo)) != AE_OK) 883 return(FALSE); 884 if ((devinfo.Valid & ACPI_VALID_HID) && (devinfo.CurrentStatus & 0xf)) 885 return(TRUE); 886 return(FALSE); 887 } 888 889 /* 890 * Evaluate a path that should return an integer. 891 */ 892 ACPI_STATUS 893 acpi_EvaluateInteger(ACPI_HANDLE handle, char *path, int *number) 894 { 895 ACPI_STATUS error; 896 ACPI_BUFFER buf; 897 ACPI_OBJECT param; 898 899 if (handle == NULL) 900 handle = ACPI_ROOT_OBJECT; 901 buf.Pointer = ¶m; 902 buf.Length = sizeof(param); 903 if ((error = AcpiEvaluateObject(handle, path, NULL, &buf)) == AE_OK) { 904 if (param.Type == ACPI_TYPE_INTEGER) { 905 *number = param.Integer.Value; 906 } else { 907 error = AE_TYPE; 908 } 909 } 910 return(error); 911 } 912 913 /* 914 * ACPI Event Handlers 915 */ 916 917 /* System Event Handlers (registered by EVENTHANDLER_REGISTER) */ 918 919 static void 920 acpi_system_eventhandler_sleep(void *arg, int state) 921 { 922 FUNCTION_TRACE_U32(__FUNCTION__, state); 923 924 if (state >= ACPI_STATE_S0 && state <= ACPI_STATE_S5) 925 acpi_SetSleepState((struct acpi_softc *)arg, state); 926 return_VOID; 927 } 928 929 static void 930 acpi_system_eventhandler_wakeup(void *arg, int state) 931 { 932 FUNCTION_TRACE_U32(__FUNCTION__, state); 933 934 /* Well, what to do? :-) */ 935 936 return_VOID; 937 } 938 939 /* 940 * ACPICA Event Handlers (FixedEvent, also called from button notify handler) 941 */ 942 UINT32 943 acpi_eventhandler_power_button_for_sleep(void *context) 944 { 945 struct acpi_softc *sc = (struct acpi_softc *)context; 946 947 FUNCTION_TRACE(__FUNCTION__); 948 949 EVENTHANDLER_INVOKE(acpi_sleep_event, sc->acpi_power_button_sx); 950 951 return_VALUE(INTERRUPT_HANDLED); 952 } 953 954 UINT32 955 acpi_eventhandler_power_button_for_wakeup(void *context) 956 { 957 struct acpi_softc *sc = (struct acpi_softc *)context; 958 959 FUNCTION_TRACE(__FUNCTION__); 960 961 EVENTHANDLER_INVOKE(acpi_wakeup_event, sc->acpi_power_button_sx); 962 963 return_VALUE(INTERRUPT_HANDLED); 964 } 965 966 UINT32 967 acpi_eventhandler_sleep_button_for_sleep(void *context) 968 { 969 struct acpi_softc *sc = (struct acpi_softc *)context; 970 971 FUNCTION_TRACE(__FUNCTION__); 972 973 EVENTHANDLER_INVOKE(acpi_sleep_event, sc->acpi_sleep_button_sx); 974 975 return_VALUE(INTERRUPT_HANDLED); 976 } 977 978 UINT32 979 acpi_eventhandler_sleep_button_for_wakeup(void *context) 980 { 981 struct acpi_softc *sc = (struct acpi_softc *)context; 982 983 FUNCTION_TRACE(__FUNCTION__); 984 985 EVENTHANDLER_INVOKE(acpi_wakeup_event, sc->acpi_sleep_button_sx); 986 987 return_VALUE(INTERRUPT_HANDLED); 988 } 989 990 /* 991 * XXX This is kinda ugly, and should not be here. 992 */ 993 struct acpi_staticbuf { 994 ACPI_BUFFER buffer; 995 char data[512]; 996 }; 997 998 char * 999 acpi_strerror(ACPI_STATUS excep) 1000 { 1001 static struct acpi_staticbuf buf; 1002 1003 buf.buffer.Length = 512; 1004 buf.buffer.Pointer = &buf.data[0]; 1005 1006 if (AcpiFormatException(excep, &buf.buffer) == AE_OK) 1007 return(buf.buffer.Pointer); 1008 return("(error formatting exception)"); 1009 } 1010 1011 char * 1012 acpi_name(ACPI_HANDLE handle) 1013 { 1014 static struct acpi_staticbuf buf; 1015 1016 buf.buffer.Length = 512; 1017 buf.buffer.Pointer = &buf.data[0]; 1018 1019 if (AcpiGetName(handle, ACPI_FULL_PATHNAME, &buf.buffer) == AE_OK) 1020 return(buf.buffer.Pointer); 1021 return("(unknown path)"); 1022 } 1023 1024 /* 1025 * Debugging/bug-avoidance. Avoid trying to fetch info on various 1026 * parts of the namespace. 1027 */ 1028 int 1029 acpi_avoid(ACPI_HANDLE handle) 1030 { 1031 char *cp, *np; 1032 int len; 1033 1034 np = acpi_name(handle); 1035 if (*np == '\\') 1036 np++; 1037 if ((cp = getenv("debug.acpi.avoid")) == NULL) 1038 return(0); 1039 1040 /* scan the avoid list checking for a match */ 1041 for (;;) { 1042 while ((*cp != 0) && isspace(*cp)) 1043 cp++; 1044 if (*cp == 0) 1045 break; 1046 len = 0; 1047 while ((cp[len] != 0) && !isspace(cp[len])) 1048 len++; 1049 if (!strncmp(cp, np, len)) { 1050 DEBUG_PRINT(TRACE_OBJECTS, ("avoiding '%s'\n", np)); 1051 return(1); 1052 } 1053 cp += len; 1054 } 1055 return(0); 1056 } 1057 1058 /* 1059 * Debugging/bug-avoidance. Disable ACPI subsystem components. 1060 */ 1061 int 1062 acpi_disabled(char *subsys) 1063 { 1064 char *cp; 1065 int len; 1066 1067 if ((cp = getenv("debug.acpi.disable")) == NULL) 1068 return(0); 1069 if (!strcmp(cp, "all")) 1070 return(1); 1071 1072 /* scan the disable list checking for a match */ 1073 for (;;) { 1074 while ((*cp != 0) && isspace(*cp)) 1075 cp++; 1076 if (*cp == 0) 1077 break; 1078 len = 0; 1079 while ((cp[len] != 0) && !isspace(cp[len])) 1080 len++; 1081 if (!strncmp(cp, subsys, len)) { 1082 DEBUG_PRINT(TRACE_OBJECTS, ("disabled '%s'\n", subsys)); 1083 return(1); 1084 } 1085 cp += len; 1086 } 1087 return(0); 1088 } 1089 1090 /* 1091 * Control interface. 1092 * 1093 * We multiplex ioctls for all participating ACPI devices here. Individual 1094 * drivers wanting to be accessible via /dev/acpi should use the register/deregister 1095 * interface to make their handlers visible. 1096 */ 1097 struct acpi_ioctl_hook 1098 { 1099 TAILQ_ENTRY(acpi_ioctl_hook) link; 1100 u_long cmd; 1101 int (* fn)(u_long cmd, caddr_t addr, void *arg); 1102 void *arg; 1103 }; 1104 1105 static TAILQ_HEAD(,acpi_ioctl_hook) acpi_ioctl_hooks; 1106 static int acpi_ioctl_hooks_initted; 1107 1108 /* 1109 * Register an ioctl handler. 1110 */ 1111 int 1112 acpi_register_ioctl(u_long cmd, int (* fn)(u_long cmd, caddr_t addr, void *arg), void *arg) 1113 { 1114 struct acpi_ioctl_hook *hp; 1115 1116 if ((hp = malloc(sizeof(*hp), M_ACPIDEV, M_NOWAIT)) == NULL) 1117 return(ENOMEM); 1118 hp->cmd = cmd; 1119 hp->fn = fn; 1120 hp->arg = arg; 1121 if (acpi_ioctl_hooks_initted == 0) { 1122 TAILQ_INIT(&acpi_ioctl_hooks); 1123 acpi_ioctl_hooks_initted = 1; 1124 } 1125 TAILQ_INSERT_TAIL(&acpi_ioctl_hooks, hp, link); 1126 return(0); 1127 } 1128 1129 /* 1130 * Deregister an ioctl handler. 1131 */ 1132 void 1133 acpi_deregister_ioctl(u_long cmd, int (* fn)(u_long cmd, caddr_t addr, void *arg)) 1134 { 1135 struct acpi_ioctl_hook *hp; 1136 1137 TAILQ_FOREACH(hp, &acpi_ioctl_hooks, link) 1138 if ((hp->cmd == cmd) && (hp->fn == fn)) 1139 break; 1140 1141 if (hp != NULL) { 1142 TAILQ_REMOVE(&acpi_ioctl_hooks, hp, link); 1143 free(hp, M_ACPIDEV); 1144 } 1145 } 1146 1147 static int 1148 acpiopen(dev_t dev, int flag, int fmt, struct proc *p) 1149 { 1150 return(0); 1151 } 1152 1153 static int 1154 acpiclose(dev_t dev, int flag, int fmt, struct proc *p) 1155 { 1156 return(0); 1157 } 1158 1159 static int 1160 acpiioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) 1161 { 1162 struct acpi_softc *sc; 1163 struct acpi_ioctl_hook *hp; 1164 int error, xerror, state; 1165 1166 error = state = 0; 1167 sc = dev->si_drv1; 1168 1169 /* 1170 * Scan the list of registered ioctls, looking for handlers. 1171 */ 1172 if (acpi_ioctl_hooks_initted) { 1173 TAILQ_FOREACH(hp, &acpi_ioctl_hooks, link) { 1174 if (hp->cmd == cmd) { 1175 xerror = hp->fn(cmd, addr, hp->arg); 1176 if (xerror != 0) 1177 error = xerror; 1178 goto out; 1179 } 1180 } 1181 } 1182 1183 /* 1184 * Core system ioctls. 1185 */ 1186 switch (cmd) { 1187 case ACPIIO_ENABLE: 1188 if (ACPI_FAILURE(acpi_Enable(sc))) 1189 error = ENXIO; 1190 break; 1191 1192 case ACPIIO_DISABLE: 1193 if (ACPI_FAILURE(acpi_Disable(sc))) 1194 error = ENXIO; 1195 break; 1196 1197 case ACPIIO_SETSLPSTATE: 1198 if (!sc->acpi_enabled) { 1199 error = ENXIO; 1200 break; 1201 } 1202 state = *(int *)addr; 1203 if (state >= ACPI_STATE_S0 && state <= ACPI_STATE_S5) { 1204 acpi_SetSleepState(sc, state); 1205 } else { 1206 error = EINVAL; 1207 } 1208 break; 1209 1210 default: 1211 if (error == 0) 1212 error = EINVAL; 1213 break; 1214 } 1215 1216 out: 1217 return(error); 1218 } 1219 1220 static int 1221 acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS) 1222 { 1223 char sleep_state[10]; 1224 int error; 1225 u_int new_state, old_state; 1226 1227 old_state = *(u_int *)oidp->oid_arg1; 1228 if (old_state > ACPI_STATE_S5) 1229 strcpy(sleep_state, "unknown"); 1230 else 1231 strncpy(sleep_state, sleep_state_names[old_state], 1232 sizeof(sleep_state_names[old_state])); 1233 error = sysctl_handle_string(oidp, sleep_state, sizeof(sleep_state), req); 1234 if (error == 0 && req->newptr != NULL) { 1235 for (new_state = ACPI_STATE_S0; new_state <= ACPI_STATE_S5; new_state++) 1236 if (strncmp(sleep_state, sleep_state_names[new_state], 1237 sizeof(sleep_state)) == 0) 1238 break; 1239 if (new_state != old_state && new_state <= ACPI_STATE_S5) 1240 *(u_int *)oidp->oid_arg1 = new_state; 1241 else 1242 error = EINVAL; 1243 } 1244 return(error); 1245 } 1246 1247 #ifdef ACPI_DEBUG 1248 /* 1249 * Support for parsing debug options from the kernel environment. 1250 * 1251 * Bits may be set in the AcpiDbgLayer and AcpiDbgLevel debug registers 1252 * by specifying the names of the bits in the debug.acpi.layer and 1253 * debug.acpi.level environment variables. Bits may be unset by 1254 * prefixing the bit name with !. 1255 */ 1256 struct debugtag 1257 { 1258 char *name; 1259 UINT32 value; 1260 }; 1261 1262 static struct debugtag dbg_layer[] = { 1263 {"GLOBAL", 0x00000001}, 1264 {"COMMON", 0x00000002}, 1265 {"PARSER", 0x00000004}, 1266 {"DISPATCHER", 0x00000008}, 1267 {"INTERPRETER", 0x00000010}, 1268 {"NAMESPACE", 0x00000020}, 1269 {"RESOURCE_MANAGER", 0x00000040}, 1270 {"TABLE_MANAGER", 0x00000080}, 1271 {"EVENT_HANDLING", 0x00000100}, 1272 {"HARDWARE", 0x00000200}, 1273 {"MISCELLANEOUS", 0x00000400}, 1274 {"OS_DEPENDENT", 0x00000800}, 1275 {"BUS_MANAGER", 0x00001000}, 1276 {"PROCESSOR_CONTROL", 0x00002000}, 1277 {"SYSTEM_CONTROL", 0x00004000}, 1278 {"THERMAL_CONTROL", 0x00008000}, 1279 {"POWER_CONTROL", 0x00010000}, 1280 {"EMBEDDED_CONTROLLER", 0x00020000}, 1281 {"BATTERY", 0x00040000}, 1282 {"DEBUGGER", 0x00100000}, 1283 {"ALL_COMPONENTS", 0x001FFFFF}, 1284 {NULL, 0} 1285 }; 1286 1287 static struct debugtag dbg_level[] = { 1288 {"ACPI_OK", 0x00000001}, 1289 {"ACPI_INFO", 0x00000002}, 1290 {"ACPI_WARN", 0x00000004}, 1291 {"ACPI_ERROR", 0x00000008}, 1292 {"ACPI_FATAL", 0x00000010}, 1293 {"ACPI_DEBUG_OBJECT", 0x00000020}, 1294 {"ACPI_ALL", 0x0000003F}, 1295 {"TRACE_PARSE", 0x00000100}, 1296 {"TRACE_DISPATCH", 0x00000200}, 1297 {"TRACE_LOAD", 0x00000400}, 1298 {"TRACE_EXEC", 0x00000800}, 1299 {"TRACE_NAMES", 0x00001000}, 1300 {"TRACE_OPREGION", 0x00002000}, 1301 {"TRACE_BFIELD", 0x00004000}, 1302 {"TRACE_TRASH", 0x00008000}, 1303 {"TRACE_TABLES", 0x00010000}, 1304 {"TRACE_FUNCTIONS", 0x00020000}, 1305 {"TRACE_VALUES", 0x00040000}, 1306 {"TRACE_OBJECTS", 0x00080000}, 1307 {"TRACE_ALLOCATIONS", 0x00100000}, 1308 {"TRACE_RESOURCES", 0x00200000}, 1309 {"TRACE_IO", 0x00400000}, 1310 {"TRACE_INTERRUPTS", 0x00800000}, 1311 {"TRACE_USER_REQUESTS", 0x01000000}, 1312 {"TRACE_PACKAGE", 0x02000000}, 1313 {"TRACE_MUTEX", 0x04000000}, 1314 {"TRACE_ALL", 0x0FFFFF00}, 1315 {"VERBOSE_AML_DISASSEMBLE", 0x10000000}, 1316 {"VERBOSE_INFO", 0x20000000}, 1317 {"VERBOSE_TABLES", 0x40000000}, 1318 {"VERBOSE_EVENTS", 0x80000000}, 1319 {"VERBOSE_ALL", 0xF0000000}, 1320 {NULL, 0} 1321 }; 1322 1323 static void 1324 acpi_parse_debug(char *cp, struct debugtag *tag, UINT32 *flag) 1325 { 1326 char *ep; 1327 int i, l; 1328 int set; 1329 1330 while (*cp) { 1331 if (isspace(*cp)) { 1332 cp++; 1333 continue; 1334 } 1335 ep = cp; 1336 while (*ep && !isspace(*ep)) 1337 ep++; 1338 if (*cp == '!') { 1339 set = 0; 1340 cp++; 1341 if (cp == ep) 1342 continue; 1343 } else { 1344 set = 1; 1345 } 1346 l = ep - cp; 1347 for (i = 0; tag[i].name != NULL; i++) { 1348 if (!strncmp(cp, tag[i].name, l)) { 1349 if (set) { 1350 *flag |= tag[i].value; 1351 } else { 1352 *flag &= ~tag[i].value; 1353 } 1354 printf("ACPI_DEBUG: set '%s'\n", tag[i].name); 1355 } 1356 } 1357 cp = ep; 1358 } 1359 } 1360 1361 static void 1362 acpi_set_debugging(void) 1363 { 1364 char *cp; 1365 1366 AcpiDbgLayer = 0; 1367 AcpiDbgLevel = 0; 1368 if ((cp = getenv("debug.acpi.layer")) != NULL) 1369 acpi_parse_debug(cp, &dbg_layer[0], &AcpiDbgLayer); 1370 if ((cp = getenv("debug.acpi.level")) != NULL) 1371 acpi_parse_debug(cp, &dbg_level[0], &AcpiDbgLevel); 1372 1373 printf("ACPI debug layer 0x%x debug level 0x%x\n", AcpiDbgLayer, AcpiDbgLevel); 1374 } 1375 #endif 1376