1 /* $OpenBSD: acpi.c,v 1.125 2008/07/02 03:14:54 fgsch Exp $ */ 2 /* 3 * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com> 4 * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/param.h> 20 #include <sys/systm.h> 21 #include <sys/device.h> 22 #include <sys/malloc.h> 23 #include <sys/fcntl.h> 24 #include <sys/ioccom.h> 25 #include <sys/event.h> 26 #include <sys/signalvar.h> 27 #include <sys/proc.h> 28 #include <sys/kthread.h> 29 30 #include <machine/conf.h> 31 #include <machine/cpufunc.h> 32 #include <machine/bus.h> 33 34 #include <dev/pci/pcivar.h> 35 #include <dev/acpi/acpireg.h> 36 #include <dev/acpi/acpivar.h> 37 #include <dev/acpi/amltypes.h> 38 #include <dev/acpi/acpidev.h> 39 #include <dev/acpi/dsdt.h> 40 41 #include <machine/apmvar.h> 42 #define APMUNIT(dev) (minor(dev)&0xf0) 43 #define APMDEV(dev) (minor(dev)&0x0f) 44 #define APMDEV_NORMAL 0 45 #define APMDEV_CTL 8 46 47 #ifdef ACPI_DEBUG 48 int acpi_debug = 16; 49 #endif 50 int acpi_enabled; 51 int acpi_poll_enabled; 52 int acpi_hasprocfvs; 53 54 #define ACPIEN_RETRIES 15 55 56 void acpi_isr_thread(void *); 57 void acpi_create_thread(void *); 58 59 int acpi_match(struct device *, void *, void *); 60 void acpi_attach(struct device *, struct device *, void *); 61 int acpi_submatch(struct device *, void *, void *); 62 int acpi_print(void *, const char *); 63 64 void acpi_map_pmregs(struct acpi_softc *); 65 66 int acpi_founddock(struct aml_node *, void *); 67 int acpi_foundpss(struct aml_node *, void *); 68 int acpi_foundhid(struct aml_node *, void *); 69 int acpi_foundec(struct aml_node *, void *); 70 int acpi_foundtmp(struct aml_node *, void *); 71 int acpi_foundprt(struct aml_node *, void *); 72 int acpi_foundprw(struct aml_node *, void *); 73 int acpi_foundvideo(struct aml_node *, void *); 74 int acpi_inidev(struct aml_node *, void *); 75 76 int acpi_loadtables(struct acpi_softc *, struct acpi_rsdp *); 77 void acpi_load_table(paddr_t, size_t, acpi_qhead_t *); 78 void acpi_load_dsdt(paddr_t, struct acpi_q **); 79 80 void acpi_init_states(struct acpi_softc *); 81 void acpi_init_gpes(struct acpi_softc *); 82 void acpi_init_pm(struct acpi_softc *); 83 84 #ifndef SMALL_KERNEL 85 int acpi_add_device(struct aml_node *node, void *arg); 86 #endif /* SMALL_KERNEL */ 87 88 void acpi_enable_onegpe(struct acpi_softc *, int, int); 89 int acpi_gpe_level(struct acpi_softc *, int, void *); 90 int acpi_gpe_edge(struct acpi_softc *, int, void *); 91 92 struct gpe_block *acpi_find_gpe(struct acpi_softc *, int); 93 94 #define ACPI_LOCK(sc) 95 #define ACPI_UNLOCK(sc) 96 97 /* XXX move this into dsdt softc at some point */ 98 extern struct aml_node aml_root; 99 100 /* XXX do we need this? */ 101 void acpi_filtdetach(struct knote *); 102 int acpi_filtread(struct knote *, long); 103 104 struct filterops acpiread_filtops = { 105 1, NULL, acpi_filtdetach, acpi_filtread 106 }; 107 108 struct cfattach acpi_ca = { 109 sizeof(struct acpi_softc), acpi_match, acpi_attach 110 }; 111 112 struct cfdriver acpi_cd = { 113 NULL, "acpi", DV_DULL 114 }; 115 116 struct acpi_softc *acpi_softc; 117 int acpi_evindex; 118 119 #define acpi_bus_space_map _bus_space_map 120 #define acpi_bus_space_unmap _bus_space_unmap 121 122 #define pch(x) (((x)>=' ' && (x)<='z') ? (x) : ' ') 123 124 #if 0 125 void 126 acpi_delay(struct acpi_softc *sc, int64_t uSecs) 127 { 128 /* XXX this needs to become a tsleep later */ 129 delay(uSecs); 130 } 131 #endif 132 133 int 134 acpi_gasio(struct acpi_softc *sc, int iodir, int iospace, uint64_t address, 135 int access_size, int len, void *buffer) 136 { 137 u_int8_t *pb; 138 bus_space_handle_t ioh; 139 struct acpi_mem_map mh; 140 pci_chipset_tag_t pc; 141 pcitag_t tag; 142 bus_addr_t ioaddr; 143 int reg, idx, ival, sval; 144 145 dnprintf(50, "gasio: %.2x 0x%.8llx %s\n", 146 iospace, address, (iodir == ACPI_IOWRITE) ? "write" : "read"); 147 148 pb = (u_int8_t *)buffer; 149 switch (iospace) { 150 case GAS_SYSTEM_MEMORY: 151 /* copy to/from system memory */ 152 acpi_map(address, len, &mh); 153 if (iodir == ACPI_IOREAD) 154 memcpy(buffer, mh.va, len); 155 else 156 memcpy(mh.va, buffer, len); 157 acpi_unmap(&mh); 158 break; 159 160 case GAS_SYSTEM_IOSPACE: 161 /* read/write from I/O registers */ 162 ioaddr = address; 163 if (acpi_bus_space_map(sc->sc_iot, ioaddr, len, 0, &ioh) != 0) { 164 printf("unable to map iospace\n"); 165 return (-1); 166 } 167 for (reg = 0; reg < len; reg += access_size) { 168 if (iodir == ACPI_IOREAD) { 169 switch (access_size) { 170 case 1: 171 *(uint8_t *)(pb+reg) = bus_space_read_1( 172 sc->sc_iot, ioh, reg); 173 dnprintf(80, "os_in8(%llx) = %x\n", 174 reg+address, *(uint8_t *)(pb+reg)); 175 break; 176 case 2: 177 *(uint16_t *)(pb+reg) = bus_space_read_2( 178 sc->sc_iot, ioh, reg); 179 dnprintf(80, "os_in16(%llx) = %x\n", 180 reg+address, *(uint16_t *)(pb+reg)); 181 break; 182 case 4: 183 *(uint32_t *)(pb+reg) = bus_space_read_4( 184 sc->sc_iot, ioh, reg); 185 break; 186 default: 187 printf("rdio: invalid size %d\n", access_size); 188 break; 189 } 190 } else { 191 switch (access_size) { 192 case 1: 193 bus_space_write_1(sc->sc_iot, ioh, reg, 194 *(uint8_t *)(pb+reg)); 195 dnprintf(80, "os_out8(%llx,%x)\n", 196 reg+address, *(uint8_t *)(pb+reg)); 197 break; 198 case 2: 199 bus_space_write_2(sc->sc_iot, ioh, reg, 200 *(uint16_t *)(pb+reg)); 201 dnprintf(80, "os_out16(%llx,%x)\n", 202 reg+address, *(uint16_t *)(pb+reg)); 203 break; 204 case 4: 205 bus_space_write_4(sc->sc_iot, ioh, reg, 206 *(uint32_t *)(pb+reg)); 207 break; 208 default: 209 printf("wrio: invalid size %d\n", access_size); 210 break; 211 } 212 } 213 214 /* During autoconf some devices are still gathering 215 * information. Delay here to give them an opportunity 216 * to finish. During runtime we simply need to ignore 217 * transient values. 218 */ 219 if (cold) 220 delay(10000); 221 } 222 acpi_bus_space_unmap(sc->sc_iot, ioh, len, &ioaddr); 223 break; 224 225 case GAS_PCI_CFG_SPACE: 226 /* format of address: 227 * bits 00..15 = register 228 * bits 16..31 = function 229 * bits 32..47 = device 230 * bits 48..63 = bus 231 */ 232 pc = NULL; 233 tag = pci_make_tag(pc, 234 ACPI_PCI_BUS(address), ACPI_PCI_DEV(address), 235 ACPI_PCI_FN(address)); 236 237 /* XXX: This is ugly. read-modify-write does a byte at a time */ 238 reg = ACPI_PCI_REG(address); 239 for (idx = reg; idx < reg+len; idx++) { 240 ival = pci_conf_read(pc, tag, idx & ~0x3); 241 if (iodir == ACPI_IOREAD) { 242 *pb = ival >> (8 * (idx & 0x3)); 243 } else { 244 sval = *pb; 245 ival &= ~(0xFF << (8* (idx & 0x3))); 246 ival |= sval << (8* (idx & 0x3)); 247 pci_conf_write(pc, tag, idx & ~0x3, ival); 248 } 249 pb++; 250 } 251 break; 252 case GAS_EMBEDDED: 253 if (sc->sc_ec == NULL) 254 break; 255 #ifndef SMALL_KERNEL 256 if (iodir == ACPI_IOREAD) 257 acpiec_read(sc->sc_ec, (u_int8_t)address, len, buffer); 258 else 259 acpiec_write(sc->sc_ec, (u_int8_t)address, len, buffer); 260 #endif 261 break; 262 } 263 return (0); 264 } 265 266 int 267 acpi_inidev(struct aml_node *node, void *arg) 268 { 269 struct acpi_softc *sc = (struct acpi_softc *)arg; 270 struct aml_value res; 271 int st = 0; 272 273 /* Default value */ 274 st = STA_PRESENT|STA_ENABLED; 275 st |= STA_SHOW_UI|STA_DEV_OK; 276 st |= STA_BATTERY; 277 278 /* 279 * Per the ACPI spec 6.5.1, only run _INI when device is there or 280 * when there is no _STA. We terminate the tree walk (with return 1) 281 * early if necessary. 282 */ 283 284 /* Evaluate _STA to decide _INI fate and walk fate */ 285 if (!aml_evalname(sc, node->parent, "_STA", 0, NULL, &res)) 286 st = (int)aml_val2int(&res); 287 aml_freevalue(&res); 288 289 /* Evaluate _INI if we are present */ 290 if (st & STA_PRESENT) 291 aml_evalnode(sc, node, 0, NULL, NULL); 292 293 /* If we are functioning, we walk/search our children */ 294 if(st & STA_DEV_OK) 295 return 0; 296 297 /* If we are not enabled, or not present, terminate search */ 298 if (!(st & (STA_PRESENT|STA_ENABLED))) 299 return 1; 300 301 /* Default just continue search */ 302 return 0; 303 } 304 305 int 306 acpi_foundprt(struct aml_node *node, void *arg) 307 { 308 struct acpi_softc *sc = (struct acpi_softc *)arg; 309 struct device *self = (struct device *)arg; 310 struct acpi_attach_args aaa; 311 struct aml_value res; 312 int st = 0; 313 314 dnprintf(10, "found prt entry: %s\n", node->parent->name); 315 316 /* Default value */ 317 st = STA_PRESENT|STA_ENABLED; 318 st |= STA_SHOW_UI|STA_DEV_OK; 319 st |= STA_BATTERY; 320 321 /* Evaluate _STA to decide _PRT fate and walk fate */ 322 if (!aml_evalname(sc, node->parent, "_STA", 0, NULL, &res)) 323 st = (int)aml_val2int(&res); 324 aml_freevalue(&res); 325 326 if (st & STA_PRESENT) { 327 memset(&aaa, 0, sizeof(aaa)); 328 aaa.aaa_iot = sc->sc_iot; 329 aaa.aaa_memt = sc->sc_memt; 330 aaa.aaa_node = node; 331 aaa.aaa_name = "acpiprt"; 332 333 config_found(self, &aaa, acpi_print); 334 } 335 336 /* If we are functioning, we walk/search our children */ 337 if(st & STA_DEV_OK) 338 return 0; 339 340 /* If we are not enabled, or not present, terminate search */ 341 if (!(st & (STA_PRESENT|STA_ENABLED))) 342 return 1; 343 344 /* Default just continue search */ 345 return 0; 346 } 347 348 int 349 acpi_match(struct device *parent, void *match, void *aux) 350 { 351 struct bios_attach_args *ba = aux; 352 struct cfdata *cf = match; 353 354 /* sanity */ 355 if (strcmp(ba->ba_name, cf->cf_driver->cd_name)) 356 return (0); 357 358 if (!acpi_probe(parent, cf, ba)) 359 return (0); 360 361 return (1); 362 } 363 364 void 365 acpi_attach(struct device *parent, struct device *self, void *aux) 366 { 367 struct bios_attach_args *ba = aux; 368 struct acpi_softc *sc = (struct acpi_softc *)self; 369 struct acpi_mem_map handle; 370 struct acpi_rsdp *rsdp; 371 struct acpi_q *entry; 372 struct acpi_dsdt *p_dsdt; 373 int idx; 374 #ifndef SMALL_KERNEL 375 struct acpi_wakeq *wentry; 376 struct device *dev; 377 struct acpi_ac *ac; 378 struct acpi_bat *bat; 379 #endif /* SMALL_KERNEL */ 380 paddr_t facspa; 381 382 sc->sc_iot = ba->ba_iot; 383 sc->sc_memt = ba->ba_memt; 384 385 if (acpi_map(ba->ba_acpipbase, sizeof(struct acpi_rsdp), &handle)) { 386 printf(": can't map memory\n"); 387 return; 388 } 389 390 rsdp = (struct acpi_rsdp *)handle.va; 391 sc->sc_revision = (int)rsdp->rsdp_revision; 392 printf(": rev %d", sc->sc_revision); 393 394 SIMPLEQ_INIT(&sc->sc_tables); 395 SIMPLEQ_INIT(&sc->sc_wakedevs); 396 397 #ifndef SMALL_KERNEL 398 sc->sc_note = malloc(sizeof(struct klist), M_DEVBUF, M_NOWAIT | M_ZERO); 399 if (sc->sc_note == NULL) { 400 printf(", can't allocate memory\n"); 401 acpi_unmap(&handle); 402 return; 403 } 404 #endif /* SMALL_KERNEL */ 405 406 if (acpi_loadtables(sc, rsdp)) { 407 printf(", can't load tables\n"); 408 acpi_unmap(&handle); 409 return; 410 } 411 412 acpi_unmap(&handle); 413 414 /* 415 * Find the FADT 416 */ 417 SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) { 418 if (memcmp(entry->q_table, FADT_SIG, 419 sizeof(FADT_SIG) - 1) == 0) { 420 sc->sc_fadt = entry->q_table; 421 break; 422 } 423 } 424 if (sc->sc_fadt == NULL) { 425 printf(", no FADT\n"); 426 return; 427 } 428 429 /* 430 * Check if we are able to enable ACPI control 431 */ 432 if (!sc->sc_fadt->smi_cmd || 433 (!sc->sc_fadt->acpi_enable && !sc->sc_fadt->acpi_disable)) { 434 printf(", ACPI control unavailable\n"); 435 return; 436 } 437 438 /* 439 * Set up a pointer to the firmware control structure 440 */ 441 if (sc->sc_fadt->hdr_revision < 3 || sc->sc_fadt->x_firmware_ctl == 0) 442 facspa = sc->sc_fadt->firmware_ctl; 443 else 444 facspa = sc->sc_fadt->x_firmware_ctl; 445 446 if (acpi_map(facspa, sizeof(struct acpi_facs), &handle)) 447 printf(" !FACS"); 448 else 449 sc->sc_facs = (struct acpi_facs *)handle.va; 450 451 acpi_enabled = 1; 452 453 /* Create opcode hashtable */ 454 aml_hashopcodes(); 455 456 /* Create Default AML objects */ 457 aml_create_defaultobjects(); 458 459 /* 460 * Load the DSDT from the FADT pointer -- use the 461 * extended (64-bit) pointer if it exists 462 */ 463 if (sc->sc_fadt->hdr_revision < 3 || sc->sc_fadt->x_dsdt == 0) 464 acpi_load_dsdt(sc->sc_fadt->dsdt, &entry); 465 else 466 acpi_load_dsdt(sc->sc_fadt->x_dsdt, &entry); 467 468 if (entry == NULL) 469 printf(" !DSDT"); 470 SIMPLEQ_INSERT_HEAD(&sc->sc_tables, entry, q_next); 471 472 p_dsdt = entry->q_table; 473 acpi_parse_aml(sc, p_dsdt->aml, p_dsdt->hdr_length - 474 sizeof(p_dsdt->hdr)); 475 476 /* Load SSDT's */ 477 SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) { 478 if (memcmp(entry->q_table, SSDT_SIG, 479 sizeof(SSDT_SIG) - 1) == 0) { 480 p_dsdt = entry->q_table; 481 acpi_parse_aml(sc, p_dsdt->aml, p_dsdt->hdr_length - 482 sizeof(p_dsdt->hdr)); 483 } 484 } 485 486 /* Perform post-parsing fixups */ 487 aml_postparse(); 488 489 #ifndef SMALL_KERNEL 490 /* Find available sleeping states */ 491 acpi_init_states(sc); 492 493 /* Find available sleep/resume related methods. */ 494 acpi_init_pm(sc); 495 #endif /* SMALL_KERNEL */ 496 497 /* Map Power Management registers */ 498 acpi_map_pmregs(sc); 499 500 #ifndef SMALL_KERNEL 501 /* Initialize GPE handlers */ 502 acpi_init_gpes(sc); 503 504 /* some devices require periodic polling */ 505 timeout_set(&sc->sc_dev_timeout, acpi_poll, sc); 506 #endif /* SMALL_KERNEL */ 507 508 /* 509 * Take over ACPI control. Note that once we do this, we 510 * effectively tell the system that we have ownership of 511 * the ACPI hardware registers, and that SMI should leave 512 * them alone 513 * 514 * This may prevent thermal control on some systems where 515 * that actually does work 516 */ 517 acpi_write_pmreg(sc, ACPIREG_SMICMD, 0, sc->sc_fadt->acpi_enable); 518 idx = 0; 519 do { 520 if (idx++ > ACPIEN_RETRIES) { 521 printf(", can't enable ACPI\n"); 522 return; 523 } 524 } while (!(acpi_read_pmreg(sc, ACPIREG_PM1_CNT, 0) & ACPI_PM1_SCI_EN)); 525 526 printf("\n%s: tables", DEVNAME(sc)); 527 SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) { 528 printf(" %.4s", entry->q_table); 529 } 530 printf("\n"); 531 532 #ifndef SMALL_KERNEL 533 /* Display wakeup devices and lowest S-state */ 534 printf("%s: wakeup devices", DEVNAME(sc)); 535 SIMPLEQ_FOREACH(wentry, &sc->sc_wakedevs, q_next) { 536 printf(" %.4s(S%d)", wentry->q_node->name, 537 wentry->q_state); 538 } 539 printf("\n"); 540 541 542 /* 543 * ACPI is enabled now -- attach timer 544 */ 545 { 546 struct acpi_attach_args aaa; 547 548 memset(&aaa, 0, sizeof(aaa)); 549 aaa.aaa_name = "acpitimer"; 550 aaa.aaa_iot = sc->sc_iot; 551 aaa.aaa_memt = sc->sc_memt; 552 #if 0 553 aaa.aaa_pcit = sc->sc_pcit; 554 aaa.aaa_smbust = sc->sc_smbust; 555 #endif 556 config_found(self, &aaa, acpi_print); 557 } 558 #endif /* SMALL_KERNEL */ 559 560 /* 561 * Attach table-defined devices 562 */ 563 SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) { 564 struct acpi_attach_args aaa; 565 566 memset(&aaa, 0, sizeof(aaa)); 567 aaa.aaa_iot = sc->sc_iot; 568 aaa.aaa_memt = sc->sc_memt; 569 #if 0 570 aaa.aaa_pcit = sc->sc_pcit; 571 aaa.aaa_smbust = sc->sc_smbust; 572 #endif 573 aaa.aaa_table = entry->q_table; 574 config_found_sm(self, &aaa, acpi_print, acpi_submatch); 575 } 576 577 acpi_softc = sc; 578 579 /* initialize runtime environment */ 580 aml_find_node(&aml_root, "_INI", acpi_inidev, sc); 581 582 /* attach pci interrupt routing tables */ 583 aml_find_node(&aml_root, "_PRT", acpi_foundprt, sc); 584 585 #ifndef SMALL_KERNEL 586 /* XXX EC needs to be attached first on some systems */ 587 aml_find_node(&aml_root, "_HID", acpi_foundec, sc); 588 589 aml_walknodes(&aml_root, AML_WALK_PRE, acpi_add_device, sc); 590 591 /* attach battery, power supply and button devices */ 592 aml_find_node(&aml_root, "_HID", acpi_foundhid, sc); 593 594 /* attach docks */ 595 aml_find_node(&aml_root, "_DCK", acpi_founddock, sc); 596 597 /* attach video */ 598 aml_find_node(&aml_root, "_DOS", acpi_foundvideo, sc); 599 600 /* create list of devices we want to query when APM come in */ 601 SLIST_INIT(&sc->sc_ac); 602 SLIST_INIT(&sc->sc_bat); 603 TAILQ_FOREACH(dev, &alldevs, dv_list) { 604 if (!strncmp(dev->dv_xname, "acpiac", strlen("acpiac"))) { 605 ac = malloc(sizeof(*ac), M_DEVBUF, M_WAITOK | M_ZERO); 606 ac->aac_softc = (struct acpiac_softc *)dev; 607 SLIST_INSERT_HEAD(&sc->sc_ac, ac, aac_link); 608 } 609 if (!strncmp(dev->dv_xname, "acpibat", strlen("acpibat"))) { 610 bat = malloc(sizeof(*bat), M_DEVBUF, M_WAITOK | M_ZERO); 611 bat->aba_softc = (struct acpibat_softc *)dev; 612 SLIST_INSERT_HEAD(&sc->sc_bat, bat, aba_link); 613 } 614 } 615 616 /* Setup threads */ 617 sc->sc_thread = malloc(sizeof(struct acpi_thread), M_DEVBUF, M_WAITOK); 618 sc->sc_thread->sc = sc; 619 sc->sc_thread->running = 1; 620 621 acpi_attach_machdep(sc); 622 623 kthread_create_deferred(acpi_create_thread, sc); 624 #endif /* SMALL_KERNEL */ 625 } 626 627 int 628 acpi_submatch(struct device *parent, void *match, void *aux) 629 { 630 struct acpi_attach_args *aaa = (struct acpi_attach_args *)aux; 631 struct cfdata *cf = match; 632 633 if (aaa->aaa_table == NULL) 634 return (0); 635 return ((*cf->cf_attach->ca_match)(parent, match, aux)); 636 } 637 638 int 639 acpi_print(void *aux, const char *pnp) 640 { 641 struct acpi_attach_args *aa = aux; 642 643 if (pnp) { 644 if (aa->aaa_name) 645 printf("%s at %s", aa->aaa_name, pnp); 646 else 647 return (QUIET); 648 } 649 650 return (UNCONF); 651 } 652 653 int 654 acpi_loadtables(struct acpi_softc *sc, struct acpi_rsdp *rsdp) 655 { 656 struct acpi_mem_map hrsdt, handle; 657 struct acpi_table_header *hdr; 658 int i, ntables; 659 size_t len; 660 661 if (rsdp->rsdp_revision == 2) { 662 struct acpi_xsdt *xsdt; 663 664 if (acpi_map(rsdp->rsdp_xsdt, sizeof(*hdr), &handle)) { 665 printf("couldn't map rsdt\n"); 666 return (ENOMEM); 667 } 668 669 hdr = (struct acpi_table_header *)handle.va; 670 len = hdr->length; 671 acpi_unmap(&handle); 672 hdr = NULL; 673 674 acpi_map(rsdp->rsdp_xsdt, len, &hrsdt); 675 xsdt = (struct acpi_xsdt *)hrsdt.va; 676 677 ntables = (len - sizeof(struct acpi_table_header)) / 678 sizeof(xsdt->table_offsets[0]); 679 680 for (i = 0; i < ntables; i++) { 681 acpi_map(xsdt->table_offsets[i], sizeof(*hdr), &handle); 682 hdr = (struct acpi_table_header *)handle.va; 683 acpi_load_table(xsdt->table_offsets[i], hdr->length, 684 &sc->sc_tables); 685 acpi_unmap(&handle); 686 } 687 acpi_unmap(&hrsdt); 688 } else { 689 struct acpi_rsdt *rsdt; 690 691 if (acpi_map(rsdp->rsdp_rsdt, sizeof(*hdr), &handle)) { 692 printf("couldn't map rsdt\n"); 693 return (ENOMEM); 694 } 695 696 hdr = (struct acpi_table_header *)handle.va; 697 len = hdr->length; 698 acpi_unmap(&handle); 699 hdr = NULL; 700 701 acpi_map(rsdp->rsdp_rsdt, len, &hrsdt); 702 rsdt = (struct acpi_rsdt *)hrsdt.va; 703 704 ntables = (len - sizeof(struct acpi_table_header)) / 705 sizeof(rsdt->table_offsets[0]); 706 707 for (i = 0; i < ntables; i++) { 708 acpi_map(rsdt->table_offsets[i], sizeof(*hdr), &handle); 709 hdr = (struct acpi_table_header *)handle.va; 710 acpi_load_table(rsdt->table_offsets[i], hdr->length, 711 &sc->sc_tables); 712 acpi_unmap(&handle); 713 } 714 acpi_unmap(&hrsdt); 715 } 716 717 return (0); 718 } 719 720 void 721 acpi_load_table(paddr_t pa, size_t len, acpi_qhead_t *queue) 722 { 723 struct acpi_mem_map handle; 724 struct acpi_q *entry; 725 726 entry = malloc(len + sizeof(struct acpi_q), M_DEVBUF, M_NOWAIT); 727 728 if (entry != NULL) { 729 if (acpi_map(pa, len, &handle)) { 730 free(entry, M_DEVBUF); 731 return; 732 } 733 memcpy(entry->q_data, handle.va, len); 734 entry->q_table = entry->q_data; 735 acpi_unmap(&handle); 736 SIMPLEQ_INSERT_TAIL(queue, entry, q_next); 737 } 738 } 739 740 void 741 acpi_load_dsdt(paddr_t pa, struct acpi_q **dsdt) 742 { 743 struct acpi_mem_map handle; 744 struct acpi_table_header *hdr; 745 size_t len; 746 747 if (acpi_map(pa, sizeof(*hdr), &handle)) 748 return; 749 hdr = (struct acpi_table_header *)handle.va; 750 len = hdr->length; 751 acpi_unmap(&handle); 752 753 *dsdt = malloc(len + sizeof(struct acpi_q), M_DEVBUF, M_NOWAIT); 754 755 if (*dsdt != NULL) { 756 if (acpi_map(pa, len, &handle)) { 757 free(*dsdt, M_DEVBUF); 758 *dsdt = NULL; 759 return; 760 } 761 memcpy((*dsdt)->q_data, handle.va, len); 762 (*dsdt)->q_table = (*dsdt)->q_data; 763 acpi_unmap(&handle); 764 } 765 } 766 767 int 768 acpiopen(dev_t dev, int flag, int mode, struct proc *p) 769 { 770 int error = 0; 771 #ifndef SMALL_KERNEL 772 struct acpi_softc *sc; 773 774 if (!acpi_cd.cd_ndevs || APMUNIT(dev) != 0 || 775 !(sc = acpi_cd.cd_devs[APMUNIT(dev)])) 776 return (ENXIO); 777 778 switch (APMDEV(dev)) { 779 case APMDEV_CTL: 780 if (!(flag & FWRITE)) { 781 error = EINVAL; 782 break; 783 } 784 break; 785 case APMDEV_NORMAL: 786 if (!(flag & FREAD) || (flag & FWRITE)) { 787 error = EINVAL; 788 break; 789 } 790 break; 791 default: 792 error = ENXIO; 793 break; 794 } 795 #else 796 error = ENXIO; 797 #endif 798 return (error); 799 } 800 801 int 802 acpiclose(dev_t dev, int flag, int mode, struct proc *p) 803 { 804 int error = 0; 805 #ifndef SMALL_KERNEL 806 struct acpi_softc *sc; 807 808 if (!acpi_cd.cd_ndevs || APMUNIT(dev) != 0 || 809 !(sc = acpi_cd.cd_devs[APMUNIT(dev)])) 810 return (ENXIO); 811 switch (APMDEV(dev)) { 812 case APMDEV_CTL: 813 case APMDEV_NORMAL: 814 break; 815 default: 816 error = ENXIO; 817 break; 818 } 819 #else 820 error = ENXIO; 821 #endif 822 return (error); 823 } 824 825 int 826 acpiioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 827 { 828 int error = 0; 829 #ifndef SMALL_KERNEL 830 struct acpi_softc *sc; 831 struct acpi_ac *ac; 832 struct acpi_bat *bat; 833 struct apm_power_info *pi = (struct apm_power_info *)data; 834 int bats; 835 unsigned int remaining, rem, minutes, rate; 836 837 if (!acpi_cd.cd_ndevs || APMUNIT(dev) != 0 || 838 !(sc = acpi_cd.cd_devs[APMUNIT(dev)])) 839 return (ENXIO); 840 841 ACPI_LOCK(sc); 842 /* fake APM */ 843 switch (cmd) { 844 case APM_IOC_GETPOWER: 845 /* A/C */ 846 pi->ac_state = APM_AC_UNKNOWN; 847 SLIST_FOREACH(ac, &sc->sc_ac, aac_link) { 848 if (ac->aac_softc->sc_ac_stat == PSR_ONLINE) 849 pi->ac_state = APM_AC_ON; 850 else if (ac->aac_softc->sc_ac_stat == PSR_OFFLINE) 851 if (pi->ac_state == APM_AC_UNKNOWN) 852 pi->ac_state = APM_AC_OFF; 853 } 854 855 /* battery */ 856 pi->battery_state = APM_BATT_UNKNOWN; 857 pi->battery_life = 0; 858 pi->minutes_left = 0; 859 bats = 0; 860 remaining = rem = 0; 861 minutes = 0; 862 rate = 0; 863 SLIST_FOREACH(bat, &sc->sc_bat, aba_link) { 864 if (bat->aba_softc->sc_bat_present == 0) 865 continue; 866 867 if (bat->aba_softc->sc_bif.bif_last_capacity == 0) 868 continue; 869 870 bats++; 871 rem = (bat->aba_softc->sc_bst.bst_capacity * 100) / 872 bat->aba_softc->sc_bif.bif_last_capacity; 873 if (rem > 100) 874 rem = 100; 875 remaining += rem; 876 877 if (bat->aba_softc->sc_bst.bst_rate == BST_UNKNOWN) 878 continue; 879 else if (bat->aba_softc->sc_bst.bst_rate > 1) 880 rate = bat->aba_softc->sc_bst.bst_rate; 881 882 minutes += bat->aba_softc->sc_bst.bst_capacity; 883 } 884 885 if (bats == 0) { 886 pi->battery_state = APM_BATTERY_ABSENT; 887 pi->battery_life = 0; 888 pi->minutes_left = (unsigned int)-1; 889 break; 890 } 891 892 if (pi->ac_state == APM_AC_ON || rate == 0) 893 pi->minutes_left = (unsigned int)-1; 894 else 895 pi->minutes_left = 100 * minutes / rate; 896 897 /* running on battery */ 898 pi->battery_life = remaining / bats; 899 if (pi->battery_life > 50) 900 pi->battery_state = APM_BATT_HIGH; 901 else if (pi->battery_life > 25) 902 pi->battery_state = APM_BATT_LOW; 903 else 904 pi->battery_state = APM_BATT_CRITICAL; 905 906 break; 907 908 default: 909 error = ENOTTY; 910 } 911 912 ACPI_UNLOCK(sc); 913 #else 914 error = ENXIO; 915 #endif /* SMALL_KERNEL */ 916 return (error); 917 } 918 919 void 920 acpi_filtdetach(struct knote *kn) 921 { 922 #ifndef SMALL_KERNEL 923 struct acpi_softc *sc = kn->kn_hook; 924 925 ACPI_LOCK(sc); 926 SLIST_REMOVE(sc->sc_note, kn, knote, kn_selnext); 927 ACPI_UNLOCK(sc); 928 #endif 929 } 930 931 int 932 acpi_filtread(struct knote *kn, long hint) 933 { 934 #ifndef SMALL_KERNEL 935 /* XXX weird kqueue_scan() semantics */ 936 if (hint & !kn->kn_data) 937 kn->kn_data = hint; 938 #endif 939 return (1); 940 } 941 942 int 943 acpikqfilter(dev_t dev, struct knote *kn) 944 { 945 #ifndef SMALL_KERNEL 946 struct acpi_softc *sc; 947 948 if (!acpi_cd.cd_ndevs || APMUNIT(dev) != 0 || 949 !(sc = acpi_cd.cd_devs[APMUNIT(dev)])) 950 return (ENXIO); 951 952 switch (kn->kn_filter) { 953 case EVFILT_READ: 954 kn->kn_fop = &acpiread_filtops; 955 break; 956 default: 957 return (1); 958 } 959 960 kn->kn_hook = sc; 961 962 ACPI_LOCK(sc); 963 SLIST_INSERT_HEAD(sc->sc_note, kn, kn_selnext); 964 ACPI_UNLOCK(sc); 965 966 return (0); 967 #else 968 return (1); 969 #endif 970 } 971 972 /* Read from power management register */ 973 int 974 acpi_read_pmreg(struct acpi_softc *sc, int reg, int offset) 975 { 976 bus_space_handle_t ioh; 977 bus_size_t size, __size; 978 int regval; 979 980 __size = 0; 981 /* Special cases: 1A/1B blocks can be OR'ed together */ 982 switch (reg) { 983 case ACPIREG_PM1_EN: 984 return (acpi_read_pmreg(sc, ACPIREG_PM1A_EN, offset) | 985 acpi_read_pmreg(sc, ACPIREG_PM1B_EN, offset)); 986 case ACPIREG_PM1_STS: 987 return (acpi_read_pmreg(sc, ACPIREG_PM1A_STS, offset) | 988 acpi_read_pmreg(sc, ACPIREG_PM1B_STS, offset)); 989 case ACPIREG_PM1_CNT: 990 return (acpi_read_pmreg(sc, ACPIREG_PM1A_CNT, offset) | 991 acpi_read_pmreg(sc, ACPIREG_PM1B_CNT, offset)); 992 case ACPIREG_GPE_STS: 993 __size = 1; 994 dnprintf(50, "read GPE_STS offset: %.2x %.2x %.2x\n", offset, 995 sc->sc_fadt->gpe0_blk_len>>1, sc->sc_fadt->gpe1_blk_len>>1); 996 if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) { 997 reg = ACPIREG_GPE0_STS; 998 } 999 break; 1000 case ACPIREG_GPE_EN: 1001 __size = 1; 1002 dnprintf(50, "read GPE_EN offset: %.2x %.2x %.2x\n", 1003 offset, sc->sc_fadt->gpe0_blk_len>>1, 1004 sc->sc_fadt->gpe1_blk_len>>1); 1005 if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) { 1006 reg = ACPIREG_GPE0_EN; 1007 } 1008 break; 1009 } 1010 1011 if (reg >= ACPIREG_MAXREG || sc->sc_pmregs[reg].size == 0) 1012 return (0); 1013 1014 regval = 0; 1015 ioh = sc->sc_pmregs[reg].ioh; 1016 size = sc->sc_pmregs[reg].size; 1017 if (__size) 1018 size = __size; 1019 if (size > 4) 1020 size = 4; 1021 1022 switch (size) { 1023 case 1: 1024 regval = bus_space_read_1(sc->sc_iot, ioh, offset); 1025 break; 1026 case 2: 1027 regval = bus_space_read_2(sc->sc_iot, ioh, offset); 1028 break; 1029 case 4: 1030 regval = bus_space_read_4(sc->sc_iot, ioh, offset); 1031 break; 1032 } 1033 1034 dnprintf(30, "acpi_readpm: %s = %.4x:%.4x %x\n", 1035 sc->sc_pmregs[reg].name, 1036 sc->sc_pmregs[reg].addr, offset, regval); 1037 return (regval); 1038 } 1039 1040 /* Write to power management register */ 1041 void 1042 acpi_write_pmreg(struct acpi_softc *sc, int reg, int offset, int regval) 1043 { 1044 bus_space_handle_t ioh; 1045 bus_size_t size, __size; 1046 1047 __size = 0; 1048 /* Special cases: 1A/1B blocks can be written with same value */ 1049 switch (reg) { 1050 case ACPIREG_PM1_EN: 1051 acpi_write_pmreg(sc, ACPIREG_PM1A_EN, offset, regval); 1052 acpi_write_pmreg(sc, ACPIREG_PM1B_EN, offset, regval); 1053 break; 1054 case ACPIREG_PM1_STS: 1055 acpi_write_pmreg(sc, ACPIREG_PM1A_STS, offset, regval); 1056 acpi_write_pmreg(sc, ACPIREG_PM1B_STS, offset, regval); 1057 break; 1058 case ACPIREG_PM1_CNT: 1059 acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, offset, regval); 1060 acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, offset, regval); 1061 break; 1062 case ACPIREG_GPE_STS: 1063 __size = 1; 1064 dnprintf(50, "write GPE_STS offset: %.2x %.2x %.2x %.2x\n", 1065 offset, sc->sc_fadt->gpe0_blk_len>>1, 1066 sc->sc_fadt->gpe1_blk_len>>1, regval); 1067 if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) { 1068 reg = ACPIREG_GPE0_STS; 1069 } 1070 break; 1071 case ACPIREG_GPE_EN: 1072 __size = 1; 1073 dnprintf(50, "write GPE_EN offset: %.2x %.2x %.2x %.2x\n", 1074 offset, sc->sc_fadt->gpe0_blk_len>>1, 1075 sc->sc_fadt->gpe1_blk_len>>1, regval); 1076 if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) { 1077 reg = ACPIREG_GPE0_EN; 1078 } 1079 break; 1080 } 1081 1082 /* All special case return here */ 1083 if (reg >= ACPIREG_MAXREG) 1084 return; 1085 1086 ioh = sc->sc_pmregs[reg].ioh; 1087 size = sc->sc_pmregs[reg].size; 1088 if (__size) 1089 size = __size; 1090 if (size > 4) 1091 size = 4; 1092 switch (size) { 1093 case 1: 1094 bus_space_write_1(sc->sc_iot, ioh, offset, regval); 1095 break; 1096 case 2: 1097 bus_space_write_2(sc->sc_iot, ioh, offset, regval); 1098 break; 1099 case 4: 1100 bus_space_write_4(sc->sc_iot, ioh, offset, regval); 1101 break; 1102 } 1103 1104 dnprintf(30, "acpi_writepm: %s = %.4x:%.4x %x\n", 1105 sc->sc_pmregs[reg].name, sc->sc_pmregs[reg].addr, offset, regval); 1106 } 1107 1108 /* Map Power Management registers */ 1109 void 1110 acpi_map_pmregs(struct acpi_softc *sc) 1111 { 1112 bus_addr_t addr; 1113 bus_size_t size; 1114 const char *name; 1115 int reg; 1116 1117 for (reg = 0; reg < ACPIREG_MAXREG; reg++) { 1118 size = 0; 1119 switch (reg) { 1120 case ACPIREG_SMICMD: 1121 name = "smi"; 1122 size = 1; 1123 addr = sc->sc_fadt->smi_cmd; 1124 break; 1125 case ACPIREG_PM1A_STS: 1126 case ACPIREG_PM1A_EN: 1127 name = "pm1a_sts"; 1128 size = sc->sc_fadt->pm1_evt_len >> 1; 1129 addr = sc->sc_fadt->pm1a_evt_blk; 1130 if (reg == ACPIREG_PM1A_EN && addr) { 1131 addr += size; 1132 name = "pm1a_en"; 1133 } 1134 break; 1135 case ACPIREG_PM1A_CNT: 1136 name = "pm1a_cnt"; 1137 size = sc->sc_fadt->pm1_cnt_len; 1138 addr = sc->sc_fadt->pm1a_cnt_blk; 1139 break; 1140 case ACPIREG_PM1B_STS: 1141 case ACPIREG_PM1B_EN: 1142 name = "pm1b_sts"; 1143 size = sc->sc_fadt->pm1_evt_len >> 1; 1144 addr = sc->sc_fadt->pm1b_evt_blk; 1145 if (reg == ACPIREG_PM1B_EN && addr) { 1146 addr += size; 1147 name = "pm1b_en"; 1148 } 1149 break; 1150 case ACPIREG_PM1B_CNT: 1151 name = "pm1b_cnt"; 1152 size = sc->sc_fadt->pm1_cnt_len; 1153 addr = sc->sc_fadt->pm1b_cnt_blk; 1154 break; 1155 case ACPIREG_PM2_CNT: 1156 name = "pm2_cnt"; 1157 size = sc->sc_fadt->pm2_cnt_len; 1158 addr = sc->sc_fadt->pm2_cnt_blk; 1159 break; 1160 #if 0 1161 case ACPIREG_PM_TMR: 1162 /* Allocated in acpitimer */ 1163 name = "pm_tmr"; 1164 size = sc->sc_fadt->pm_tmr_len; 1165 addr = sc->sc_fadt->pm_tmr_blk; 1166 break; 1167 #endif 1168 case ACPIREG_GPE0_STS: 1169 case ACPIREG_GPE0_EN: 1170 name = "gpe0_sts"; 1171 size = sc->sc_fadt->gpe0_blk_len >> 1; 1172 addr = sc->sc_fadt->gpe0_blk; 1173 1174 dnprintf(20, "gpe0 block len : %x\n", 1175 sc->sc_fadt->gpe0_blk_len >> 1); 1176 dnprintf(20, "gpe0 block addr: %x\n", 1177 sc->sc_fadt->gpe0_blk); 1178 if (reg == ACPIREG_GPE0_EN && addr) { 1179 addr += size; 1180 name = "gpe0_en"; 1181 } 1182 break; 1183 case ACPIREG_GPE1_STS: 1184 case ACPIREG_GPE1_EN: 1185 name = "gpe1_sts"; 1186 size = sc->sc_fadt->gpe1_blk_len >> 1; 1187 addr = sc->sc_fadt->gpe1_blk; 1188 1189 dnprintf(20, "gpe1 block len : %x\n", 1190 sc->sc_fadt->gpe1_blk_len >> 1); 1191 dnprintf(20, "gpe1 block addr: %x\n", 1192 sc->sc_fadt->gpe1_blk); 1193 if (reg == ACPIREG_GPE1_EN && addr) { 1194 addr += size; 1195 name = "gpe1_en"; 1196 } 1197 break; 1198 } 1199 if (size && addr) { 1200 dnprintf(50, "mapping: %.4x %.4x %s\n", 1201 addr, size, name); 1202 1203 /* Size and address exist; map register space */ 1204 bus_space_map(sc->sc_iot, addr, size, 0, 1205 &sc->sc_pmregs[reg].ioh); 1206 1207 sc->sc_pmregs[reg].name = name; 1208 sc->sc_pmregs[reg].size = size; 1209 sc->sc_pmregs[reg].addr = addr; 1210 } 1211 } 1212 } 1213 1214 /* move all stuff that doesn't go on the boot media in here */ 1215 #ifndef SMALL_KERNEL 1216 void 1217 acpi_reset(void) 1218 { 1219 struct acpi_fadt *fadt; 1220 u_int32_t reset_as, reset_len; 1221 u_int32_t value; 1222 1223 fadt = acpi_softc->sc_fadt; 1224 1225 /* 1226 * RESET_REG_SUP is not properly set in some implementations, 1227 * but not testing against it breaks more machines than it fixes 1228 */ 1229 if (acpi_softc->sc_revision <= 1 || 1230 !(fadt->flags & FADT_RESET_REG_SUP) || fadt->reset_reg.address == 0) 1231 return; 1232 1233 value = fadt->reset_value; 1234 1235 reset_as = fadt->reset_reg.register_bit_width / 8; 1236 if (reset_as == 0) 1237 reset_as = 1; 1238 1239 reset_len = fadt->reset_reg.access_size; 1240 if (reset_len == 0) 1241 reset_len = reset_as; 1242 1243 acpi_gasio(acpi_softc, ACPI_IOWRITE, 1244 fadt->reset_reg.address_space_id, 1245 fadt->reset_reg.address, reset_as, reset_len, &value); 1246 1247 delay(100000); 1248 } 1249 1250 int 1251 acpi_interrupt(void *arg) 1252 { 1253 struct acpi_softc *sc = (struct acpi_softc *)arg; 1254 u_int32_t processed, sts, en, idx, jdx; 1255 1256 processed = 0; 1257 1258 #if 0 1259 acpi_add_gpeblock(sc, sc->sc_fadt->gpe0_blk, sc->sc_fadt->gpe0_blk_len>>1, 0); 1260 acpi_add_gpeblock(sc, sc->sc_fadt->gpe1_blk, sc->sc_fadt->gpe1_blk_len>>1, 1261 sc->sc_fadt->gpe1_base); 1262 #endif 1263 1264 dnprintf(40, "ACPI Interrupt\n"); 1265 for (idx = 0; idx < sc->sc_lastgpe; idx += 8) { 1266 sts = acpi_read_pmreg(sc, ACPIREG_GPE_STS, idx>>3); 1267 en = acpi_read_pmreg(sc, ACPIREG_GPE_EN, idx>>3); 1268 if (en & sts) { 1269 dnprintf(10, "GPE block: %.2x %.2x %.2x\n", idx, sts, 1270 en); 1271 acpi_write_pmreg(sc, ACPIREG_GPE_EN, idx>>3, en & ~sts); 1272 for (jdx = 0; jdx < 8; jdx++) { 1273 if (en & sts & (1L << jdx)) { 1274 /* Signal this GPE */ 1275 sc->gpe_table[idx+jdx].active = 1; 1276 processed = 1; 1277 } 1278 } 1279 } 1280 } 1281 1282 sts = acpi_read_pmreg(sc, ACPIREG_PM1_STS, 0); 1283 en = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0); 1284 if (sts & en) { 1285 dnprintf(10,"GEN interrupt: %.4x\n", sts & en); 1286 acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en & ~sts); 1287 acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, en); 1288 acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en); 1289 if (sts & ACPI_PM1_PWRBTN_STS) 1290 sc->sc_powerbtn = 1; 1291 if (sts & ACPI_PM1_SLPBTN_STS) 1292 sc->sc_sleepbtn = 1; 1293 processed = 1; 1294 } 1295 1296 if (processed) { 1297 sc->sc_wakeup = 0; 1298 wakeup(sc); 1299 } 1300 1301 return (processed); 1302 } 1303 1304 int 1305 acpi_add_device(struct aml_node *node, void *arg) 1306 { 1307 static int nacpicpus = 0; 1308 struct device *self = arg; 1309 struct acpi_softc *sc = arg; 1310 struct acpi_attach_args aaa; 1311 #ifdef MULTIPROCESSOR 1312 struct aml_value res; 1313 int proc_id = -1; 1314 #endif 1315 1316 memset(&aaa, 0, sizeof(aaa)); 1317 aaa.aaa_node = node; 1318 aaa.aaa_iot = sc->sc_iot; 1319 aaa.aaa_memt = sc->sc_memt; 1320 if (node == NULL || node->value == NULL) 1321 return 0; 1322 1323 switch (node->value->type) { 1324 case AML_OBJTYPE_PROCESSOR: 1325 if (nacpicpus >= ncpus) 1326 return 0; 1327 #ifdef MULTIPROCESSOR 1328 if (aml_evalnode(sc, aaa.aaa_node, 0, NULL, &res) == 0) { 1329 if (res.type == AML_OBJTYPE_PROCESSOR) 1330 proc_id = res.v_processor.proc_id; 1331 aml_freevalue(&res); 1332 } 1333 if (proc_id < -1 || proc_id >= LAPIC_MAP_SIZE || 1334 (acpi_lapic_flags[proc_id] & ACPI_PROC_ENABLE) == 0) 1335 return 0; 1336 #endif 1337 nacpicpus++; 1338 1339 aaa.aaa_name = "acpicpu"; 1340 break; 1341 case AML_OBJTYPE_THERMZONE: 1342 aaa.aaa_name = "acpitz"; 1343 break; 1344 default: 1345 return 0; 1346 } 1347 config_found(self, &aaa, acpi_print); 1348 return 0; 1349 } 1350 1351 void 1352 acpi_enable_onegpe(struct acpi_softc *sc, int gpe, int enable) 1353 { 1354 uint8_t mask = (1L << (gpe & 7)); 1355 uint8_t en; 1356 1357 /* Read enabled register */ 1358 en = acpi_read_pmreg(sc, ACPIREG_GPE_EN, gpe>>3); 1359 dnprintf(50, "%sabling GPE %.2x (current: %sabled) %.2x\n", 1360 enable ? "en" : "dis", gpe, (en & mask) ? "en" : "dis", en); 1361 if (enable) 1362 en |= mask; 1363 else 1364 en &= ~mask; 1365 acpi_write_pmreg(sc, ACPIREG_GPE_EN, gpe>>3, en); 1366 } 1367 1368 int 1369 acpi_set_gpehandler(struct acpi_softc *sc, int gpe, int (*handler) 1370 (struct acpi_softc *, int, void *), void *arg, const char *label) 1371 { 1372 struct gpe_block *ptbl; 1373 1374 ptbl = acpi_find_gpe(sc, gpe); 1375 if (ptbl == NULL || handler == NULL) 1376 return -EINVAL; 1377 if (ptbl->handler != NULL) { 1378 dnprintf(10, "error: GPE %.2x already enabled\n", gpe); 1379 return -EBUSY; 1380 } 1381 dnprintf(50, "Adding GPE handler %.2x (%s)\n", gpe, label); 1382 ptbl->handler = handler; 1383 ptbl->arg = arg; 1384 1385 return (0); 1386 } 1387 1388 int 1389 acpi_gpe_level(struct acpi_softc *sc, int gpe, void *arg) 1390 { 1391 struct aml_node *node = arg; 1392 uint8_t mask; 1393 1394 dnprintf(10, "handling Level-sensitive GPE %.2x\n", gpe); 1395 mask = (1L << (gpe & 7)); 1396 1397 aml_evalnode(sc, node, 0, NULL, NULL); 1398 acpi_write_pmreg(sc, ACPIREG_GPE_STS, gpe>>3, mask); 1399 acpi_write_pmreg(sc, ACPIREG_GPE_EN, gpe>>3, mask); 1400 1401 return (0); 1402 } 1403 1404 int 1405 acpi_gpe_edge(struct acpi_softc *sc, int gpe, void *arg) 1406 { 1407 1408 struct aml_node *node = arg; 1409 uint8_t mask; 1410 1411 dnprintf(10, "handling Edge-sensitive GPE %.2x\n", gpe); 1412 mask = (1L << (gpe & 7)); 1413 1414 aml_evalnode(sc, node, 0, NULL, NULL); 1415 acpi_write_pmreg(sc, ACPIREG_GPE_STS, gpe>>3, mask); 1416 acpi_write_pmreg(sc, ACPIREG_GPE_EN, gpe>>3, mask); 1417 1418 return (0); 1419 } 1420 1421 /* Discover Devices that can wakeup the system 1422 * _PRW returns a package 1423 * pkg[0] = integer (FADT gpe bit) or package (gpe block,gpe bit) 1424 * pkg[1] = lowest sleep state 1425 * pkg[2+] = power resource devices (optional) 1426 * 1427 * To enable wakeup devices: 1428 * Evaluate _ON method in each power resource device 1429 * Evaluate _PSW method 1430 */ 1431 int 1432 acpi_foundprw(struct aml_node *node, void *arg) 1433 { 1434 struct acpi_softc *sc = arg; 1435 struct acpi_wakeq *wq; 1436 1437 wq = (struct acpi_wakeq *)malloc(sizeof(struct acpi_wakeq), M_DEVBUF, M_NOWAIT); 1438 if (wq == NULL) { 1439 return 0; 1440 } 1441 memset(wq, 0, sizeof(struct acpi_wakeq)); 1442 1443 wq->q_wakepkg = (struct aml_value *)malloc(sizeof(struct aml_value), 1444 M_DEVBUF, M_NOWAIT); 1445 if (wq->q_wakepkg == NULL) { 1446 free(wq, M_DEVBUF); 1447 return 0; 1448 } 1449 memset(wq->q_wakepkg, 0, sizeof(struct aml_value)); 1450 dnprintf(10, "Found _PRW (%s)\n", node->parent->name); 1451 aml_evalnode(sc, node, 0, NULL, wq->q_wakepkg); 1452 wq->q_node = node->parent; 1453 wq->q_gpe = -1; 1454 1455 /* Get GPE of wakeup device, and lowest sleep level */ 1456 if (wq->q_wakepkg->type == AML_OBJTYPE_PACKAGE && wq->q_wakepkg->length >= 2) { 1457 if (wq->q_wakepkg->v_package[0]->type == AML_OBJTYPE_INTEGER) { 1458 wq->q_gpe = wq->q_wakepkg->v_package[0]->v_integer; 1459 } 1460 if (wq->q_wakepkg->v_package[1]->type == AML_OBJTYPE_INTEGER) { 1461 wq->q_state = wq->q_wakepkg->v_package[1]->v_integer; 1462 } 1463 } 1464 SIMPLEQ_INSERT_TAIL(&sc->sc_wakedevs, wq, q_next); 1465 return 0; 1466 } 1467 1468 struct gpe_block * 1469 acpi_find_gpe(struct acpi_softc *sc, int gpe) 1470 { 1471 #if 1 1472 if (gpe >= sc->sc_lastgpe) 1473 return NULL; 1474 return &sc->gpe_table[gpe]; 1475 #else 1476 SIMPLEQ_FOREACH(pgpe, &sc->sc_gpes, gpe_link) { 1477 if (gpe >= pgpe->start && gpe <= (pgpe->start+7)) 1478 return &pgpe->table[gpe & 7]; 1479 } 1480 return NULL; 1481 #endif 1482 } 1483 1484 #if 0 1485 /* New GPE handling code: Create GPE block */ 1486 void 1487 acpi_init_gpeblock(struct acpi_softc *sc, int reg, int len, int base) 1488 { 1489 int i, j; 1490 1491 if (!reg || !len) 1492 return; 1493 for (i=0; i<len; i++) { 1494 pgpe = acpi_os_malloc(sizeof(gpeblock)); 1495 if (pgpe == NULL) 1496 return; 1497 1498 /* Allocate GPE Handler Block */ 1499 pgpe->start = base + i; 1500 acpi_bus_space_map(sc->sc_iot, reg+i, 1, 0, &pgpe->sts_ioh); 1501 acpi_bus_space_map(sc->sc_iot, reg+i+len, 1, 0, &pgpe->en_ioh); 1502 SIMPLEQ_INSERT_TAIL(&sc->sc_gpes, gpe, gpe_link); 1503 1504 /* Clear pending GPEs */ 1505 bus_space_write_1(sc->sc_iot, pgpe->sts_ioh, 0, 0xFF); 1506 bus_space_write_1(sc->sc_iot, pgpe->en_ioh, 0, 0x00); 1507 } 1508 1509 /* Search for GPE handlers */ 1510 for (i=0; i<len*8; i++) { 1511 char gpestr[32]; 1512 struct aml_node *h; 1513 1514 snprintf(gpestr, sizeof(gpestr), "\\_GPE._L%.2X", base+i); 1515 h = aml_searchnode(&aml_root, gpestr); 1516 if (acpi_set_gpehandler(sc, base+i, acpi_gpe_level, h, "level") != 0) { 1517 snprintf(gpestr, sizeof(gpestr), "\\_GPE._E%.2X", base+i); 1518 h = aml_searchnode(&aml_root, gpestr); 1519 acpi_set_gpehandler(sc, base+i, acpi_gpe_edge, h, "edge"); 1520 } 1521 } 1522 } 1523 1524 /* Process GPE interrupts */ 1525 int 1526 acpi_handle_gpes(struct acpi_softc *sc) 1527 { 1528 uint8_t en, sts; 1529 int processed, i; 1530 1531 processed=0; 1532 SIMPLEQ_FOREACH(pgpe, &sc->sc_gpes, gpe_link) { 1533 sts = bus_space_read_1(sc->sc_iot, pgpe->sts_ioh, 0); 1534 en = bus_space_read_1(sc->sc_iot, pgpe->en_ioh, 0); 1535 for (i=0; i<8; i++) { 1536 if (en & sts & (1L << i)) { 1537 pgpe->table[i].active = 1; 1538 processed=1; 1539 } 1540 } 1541 } 1542 return processed; 1543 } 1544 #endif 1545 1546 #if 0 1547 void 1548 acpi_add_gpeblock(struct acpi_softc *sc, int reg, int len, int gpe) 1549 { 1550 int idx, jdx; 1551 u_int8_t en, sts; 1552 1553 if (!reg || !len) 1554 return; 1555 for (idx=0; idx<len; idx++) { 1556 sts = inb(reg + idx); 1557 en = inb(reg + len + idx); 1558 printf("-- gpe %.2x-%.2x : en:%.2x sts:%.2x %.2x\n", 1559 gpe+idx*8, gpe+idx*8+7, en, sts, en&sts); 1560 for (jdx=0; jdx<8; jdx++) { 1561 char gpestr[32]; 1562 struct aml_node *l, *e; 1563 1564 if (en & sts & (1L << jdx)) { 1565 snprintf(gpestr,sizeof(gpestr), "\\_GPE._L%.2X", gpe+idx*8+jdx); 1566 l = aml_searchname(&aml_root, gpestr); 1567 snprintf(gpestr,sizeof(gpestr), "\\_GPE._E%.2X", gpe+idx*8+jdx); 1568 e = aml_searchname(&aml_root, gpestr); 1569 printf(" GPE %.2x active L%x E%x\n", gpe+idx*8+jdx, l, e); 1570 } 1571 } 1572 } 1573 } 1574 #endif 1575 1576 void 1577 acpi_init_gpes(struct acpi_softc *sc) 1578 { 1579 struct aml_node *gpe; 1580 char name[12]; 1581 int idx, ngpe; 1582 1583 #if 0 1584 acpi_add_gpeblock(sc, sc->sc_fadt->gpe0_blk, sc->sc_fadt->gpe0_blk_len>>1, 0); 1585 acpi_add_gpeblock(sc, sc->sc_fadt->gpe1_blk, sc->sc_fadt->gpe1_blk_len>>1, 1586 sc->sc_fadt->gpe1_base); 1587 #endif 1588 1589 sc->sc_lastgpe = sc->sc_fadt->gpe0_blk_len << 2; 1590 if (sc->sc_fadt->gpe1_blk_len) { 1591 } 1592 dnprintf(50, "Last GPE: %.2x\n", sc->sc_lastgpe); 1593 1594 /* Allocate GPE table */ 1595 sc->gpe_table = malloc(sc->sc_lastgpe * sizeof(struct gpe_block), 1596 M_DEVBUF, M_WAITOK | M_ZERO); 1597 1598 ngpe = 0; 1599 1600 /* Clear GPE status */ 1601 for (idx = 0; idx < sc->sc_lastgpe; idx += 8) { 1602 acpi_write_pmreg(sc, ACPIREG_GPE_EN, idx>>3, 0); 1603 acpi_write_pmreg(sc, ACPIREG_GPE_STS, idx>>3, -1); 1604 } 1605 for (idx = 0; idx < sc->sc_lastgpe; idx++) { 1606 /* Search Level-sensitive GPES */ 1607 snprintf(name, sizeof(name), "\\_GPE._L%.2X", idx); 1608 gpe = aml_searchname(&aml_root, name); 1609 if (gpe != NULL) 1610 acpi_set_gpehandler(sc, idx, acpi_gpe_level, gpe, 1611 "level"); 1612 if (gpe == NULL) { 1613 /* Search Edge-sensitive GPES */ 1614 snprintf(name, sizeof(name), "\\_GPE._E%.2X", idx); 1615 gpe = aml_searchname(&aml_root, name); 1616 if (gpe != NULL) 1617 acpi_set_gpehandler(sc, idx, acpi_gpe_edge, gpe, 1618 "edge"); 1619 } 1620 } 1621 aml_find_node(&aml_root, "_PRW", acpi_foundprw, sc); 1622 sc->sc_maxgpe = ngpe; 1623 } 1624 1625 void 1626 acpi_init_states(struct acpi_softc *sc) 1627 { 1628 struct aml_value res; 1629 char name[8]; 1630 int i; 1631 1632 for (i = ACPI_STATE_S0; i <= ACPI_STATE_S5; i++) { 1633 snprintf(name, sizeof(name), "_S%d_", i); 1634 sc->sc_sleeptype[i].slp_typa = -1; 1635 sc->sc_sleeptype[i].slp_typb = -1; 1636 if (aml_evalname(sc, &aml_root, name, 0, NULL, &res) == 0) { 1637 if (res.type == AML_OBJTYPE_PACKAGE) { 1638 sc->sc_sleeptype[i].slp_typa = aml_val2int(res.v_package[0]); 1639 sc->sc_sleeptype[i].slp_typb = aml_val2int(res.v_package[1]); 1640 } 1641 aml_freevalue(&res); 1642 } 1643 } 1644 } 1645 1646 void 1647 acpi_init_pm(struct acpi_softc *sc) 1648 { 1649 sc->sc_tts = aml_searchname(&aml_root, "_TTS"); 1650 sc->sc_pts = aml_searchname(&aml_root, "_PTS"); 1651 sc->sc_wak = aml_searchname(&aml_root, "_WAK"); 1652 sc->sc_bfs = aml_searchname(&aml_root, "_BFS"); 1653 sc->sc_gts = aml_searchname(&aml_root, "_GTS"); 1654 } 1655 1656 void 1657 acpi_enter_sleep_state(struct acpi_softc *sc, int state) 1658 { 1659 struct aml_value env; 1660 u_int16_t rega, regb; 1661 int retries; 1662 1663 if (state == ACPI_STATE_S0) 1664 return; 1665 if (sc->sc_sleeptype[state].slp_typa == -1 || 1666 sc->sc_sleeptype[state].slp_typb == -1) { 1667 printf("%s: state S%d unavailable\n", 1668 sc->sc_dev.dv_xname, state); 1669 return; 1670 } 1671 1672 memset(&env, 0, sizeof(env)); 1673 env.type = AML_OBJTYPE_INTEGER; 1674 env.v_integer = state; 1675 /* _TTS(state) */ 1676 if (sc->sc_tts) { 1677 if (aml_evalnode(sc, sc->sc_tts, 1, &env, NULL) != 0) { 1678 dnprintf(10, "%s evaluating method _TTS failed.\n", 1679 DEVNAME(sc)); 1680 return; 1681 } 1682 } 1683 switch (state) { 1684 case ACPI_STATE_S1: 1685 case ACPI_STATE_S2: 1686 resettodr(); 1687 dopowerhooks(PWR_SUSPEND); 1688 break; 1689 case ACPI_STATE_S3: 1690 resettodr(); 1691 dopowerhooks(PWR_STANDBY); 1692 break; 1693 } 1694 /* _PTS(state) */ 1695 if (sc->sc_pts) { 1696 if (aml_evalnode(sc, sc->sc_pts, 1, &env, NULL) != 0) { 1697 dnprintf(10, "%s evaluating method _PTS failed.\n", 1698 DEVNAME(sc)); 1699 return; 1700 } 1701 } 1702 sc->sc_state = state; 1703 /* _GTS(state) */ 1704 if (sc->sc_gts) { 1705 if (aml_evalnode(sc, sc->sc_gts, 1, &env, NULL) != 0) { 1706 dnprintf(10, "%s evaluating method _GTS failed.\n", 1707 DEVNAME(sc)); 1708 return; 1709 } 1710 } 1711 disable_intr(); 1712 1713 /* Clear WAK_STS bit */ 1714 acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, ACPI_PM1_WAK_STS); 1715 1716 /* Write SLP_TYPx values */ 1717 rega = acpi_read_pmreg(sc, ACPIREG_PM1A_CNT, 0); 1718 regb = acpi_read_pmreg(sc, ACPIREG_PM1B_CNT, 0); 1719 rega &= ~(ACPI_PM1_SLP_TYPX_MASK | ACPI_PM1_SLP_EN); 1720 regb &= ~(ACPI_PM1_SLP_TYPX_MASK | ACPI_PM1_SLP_EN); 1721 rega |= ACPI_PM1_SLP_TYPX(sc->sc_sleeptype[state].slp_typa); 1722 regb |= ACPI_PM1_SLP_TYPX(sc->sc_sleeptype[state].slp_typb); 1723 acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, 0, rega); 1724 acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, 0, regb); 1725 1726 /* Set SLP_EN bit */ 1727 rega |= ACPI_PM1_SLP_EN; 1728 regb |= ACPI_PM1_SLP_EN; 1729 acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, 0, rega); 1730 acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, 0, regb); 1731 1732 /* Loop on WAK_STS */ 1733 for (retries = 1000; retries > 0; retries--) { 1734 rega = acpi_read_pmreg(sc, ACPIREG_PM1A_STS, 0); 1735 regb = acpi_read_pmreg(sc, ACPIREG_PM1B_STS, 0); 1736 if (rega & ACPI_PM1_WAK_STS || 1737 regb & ACPI_PM1_WAK_STS) 1738 break; 1739 DELAY(10); 1740 } 1741 1742 enable_intr(); 1743 } 1744 1745 #if 0 1746 void 1747 acpi_resume(struct acpi_softc *sc) 1748 { 1749 struct aml_value env; 1750 1751 memset(&env, 0, sizeof(env)); 1752 env.type = AML_OBJTYPE_INTEGER; 1753 env.v_integer = sc->sc_state; 1754 1755 if (sc->sc_bfs) { 1756 if (aml_evalnode(sc, sc->sc_pts, 1, &env, NULL) != 0) { 1757 dnprintf(10, "%s evaluating method _BFS failed.\n", 1758 DEVNAME(sc)); 1759 } 1760 } 1761 dopowerhooks(PWR_RESUME); 1762 inittodr(0); 1763 if (sc->sc_wak) { 1764 if (aml_evalnode(sc, sc->sc_wak, 1, &env, NULL) != 0) { 1765 dnprintf(10, "%s evaluating method _WAK failed.\n", 1766 DEVNAME(sc)); 1767 } 1768 } 1769 sc->sc_state = ACPI_STATE_S0; 1770 if (sc->sc_tts) { 1771 env.v_integer = sc->sc_state; 1772 if (aml_evalnode(sc, sc->sc_wak, 1, &env, NULL) != 0) { 1773 dnprintf(10, "%s evaluating method _TTS failed.\n", 1774 DEVNAME(sc)); 1775 } 1776 } 1777 } 1778 #endif 1779 1780 void 1781 acpi_powerdown(void) 1782 { 1783 acpi_enter_sleep_state(acpi_softc, ACPI_STATE_S5); 1784 } 1785 1786 extern int aml_busy; 1787 1788 void 1789 acpi_isr_thread(void *arg) 1790 { 1791 struct acpi_thread *thread = arg; 1792 struct acpi_softc *sc = thread->sc; 1793 u_int32_t gpe; 1794 1795 /* 1796 * If we have an interrupt handler, we can get notification 1797 * when certain status bits changes in the ACPI registers, 1798 * so let us enable some events we can forward to userland 1799 */ 1800 if (sc->sc_interrupt) { 1801 int16_t flag; 1802 1803 dnprintf(1,"slpbtn:%c pwrbtn:%c\n", 1804 sc->sc_fadt->flags & FADT_SLP_BUTTON ? 'n' : 'y', 1805 sc->sc_fadt->flags & FADT_PWR_BUTTON ? 'n' : 'y'); 1806 dnprintf(10, "Enabling acpi interrupts...\n"); 1807 sc->sc_wakeup = 1; 1808 1809 /* Enable Sleep/Power buttons if they exist */ 1810 flag = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0); 1811 if (!(sc->sc_fadt->flags & FADT_PWR_BUTTON)) { 1812 flag |= ACPI_PM1_PWRBTN_EN; 1813 } 1814 if (!(sc->sc_fadt->flags & FADT_SLP_BUTTON)) { 1815 flag |= ACPI_PM1_SLPBTN_EN; 1816 } 1817 acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, flag); 1818 1819 /* Enable handled GPEs here */ 1820 for (gpe = 0; gpe < sc->sc_lastgpe; gpe++) { 1821 if (sc->gpe_table[gpe].handler) 1822 acpi_enable_onegpe(sc, gpe, 1); 1823 } 1824 } 1825 1826 while (thread->running) { 1827 dnprintf(10, "sleep... %d\n", sc->sc_wakeup); 1828 while (sc->sc_wakeup) 1829 tsleep(sc, PWAIT, "acpi_idle", 0); 1830 sc->sc_wakeup = 1; 1831 dnprintf(10, "wakeup..\n"); 1832 if (aml_busy) 1833 continue; 1834 1835 for (gpe = 0; gpe < sc->sc_lastgpe; gpe++) { 1836 struct gpe_block *pgpe = &sc->gpe_table[gpe]; 1837 1838 if (pgpe->active) { 1839 pgpe->active = 0; 1840 dnprintf(50, "softgpe: %.2x\n", gpe); 1841 if (pgpe->handler) 1842 pgpe->handler(sc, gpe, pgpe->arg); 1843 } 1844 } 1845 if (sc->sc_powerbtn) { 1846 sc->sc_powerbtn = 0; 1847 1848 aml_notify_dev(ACPI_DEV_PBD, 0x80); 1849 1850 acpi_evindex++; 1851 dnprintf(1,"power button pressed\n"); 1852 KNOTE(sc->sc_note, ACPI_EVENT_COMPOSE(ACPI_EV_PWRBTN, 1853 acpi_evindex)); 1854 } 1855 if (sc->sc_sleepbtn) { 1856 sc->sc_sleepbtn = 0; 1857 1858 aml_notify_dev(ACPI_DEV_SBD, 0x80); 1859 1860 acpi_evindex++; 1861 dnprintf(1,"sleep button pressed\n"); 1862 KNOTE(sc->sc_note, ACPI_EVENT_COMPOSE(ACPI_EV_SLPBTN, 1863 acpi_evindex)); 1864 } 1865 1866 /* handle polling here to keep code non-concurrent*/ 1867 if (sc->sc_poll) { 1868 sc->sc_poll = 0; 1869 acpi_poll_notify(); 1870 } 1871 } 1872 free(thread, M_DEVBUF); 1873 1874 kthread_exit(0); 1875 } 1876 1877 void 1878 acpi_create_thread(void *arg) 1879 { 1880 struct acpi_softc *sc = arg; 1881 1882 if (kthread_create(acpi_isr_thread, sc->sc_thread, NULL, DEVNAME(sc)) 1883 != 0) { 1884 printf("%s: unable to create isr thread, GPEs disabled\n", 1885 DEVNAME(sc)); 1886 return; 1887 } 1888 } 1889 1890 int 1891 acpi_map_address(struct acpi_softc *sc, struct acpi_gas *gas, bus_addr_t base, 1892 bus_size_t size, bus_space_handle_t *pioh, bus_space_tag_t *piot) 1893 { 1894 int iospace = GAS_SYSTEM_IOSPACE; 1895 1896 /* No GAS structure, default to I/O space */ 1897 if (gas != NULL) { 1898 base += gas->address; 1899 iospace = gas->address_space_id; 1900 } 1901 switch (iospace) { 1902 case GAS_SYSTEM_MEMORY: 1903 *piot = sc->sc_memt; 1904 break; 1905 case GAS_SYSTEM_IOSPACE: 1906 *piot = sc->sc_iot; 1907 break; 1908 default: 1909 return -1; 1910 } 1911 if (bus_space_map(*piot, base, size, 0, pioh)) 1912 return -1; 1913 1914 return 0; 1915 } 1916 1917 int 1918 acpi_foundec(struct aml_node *node, void *arg) 1919 { 1920 struct acpi_softc *sc = (struct acpi_softc *)arg; 1921 struct device *self = (struct device *)arg; 1922 const char *dev; 1923 struct aml_value res; 1924 struct acpi_attach_args aaa; 1925 1926 if (aml_evalnode(sc, node, 0, NULL, &res) != 0) 1927 return 0; 1928 1929 switch (res.type) { 1930 case AML_OBJTYPE_STRING: 1931 dev = res.v_string; 1932 break; 1933 case AML_OBJTYPE_INTEGER: 1934 dev = aml_eisaid(aml_val2int(&res)); 1935 break; 1936 default: 1937 dev = "unknown"; 1938 break; 1939 } 1940 1941 if (strcmp(dev, ACPI_DEV_ECD)) 1942 return 0; 1943 1944 memset(&aaa, 0, sizeof(aaa)); 1945 aaa.aaa_iot = sc->sc_iot; 1946 aaa.aaa_memt = sc->sc_memt; 1947 aaa.aaa_node = node->parent; 1948 aaa.aaa_dev = dev; 1949 aaa.aaa_name = "acpiec"; 1950 config_found(self, &aaa, acpi_print); 1951 aml_freevalue(&res); 1952 1953 return 0; 1954 } 1955 1956 int 1957 acpi_foundhid(struct aml_node *node, void *arg) 1958 { 1959 struct acpi_softc *sc = (struct acpi_softc *)arg; 1960 struct device *self = (struct device *)arg; 1961 const char *dev; 1962 struct aml_value res; 1963 struct acpi_attach_args aaa; 1964 1965 dnprintf(10, "found hid device: %s ", node->parent->name); 1966 if (aml_evalnode(sc, node, 0, NULL, &res) != 0) 1967 return 0; 1968 1969 switch (res.type) { 1970 case AML_OBJTYPE_STRING: 1971 dev = res.v_string; 1972 break; 1973 case AML_OBJTYPE_INTEGER: 1974 dev = aml_eisaid(aml_val2int(&res)); 1975 break; 1976 default: 1977 dev = "unknown"; 1978 break; 1979 } 1980 dnprintf(10, " device: %s\n", dev); 1981 1982 memset(&aaa, 0, sizeof(aaa)); 1983 aaa.aaa_iot = sc->sc_iot; 1984 aaa.aaa_memt = sc->sc_memt; 1985 aaa.aaa_node = node->parent; 1986 aaa.aaa_dev = dev; 1987 1988 if (!strcmp(dev, ACPI_DEV_AC)) 1989 aaa.aaa_name = "acpiac"; 1990 else if (!strcmp(dev, ACPI_DEV_CMB)) 1991 aaa.aaa_name = "acpibat"; 1992 else if (!strcmp(dev, ACPI_DEV_LD) || 1993 !strcmp(dev, ACPI_DEV_PBD) || 1994 !strcmp(dev, ACPI_DEV_SBD)) 1995 aaa.aaa_name = "acpibtn"; 1996 else if (!strcmp(dev, ACPI_DEV_ASUS)) 1997 aaa.aaa_name = "acpiasus"; 1998 else if (!strcmp(dev, ACPI_DEV_THINKPAD)) 1999 aaa.aaa_name = "acpithinkpad"; 2000 2001 if (aaa.aaa_name) 2002 config_found(self, &aaa, acpi_print); 2003 2004 aml_freevalue(&res); 2005 2006 return 0; 2007 } 2008 2009 int 2010 acpi_founddock(struct aml_node *node, void *arg) 2011 { 2012 struct acpi_softc *sc = (struct acpi_softc *)arg; 2013 struct device *self = (struct device *)arg; 2014 struct acpi_attach_args aaa; 2015 2016 dnprintf(10, "found dock entry: %s\n", node->parent->name); 2017 2018 memset(&aaa, 0, sizeof(aaa)); 2019 aaa.aaa_iot = sc->sc_iot; 2020 aaa.aaa_memt = sc->sc_memt; 2021 aaa.aaa_node = node->parent; 2022 aaa.aaa_name = "acpidock"; 2023 2024 config_found(self, &aaa, acpi_print); 2025 2026 return 0; 2027 } 2028 2029 int 2030 acpi_foundvideo(struct aml_node *node, void *arg) 2031 { 2032 struct acpi_softc *sc = (struct acpi_softc *)arg; 2033 struct device *self = (struct device *)arg; 2034 struct acpi_attach_args aaa; 2035 2036 memset(&aaa, 0, sizeof(aaa)); 2037 aaa.aaa_iot = sc->sc_iot; 2038 aaa.aaa_memt = sc->sc_memt; 2039 aaa.aaa_node = node->parent; 2040 aaa.aaa_name = "acpivideo"; 2041 2042 config_found(self, &aaa, acpi_print); 2043 2044 return (0); 2045 } 2046 #endif /* SMALL_KERNEL */ 2047