1 /* $NetBSD: acpi.c,v 1.36 2003/05/15 21:29:49 fvdl Exp $ */ 2 3 /* 4 * Copyright 2001, 2003 Wasabi Systems, Inc. 5 * All rights reserved. 6 * 7 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed for the NetBSD Project by 20 * Wasabi Systems, Inc. 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 * or promote products derived from this software without specific prior 23 * written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38 /* 39 * Autoconfiguration support for the Intel ACPI Component Architecture 40 * ACPI reference implementation. 41 */ 42 43 #include <sys/cdefs.h> 44 __KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.36 2003/05/15 21:29:49 fvdl Exp $"); 45 46 #include "opt_acpi.h" 47 48 #include <sys/param.h> 49 #include <sys/systm.h> 50 #include <sys/device.h> 51 #include <sys/malloc.h> 52 #include <sys/kernel.h> 53 #include <sys/proc.h> 54 55 #include <dev/acpi/acpica.h> 56 #include <dev/acpi/acpireg.h> 57 #include <dev/acpi/acpivar.h> 58 #include <dev/acpi/acpi_osd.h> 59 #ifdef ACPIVERBOSE 60 #include <dev/acpi/acpidevs_data.h> 61 #endif 62 63 #ifndef ACPI_ACTIVATE_DEV 64 #define ACPI_ACTIVATE_DEV 0 65 #endif 66 67 #ifdef ACPI_PCI_FIXUP 68 #include <dev/acpi/acpica/Subsystem/acnamesp.h> /* AcpiNsGetNodeByPath() */ 69 #include <dev/pci/pcidevs.h> 70 #endif 71 72 MALLOC_DECLARE(M_ACPI); 73 74 #include <machine/acpi_machdep.h> 75 76 #ifdef ENABLE_DEBUGGER 77 #define ACPI_DBGR_INIT 0x01 78 #define ACPI_DBGR_TABLES 0x02 79 #define ACPI_DBGR_ENABLE 0x04 80 #define ACPI_DBGR_PROBE 0x08 81 #define ACPI_DBGR_RUNNING 0x10 82 83 int acpi_dbgr = 0x00; 84 #endif 85 86 int acpi_match(struct device *, struct cfdata *, void *); 87 void acpi_attach(struct device *, struct device *, void *); 88 89 int acpi_print(void *aux, const char *); 90 91 extern struct cfdriver acpi_cd; 92 93 CFATTACH_DECL(acpi, sizeof(struct acpi_softc), 94 acpi_match, acpi_attach, NULL, NULL); 95 96 /* 97 * This is a flag we set when the ACPI subsystem is active. Machine 98 * dependent code may wish to skip other steps (such as attaching 99 * subsystems that ACPI supercedes) when ACPI is active. 100 */ 101 int acpi_active; 102 103 /* 104 * Pointer to the ACPI subsystem's state. There can be only 105 * one ACPI instance. 106 */ 107 struct acpi_softc *acpi_softc; 108 109 /* 110 * Locking stuff. 111 */ 112 static struct simplelock acpi_slock; 113 static int acpi_locked; 114 115 /* 116 * Prototypes. 117 */ 118 void acpi_shutdown(void *); 119 ACPI_STATUS acpi_disable(struct acpi_softc *sc); 120 void acpi_build_tree(struct acpi_softc *); 121 ACPI_STATUS acpi_make_devnode(ACPI_HANDLE, UINT32, void *, void **); 122 123 void acpi_enable_fixed_events(struct acpi_softc *); 124 #ifdef ACPI_PCI_FIXUP 125 void acpi_pci_fixup(struct acpi_softc *); 126 #endif 127 #if defined(ACPI_PCI_FIXUP) || ACPI_ACTIVATE_DEV 128 ACPI_STATUS acpi_allocate_resources(ACPI_HANDLE handle); 129 #endif 130 131 /* 132 * acpi_probe: 133 * 134 * Probe for ACPI support. This is called by the 135 * machine-dependent ACPI front-end. All of the 136 * actual work is done by ACPICA. 137 * 138 * NOTE: This is not an autoconfiguration interface function. 139 */ 140 int 141 acpi_probe(void) 142 { 143 static int beenhere; 144 ACPI_STATUS rv; 145 146 if (beenhere != 0) 147 panic("acpi_probe: ACPI has already been probed"); 148 beenhere = 1; 149 150 simple_lock_init(&acpi_slock); 151 acpi_locked = 0; 152 153 /* 154 * Start up ACPICA. 155 */ 156 #ifdef ENABLE_DEBUGGER 157 if (acpi_dbgr & ACPI_DBGR_INIT) 158 acpi_osd_debugger(); 159 #endif 160 161 rv = AcpiInitializeSubsystem(); 162 if (rv != AE_OK) { 163 printf("ACPI: unable to initialize ACPICA: %d\n", rv); 164 return (0); 165 } 166 167 #ifdef ENABLE_DEBUGGER 168 if (acpi_dbgr & ACPI_DBGR_TABLES) 169 acpi_osd_debugger(); 170 #endif 171 172 rv = AcpiLoadTables(); 173 if (rv != AE_OK) { 174 printf("ACPI: unable to load tables: %d\n", rv); 175 return (0); 176 } 177 178 /* 179 * Looks like we have ACPI! 180 */ 181 182 return (1); 183 } 184 185 /* 186 * acpi_match: 187 * 188 * Autoconfiguration `match' routine. 189 */ 190 int 191 acpi_match(struct device *parent, struct cfdata *match, void *aux) 192 { 193 struct acpibus_attach_args *aa = aux; 194 195 if (strcmp(aa->aa_busname, acpi_cd.cd_name) != 0) 196 return (0); 197 198 /* 199 * XXX Check other locators? Hard to know -- machine 200 * dependent code has already checked for the presence 201 * of ACPI by calling acpi_probe(), so I suppose we 202 * don't really have to do anything else. 203 */ 204 return (1); 205 } 206 207 /* 208 * acpi_attach: 209 * 210 * Autoconfiguration `attach' routine. Finish initializing 211 * ACPICA (some initialization was done in acpi_probe(), 212 * which was required to check for the presence of ACPI), 213 * and enable the ACPI subsystem. 214 */ 215 void 216 acpi_attach(struct device *parent, struct device *self, void *aux) 217 { 218 struct acpi_softc *sc = (void *) self; 219 struct acpibus_attach_args *aa = aux; 220 ACPI_TABLE_HEADER *ap = &AcpiGbl_XSDT->Header; 221 ACPI_STATUS rv; 222 223 printf("\n"); 224 225 if (acpi_softc != NULL) 226 panic("acpi_attach: ACPI has already been attached"); 227 228 sysmon_power_settype("acpi"); 229 230 printf("%s: X/RSDT: OemId <%6.6s,%8.8s,%08x>, AslId <%4.4s,%08x>\n", 231 sc->sc_dev.dv_xname, 232 ap->OemId, ap->OemTableId, ap->OemRevision, 233 ap->AslCompilerId, ap->AslCompilerRevision); 234 235 sc->sc_quirks = acpi_find_quirks(); 236 237 sc->sc_iot = aa->aa_iot; 238 sc->sc_memt = aa->aa_memt; 239 sc->sc_pc = aa->aa_pc; 240 sc->sc_pciflags = aa->aa_pciflags; 241 sc->sc_ic = aa->aa_ic; 242 243 acpi_softc = sc; 244 245 /* 246 * Install the default address space handlers. 247 */ 248 249 rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT, 250 ACPI_ADR_SPACE_SYSTEM_MEMORY, ACPI_DEFAULT_HANDLER, NULL, NULL); 251 if (rv != AE_OK) { 252 printf("%s: unable to install SYSTEM MEMORY handler: %d\n", 253 sc->sc_dev.dv_xname, rv); 254 return; 255 } 256 257 rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT, 258 ACPI_ADR_SPACE_SYSTEM_IO, ACPI_DEFAULT_HANDLER, NULL, NULL); 259 if (rv != AE_OK) { 260 printf("%s: unable to install SYSTEM IO handler: %d\n", 261 sc->sc_dev.dv_xname, rv); 262 return; 263 } 264 265 rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT, 266 ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); 267 if (rv != AE_OK) { 268 printf("%s: unable to install PCI CONFIG handler: %d\n", 269 sc->sc_dev.dv_xname, rv); 270 return; 271 } 272 273 /* 274 * Bring ACPI on-line. 275 * 276 * Note that we request that _STA (device init) and _INI (object init) 277 * methods not be run. 278 * 279 * XXX We need to arrange for the object init pass after we have 280 * XXX attached all of our children. 281 */ 282 #ifdef ENABLE_DEBUGGER 283 if (acpi_dbgr & ACPI_DBGR_ENABLE) 284 acpi_osd_debugger(); 285 #endif 286 rv = AcpiEnableSubsystem(ACPI_NO_DEVICE_INIT | ACPI_NO_OBJECT_INIT); 287 if (rv != AE_OK) { 288 printf("%s: unable to enable ACPI: %d\n", 289 sc->sc_dev.dv_xname, rv); 290 return; 291 } 292 acpi_active = 1; 293 294 /* Our current state is "awake". */ 295 sc->sc_sleepstate = ACPI_STATE_S0; 296 297 /* Show SCI interrupt. */ 298 if (AcpiGbl_FADT != NULL) 299 printf("%s: SCI interrupting at int %d\n", 300 sc->sc_dev.dv_xname, AcpiGbl_FADT->SciInt); 301 /* 302 * Check for fixed-hardware features. 303 */ 304 acpi_enable_fixed_events(sc); 305 306 /* 307 * Fix up PCI devices. 308 */ 309 #ifdef ACPI_PCI_FIXUP 310 if ((sc->sc_quirks & (ACPI_QUIRK_BADPCI | ACPI_QUIRK_BADIRQ)) == 0) 311 acpi_pci_fixup(sc); 312 #endif 313 314 /* 315 * Scan the namespace and build our device tree. 316 */ 317 #ifdef ENABLE_DEBUGGER 318 if (acpi_dbgr & ACPI_DBGR_PROBE) 319 acpi_osd_debugger(); 320 #endif 321 acpi_md_callback((struct device *)sc); 322 acpi_build_tree(sc); 323 324 /* 325 * Register a shutdown hook that disables certain ACPI 326 * events that might happen and confuse us while we're 327 * trying to shut down. 328 */ 329 sc->sc_sdhook = shutdownhook_establish(acpi_shutdown, sc); 330 if (sc->sc_sdhook == NULL) 331 printf("%s: WARNING: unable to register shutdown hook\n", 332 sc->sc_dev.dv_xname); 333 334 #ifdef ENABLE_DEBUGGER 335 if (acpi_dbgr & ACPI_DBGR_RUNNING) 336 acpi_osd_debugger(); 337 #endif 338 } 339 340 /* 341 * acpi_shutdown: 342 * 343 * Shutdown hook for ACPI -- disable some events that 344 * might confuse us. 345 */ 346 void 347 acpi_shutdown(void *arg) 348 { 349 struct acpi_softc *sc = arg; 350 351 if (acpi_disable(sc) != AE_OK) 352 printf("%s: WARNING: unable to disable ACPI\n", 353 sc->sc_dev.dv_xname); 354 } 355 356 /* 357 * acpi_disable: 358 * 359 * Disable ACPI. 360 */ 361 ACPI_STATUS 362 acpi_disable(struct acpi_softc *sc) 363 { 364 ACPI_STATUS rv = AE_OK; 365 366 if (acpi_active) { 367 rv = AcpiDisable(); 368 if (rv == AE_OK) 369 acpi_active = 0; 370 } 371 return (rv); 372 } 373 374 struct acpi_make_devnode_state { 375 struct acpi_softc *softc; 376 struct acpi_scope *scope; 377 }; 378 379 /* 380 * acpi_build_tree: 381 * 382 * Scan relevant portions of the ACPI namespace and attach 383 * child devices. 384 */ 385 void 386 acpi_build_tree(struct acpi_softc *sc) 387 { 388 static const char *scopes[] = { 389 "\\_PR_", /* ACPI 1.0 processor namespace */ 390 "\\_SB_", /* system bus namespace */ 391 "\\_SI_", /* system idicator namespace */ 392 "\\_TZ_", /* ACPI 1.0 thermal zone namespace */ 393 NULL, 394 }; 395 struct acpi_attach_args aa; 396 struct acpi_make_devnode_state state; 397 struct acpi_scope *as; 398 struct acpi_devnode *ad; 399 ACPI_HANDLE parent; 400 int i; 401 402 TAILQ_INIT(&sc->sc_scopes); 403 404 state.softc = sc; 405 406 /* 407 * Scan the namespace and build our tree. 408 */ 409 for (i = 0; scopes[i] != NULL; i++) { 410 as = malloc(sizeof(*as), M_ACPI, M_WAITOK); 411 as->as_name = scopes[i]; 412 TAILQ_INIT(&as->as_devnodes); 413 414 TAILQ_INSERT_TAIL(&sc->sc_scopes, as, as_list); 415 416 state.scope = as; 417 418 if (AcpiGetHandle(ACPI_ROOT_OBJECT, (char *) scopes[i], 419 &parent) == AE_OK) { 420 AcpiWalkNamespace(ACPI_TYPE_ANY, parent, 100, 421 acpi_make_devnode, &state, NULL); 422 } 423 424 /* Now, for this namespace, try and attach the devices. */ 425 TAILQ_FOREACH(ad, &as->as_devnodes, ad_list) { 426 aa.aa_node = ad; 427 aa.aa_iot = sc->sc_iot; 428 aa.aa_memt = sc->sc_memt; 429 aa.aa_pc = sc->sc_pc; 430 aa.aa_pciflags = sc->sc_pciflags; 431 aa.aa_ic = sc->sc_ic; 432 433 if (ad->ad_devinfo.Type == ACPI_TYPE_DEVICE) { 434 /* 435 * XXX We only attach devices which are: 436 * 437 * - present 438 * - enabled 439 * - functioning properly 440 * 441 * However, if enabled, it's decoding resources, 442 * so we should claim them, if possible. 443 * Requires changes to bus_space(9). 444 */ 445 if ((ad->ad_devinfo.CurrentStatus & 446 (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED| 447 ACPI_STA_DEV_OK)) != 448 (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED| 449 ACPI_STA_DEV_OK)) 450 continue; 451 452 /* 453 * XXX Same problem as above... 454 */ 455 if ((ad->ad_devinfo.Valid & ACPI_VALID_HID) 456 == 0) 457 continue; 458 } 459 460 ad->ad_device = config_found(&sc->sc_dev, 461 &aa, acpi_print); 462 } 463 } 464 } 465 466 #if ACPI_ACTIVATE_DEV 467 static void 468 acpi_activate_device(ACPI_HANDLE handle, ACPI_DEVICE_INFO *di) 469 { 470 ACPI_STATUS rv; 471 472 #ifdef ACPI_DEBUG 473 printf("acpi_activate_device: %s, old status=%x\n", 474 di->HardwareId, di->CurrentStatus); 475 #endif 476 477 rv = acpi_allocate_resources(handle); 478 if (ACPI_FAILURE(rv)) { 479 printf("acpi: activate failed for %s\n", di->HardwareId); 480 } else { 481 printf("acpi: activated %s\n", di->HardwareId); 482 } 483 484 (void)AcpiGetObjectInfo(handle, di); 485 #ifdef ACPI_DEBUG 486 printf("acpi_activate_device: %s, new status=%x\n", 487 di->HardwareId, di->CurrentStatus); 488 #endif 489 } 490 #endif /* ACPI_ACTIVATE_DEV */ 491 492 /* 493 * acpi_make_devnode: 494 * 495 * Make an ACPI devnode. 496 */ 497 ACPI_STATUS 498 acpi_make_devnode(ACPI_HANDLE handle, UINT32 level, void *context, 499 void **status) 500 { 501 struct acpi_make_devnode_state *state = context; 502 #if defined(ACPI_DEBUG) || defined(ACPI_EXTRA_DEBUG) 503 struct acpi_softc *sc = state->softc; 504 #endif 505 struct acpi_scope *as = state->scope; 506 struct acpi_devnode *ad; 507 ACPI_DEVICE_INFO devinfo; 508 ACPI_OBJECT_TYPE type; 509 ACPI_STATUS rv; 510 511 if (AcpiGetType(handle, &type) == AE_OK) { 512 rv = AcpiGetObjectInfo(handle, &devinfo); 513 if (rv != AE_OK) { 514 #ifdef ACPI_DEBUG 515 printf("%s: AcpiGetObjectInfo failed\n", 516 sc->sc_dev.dv_xname); 517 #endif 518 goto out; /* XXX why return OK */ 519 } 520 521 switch (type) { 522 case ACPI_TYPE_DEVICE: 523 #if ACPI_ACTIVATE_DEV 524 if ((devinfo.Valid & ACPI_VALID_STA) && 525 (devinfo.CurrentStatus & 526 (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED)) == 527 ACPI_STA_DEV_PRESENT) 528 acpi_activate_device(handle, &devinfo); 529 /* FALLTHROUGH */ 530 #endif 531 532 case ACPI_TYPE_PROCESSOR: 533 case ACPI_TYPE_THERMAL: 534 case ACPI_TYPE_POWER: 535 ad = malloc(sizeof(*ad), M_ACPI, M_NOWAIT|M_ZERO); 536 if (ad == NULL) 537 return (AE_NO_MEMORY); 538 539 ad->ad_handle = handle; 540 ad->ad_level = level; 541 ad->ad_scope = as; 542 ad->ad_type = type; 543 544 TAILQ_INSERT_TAIL(&as->as_devnodes, ad, ad_list); 545 546 rv = AcpiGetObjectInfo(handle, &ad->ad_devinfo); 547 if (rv != AE_OK) 548 goto out; 549 550 if ((ad->ad_devinfo.Valid & ACPI_VALID_HID) == 0) 551 goto out; 552 553 #ifdef ACPI_EXTRA_DEBUG 554 printf("%s: HID %s found in scope %s level %d\n", 555 sc->sc_dev.dv_xname, ad->ad_devinfo.HardwareId, 556 as->as_name, ad->ad_level); 557 if (ad->ad_devinfo.Valid & ACPI_VALID_UID) 558 printf(" UID %s\n", 559 ad->ad_devinfo.UniqueId); 560 if (ad->ad_devinfo.Valid & ACPI_VALID_ADR) 561 printf(" ADR 0x%016qx\n", 562 ad->ad_devinfo.Address); 563 if (ad->ad_devinfo.Valid & ACPI_VALID_STA) 564 printf(" STA 0x%08x\n", 565 ad->ad_devinfo.CurrentStatus); 566 #endif 567 } 568 } 569 out: 570 return (AE_OK); 571 } 572 573 /* 574 * acpi_print: 575 * 576 * Autoconfiguration print routine. 577 */ 578 int 579 acpi_print(void *aux, const char *pnp) 580 { 581 struct acpi_attach_args *aa = aux; 582 583 if (pnp) { 584 if (aa->aa_node->ad_devinfo.Valid & ACPI_VALID_HID) { 585 char *pnpstr = aa->aa_node->ad_devinfo.HardwareId; 586 char *str; 587 588 aprint_normal("%s ", pnpstr); 589 if (acpi_eval_string(aa->aa_node->ad_handle, 590 "_STR", &str) == AE_OK) { 591 aprint_normal("[%s] ", str); 592 AcpiOsFree(str); 593 } 594 #ifdef ACPIVERBOSE 595 else { 596 int i; 597 598 for (i = 0; i < sizeof(acpi_knowndevs) / 599 sizeof(acpi_knowndevs[0]); i++) { 600 if (strcmp(acpi_knowndevs[i].pnp, 601 pnpstr) == 0) { 602 printf("[%s] ", 603 acpi_knowndevs[i].str); 604 } 605 } 606 } 607 608 #endif 609 } else { 610 aprint_normal("ACPI Object Type '%s' (0x%02x) ", 611 AcpiUtGetTypeName(aa->aa_node->ad_devinfo.Type), 612 aa->aa_node->ad_devinfo.Type); 613 } 614 aprint_normal("at %s", pnp); 615 } else { 616 aprint_normal(" (%s", aa->aa_node->ad_devinfo.HardwareId); 617 if (aa->aa_node->ad_devinfo.Valid & ACPI_VALID_UID) { 618 char *uid; 619 620 if (aa->aa_node->ad_devinfo.UniqueId[0] == '\0') 621 uid = "<null>"; 622 else 623 uid = aa->aa_node->ad_devinfo.UniqueId; 624 aprint_normal("-%s", uid); 625 } 626 aprint_normal(")"); 627 } 628 629 return (UNCONF); 630 } 631 632 /***************************************************************************** 633 * ACPI fixed-hardware feature handlers 634 *****************************************************************************/ 635 636 UINT32 acpi_fixed_button_handler(void *); 637 void acpi_fixed_button_pressed(void *); 638 639 /* 640 * acpi_enable_fixed_events: 641 * 642 * Enable any fixed-hardware feature handlers. 643 */ 644 void 645 acpi_enable_fixed_events(struct acpi_softc *sc) 646 { 647 static int beenhere; 648 ACPI_STATUS rv; 649 650 KASSERT(beenhere == 0); 651 beenhere = 1; 652 653 /* 654 * Check for fixed-hardware buttons. 655 */ 656 657 if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->PwrButton == 0) { 658 printf("%s: fixed-feature power button present\n", 659 sc->sc_dev.dv_xname); 660 sc->sc_smpsw_power.smpsw_name = sc->sc_dev.dv_xname; 661 sc->sc_smpsw_power.smpsw_type = PSWITCH_TYPE_POWER; 662 if (sysmon_pswitch_register(&sc->sc_smpsw_power) != 0) { 663 printf("%s: unable to register fixed power button " 664 "with sysmon\n", sc->sc_dev.dv_xname); 665 } else { 666 rv = AcpiInstallFixedEventHandler( 667 ACPI_EVENT_POWER_BUTTON, 668 acpi_fixed_button_handler, &sc->sc_smpsw_power); 669 if (rv != AE_OK) { 670 printf("%s: unable to install handler for " 671 "fixed power button: %d\n", 672 sc->sc_dev.dv_xname, rv); 673 } 674 } 675 } 676 677 if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->SleepButton == 0) { 678 printf("%s: fixed-feature sleep button present\n", 679 sc->sc_dev.dv_xname); 680 sc->sc_smpsw_sleep.smpsw_name = sc->sc_dev.dv_xname; 681 sc->sc_smpsw_sleep.smpsw_type = PSWITCH_TYPE_SLEEP; 682 if (sysmon_pswitch_register(&sc->sc_smpsw_power) != 0) { 683 printf("%s: unable to register fixed sleep button " 684 "with sysmon\n", sc->sc_dev.dv_xname); 685 } else { 686 rv = AcpiInstallFixedEventHandler( 687 ACPI_EVENT_SLEEP_BUTTON, 688 acpi_fixed_button_handler, &sc->sc_smpsw_sleep); 689 if (rv != AE_OK) { 690 printf("%s: unable to install handler for " 691 "fixed sleep button: %d\n", 692 sc->sc_dev.dv_xname, rv); 693 } 694 } 695 } 696 } 697 698 /* 699 * acpi_fixed_button_handler: 700 * 701 * Event handler for the fixed buttons. 702 */ 703 UINT32 704 acpi_fixed_button_handler(void *context) 705 { 706 struct sysmon_pswitch *smpsw = context; 707 int rv; 708 709 #ifdef ACPI_BUT_DEBUG 710 printf("%s: fixed button handler\n", smpsw->smpsw_name); 711 #endif 712 713 rv = AcpiOsQueueForExecution(OSD_PRIORITY_LO, 714 acpi_fixed_button_pressed, smpsw); 715 if (rv != AE_OK) 716 printf("%s: WARNING: unable to queue fixed button pressed " 717 "callback: %d\n", smpsw->smpsw_name, rv); 718 719 return (ACPI_INTERRUPT_HANDLED); 720 } 721 722 /* 723 * acpi_fixed_button_pressed: 724 * 725 * Deal with a fixed button being pressed. 726 */ 727 void 728 acpi_fixed_button_pressed(void *context) 729 { 730 struct sysmon_pswitch *smpsw = context; 731 732 #ifdef ACPI_BUT_DEBUG 733 printf("%s: fixed button pressed, calling sysmon\n", 734 smpsw->smpsw_name); 735 #endif 736 737 sysmon_pswitch_event(smpsw, PSWITCH_EVENT_PRESSED); 738 } 739 740 /***************************************************************************** 741 * ACPI utility routines. 742 *****************************************************************************/ 743 744 /* 745 * acpi_eval_integer: 746 * 747 * Evaluate an integer object. 748 */ 749 ACPI_STATUS 750 acpi_eval_integer(ACPI_HANDLE handle, char *path, int *valp) 751 { 752 ACPI_STATUS rv; 753 ACPI_BUFFER buf; 754 ACPI_OBJECT param; 755 756 if (handle == NULL) 757 handle = ACPI_ROOT_OBJECT; 758 759 buf.Pointer = ¶m; 760 buf.Length = sizeof(param); 761 762 rv = AcpiEvaluateObject(handle, path, NULL, &buf); 763 if (rv == AE_OK) { 764 if (param.Type == ACPI_TYPE_INTEGER) 765 *valp = param.Integer.Value; 766 else 767 rv = AE_TYPE; 768 } 769 770 return (rv); 771 } 772 773 /* 774 * acpi_eval_string: 775 * 776 * Evaluate a (Unicode) string object. 777 */ 778 ACPI_STATUS 779 acpi_eval_string(ACPI_HANDLE handle, char *path, char **stringp) 780 { 781 ACPI_STATUS rv; 782 ACPI_BUFFER buf; 783 ACPI_OBJECT *param; 784 785 if (handle == NULL) 786 handle = ACPI_ROOT_OBJECT; 787 788 buf.Pointer = NULL; 789 buf.Length = ACPI_ALLOCATE_BUFFER; 790 791 rv = AcpiEvaluateObject(handle, path, NULL, &buf); 792 param = (ACPI_OBJECT *)buf.Pointer; 793 if (rv == AE_OK && param) { 794 if (param->Type == ACPI_TYPE_STRING) { 795 char *ptr = param->String.Pointer; 796 size_t len; 797 while (*ptr++) 798 continue; 799 len = ptr - param->String.Pointer; 800 if ((*stringp = AcpiOsAllocate(len)) == NULL) { 801 rv = AE_NO_MEMORY; 802 goto done; 803 } 804 (void)memcpy(*stringp, param->String.Pointer, len); 805 goto done; 806 } 807 rv = AE_TYPE; 808 } 809 done: 810 if (buf.Pointer) 811 AcpiOsFree(buf.Pointer); 812 return (rv); 813 } 814 815 816 /* 817 * acpi_eval_struct: 818 * 819 * Evaluate a more complex structure. Caller must free buf.Pointer. 820 */ 821 ACPI_STATUS 822 acpi_eval_struct(ACPI_HANDLE handle, char *path, ACPI_BUFFER *bufp) 823 { 824 ACPI_STATUS rv; 825 826 if (handle == NULL) 827 handle = ACPI_ROOT_OBJECT; 828 829 bufp->Pointer = NULL; 830 bufp->Length = ACPI_ALLOCATE_BUFFER; 831 832 rv = AcpiEvaluateObject(handle, path, NULL, bufp); 833 834 return (rv); 835 } 836 837 /* 838 * acpi_get: 839 * 840 * Fetch data info the specified (empty) ACPI buffer. 841 */ 842 ACPI_STATUS 843 acpi_get(ACPI_HANDLE handle, ACPI_BUFFER *buf, 844 ACPI_STATUS (*getit)(ACPI_HANDLE, ACPI_BUFFER *)) 845 { 846 ACPI_STATUS rv; 847 848 buf->Pointer = NULL; 849 buf->Length = 0; 850 851 rv = (*getit)(handle, buf); 852 if (rv != AE_BUFFER_OVERFLOW) 853 return (rv); 854 855 buf->Pointer = AcpiOsAllocate(buf->Length); 856 if (buf->Pointer == NULL) 857 return (AE_NO_MEMORY); 858 memset(buf->Pointer, 0, buf->Length); 859 860 return ((*getit)(handle, buf)); 861 } 862 863 864 /* 865 * acpi_acquire_global_lock: 866 * 867 * Acquire global lock, with sleeping appropriately. 868 */ 869 #define ACQUIRE_WAIT 1000 870 871 ACPI_STATUS 872 acpi_acquire_global_lock(UINT32 *handle) 873 { 874 ACPI_STATUS status; 875 UINT32 h; 876 int s; 877 878 s = splhigh(); 879 simple_lock(&acpi_slock); 880 while (acpi_locked) 881 ltsleep(&acpi_slock, PVM, "acpi_lock", 0, &acpi_slock); 882 acpi_locked = 1; 883 simple_unlock(&acpi_slock); 884 splx(s); 885 status = AcpiAcquireGlobalLock(ACQUIRE_WAIT, &h); 886 if (ACPI_SUCCESS(status)) 887 *handle = h; 888 else { 889 printf("acpi: cannot acquire lock. status=0x%X\n", status); 890 s = splhigh(); 891 simple_lock(&acpi_slock); 892 acpi_locked = 0; 893 simple_unlock(&acpi_slock); 894 splx(s); 895 } 896 897 return (status); 898 } 899 900 void 901 acpi_release_global_lock(UINT32 handle) 902 { 903 ACPI_STATUS status; 904 int s; 905 906 if (!acpi_locked) { 907 printf("acpi: not locked.\n"); 908 return; 909 } 910 911 status = AcpiReleaseGlobalLock(handle); 912 if (ACPI_FAILURE(status)) { 913 printf("acpi: AcpiReleaseGlobalLock failed. status=0x%X\n", 914 status); 915 return; 916 } 917 918 s = splhigh(); 919 simple_lock(&acpi_slock); 920 acpi_locked = 0; 921 simple_unlock(&acpi_slock); 922 splx(s); 923 wakeup(&acpi_slock); 924 } 925 926 int 927 acpi_is_global_locked(void) 928 { 929 return (acpi_locked); 930 } 931 932 933 934 /***************************************************************************** 935 * ACPI sleep support. 936 *****************************************************************************/ 937 938 static int 939 is_available_state(struct acpi_softc *sc, int state) 940 { 941 UINT8 type_a, type_b; 942 943 return (ACPI_SUCCESS(AcpiGetSleepTypeData((UINT8)state, 944 &type_a, &type_b))); 945 } 946 947 /* 948 * acpi_enter_sleep_state: 949 * 950 * enter to the specified sleep state. 951 */ 952 953 ACPI_STATUS 954 acpi_enter_sleep_state(struct acpi_softc *sc, int state) 955 { 956 int s; 957 ACPI_STATUS ret = AE_OK; 958 959 switch (state) { 960 case ACPI_STATE_S0: 961 break; 962 case ACPI_STATE_S1: 963 case ACPI_STATE_S2: 964 case ACPI_STATE_S3: 965 case ACPI_STATE_S4: 966 if (!is_available_state(sc, state)) { 967 printf("acpi: cannot enter the sleep state (%d).\n", 968 state); 969 break; 970 } 971 ret = AcpiEnterSleepStatePrep(state); 972 if (ACPI_FAILURE(ret)) { 973 printf("acpi: failed preparing to sleep (%s)\n", 974 AcpiFormatException(ret)); 975 break; 976 } 977 if (state==ACPI_STATE_S1) { 978 /* just enter the state */ 979 acpi_md_OsDisableInterrupt(); 980 AcpiEnterSleepState((UINT8)state); 981 AcpiUtReleaseMutex(ACPI_MTX_HARDWARE); 982 } else { 983 /* XXX: powerhooks(9) framework is too poor to 984 * support ACPI sleep state... 985 */ 986 dopowerhooks(PWR_SOFTSUSPEND); 987 s = splhigh(); 988 dopowerhooks(PWR_SUSPEND); 989 acpi_md_sleep(state); 990 dopowerhooks(PWR_RESUME); 991 splx(s); 992 dopowerhooks(PWR_SOFTRESUME); 993 if (state==ACPI_STATE_S4) 994 AcpiEnable(); 995 } 996 AcpiLeaveSleepState((UINT8)state); 997 break; 998 case ACPI_STATE_S5: 999 AcpiEnterSleepStatePrep(ACPI_STATE_S5); 1000 acpi_md_OsDisableInterrupt(); 1001 AcpiEnterSleepState(ACPI_STATE_S5); 1002 printf("WARNING: powerdown failed!\n"); 1003 break; 1004 } 1005 1006 return (ret); 1007 } 1008 1009 #ifdef ACPI_PCI_FIXUP 1010 ACPI_STATUS acpi_pci_fixup_bus(ACPI_HANDLE, UINT32, void *, void **); 1011 /* 1012 * acpi_pci_fixup: 1013 * 1014 * Set up PCI devices that BIOS didn't handle right. 1015 * Iterate through all devices and try to get the _PTR 1016 * (PCI Routing Table). If it exists then make sure all 1017 * interrupt links that it uses are working. 1018 */ 1019 void 1020 acpi_pci_fixup(struct acpi_softc *sc) 1021 { 1022 ACPI_HANDLE parent; 1023 1024 #ifdef ACPI_DEBUG 1025 printf("acpi_pci_fixup starts:\n"); 1026 #endif 1027 if (AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SB_", &parent) != AE_OK) 1028 return; 1029 sc->sc_pci_bus = 0; 1030 AcpiWalkNamespace(ACPI_TYPE_DEVICE, parent, 100, 1031 acpi_pci_fixup_bus, sc, NULL); 1032 } 1033 1034 static ACPI_HANDLE 1035 acpi_get_node(char *name) 1036 { 1037 ACPI_NAMESPACE_NODE *ObjDesc; 1038 ACPI_STATUS Status; 1039 1040 Status = AcpiNsGetNodeByPath(name, NULL, 0, &ObjDesc); 1041 if (ACPI_FAILURE (Status)) { 1042 printf("acpi_get_node: could not find: %s\n", 1043 AcpiFormatException (Status)); 1044 return NULL; 1045 } 1046 return ObjDesc; 1047 } 1048 1049 static uint 1050 acpi_get_intr(ACPI_HANDLE handle) 1051 { 1052 ACPI_BUFFER ret; 1053 ACPI_STATUS rv; 1054 ACPI_RESOURCE *res; 1055 ACPI_RESOURCE_IRQ *irq; 1056 uint intr; 1057 1058 intr = -1; 1059 rv = acpi_get(handle, &ret, AcpiGetCurrentResources); 1060 if (ACPI_FAILURE(rv)) 1061 return (intr); 1062 for (res = ret.Pointer; res->Id != ACPI_RSTYPE_END_TAG; 1063 res = ACPI_NEXT_RESOURCE(res)) { 1064 if (res->Id == ACPI_RSTYPE_IRQ) { 1065 irq = (ACPI_RESOURCE_IRQ *)&res->Data; 1066 if (irq->NumberOfInterrupts == 1) 1067 intr = irq->Interrupts[0]; 1068 break; 1069 } 1070 } 1071 free(ret.Pointer, M_ACPI); 1072 return (intr); 1073 } 1074 1075 static void 1076 acpi_pci_set_line(int bus, int dev, int pin, int line) 1077 { 1078 ACPI_STATUS err; 1079 ACPI_PCI_ID pid; 1080 UINT32 intr, id, bhlc; 1081 int func, nfunc; 1082 1083 pid.Bus = bus; 1084 pid.Device = dev; 1085 pid.Function = 0; 1086 1087 err = AcpiOsReadPciConfiguration(&pid, PCI_BHLC_REG, &bhlc, 32); 1088 if (err) 1089 return; 1090 if (PCI_HDRTYPE_MULTIFN(bhlc)) 1091 nfunc = 8; 1092 else 1093 nfunc = 1; 1094 1095 for (func = 0; func < nfunc; func++) { 1096 pid.Function = func; 1097 1098 err = AcpiOsReadPciConfiguration(&pid, PCI_ID_REG, &id, 32); 1099 if (err || PCI_VENDOR(id) == PCI_VENDOR_INVALID || 1100 PCI_VENDOR(id) == 0) 1101 continue; 1102 1103 err = AcpiOsReadPciConfiguration(&pid, PCI_INTERRUPT_REG, 1104 &intr, 32); 1105 if (err) { 1106 printf("AcpiOsReadPciConfiguration failed %d\n", err); 1107 return; 1108 } 1109 if (pin == PCI_INTERRUPT_PIN(intr) && 1110 line != PCI_INTERRUPT_LINE(intr)) { 1111 #ifdef ACPI_DEBUG 1112 printf("acpi fixup pci intr: %d:%d:%d %c: %d -> %d\n", 1113 bus, dev, func, 1114 pin + '@', PCI_INTERRUPT_LINE(intr), 1115 line); 1116 #endif 1117 intr &= ~(PCI_INTERRUPT_LINE_MASK << 1118 PCI_INTERRUPT_LINE_SHIFT); 1119 intr |= line << PCI_INTERRUPT_LINE_SHIFT; 1120 err = AcpiOsWritePciConfiguration(&pid, 1121 PCI_INTERRUPT_REG, intr, 32); 1122 if (err) { 1123 printf("AcpiOsWritePciConfiguration failed" 1124 " %d\n", err); 1125 return; 1126 } 1127 } 1128 } 1129 } 1130 1131 ACPI_STATUS 1132 acpi_pci_fixup_bus(ACPI_HANDLE handle, UINT32 level, void *context, 1133 void **status) 1134 { 1135 struct acpi_softc *sc = context; 1136 ACPI_STATUS rv; 1137 ACPI_BUFFER buf; 1138 UINT8 *Buffer; 1139 ACPI_PCI_ROUTING_TABLE *PrtElement; 1140 ACPI_HANDLE link; 1141 uint line; 1142 ACPI_NAMESPACE_NODE *node; 1143 ACPI_INTEGER val; 1144 1145 rv = acpi_get(handle, &buf, AcpiGetIrqRoutingTable); 1146 if (ACPI_FAILURE(rv)) 1147 return (AE_OK); 1148 1149 /* 1150 * If at level 1, this is a PCI root bus. Try the _BBN method 1151 * to get the right PCI bus numbering for the following 1152 * busses (this is a depth-first walk). It may fail, 1153 * for example if there's only one root bus, but that 1154 * case should be ok, so we'll ignore that. 1155 */ 1156 if (level == 1) { 1157 node = AcpiNsMapHandleToNode(handle); 1158 rv = AcpiUtEvaluateNumericObject(METHOD_NAME__BBN, node, &val); 1159 if (!ACPI_FAILURE(rv)) { 1160 #ifdef ACPI_DEBUG 1161 printf("%s: fixup: _BBN success, bus # was %d now %d\n", 1162 sc->sc_dev.dv_xname, sc->sc_pci_bus, 1163 ACPI_LOWORD(val)); 1164 #endif 1165 sc->sc_pci_bus = ACPI_LOWORD(val); 1166 } 1167 } 1168 1169 1170 #ifdef ACPI_DEBUG 1171 printf("%s: fixing up PCI bus %d at level %u\n", sc->sc_dev.dv_xname, 1172 sc->sc_pci_bus, level); 1173 #endif 1174 1175 for (Buffer = buf.Pointer; ; Buffer += PrtElement->Length) { 1176 PrtElement = (ACPI_PCI_ROUTING_TABLE *)Buffer; 1177 if (PrtElement->Length == 0) 1178 break; 1179 if (PrtElement->Source[0] == 0) 1180 continue; 1181 1182 link = acpi_get_node(PrtElement->Source); 1183 if (link == NULL) 1184 continue; 1185 line = acpi_get_intr(link); 1186 if (line == -1) { 1187 #ifdef ACPI_DEBUG 1188 printf("%s: fixing up intr link %s\n", 1189 sc->sc_dev.dv_xname, PrtElement->Source); 1190 #endif 1191 rv = acpi_allocate_resources(link); 1192 if (ACPI_FAILURE(rv)) { 1193 printf("%s: interrupt allocation failed %s\n", 1194 sc->sc_dev.dv_xname, PrtElement->Source); 1195 continue; 1196 } 1197 line = acpi_get_intr(link); 1198 if (line == -1) { 1199 printf("%s: get intr failed %s\n", 1200 sc->sc_dev.dv_xname, PrtElement->Source); 1201 continue; 1202 } 1203 } 1204 1205 acpi_pci_set_line(sc->sc_pci_bus, PrtElement->Address >> 16, 1206 PrtElement->Pin + 1, line); 1207 } 1208 1209 sc->sc_pci_bus++; 1210 1211 free(buf.Pointer, M_ACPI); 1212 return (AE_OK); 1213 } 1214 #endif /* ACPI_PCI_FIXUP */ 1215 1216 #if defined(ACPI_PCI_FIXUP) || ACPI_ACTIVATE_DEV 1217 /* XXX This very incomplete */ 1218 ACPI_STATUS 1219 acpi_allocate_resources(ACPI_HANDLE handle) 1220 { 1221 ACPI_BUFFER bufp, bufc, bufn; 1222 ACPI_RESOURCE *resp, *resc, *resn; 1223 ACPI_RESOURCE_IRQ *irq; 1224 ACPI_STATUS rv; 1225 uint delta; 1226 1227 rv = acpi_get(handle, &bufp, AcpiGetPossibleResources); 1228 if (ACPI_FAILURE(rv)) 1229 goto out; 1230 rv = acpi_get(handle, &bufc, AcpiGetCurrentResources); 1231 if (ACPI_FAILURE(rv)) { 1232 goto out1; 1233 } 1234 1235 bufn.Length = 1000; 1236 bufn.Pointer = resn = malloc(bufn.Length, M_ACPI, M_WAITOK); 1237 resp = bufp.Pointer; 1238 resc = bufc.Pointer; 1239 while (resc->Id != ACPI_RSTYPE_END_TAG && 1240 resp->Id != ACPI_RSTYPE_END_TAG) { 1241 while (resc->Id != resp->Id && resp->Id != ACPI_RSTYPE_END_TAG) 1242 resp = ACPI_NEXT_RESOURCE(resp); 1243 if (resp->Id == ACPI_RSTYPE_END_TAG) 1244 break; 1245 /* Found identical Id */ 1246 resn->Id = resc->Id; 1247 switch (resc->Id) { 1248 case ACPI_RSTYPE_IRQ: 1249 memcpy(&resn->Data, &resp->Data, 1250 sizeof(ACPI_RESOURCE_IRQ)); 1251 irq = (ACPI_RESOURCE_IRQ *)&resn->Data; 1252 irq->Interrupts[0] = 1253 ((ACPI_RESOURCE_IRQ *)&resp->Data)-> 1254 Interrupts[irq->NumberOfInterrupts-1]; 1255 irq->NumberOfInterrupts = 1; 1256 resn->Length = ACPI_SIZEOF_RESOURCE(ACPI_RESOURCE_IRQ); 1257 break; 1258 case ACPI_RSTYPE_IO: 1259 memcpy(&resn->Data, &resp->Data, 1260 sizeof(ACPI_RESOURCE_IO)); 1261 resn->Length = resp->Length; 1262 break; 1263 default: 1264 printf("acpi_allocate_resources: res=%d\n", resc->Id); 1265 rv = AE_BAD_DATA; 1266 goto out2; 1267 } 1268 resc = ACPI_NEXT_RESOURCE(resc); 1269 resn = ACPI_NEXT_RESOURCE(resn); 1270 delta = (UINT8 *)resn - (UINT8 *)bufn.Pointer; 1271 if (delta >= 1272 bufn.Length-ACPI_SIZEOF_RESOURCE(ACPI_RESOURCE_DATA)) { 1273 bufn.Length *= 2; 1274 bufn.Pointer = realloc(bufn.Pointer, bufn.Length, 1275 M_ACPI, M_WAITOK); 1276 resn = (ACPI_RESOURCE *)((UINT8 *)bufn.Pointer + delta); 1277 } 1278 } 1279 if (resc->Id != ACPI_RSTYPE_END_TAG) { 1280 printf("acpi_allocate_resources: resc not exhausted\n"); 1281 rv = AE_BAD_DATA; 1282 goto out3; 1283 } 1284 1285 resn->Id = ACPI_RSTYPE_END_TAG; 1286 rv = AcpiSetCurrentResources(handle, &bufn); 1287 if (ACPI_FAILURE(rv)) { 1288 printf("acpi_allocate_resources: AcpiSetCurrentResources %s\n", 1289 AcpiFormatException(rv)); 1290 } 1291 1292 out3: 1293 free(bufn.Pointer, M_ACPI); 1294 out2: 1295 free(bufc.Pointer, M_ACPI); 1296 out1: 1297 free(bufp.Pointer, M_ACPI); 1298 out: 1299 return rv; 1300 } 1301 #endif /* ACPI_PCI_FIXUP || ACPI_ACTIVATE_DEV */ 1302