acpi.c revision 1.360
1/* $OpenBSD: acpi.c,v 1.360 2018/10/26 20:26:19 kettenis 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/buf.h> 22#include <sys/device.h> 23#include <sys/malloc.h> 24#include <sys/fcntl.h> 25#include <sys/ioccom.h> 26#include <sys/event.h> 27#include <sys/signalvar.h> 28#include <sys/proc.h> 29#include <sys/kthread.h> 30#include <sys/sched.h> 31#include <sys/reboot.h> 32#include <sys/sysctl.h> 33#include <sys/mount.h> 34#include <sys/syscallargs.h> 35 36#ifdef HIBERNATE 37#include <sys/hibernate.h> 38#endif 39 40#include <machine/conf.h> 41#include <machine/cpufunc.h> 42#include <machine/bus.h> 43 44#include <dev/rndvar.h> 45#include <dev/pci/pcivar.h> 46#include <dev/acpi/acpireg.h> 47#include <dev/acpi/acpivar.h> 48#include <dev/acpi/amltypes.h> 49#include <dev/acpi/acpidev.h> 50#include <dev/acpi/dsdt.h> 51#include <dev/wscons/wsdisplayvar.h> 52 53#include <dev/pci/pcidevs.h> 54#include <dev/pci/ppbreg.h> 55 56#include <dev/pci/pciidevar.h> 57 58#include <machine/apmvar.h> 59#define APMUNIT(dev) (minor(dev)&0xf0) 60#define APMDEV(dev) (minor(dev)&0x0f) 61#define APMDEV_NORMAL 0 62#define APMDEV_CTL 8 63 64#include "wd.h" 65#include "wsdisplay.h" 66#include "softraid.h" 67 68#ifdef ACPI_DEBUG 69int acpi_debug = 16; 70#endif 71 72int acpi_poll_enabled; 73int acpi_hasprocfvs; 74 75#define ACPIEN_RETRIES 15 76 77struct aml_node *acpi_pci_match(struct device *, struct pci_attach_args *); 78pcireg_t acpi_pci_min_powerstate(pci_chipset_tag_t, pcitag_t); 79void acpi_pci_set_powerstate(pci_chipset_tag_t, pcitag_t, int, int); 80int acpi_pci_notify(struct aml_node *, int, void *); 81 82int acpi_submatch(struct device *, void *, void *); 83int acpi_print(void *, const char *); 84 85void acpi_map_pmregs(struct acpi_softc *); 86void acpi_unmap_pmregs(struct acpi_softc *); 87 88int acpi_loadtables(struct acpi_softc *, struct acpi_rsdp *); 89 90int _acpi_matchhids(const char *, const char *[]); 91 92int acpi_inidev(struct aml_node *, void *); 93int acpi_foundprt(struct aml_node *, void *); 94 95int acpi_enable(struct acpi_softc *); 96void acpi_init_states(struct acpi_softc *); 97 98void acpi_gpe_task(void *, int); 99void acpi_sbtn_task(void *, int); 100void acpi_pbtn_task(void *, int); 101 102int acpi_enabled; 103 104void acpi_init_gpes(struct acpi_softc *); 105void acpi_disable_allgpes(struct acpi_softc *); 106struct gpe_block *acpi_find_gpe(struct acpi_softc *, int); 107void acpi_enable_onegpe(struct acpi_softc *, int); 108int acpi_gpe(struct acpi_softc *, int, void *); 109 110void acpi_enable_rungpes(struct acpi_softc *); 111void acpi_enable_wakegpes(struct acpi_softc *, int); 112 113 114int acpi_foundec(struct aml_node *, void *); 115int acpi_foundsony(struct aml_node *node, void *arg); 116int acpi_foundhid(struct aml_node *, void *); 117int acpi_add_device(struct aml_node *node, void *arg); 118 119void acpi_thread(void *); 120void acpi_create_thread(void *); 121 122#ifndef SMALL_KERNEL 123 124void acpi_indicator(struct acpi_softc *, int); 125 126void acpi_init_pm(struct acpi_softc *); 127 128int acpi_founddock(struct aml_node *, void *); 129int acpi_foundpss(struct aml_node *, void *); 130int acpi_foundtmp(struct aml_node *, void *); 131int acpi_foundprw(struct aml_node *, void *); 132int acpi_foundvideo(struct aml_node *, void *); 133int acpi_foundsbs(struct aml_node *node, void *); 134 135int acpi_foundide(struct aml_node *node, void *arg); 136int acpiide_notify(struct aml_node *, int, void *); 137void wdcattach(struct channel_softc *); 138int wdcdetach(struct channel_softc *, int); 139int is_ejectable_bay(struct aml_node *node); 140int is_ata(struct aml_node *node); 141int is_ejectable(struct aml_node *node); 142 143struct idechnl { 144 struct acpi_softc *sc; 145 int64_t addr; 146 int64_t chnl; 147 int64_t sta; 148}; 149 150/* 151 * This is a list of Synaptics devices with a 'top button area' 152 * based on the list in Linux supplied by Synaptics 153 * Synaptics clickpads with the following pnp ids will get a unique 154 * wscons mouse type that is used to define trackpad regions that will 155 * emulate mouse buttons 156 */ 157static const char *sbtn_pnp[] = { 158 "LEN0017", 159 "LEN0018", 160 "LEN0019", 161 "LEN0023", 162 "LEN002A", 163 "LEN002B", 164 "LEN002C", 165 "LEN002D", 166 "LEN002E", 167 "LEN0033", 168 "LEN0034", 169 "LEN0035", 170 "LEN0036", 171 "LEN0037", 172 "LEN0038", 173 "LEN0039", 174 "LEN0041", 175 "LEN0042", 176 "LEN0045", 177 "LEN0047", 178 "LEN0049", 179 "LEN2000", 180 "LEN2001", 181 "LEN2002", 182 "LEN2003", 183 "LEN2004", 184 "LEN2005", 185 "LEN2006", 186 "LEN2007", 187 "LEN2008", 188 "LEN2009", 189 "LEN200A", 190 "LEN200B", 191}; 192 193int mouse_has_softbtn; 194#endif /* SMALL_KERNEL */ 195 196struct acpi_softc *acpi_softc; 197 198/* XXX move this into dsdt softc at some point */ 199extern struct aml_node aml_root; 200 201struct cfdriver acpi_cd = { 202 NULL, "acpi", DV_DULL 203}; 204 205uint8_t 206acpi_pci_conf_read_1(pci_chipset_tag_t pc, pcitag_t tag, int reg) 207{ 208 uint32_t val = pci_conf_read(pc, tag, reg & ~0x3); 209 return (val >> ((reg & 0x3) << 3)); 210} 211 212uint16_t 213acpi_pci_conf_read_2(pci_chipset_tag_t pc, pcitag_t tag, int reg) 214{ 215 uint32_t val = pci_conf_read(pc, tag, reg & ~0x2); 216 return (val >> ((reg & 0x2) << 3)); 217} 218 219uint32_t 220acpi_pci_conf_read_4(pci_chipset_tag_t pc, pcitag_t tag, int reg) 221{ 222 return pci_conf_read(pc, tag, reg); 223} 224 225void 226acpi_pci_conf_write_1(pci_chipset_tag_t pc, pcitag_t tag, int reg, uint8_t val) 227{ 228 uint32_t tmp = pci_conf_read(pc, tag, reg & ~0x3); 229 tmp &= ~(0xff << ((reg & 0x3) << 3)); 230 tmp |= (val << ((reg & 0x3) << 3)); 231 pci_conf_write(pc, tag, reg & ~0x3, tmp); 232} 233 234void 235acpi_pci_conf_write_2(pci_chipset_tag_t pc, pcitag_t tag, int reg, uint16_t val) 236{ 237 uint32_t tmp = pci_conf_read(pc, tag, reg & ~0x2); 238 tmp &= ~(0xffff << ((reg & 0x2) << 3)); 239 tmp |= (val << ((reg & 0x2) << 3)); 240 pci_conf_write(pc, tag, reg & ~0x2, tmp); 241} 242 243void 244acpi_pci_conf_write_4(pci_chipset_tag_t pc, pcitag_t tag, int reg, uint32_t val) 245{ 246 pci_conf_write(pc, tag, reg, val); 247} 248 249int 250acpi_gasio(struct acpi_softc *sc, int iodir, int iospace, uint64_t address, 251 int access_size, int len, void *buffer) 252{ 253 uint8_t *pb; 254 bus_space_tag_t iot; 255 bus_space_handle_t ioh; 256 pci_chipset_tag_t pc; 257 pcitag_t tag; 258 int reg, idx; 259 260 dnprintf(50, "gasio: %.2x 0x%.8llx %s\n", 261 iospace, address, (iodir == ACPI_IOWRITE) ? "write" : "read"); 262 263 KASSERT((len % access_size) == 0); 264 265 pb = (uint8_t *)buffer; 266 switch (iospace) { 267 case GAS_SYSTEM_MEMORY: 268 case GAS_SYSTEM_IOSPACE: 269 if (iospace == GAS_SYSTEM_MEMORY) 270 iot = sc->sc_memt; 271 else 272 iot = sc->sc_iot; 273 274 if (acpi_bus_space_map(iot, address, len, 0, &ioh) != 0) { 275 printf("%s: unable to map iospace\n", DEVNAME(sc)); 276 return (-1); 277 } 278 for (reg = 0; reg < len; reg += access_size) { 279 if (iodir == ACPI_IOREAD) { 280 switch (access_size) { 281 case 1: 282 *(uint8_t *)(pb + reg) = 283 bus_space_read_1(iot, ioh, reg); 284 dnprintf(80, "os_in8(%llx) = %x\n", 285 reg+address, *(uint8_t *)(pb+reg)); 286 break; 287 case 2: 288 *(uint16_t *)(pb + reg) = 289 bus_space_read_2(iot, ioh, reg); 290 dnprintf(80, "os_in16(%llx) = %x\n", 291 reg+address, *(uint16_t *)(pb+reg)); 292 break; 293 case 4: 294 *(uint32_t *)(pb + reg) = 295 bus_space_read_4(iot, ioh, reg); 296 break; 297 default: 298 printf("%s: rdio: invalid size %d\n", 299 DEVNAME(sc), access_size); 300 return (-1); 301 } 302 } else { 303 switch (access_size) { 304 case 1: 305 bus_space_write_1(iot, ioh, reg, 306 *(uint8_t *)(pb + reg)); 307 dnprintf(80, "os_out8(%llx,%x)\n", 308 reg+address, *(uint8_t *)(pb+reg)); 309 break; 310 case 2: 311 bus_space_write_2(iot, ioh, reg, 312 *(uint16_t *)(pb + reg)); 313 dnprintf(80, "os_out16(%llx,%x)\n", 314 reg+address, *(uint16_t *)(pb+reg)); 315 break; 316 case 4: 317 bus_space_write_4(iot, ioh, reg, 318 *(uint32_t *)(pb + reg)); 319 break; 320 default: 321 printf("%s: wrio: invalid size %d\n", 322 DEVNAME(sc), access_size); 323 return (-1); 324 } 325 } 326 } 327 acpi_bus_space_unmap(iot, ioh, len); 328 break; 329 330 case GAS_PCI_CFG_SPACE: 331 /* 332 * The ACPI standard says that a function number of 333 * FFFF can be used to refer to all functions on a 334 * device. This makes no sense though in the context 335 * of accessing PCI config space. Yet there is AML 336 * out there that does this. We simulate a read from 337 * a nonexistent device here. Writes will panic when 338 * we try to construct the tag below. 339 */ 340 if (ACPI_PCI_FN(address) == 0xffff && iodir == ACPI_IOREAD) { 341 memset(buffer, 0xff, len); 342 return (0); 343 } 344 345 pc = pci_lookup_segment(ACPI_PCI_SEG(address)); 346 tag = pci_make_tag(pc, 347 ACPI_PCI_BUS(address), ACPI_PCI_DEV(address), 348 ACPI_PCI_FN(address)); 349 350 reg = ACPI_PCI_REG(address); 351 for (idx = 0; idx < len; idx += access_size) { 352 if (iodir == ACPI_IOREAD) { 353 switch (access_size) { 354 case 1: 355 *(uint8_t *)(pb + idx) = 356 acpi_pci_conf_read_1(pc, tag, reg + idx); 357 break; 358 case 2: 359 *(uint16_t *)(pb + idx) = 360 acpi_pci_conf_read_2(pc, tag, reg + idx); 361 break; 362 case 4: 363 *(uint32_t *)(pb + idx) = 364 acpi_pci_conf_read_4(pc, tag, reg + idx); 365 break; 366 default: 367 printf("%s: rdcfg: invalid size %d\n", 368 DEVNAME(sc), access_size); 369 return (-1); 370 } 371 } else { 372 switch (access_size) { 373 case 1: 374 acpi_pci_conf_write_1(pc, tag, reg + idx, 375 *(uint8_t *)(pb + idx)); 376 break; 377 case 2: 378 acpi_pci_conf_write_2(pc, tag, reg + idx, 379 *(uint16_t *)(pb + idx)); 380 break; 381 case 4: 382 acpi_pci_conf_write_4(pc, tag, reg + idx, 383 *(uint32_t *)(pb + idx)); 384 break; 385 default: 386 printf("%s: wrcfg: invalid size %d\n", 387 DEVNAME(sc), access_size); 388 return (-1); 389 } 390 } 391 } 392 break; 393 394 case GAS_EMBEDDED: 395 if (sc->sc_ec == NULL) { 396 printf("%s: WARNING EC not initialized\n", DEVNAME(sc)); 397 return (-1); 398 } 399 if (iodir == ACPI_IOREAD) 400 acpiec_read(sc->sc_ec, (uint8_t)address, len, buffer); 401 else 402 acpiec_write(sc->sc_ec, (uint8_t)address, len, buffer); 403 break; 404 } 405 return (0); 406} 407 408int 409acpi_inidev(struct aml_node *node, void *arg) 410{ 411 struct acpi_softc *sc = (struct acpi_softc *)arg; 412 int64_t st; 413 414 /* 415 * Per the ACPI spec 6.5.1, only run _INI when device is there or 416 * when there is no _STA. We terminate the tree walk (with return 1) 417 * early if necessary. 418 */ 419 420 /* Evaluate _STA to decide _INI fate and walk fate */ 421 if (aml_evalinteger(sc, node->parent, "_STA", 0, NULL, &st)) 422 st = STA_PRESENT | STA_ENABLED | STA_DEV_OK | 0x1000; 423 424 /* Evaluate _INI if we are present */ 425 if (st & STA_PRESENT) 426 aml_evalnode(sc, node, 0, NULL, NULL); 427 428 /* If we are functioning, we walk/search our children */ 429 if (st & STA_DEV_OK) 430 return 0; 431 432 /* If we are not enabled, or not present, terminate search */ 433 if (!(st & (STA_PRESENT|STA_ENABLED))) 434 return 1; 435 436 /* Default just continue search */ 437 return 0; 438} 439 440int 441acpi_foundprt(struct aml_node *node, void *arg) 442{ 443 struct acpi_softc *sc = (struct acpi_softc *)arg; 444 struct device *self = (struct device *)arg; 445 struct acpi_attach_args aaa; 446 int64_t st = 0; 447 448 dnprintf(10, "found prt entry: %s\n", node->parent->name); 449 450 /* Evaluate _STA to decide _PRT fate and walk fate */ 451 if (aml_evalinteger(sc, node->parent, "_STA", 0, NULL, &st)) 452 st = STA_PRESENT | STA_ENABLED | STA_DEV_OK | 0x1000; 453 454 if (st & STA_PRESENT) { 455 memset(&aaa, 0, sizeof(aaa)); 456 aaa.aaa_iot = sc->sc_iot; 457 aaa.aaa_memt = sc->sc_memt; 458 aaa.aaa_node = node; 459 aaa.aaa_name = "acpiprt"; 460 461 config_found(self, &aaa, acpi_print); 462 } 463 464 /* If we are functioning, we walk/search our children */ 465 if (st & STA_DEV_OK) 466 return 0; 467 468 /* If we are not enabled, or not present, terminate search */ 469 if (!(st & (STA_PRESENT|STA_ENABLED))) 470 return 1; 471 472 /* Default just continue search */ 473 return 0; 474} 475 476TAILQ_HEAD(, acpi_pci) acpi_pcidevs = 477 TAILQ_HEAD_INITIALIZER(acpi_pcidevs); 478TAILQ_HEAD(, acpi_pci) acpi_pcirootdevs = 479 TAILQ_HEAD_INITIALIZER(acpi_pcirootdevs); 480 481int acpi_getpci(struct aml_node *node, void *arg); 482int acpi_getminbus(int crsidx, union acpi_resource *crs, void *arg); 483 484int 485acpi_getminbus(int crsidx, union acpi_resource *crs, void *arg) 486{ 487 int *bbn = arg; 488 int typ = AML_CRSTYPE(crs); 489 490 /* Check for embedded bus number */ 491 if (typ == LR_WORD && crs->lr_word.type == 2) { 492 /* If _MIN > _MAX, the resource is considered to be invalid. */ 493 if (crs->lr_word._min > crs->lr_word._max) 494 return -1; 495 *bbn = crs->lr_word._min; 496 } 497 return 0; 498} 499 500int 501acpi_matchcls(struct acpi_attach_args *aaa, int class, int subclass, 502 int interface) 503{ 504 struct acpi_softc *sc = acpi_softc; 505 struct aml_value res; 506 507 if (aaa->aaa_dev == NULL || aaa->aaa_node == NULL) 508 return (0); 509 510 if (aml_evalname(sc, aaa->aaa_node, "_CLS", 0, NULL, &res)) 511 return (0); 512 513 if (res.type != AML_OBJTYPE_PACKAGE || res.length != 3 || 514 res.v_package[0]->type != AML_OBJTYPE_INTEGER || 515 res.v_package[1]->type != AML_OBJTYPE_INTEGER || 516 res.v_package[2]->type != AML_OBJTYPE_INTEGER) 517 return (0); 518 519 if (res.v_package[0]->v_integer == class && 520 res.v_package[1]->v_integer == subclass && 521 res.v_package[2]->v_integer == interface) 522 return (1); 523 524 return (0); 525} 526 527int 528_acpi_matchhids(const char *hid, const char *hids[]) 529{ 530 int i; 531 532 for (i = 0; hids[i]; i++) 533 if (!strcmp(hid, hids[i])) 534 return (1); 535 return (0); 536} 537 538int 539acpi_matchhids(struct acpi_attach_args *aa, const char *hids[], 540 const char *driver) 541{ 542 if (aa->aaa_dev == NULL || aa->aaa_node == NULL) 543 return (0); 544 545 if (_acpi_matchhids(aa->aaa_dev, hids)) { 546 dnprintf(5, "driver %s matches at least one hid\n", driver); 547 return (2); 548 } 549 if (aa->aaa_cdev && _acpi_matchhids(aa->aaa_cdev, hids)) { 550 dnprintf(5, "driver %s matches at least one cid\n", driver); 551 return (1); 552 } 553 554 return (0); 555} 556 557/* Map ACPI device node to PCI */ 558int 559acpi_getpci(struct aml_node *node, void *arg) 560{ 561 const char *pcihid[] = { ACPI_DEV_PCIB, ACPI_DEV_PCIEB, "HWP0002", 0 }; 562 struct acpi_pci *pci, *ppci; 563 struct aml_value res; 564 struct acpi_softc *sc = arg; 565 pci_chipset_tag_t pc; 566 pcitag_t tag; 567 uint64_t val; 568 uint32_t reg; 569 570 if (!node->value || node->value->type != AML_OBJTYPE_DEVICE) 571 return 0; 572 if (!aml_evalhid(node, &res)) { 573 /* Check if this is a PCI Root node */ 574 if (_acpi_matchhids(res.v_string, pcihid)) { 575 aml_freevalue(&res); 576 577 pci = malloc(sizeof(*pci), M_DEVBUF, M_WAITOK|M_ZERO); 578 579 pci->bus = -1; 580 if (!aml_evalinteger(sc, node, "_SEG", 0, NULL, &val)) 581 pci->seg = val; 582 if (!aml_evalname(sc, node, "_CRS", 0, NULL, &res)) { 583 aml_parse_resource(&res, acpi_getminbus, 584 &pci->bus); 585 dnprintf(10, "%s post-crs: %d\n", 586 aml_nodename(node), pci->bus); 587 } 588 if (!aml_evalinteger(sc, node, "_BBN", 0, NULL, &val)) { 589 dnprintf(10, "%s post-bbn: %d, %lld\n", 590 aml_nodename(node), pci->bus, val); 591 if (pci->bus == -1) 592 pci->bus = val; 593 } 594 pci->sub = pci->bus; 595 node->pci = pci; 596 dnprintf(10, "found PCI root: %s %d\n", 597 aml_nodename(node), pci->bus); 598 TAILQ_INSERT_TAIL(&acpi_pcirootdevs, pci, next); 599 } 600 aml_freevalue(&res); 601 return 0; 602 } 603 604 /* If parent is not PCI, or device does not have _ADR, return */ 605 if (!node->parent || (ppci = node->parent->pci) == NULL) 606 return 0; 607 if (aml_evalinteger(sc, node, "_ADR", 0, NULL, &val)) 608 return 0; 609 610 pci = malloc(sizeof(*pci), M_DEVBUF, M_WAITOK|M_ZERO); 611 pci->seg = ppci->seg; 612 pci->bus = ppci->sub; 613 pci->dev = ACPI_ADR_PCIDEV(val); 614 pci->fun = ACPI_ADR_PCIFUN(val); 615 pci->node = node; 616 pci->sub = -1; 617 618 dnprintf(10, "%.2x:%.2x.%x -> %s\n", 619 pci->bus, pci->dev, pci->fun, 620 aml_nodename(node)); 621 622 /* Collect device power state information. */ 623 if (aml_evalinteger(sc, node, "_S3D", 0, NULL, &val) == 0) 624 pci->_s3d = val; 625 else 626 pci->_s3d = -1; 627 if (aml_evalinteger(sc, node, "_S3W", 0, NULL, &val) == 0) 628 pci->_s3w = val; 629 else 630 pci->_s3w = -1; 631 if (aml_evalinteger(sc, node, "_S4D", 0, NULL, &val) == 0) 632 pci->_s4d = val; 633 else 634 pci->_s4d = -1; 635 if (aml_evalinteger(sc, node, "_S4W", 0, NULL, &val) == 0) 636 pci->_s4w = val; 637 else 638 pci->_s4w = -1; 639 640 /* Check if PCI device exists */ 641 if (pci->dev > 0x1F || pci->fun > 7) { 642 free(pci, M_DEVBUF, sizeof(*pci)); 643 return (1); 644 } 645 pc = pci_lookup_segment(pci->seg); 646 tag = pci_make_tag(pc, pci->bus, pci->dev, pci->fun); 647 reg = pci_conf_read(pc, tag, PCI_ID_REG); 648 if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID) { 649 free(pci, M_DEVBUF, sizeof(*pci)); 650 return (1); 651 } 652 node->pci = pci; 653 654 TAILQ_INSERT_TAIL(&acpi_pcidevs, pci, next); 655 656 /* Check if this is a PCI bridge */ 657 reg = pci_conf_read(pc, tag, PCI_CLASS_REG); 658 if (PCI_CLASS(reg) == PCI_CLASS_BRIDGE && 659 PCI_SUBCLASS(reg) == PCI_SUBCLASS_BRIDGE_PCI) { 660 reg = pci_conf_read(pc, tag, PPB_REG_BUSINFO); 661 pci->sub = PPB_BUSINFO_SECONDARY(reg); 662 663 dnprintf(10, "found PCI bridge: %s %d\n", 664 aml_nodename(node), pci->sub); 665 666 /* Continue scanning */ 667 return (0); 668 } 669 670 /* Device does not have children, stop scanning */ 671 return (1); 672} 673 674struct aml_node * 675acpi_find_pci(pci_chipset_tag_t pc, pcitag_t tag) 676{ 677 struct acpi_pci *pdev; 678 int bus, dev, fun; 679 680 pci_decompose_tag(pc, tag, &bus, &dev, &fun); 681 TAILQ_FOREACH(pdev, &acpi_pcidevs, next) { 682 if (pdev->bus == bus && pdev->dev == dev && pdev->fun == fun) 683 return pdev->node; 684 } 685 686 return NULL; 687} 688 689struct aml_node * 690acpi_pci_match(struct device *dev, struct pci_attach_args *pa) 691{ 692 struct acpi_pci *pdev; 693 int state; 694 695 TAILQ_FOREACH(pdev, &acpi_pcidevs, next) { 696 if (pdev->bus != pa->pa_bus || 697 pdev->dev != pa->pa_device || 698 pdev->fun != pa->pa_function) 699 continue; 700 701 dnprintf(10,"%s at acpi0 %s\n", dev->dv_xname, 702 aml_nodename(pdev->node)); 703 704 pdev->device = dev; 705 706 /* 707 * If some Power Resources are dependent on this device 708 * initialize them. 709 */ 710 state = pci_get_powerstate(pa->pa_pc, pa->pa_tag); 711 acpi_pci_set_powerstate(pa->pa_pc, pa->pa_tag, state, 1); 712 acpi_pci_set_powerstate(pa->pa_pc, pa->pa_tag, state, 0); 713 714 aml_register_notify(pdev->node, NULL, acpi_pci_notify, pdev, 0); 715 716 return pdev->node; 717 } 718 719 return NULL; 720} 721 722pcireg_t 723acpi_pci_min_powerstate(pci_chipset_tag_t pc, pcitag_t tag) 724{ 725 struct acpi_pci *pdev; 726 int bus, dev, fun; 727 int state = -1, defaultstate = pci_get_powerstate(pc, tag); 728 729 pci_decompose_tag(pc, tag, &bus, &dev, &fun); 730 TAILQ_FOREACH(pdev, &acpi_pcidevs, next) { 731 if (pdev->bus == bus && pdev->dev == dev && pdev->fun == fun) { 732 switch (acpi_softc->sc_state) { 733 case ACPI_STATE_S3: 734 defaultstate = PCI_PMCSR_STATE_D3; 735 state = MAX(pdev->_s3d, pdev->_s3w); 736 break; 737 case ACPI_STATE_S4: 738 state = MAX(pdev->_s4d, pdev->_s4w); 739 break; 740 case ACPI_STATE_S5: 741 default: 742 break; 743 } 744 745 if (state >= PCI_PMCSR_STATE_D0 && 746 state <= PCI_PMCSR_STATE_D3) 747 return state; 748 } 749 } 750 751 return defaultstate; 752} 753 754void 755acpi_pci_set_powerstate(pci_chipset_tag_t pc, pcitag_t tag, int state, int pre) 756{ 757#if NACPIPWRRES > 0 758 struct acpi_softc *sc = acpi_softc; 759 struct acpi_pwrres *pr; 760 struct acpi_pci *pdev; 761 int bus, dev, fun; 762 char name[5]; 763 764 pci_decompose_tag(pc, tag, &bus, &dev, &fun); 765 TAILQ_FOREACH(pdev, &acpi_pcidevs, next) { 766 if (pdev->bus == bus && pdev->dev == dev && pdev->fun == fun) 767 break; 768 } 769 770 /* XXX Add a check to discard nodes without Power Resources? */ 771 if (pdev == NULL) 772 return; 773 774 SIMPLEQ_FOREACH(pr, &sc->sc_pwrresdevs, p_next) { 775 if (pr->p_node != pdev->node) 776 continue; 777 778 /* 779 * If the firmware is already aware that the device 780 * is in the given state, there's nothing to do. 781 */ 782 if (pr->p_state == state) 783 continue; 784 785 if (pre) { 786 /* 787 * If a Resource is dependent on this device for 788 * the given state, make sure it is turned "_ON". 789 */ 790 if (pr->p_res_state == state) 791 acpipwrres_ref_incr(pr->p_res_sc, pr->p_node); 792 } else { 793 /* 794 * If a Resource was referenced for the state we 795 * left, drop a reference and turn it "_OFF" if 796 * it was the last one. 797 */ 798 if (pr->p_res_state == pr->p_state) 799 acpipwrres_ref_decr(pr->p_res_sc, pr->p_node); 800 801 if (pr->p_res_state == state) { 802 snprintf(name, sizeof(name), "_PS%d", state); 803 aml_evalname(sc, pr->p_node, name, 0, 804 NULL, NULL); 805 } 806 807 pr->p_state = state; 808 } 809 810 } 811#endif /* NACPIPWRRES > 0 */ 812} 813 814int 815acpi_pci_notify(struct aml_node *node, int ntype, void *arg) 816{ 817 struct acpi_pci *pdev = arg; 818 pci_chipset_tag_t pc; 819 pcitag_t tag; 820 pcireg_t reg; 821 int offset; 822 823 /* We're only interested in Device Wake notifications. */ 824 if (ntype != 2) 825 return (0); 826 827 pc = pci_lookup_segment(pdev->seg); 828 tag = pci_make_tag(pc, pdev->bus, pdev->dev, pdev->fun); 829 if (pci_get_capability(pc, tag, PCI_CAP_PWRMGMT, &offset, 0)) { 830 /* Clear the PME Status bit if it is set. */ 831 reg = pci_conf_read(pc, tag, offset + PCI_PMCSR); 832 pci_conf_write(pc, tag, offset + PCI_PMCSR, reg); 833 } 834 835 return (0); 836} 837 838void 839acpi_pciroots_attach(struct device *dev, void *aux, cfprint_t pr) 840{ 841 struct acpi_pci *pdev; 842 struct pcibus_attach_args *pba = aux; 843 844 KASSERT(pba->pba_busex != NULL); 845 846 TAILQ_FOREACH(pdev, &acpi_pcirootdevs, next) { 847 if (extent_alloc_region(pba->pba_busex, pdev->bus, 848 1, EX_NOWAIT) != 0) 849 continue; 850 pba->pba_bus = pdev->bus; 851 config_found(dev, pba, pr); 852 } 853} 854 855/* GPIO support */ 856 857struct acpi_gpio_event { 858 struct aml_node *node; 859 uint16_t pin; 860}; 861 862void 863acpi_gpio_event_task(void *arg0, int arg1) 864{ 865 struct aml_node *node = arg0; 866 uint16_t pin = arg1; 867 char name[5]; 868 869 snprintf(name, sizeof(name), "_E%.2X", pin); 870 aml_evalname(acpi_softc, node, name, 0, NULL, NULL); 871} 872 873int 874acpi_gpio_event(void *arg) 875{ 876 struct acpi_gpio_event *ev = arg; 877 878 acpi_addtask(acpi_softc, acpi_gpio_event_task, ev->node, ev->pin); 879 acpi_wakeup(acpi_softc); 880 return 1; 881} 882 883int 884acpi_gpio_parse_events(int crsidx, union acpi_resource *crs, void *arg) 885{ 886 struct aml_node *devnode = arg; 887 struct aml_node *node; 888 uint16_t pin; 889 890 switch (AML_CRSTYPE(crs)) { 891 case LR_GPIO: 892 node = aml_searchname(devnode, 893 (char *)&crs->pad[crs->lr_gpio.res_off]); 894 pin = *(uint16_t *)&crs->pad[crs->lr_gpio.pin_off]; 895 if (crs->lr_gpio.type == LR_GPIO_INT && 896 node && node->gpio && pin < 256) { 897 struct acpi_gpio *gpio = node->gpio; 898 struct acpi_gpio_event *ev; 899 900 ev = malloc(sizeof(*ev), M_DEVBUF, M_WAITOK); 901 ev->node = devnode; 902 ev->pin = pin; 903 gpio->intr_establish(gpio->cookie, pin, 904 crs->lr_gpio.tflags, acpi_gpio_event, ev); 905 } 906 break; 907 default: 908 printf("%s: unknown resource type %d\n", __func__, 909 AML_CRSTYPE(crs)); 910 } 911 912 return 0; 913} 914 915void 916acpi_register_gpio(struct acpi_softc *sc, struct aml_node *devnode) 917{ 918 struct aml_value arg[2]; 919 struct aml_node *node; 920 struct aml_value res; 921 922 /* Register GeneralPurposeIO address space. */ 923 memset(&arg, 0, sizeof(arg)); 924 arg[0].type = AML_OBJTYPE_INTEGER; 925 arg[0].v_integer = ACPI_OPREG_GPIO; 926 arg[1].type = AML_OBJTYPE_INTEGER; 927 arg[1].v_integer = 1; 928 node = aml_searchname(devnode, "_REG"); 929 if (node && aml_evalnode(sc, node, 2, arg, NULL)) 930 printf("%s: _REG failed\n", node->name); 931 932 /* Register GPIO signaled ACPI events. */ 933 if (aml_evalname(sc, devnode, "_AEI", 0, NULL, &res)) 934 return; 935 aml_parse_resource(&res, acpi_gpio_parse_events, devnode); 936} 937 938#ifndef SMALL_KERNEL 939 940void 941acpi_register_gsb(struct acpi_softc *sc, struct aml_node *devnode) 942{ 943 struct aml_value arg[2]; 944 struct aml_node *node; 945 946 /* Register GenericSerialBus address space. */ 947 memset(&arg, 0, sizeof(arg)); 948 arg[0].type = AML_OBJTYPE_INTEGER; 949 arg[0].v_integer = ACPI_OPREG_GSB; 950 arg[1].type = AML_OBJTYPE_INTEGER; 951 arg[1].v_integer = 1; 952 node = aml_searchname(devnode, "_REG"); 953 if (node && aml_evalnode(sc, node, 2, arg, NULL)) 954 printf("%s: _REG failed\n", node->name); 955} 956 957#endif 958 959void 960acpi_attach_common(struct acpi_softc *sc, paddr_t base) 961{ 962 struct acpi_mem_map handle; 963 struct acpi_rsdp *rsdp; 964 struct acpi_q *entry; 965 struct acpi_dsdt *p_dsdt; 966#ifndef SMALL_KERNEL 967 int wakeup_dev_ct; 968 struct acpi_wakeq *wentry; 969 struct device *dev; 970#endif /* SMALL_KERNEL */ 971 paddr_t facspa; 972 uint16_t pm1; 973 int s; 974 975 rw_init(&sc->sc_lck, "acpilk"); 976 977 acpi_softc = sc; 978 979 if (acpi_map(base, sizeof(struct acpi_rsdp), &handle)) { 980 printf(": can't map memory\n"); 981 return; 982 } 983 984 rsdp = (struct acpi_rsdp *)handle.va; 985 sc->sc_revision = (int)rsdp->rsdp_revision; 986 printf(": rev %d", sc->sc_revision); 987 988 SIMPLEQ_INIT(&sc->sc_tables); 989 SIMPLEQ_INIT(&sc->sc_wakedevs); 990#if NACPIPWRRES > 0 991 SIMPLEQ_INIT(&sc->sc_pwrresdevs); 992#endif /* NACPIPWRRES > 0 */ 993 994 995#ifndef SMALL_KERNEL 996 sc->sc_note = malloc(sizeof(struct klist), M_DEVBUF, M_NOWAIT | M_ZERO); 997 if (sc->sc_note == NULL) { 998 printf(", can't allocate memory\n"); 999 acpi_unmap(&handle); 1000 return; 1001 } 1002#endif /* SMALL_KERNEL */ 1003 1004 if (acpi_loadtables(sc, rsdp)) { 1005 printf(", can't load tables\n"); 1006 acpi_unmap(&handle); 1007 return; 1008 } 1009 1010 acpi_unmap(&handle); 1011 1012 /* 1013 * Find the FADT 1014 */ 1015 SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) { 1016 if (memcmp(entry->q_table, FADT_SIG, 1017 sizeof(FADT_SIG) - 1) == 0) { 1018 sc->sc_fadt = entry->q_table; 1019 break; 1020 } 1021 } 1022 if (sc->sc_fadt == NULL) { 1023 printf(", no FADT\n"); 1024 return; 1025 } 1026 1027 /* 1028 * A bunch of things need to be done differently for 1029 * Hardware-reduced ACPI. 1030 */ 1031 if (sc->sc_fadt->hdr_revision >= 5 && 1032 sc->sc_fadt->flags & FADT_HW_REDUCED_ACPI) 1033 sc->sc_hw_reduced = 1; 1034 1035 /* Map Power Management registers */ 1036 acpi_map_pmregs(sc); 1037 1038 /* 1039 * Check if we can and need to enable ACPI control. 1040 */ 1041 pm1 = acpi_read_pmreg(sc, ACPIREG_PM1_CNT, 0); 1042 if ((pm1 & ACPI_PM1_SCI_EN) == 0 && sc->sc_fadt->smi_cmd && 1043 (!sc->sc_fadt->acpi_enable && !sc->sc_fadt->acpi_disable)) { 1044 printf(", ACPI control unavailable\n"); 1045 acpi_unmap_pmregs(sc); 1046 return; 1047 } 1048 1049 /* 1050 * Set up a pointer to the firmware control structure 1051 */ 1052 if (sc->sc_fadt->hdr_revision < 3 || sc->sc_fadt->x_firmware_ctl == 0) 1053 facspa = sc->sc_fadt->firmware_ctl; 1054 else 1055 facspa = sc->sc_fadt->x_firmware_ctl; 1056 1057 if (acpi_map(facspa, sizeof(struct acpi_facs), &handle)) 1058 printf(" !FACS"); 1059 else 1060 sc->sc_facs = (struct acpi_facs *)handle.va; 1061 1062 /* Create opcode hashtable */ 1063 aml_hashopcodes(); 1064 1065 /* Create Default AML objects */ 1066 aml_create_defaultobjects(); 1067 1068 /* 1069 * Load the DSDT from the FADT pointer -- use the 1070 * extended (64-bit) pointer if it exists 1071 */ 1072 if (sc->sc_fadt->hdr_revision < 3 || sc->sc_fadt->x_dsdt == 0) 1073 entry = acpi_maptable(sc, sc->sc_fadt->dsdt, NULL, NULL, NULL, 1074 -1); 1075 else 1076 entry = acpi_maptable(sc, sc->sc_fadt->x_dsdt, NULL, NULL, NULL, 1077 -1); 1078 1079 if (entry == NULL) 1080 printf(" !DSDT"); 1081 1082 p_dsdt = entry->q_table; 1083 acpi_parse_aml(sc, p_dsdt->aml, p_dsdt->hdr_length - 1084 sizeof(p_dsdt->hdr)); 1085 1086 /* Load SSDT's */ 1087 SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) { 1088 if (memcmp(entry->q_table, SSDT_SIG, 1089 sizeof(SSDT_SIG) - 1) == 0) { 1090 p_dsdt = entry->q_table; 1091 acpi_parse_aml(sc, p_dsdt->aml, p_dsdt->hdr_length - 1092 sizeof(p_dsdt->hdr)); 1093 } 1094 } 1095 1096 /* Perform post-parsing fixups */ 1097 aml_postparse(); 1098 1099 1100#ifndef SMALL_KERNEL 1101 /* Find available sleeping states */ 1102 acpi_init_states(sc); 1103 1104 /* Find available sleep/resume related methods. */ 1105 acpi_init_pm(sc); 1106#endif /* SMALL_KERNEL */ 1107 1108 /* Initialize GPE handlers */ 1109 s = spltty(); 1110 acpi_init_gpes(sc); 1111 splx(s); 1112 1113 /* some devices require periodic polling */ 1114 timeout_set(&sc->sc_dev_timeout, acpi_poll, sc); 1115 1116 acpi_enabled = 1; 1117 1118 /* 1119 * Take over ACPI control. Note that once we do this, we 1120 * effectively tell the system that we have ownership of 1121 * the ACPI hardware registers, and that SMI should leave 1122 * them alone 1123 * 1124 * This may prevent thermal control on some systems where 1125 * that actually does work 1126 */ 1127 if ((pm1 & ACPI_PM1_SCI_EN) == 0 && sc->sc_fadt->smi_cmd) { 1128 if (acpi_enable(sc)) { 1129 printf(", can't enable ACPI\n"); 1130 return; 1131 } 1132 } 1133 1134 printf("\n%s: tables", DEVNAME(sc)); 1135 SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) { 1136 printf(" %.4s", (char *)entry->q_table); 1137 } 1138 printf("\n"); 1139 1140#ifndef SMALL_KERNEL 1141 /* Display wakeup devices and lowest S-state */ 1142 wakeup_dev_ct = 0; 1143 printf("%s: wakeup devices", DEVNAME(sc)); 1144 SIMPLEQ_FOREACH(wentry, &sc->sc_wakedevs, q_next) { 1145 if (wakeup_dev_ct < 16) 1146 printf(" %.4s(S%d)", wentry->q_node->name, 1147 wentry->q_state); 1148 else if (wakeup_dev_ct == 16) 1149 printf(" [...]"); 1150 wakeup_dev_ct ++; 1151 } 1152 printf("\n"); 1153 1154 /* 1155 * ACPI is enabled now -- attach timer 1156 */ 1157 if (!sc->sc_hw_reduced && 1158 (sc->sc_fadt->pm_tmr_blk || sc->sc_fadt->x_pm_tmr_blk.address)) { 1159 struct acpi_attach_args aaa; 1160 1161 memset(&aaa, 0, sizeof(aaa)); 1162 aaa.aaa_name = "acpitimer"; 1163 aaa.aaa_iot = sc->sc_iot; 1164 aaa.aaa_memt = sc->sc_memt; 1165 config_found(&sc->sc_dev, &aaa, acpi_print); 1166 } 1167#endif /* SMALL_KERNEL */ 1168 1169 /* 1170 * Attach table-defined devices 1171 */ 1172 SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) { 1173 struct acpi_attach_args aaa; 1174 1175 memset(&aaa, 0, sizeof(aaa)); 1176 aaa.aaa_iot = sc->sc_iot; 1177 aaa.aaa_memt = sc->sc_memt; 1178 aaa.aaa_table = entry->q_table; 1179 config_found_sm(&sc->sc_dev, &aaa, acpi_print, acpi_submatch); 1180 } 1181 1182 /* initialize runtime environment */ 1183 aml_find_node(&aml_root, "_INI", acpi_inidev, sc); 1184 1185 /* Get PCI mapping */ 1186 aml_walknodes(&aml_root, AML_WALK_PRE, acpi_getpci, sc); 1187 1188#if defined (__amd64__) || defined(__i386__) 1189 /* attach pci interrupt routing tables */ 1190 aml_find_node(&aml_root, "_PRT", acpi_foundprt, sc); 1191#endif 1192 1193 aml_find_node(&aml_root, "_HID", acpi_foundec, sc); 1194 1195 /* check if we're running on a sony */ 1196 aml_find_node(&aml_root, "GBRT", acpi_foundsony, sc); 1197 1198 aml_walknodes(&aml_root, AML_WALK_PRE, acpi_add_device, sc); 1199 1200#ifndef SMALL_KERNEL 1201 /* try to find smart battery first */ 1202 aml_find_node(&aml_root, "_HID", acpi_foundsbs, sc); 1203#endif /* SMALL_KERNEL */ 1204 1205 /* attach battery, power supply and button devices */ 1206 aml_find_node(&aml_root, "_HID", acpi_foundhid, sc); 1207 1208#ifndef SMALL_KERNEL 1209#if NWD > 0 1210 /* Attach IDE bay */ 1211 aml_walknodes(&aml_root, AML_WALK_PRE, acpi_foundide, sc); 1212#endif 1213 1214 /* attach docks */ 1215 aml_find_node(&aml_root, "_DCK", acpi_founddock, sc); 1216 1217 /* attach video */ 1218 aml_find_node(&aml_root, "_DOS", acpi_foundvideo, sc); 1219 1220 /* create list of devices we want to query when APM comes in */ 1221 SLIST_INIT(&sc->sc_ac); 1222 SLIST_INIT(&sc->sc_bat); 1223 TAILQ_FOREACH(dev, &alldevs, dv_list) { 1224 if (!strcmp(dev->dv_cfdata->cf_driver->cd_name, "acpiac")) { 1225 struct acpi_ac *ac; 1226 1227 ac = malloc(sizeof(*ac), M_DEVBUF, M_WAITOK | M_ZERO); 1228 ac->aac_softc = (struct acpiac_softc *)dev; 1229 SLIST_INSERT_HEAD(&sc->sc_ac, ac, aac_link); 1230 } else if (!strcmp(dev->dv_cfdata->cf_driver->cd_name, "acpibat")) { 1231 struct acpi_bat *bat; 1232 1233 bat = malloc(sizeof(*bat), M_DEVBUF, M_WAITOK | M_ZERO); 1234 bat->aba_softc = (struct acpibat_softc *)dev; 1235 SLIST_INSERT_HEAD(&sc->sc_bat, bat, aba_link); 1236 } else if (!strcmp(dev->dv_cfdata->cf_driver->cd_name, "acpisbs")) { 1237 struct acpi_sbs *sbs; 1238 1239 sbs = malloc(sizeof(*sbs), M_DEVBUF, M_WAITOK | M_ZERO); 1240 sbs->asbs_softc = (struct acpisbs_softc *)dev; 1241 SLIST_INSERT_HEAD(&sc->sc_sbs, sbs, asbs_link); 1242 } 1243 } 1244 1245#endif /* SMALL_KERNEL */ 1246 1247 /* Setup threads */ 1248 sc->sc_thread = malloc(sizeof(struct acpi_thread), M_DEVBUF, M_WAITOK); 1249 sc->sc_thread->sc = sc; 1250 sc->sc_thread->running = 1; 1251 1252 /* Enable PCI Power Management. */ 1253 pci_dopm = 1; 1254 1255 acpi_attach_machdep(sc); 1256 1257 kthread_create_deferred(acpi_create_thread, sc); 1258} 1259 1260int 1261acpi_submatch(struct device *parent, void *match, void *aux) 1262{ 1263 struct acpi_attach_args *aaa = (struct acpi_attach_args *)aux; 1264 struct cfdata *cf = match; 1265 1266 if (aaa->aaa_table == NULL) 1267 return (0); 1268 return ((*cf->cf_attach->ca_match)(parent, match, aux)); 1269} 1270 1271int 1272acpi_print(void *aux, const char *pnp) 1273{ 1274 struct acpi_attach_args *aa = aux; 1275 1276 if (pnp) { 1277 if (aa->aaa_name) 1278 printf("%s at %s", aa->aaa_name, pnp); 1279 else if (aa->aaa_dev) 1280 printf("\"%s\" at %s", aa->aaa_dev, pnp); 1281 else 1282 return (QUIET); 1283 } 1284 1285 return (UNCONF); 1286} 1287 1288struct acpi_q * 1289acpi_maptable(struct acpi_softc *sc, paddr_t addr, const char *sig, 1290 const char *oem, const char *tbl, int flag) 1291{ 1292 static int tblid; 1293 struct acpi_mem_map handle; 1294 struct acpi_table_header *hdr; 1295 struct acpi_q *entry; 1296 size_t len; 1297 1298 /* Check if we can map address */ 1299 if (addr == 0) 1300 return NULL; 1301 if (acpi_map(addr, sizeof(*hdr), &handle)) 1302 return NULL; 1303 hdr = (struct acpi_table_header *)handle.va; 1304 len = hdr->length; 1305 acpi_unmap(&handle); 1306 1307 /* Validate length/checksum */ 1308 if (acpi_map(addr, len, &handle)) 1309 return NULL; 1310 hdr = (struct acpi_table_header *)handle.va; 1311 if (acpi_checksum(hdr, len)) 1312 printf("\n%s: %.4s checksum error", 1313 DEVNAME(sc), hdr->signature); 1314 1315 if ((sig && memcmp(sig, hdr->signature, 4)) || 1316 (oem && memcmp(oem, hdr->oemid, 6)) || 1317 (tbl && memcmp(tbl, hdr->oemtableid, 8))) { 1318 acpi_unmap(&handle); 1319 return NULL; 1320 } 1321 1322 /* Allocate copy */ 1323 entry = malloc(sizeof(*entry) + len, M_DEVBUF, M_NOWAIT); 1324 if (entry != NULL) { 1325 memcpy(entry->q_data, handle.va, len); 1326 entry->q_table = entry->q_data; 1327 entry->q_id = ++tblid; 1328 1329 if (flag < 0) 1330 SIMPLEQ_INSERT_HEAD(&sc->sc_tables, entry, 1331 q_next); 1332 else if (flag > 0) 1333 SIMPLEQ_INSERT_TAIL(&sc->sc_tables, entry, 1334 q_next); 1335 } 1336 acpi_unmap(&handle); 1337 return entry; 1338} 1339 1340int 1341acpi_loadtables(struct acpi_softc *sc, struct acpi_rsdp *rsdp) 1342{ 1343 struct acpi_q *sdt; 1344 int i, ntables; 1345 size_t len; 1346 1347 if (rsdp->rsdp_revision == 2 && rsdp->rsdp_xsdt) { 1348 struct acpi_xsdt *xsdt; 1349 1350 sdt = acpi_maptable(sc, rsdp->rsdp_xsdt, NULL, NULL, NULL, 0); 1351 if (sdt == NULL) { 1352 printf("couldn't map rsdt\n"); 1353 return (ENOMEM); 1354 } 1355 1356 xsdt = (struct acpi_xsdt *)sdt->q_data; 1357 len = xsdt->hdr.length; 1358 ntables = (len - sizeof(struct acpi_table_header)) / 1359 sizeof(xsdt->table_offsets[0]); 1360 1361 for (i = 0; i < ntables; i++) 1362 acpi_maptable(sc, xsdt->table_offsets[i], NULL, NULL, 1363 NULL, 1); 1364 1365 free(sdt, M_DEVBUF, 0); 1366 } else { 1367 struct acpi_rsdt *rsdt; 1368 1369 sdt = acpi_maptable(sc, rsdp->rsdp_rsdt, NULL, NULL, NULL, 0); 1370 if (sdt == NULL) { 1371 printf("couldn't map rsdt\n"); 1372 return (ENOMEM); 1373 } 1374 1375 rsdt = (struct acpi_rsdt *)sdt->q_data; 1376 len = rsdt->hdr.length; 1377 ntables = (len - sizeof(struct acpi_table_header)) / 1378 sizeof(rsdt->table_offsets[0]); 1379 1380 for (i = 0; i < ntables; i++) 1381 acpi_maptable(sc, rsdt->table_offsets[i], NULL, NULL, 1382 NULL, 1); 1383 1384 free(sdt, M_DEVBUF, 0); 1385 } 1386 1387 return (0); 1388} 1389 1390/* Read from power management register */ 1391int 1392acpi_read_pmreg(struct acpi_softc *sc, int reg, int offset) 1393{ 1394 bus_space_handle_t ioh; 1395 bus_size_t size; 1396 int regval; 1397 1398 /* 1399 * For Hardware-reduced ACPI we emulate PM1B_CNT to reflect 1400 * that the system is always in ACPI mode. 1401 */ 1402 if (sc->sc_hw_reduced && reg == ACPIREG_PM1B_CNT) { 1403 KASSERT(offset == 0); 1404 return ACPI_PM1_SCI_EN; 1405 } 1406 1407 /* 1408 * For Hardware-reduced ACPI we also emulate PM1A_STS using 1409 * SLEEP_STATUS_REG. 1410 */ 1411 if (sc->sc_hw_reduced && reg == ACPIREG_PM1A_STS) { 1412 uint8_t value; 1413 1414 KASSERT(offset == 0); 1415 acpi_gasio(sc, ACPI_IOREAD, 1416 sc->sc_fadt->sleep_status_reg.address_space_id, 1417 sc->sc_fadt->sleep_status_reg.address, 1418 sc->sc_fadt->sleep_status_reg.register_bit_width / 8, 1419 sc->sc_fadt->sleep_status_reg.access_size, &value); 1420 return ((int)value << 8); 1421 } 1422 1423 /* Special cases: 1A/1B blocks can be OR'ed together */ 1424 switch (reg) { 1425 case ACPIREG_PM1_EN: 1426 return (acpi_read_pmreg(sc, ACPIREG_PM1A_EN, offset) | 1427 acpi_read_pmreg(sc, ACPIREG_PM1B_EN, offset)); 1428 case ACPIREG_PM1_STS: 1429 return (acpi_read_pmreg(sc, ACPIREG_PM1A_STS, offset) | 1430 acpi_read_pmreg(sc, ACPIREG_PM1B_STS, offset)); 1431 case ACPIREG_PM1_CNT: 1432 return (acpi_read_pmreg(sc, ACPIREG_PM1A_CNT, offset) | 1433 acpi_read_pmreg(sc, ACPIREG_PM1B_CNT, offset)); 1434 case ACPIREG_GPE_STS: 1435 dnprintf(50, "read GPE_STS offset: %.2x %.2x %.2x\n", offset, 1436 sc->sc_fadt->gpe0_blk_len>>1, sc->sc_fadt->gpe1_blk_len>>1); 1437 if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) { 1438 reg = ACPIREG_GPE0_STS; 1439 } 1440 break; 1441 case ACPIREG_GPE_EN: 1442 dnprintf(50, "read GPE_EN offset: %.2x %.2x %.2x\n", 1443 offset, sc->sc_fadt->gpe0_blk_len>>1, 1444 sc->sc_fadt->gpe1_blk_len>>1); 1445 if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) { 1446 reg = ACPIREG_GPE0_EN; 1447 } 1448 break; 1449 } 1450 1451 if (reg >= ACPIREG_MAXREG || sc->sc_pmregs[reg].size == 0) 1452 return (0); 1453 1454 regval = 0; 1455 ioh = sc->sc_pmregs[reg].ioh; 1456 size = sc->sc_pmregs[reg].size; 1457 if (size > sc->sc_pmregs[reg].access) 1458 size = sc->sc_pmregs[reg].access; 1459 1460 switch (size) { 1461 case 1: 1462 regval = bus_space_read_1(sc->sc_iot, ioh, offset); 1463 break; 1464 case 2: 1465 regval = bus_space_read_2(sc->sc_iot, ioh, offset); 1466 break; 1467 case 4: 1468 regval = bus_space_read_4(sc->sc_iot, ioh, offset); 1469 break; 1470 } 1471 1472 dnprintf(30, "acpi_readpm: %s = %.4x:%.4x %x\n", 1473 sc->sc_pmregs[reg].name, 1474 sc->sc_pmregs[reg].addr, offset, regval); 1475 return (regval); 1476} 1477 1478/* Write to power management register */ 1479void 1480acpi_write_pmreg(struct acpi_softc *sc, int reg, int offset, int regval) 1481{ 1482 bus_space_handle_t ioh; 1483 bus_size_t size; 1484 1485 /* 1486 * For Hardware-reduced ACPI we also emulate PM1A_STS using 1487 * SLEEP_STATUS_REG. 1488 */ 1489 if (sc->sc_hw_reduced && reg == ACPIREG_PM1A_STS) { 1490 uint8_t value = (regval >> 8); 1491 1492 KASSERT(offset == 0); 1493 acpi_gasio(sc, ACPI_IOWRITE, 1494 sc->sc_fadt->sleep_status_reg.address_space_id, 1495 sc->sc_fadt->sleep_status_reg.address, 1496 sc->sc_fadt->sleep_status_reg.register_bit_width / 8, 1497 sc->sc_fadt->sleep_status_reg.access_size, &value); 1498 return; 1499 } 1500 1501 /* 1502 * For Hardware-reduced ACPI we also emulate PM1A_CNT using 1503 * SLEEP_CONTROL_REG. 1504 */ 1505 if (sc->sc_hw_reduced && reg == ACPIREG_PM1A_CNT) { 1506 uint8_t value = (regval >> 8); 1507 1508 KASSERT(offset == 0); 1509 acpi_gasio(sc, ACPI_IOWRITE, 1510 sc->sc_fadt->sleep_control_reg.address_space_id, 1511 sc->sc_fadt->sleep_control_reg.address, 1512 sc->sc_fadt->sleep_control_reg.register_bit_width / 8, 1513 sc->sc_fadt->sleep_control_reg.access_size, &value); 1514 return; 1515 } 1516 1517 /* Special cases: 1A/1B blocks can be written with same value */ 1518 switch (reg) { 1519 case ACPIREG_PM1_EN: 1520 acpi_write_pmreg(sc, ACPIREG_PM1A_EN, offset, regval); 1521 acpi_write_pmreg(sc, ACPIREG_PM1B_EN, offset, regval); 1522 break; 1523 case ACPIREG_PM1_STS: 1524 acpi_write_pmreg(sc, ACPIREG_PM1A_STS, offset, regval); 1525 acpi_write_pmreg(sc, ACPIREG_PM1B_STS, offset, regval); 1526 break; 1527 case ACPIREG_PM1_CNT: 1528 acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, offset, regval); 1529 acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, offset, regval); 1530 break; 1531 case ACPIREG_GPE_STS: 1532 dnprintf(50, "write GPE_STS offset: %.2x %.2x %.2x %.2x\n", 1533 offset, sc->sc_fadt->gpe0_blk_len>>1, 1534 sc->sc_fadt->gpe1_blk_len>>1, regval); 1535 if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) { 1536 reg = ACPIREG_GPE0_STS; 1537 } 1538 break; 1539 case ACPIREG_GPE_EN: 1540 dnprintf(50, "write GPE_EN offset: %.2x %.2x %.2x %.2x\n", 1541 offset, sc->sc_fadt->gpe0_blk_len>>1, 1542 sc->sc_fadt->gpe1_blk_len>>1, regval); 1543 if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) { 1544 reg = ACPIREG_GPE0_EN; 1545 } 1546 break; 1547 } 1548 1549 /* All special case return here */ 1550 if (reg >= ACPIREG_MAXREG) 1551 return; 1552 1553 ioh = sc->sc_pmregs[reg].ioh; 1554 size = sc->sc_pmregs[reg].size; 1555 if (size > sc->sc_pmregs[reg].access) 1556 size = sc->sc_pmregs[reg].access; 1557 1558 switch (size) { 1559 case 1: 1560 bus_space_write_1(sc->sc_iot, ioh, offset, regval); 1561 break; 1562 case 2: 1563 bus_space_write_2(sc->sc_iot, ioh, offset, regval); 1564 break; 1565 case 4: 1566 bus_space_write_4(sc->sc_iot, ioh, offset, regval); 1567 break; 1568 } 1569 1570 dnprintf(30, "acpi_writepm: %s = %.4x:%.4x %x\n", 1571 sc->sc_pmregs[reg].name, sc->sc_pmregs[reg].addr, offset, regval); 1572} 1573 1574/* Map Power Management registers */ 1575void 1576acpi_map_pmregs(struct acpi_softc *sc) 1577{ 1578 bus_addr_t addr; 1579 bus_size_t size, access; 1580 const char *name; 1581 int reg; 1582 1583 /* Registers don't exist on Hardware-reduced ACPI. */ 1584 if (sc->sc_hw_reduced) 1585 return; 1586 1587 for (reg = 0; reg < ACPIREG_MAXREG; reg++) { 1588 size = 0; 1589 access = 0; 1590 switch (reg) { 1591 case ACPIREG_SMICMD: 1592 name = "smi"; 1593 size = access = 1; 1594 addr = sc->sc_fadt->smi_cmd; 1595 break; 1596 case ACPIREG_PM1A_STS: 1597 case ACPIREG_PM1A_EN: 1598 name = "pm1a_sts"; 1599 size = sc->sc_fadt->pm1_evt_len >> 1; 1600 addr = sc->sc_fadt->pm1a_evt_blk; 1601 access = 2; 1602 if (reg == ACPIREG_PM1A_EN && addr) { 1603 addr += size; 1604 name = "pm1a_en"; 1605 } 1606 break; 1607 case ACPIREG_PM1A_CNT: 1608 name = "pm1a_cnt"; 1609 size = sc->sc_fadt->pm1_cnt_len; 1610 addr = sc->sc_fadt->pm1a_cnt_blk; 1611 access = 2; 1612 break; 1613 case ACPIREG_PM1B_STS: 1614 case ACPIREG_PM1B_EN: 1615 name = "pm1b_sts"; 1616 size = sc->sc_fadt->pm1_evt_len >> 1; 1617 addr = sc->sc_fadt->pm1b_evt_blk; 1618 access = 2; 1619 if (reg == ACPIREG_PM1B_EN && addr) { 1620 addr += size; 1621 name = "pm1b_en"; 1622 } 1623 break; 1624 case ACPIREG_PM1B_CNT: 1625 name = "pm1b_cnt"; 1626 size = sc->sc_fadt->pm1_cnt_len; 1627 addr = sc->sc_fadt->pm1b_cnt_blk; 1628 access = 2; 1629 break; 1630 case ACPIREG_PM2_CNT: 1631 name = "pm2_cnt"; 1632 size = sc->sc_fadt->pm2_cnt_len; 1633 addr = sc->sc_fadt->pm2_cnt_blk; 1634 access = size; 1635 break; 1636#if 0 1637 case ACPIREG_PM_TMR: 1638 /* Allocated in acpitimer */ 1639 name = "pm_tmr"; 1640 size = sc->sc_fadt->pm_tmr_len; 1641 addr = sc->sc_fadt->pm_tmr_blk; 1642 access = 4; 1643 break; 1644#endif 1645 case ACPIREG_GPE0_STS: 1646 case ACPIREG_GPE0_EN: 1647 name = "gpe0_sts"; 1648 size = sc->sc_fadt->gpe0_blk_len >> 1; 1649 addr = sc->sc_fadt->gpe0_blk; 1650 access = 1; 1651 1652 dnprintf(20, "gpe0 block len : %x\n", 1653 sc->sc_fadt->gpe0_blk_len >> 1); 1654 dnprintf(20, "gpe0 block addr: %x\n", 1655 sc->sc_fadt->gpe0_blk); 1656 if (reg == ACPIREG_GPE0_EN && addr) { 1657 addr += size; 1658 name = "gpe0_en"; 1659 } 1660 break; 1661 case ACPIREG_GPE1_STS: 1662 case ACPIREG_GPE1_EN: 1663 name = "gpe1_sts"; 1664 size = sc->sc_fadt->gpe1_blk_len >> 1; 1665 addr = sc->sc_fadt->gpe1_blk; 1666 access = 1; 1667 1668 dnprintf(20, "gpe1 block len : %x\n", 1669 sc->sc_fadt->gpe1_blk_len >> 1); 1670 dnprintf(20, "gpe1 block addr: %x\n", 1671 sc->sc_fadt->gpe1_blk); 1672 if (reg == ACPIREG_GPE1_EN && addr) { 1673 addr += size; 1674 name = "gpe1_en"; 1675 } 1676 break; 1677 } 1678 if (size && addr) { 1679 dnprintf(50, "mapping: %.4lx %.4lx %s\n", 1680 addr, size, name); 1681 1682 /* Size and address exist; map register space */ 1683 bus_space_map(sc->sc_iot, addr, size, 0, 1684 &sc->sc_pmregs[reg].ioh); 1685 1686 sc->sc_pmregs[reg].name = name; 1687 sc->sc_pmregs[reg].size = size; 1688 sc->sc_pmregs[reg].addr = addr; 1689 sc->sc_pmregs[reg].access = min(access, 4); 1690 } 1691 } 1692} 1693 1694void 1695acpi_unmap_pmregs(struct acpi_softc *sc) 1696{ 1697 int reg; 1698 1699 for (reg = 0; reg < ACPIREG_MAXREG; reg++) { 1700 if (sc->sc_pmregs[reg].size && sc->sc_pmregs[reg].addr) 1701 bus_space_unmap(sc->sc_iot, sc->sc_pmregs[reg].ioh, 1702 sc->sc_pmregs[reg].size); 1703 } 1704} 1705 1706int 1707acpi_enable(struct acpi_softc *sc) 1708{ 1709 int idx; 1710 1711 acpi_write_pmreg(sc, ACPIREG_SMICMD, 0, sc->sc_fadt->acpi_enable); 1712 idx = 0; 1713 do { 1714 if (idx++ > ACPIEN_RETRIES) { 1715 return ETIMEDOUT; 1716 } 1717 } while (!(acpi_read_pmreg(sc, ACPIREG_PM1_CNT, 0) & ACPI_PM1_SCI_EN)); 1718 1719 return 0; 1720} 1721 1722/* ACPI Workqueue support */ 1723SIMPLEQ_HEAD(,acpi_taskq) acpi_taskq = 1724 SIMPLEQ_HEAD_INITIALIZER(acpi_taskq); 1725 1726void 1727acpi_addtask(struct acpi_softc *sc, void (*handler)(void *, int), 1728 void *arg0, int arg1) 1729{ 1730 struct acpi_taskq *wq; 1731 int s; 1732 1733 wq = malloc(sizeof(*wq), M_DEVBUF, M_ZERO | M_NOWAIT); 1734 if (wq == NULL) 1735 return; 1736 wq->handler = handler; 1737 wq->arg0 = arg0; 1738 wq->arg1 = arg1; 1739 1740 s = spltty(); 1741 SIMPLEQ_INSERT_TAIL(&acpi_taskq, wq, next); 1742 splx(s); 1743} 1744 1745int 1746acpi_dotask(struct acpi_softc *sc) 1747{ 1748 struct acpi_taskq *wq; 1749 int s; 1750 1751 s = spltty(); 1752 if (SIMPLEQ_EMPTY(&acpi_taskq)) { 1753 splx(s); 1754 1755 /* we don't have anything to do */ 1756 return (0); 1757 } 1758 wq = SIMPLEQ_FIRST(&acpi_taskq); 1759 SIMPLEQ_REMOVE_HEAD(&acpi_taskq, next); 1760 splx(s); 1761 1762 wq->handler(wq->arg0, wq->arg1); 1763 1764 free(wq, M_DEVBUF, sizeof(*wq)); 1765 1766 /* We did something */ 1767 return (1); 1768} 1769 1770#ifndef SMALL_KERNEL 1771 1772int 1773is_ata(struct aml_node *node) 1774{ 1775 return (aml_searchname(node, "_GTM") != NULL || 1776 aml_searchname(node, "_GTF") != NULL || 1777 aml_searchname(node, "_STM") != NULL || 1778 aml_searchname(node, "_SDD") != NULL); 1779} 1780 1781int 1782is_ejectable(struct aml_node *node) 1783{ 1784 return (aml_searchname(node, "_EJ0") != NULL); 1785} 1786 1787int 1788is_ejectable_bay(struct aml_node *node) 1789{ 1790 return ((is_ata(node) || is_ata(node->parent)) && is_ejectable(node)); 1791} 1792 1793#if NWD > 0 1794int 1795acpiide_notify(struct aml_node *node, int ntype, void *arg) 1796{ 1797 struct idechnl *ide = arg; 1798 struct acpi_softc *sc = ide->sc; 1799 struct pciide_softc *wsc; 1800 struct device *dev; 1801 int b,d,f; 1802 int64_t sta; 1803 1804 if (aml_evalinteger(sc, node, "_STA", 0, NULL, &sta) != 0) 1805 return (0); 1806 1807 dnprintf(10, "IDE notify! %s %d status:%llx\n", aml_nodename(node), 1808 ntype, sta); 1809 1810 /* Walk device list looking for IDE device match */ 1811 TAILQ_FOREACH(dev, &alldevs, dv_list) { 1812 if (strcmp(dev->dv_cfdata->cf_driver->cd_name, "pciide")) 1813 continue; 1814 1815 wsc = (struct pciide_softc *)dev; 1816 pci_decompose_tag(NULL, wsc->sc_tag, &b, &d, &f); 1817 if (b != ACPI_PCI_BUS(ide->addr) || 1818 d != ACPI_PCI_DEV(ide->addr) || 1819 f != ACPI_PCI_FN(ide->addr)) 1820 continue; 1821 dnprintf(10, "Found pciide: %s %x.%x.%x channel:%llx\n", 1822 dev->dv_xname, b,d,f, ide->chnl); 1823 1824 if (sta == 0 && ide->sta) 1825 wdcdetach( 1826 &wsc->pciide_channels[ide->chnl].wdc_channel, 0); 1827 else if (sta && !ide->sta) 1828 wdcattach( 1829 &wsc->pciide_channels[ide->chnl].wdc_channel); 1830 ide->sta = sta; 1831 } 1832 return (0); 1833} 1834 1835int 1836acpi_foundide(struct aml_node *node, void *arg) 1837{ 1838 struct acpi_softc *sc = arg; 1839 struct aml_node *pp; 1840 struct idechnl *ide; 1841 union amlpci_t pi; 1842 int lvl; 1843 1844 /* Check if this is an ejectable bay */ 1845 if (!is_ejectable_bay(node)) 1846 return (0); 1847 1848 ide = malloc(sizeof(struct idechnl), M_DEVBUF, M_NOWAIT | M_ZERO); 1849 ide->sc = sc; 1850 1851 /* GTM/GTF can be at 2/3 levels: pciX.ideX.channelX[.driveX] */ 1852 lvl = 0; 1853 for (pp=node->parent; pp; pp=pp->parent) { 1854 lvl++; 1855 if (aml_searchname(pp, "_HID")) 1856 break; 1857 } 1858 1859 /* Get PCI address and channel */ 1860 if (lvl == 3) { 1861 aml_evalinteger(sc, node->parent, "_ADR", 0, NULL, 1862 &ide->chnl); 1863 aml_rdpciaddr(node->parent->parent, &pi); 1864 ide->addr = pi.addr; 1865 } else if (lvl == 4) { 1866 aml_evalinteger(sc, node->parent->parent, "_ADR", 0, NULL, 1867 &ide->chnl); 1868 aml_rdpciaddr(node->parent->parent->parent, &pi); 1869 ide->addr = pi.addr; 1870 } 1871 dnprintf(10, "%s %llx channel:%llx\n", 1872 aml_nodename(node), ide->addr, ide->chnl); 1873 1874 aml_evalinteger(sc, node, "_STA", 0, NULL, &ide->sta); 1875 dnprintf(10, "Got Initial STA: %llx\n", ide->sta); 1876 1877 aml_register_notify(node, "acpiide", acpiide_notify, ide, 0); 1878 return (0); 1879} 1880#endif /* NWD > 0 */ 1881 1882void 1883acpi_sleep_task(void *arg0, int sleepmode) 1884{ 1885 struct acpi_softc *sc = arg0; 1886 struct acpi_ac *ac; 1887 struct acpi_bat *bat; 1888 struct acpi_sbs *sbs; 1889 1890 /* System goes to sleep here.. */ 1891 acpi_sleep_state(sc, sleepmode); 1892 1893 /* AC and battery information needs refreshing */ 1894 SLIST_FOREACH(ac, &sc->sc_ac, aac_link) 1895 aml_notify(ac->aac_softc->sc_devnode, 0x80); 1896 SLIST_FOREACH(bat, &sc->sc_bat, aba_link) 1897 aml_notify(bat->aba_softc->sc_devnode, 0x80); 1898 SLIST_FOREACH(sbs, &sc->sc_sbs, asbs_link) 1899 aml_notify(sbs->asbs_softc->sc_devnode, 0x80); 1900} 1901 1902#endif /* SMALL_KERNEL */ 1903 1904void 1905acpi_reset(void) 1906{ 1907 uint32_t reset_as, reset_len; 1908 uint32_t value; 1909 struct acpi_softc *sc = acpi_softc; 1910 struct acpi_fadt *fadt = sc->sc_fadt; 1911 1912 if (acpi_enabled == 0) 1913 return; 1914 1915 /* 1916 * RESET_REG_SUP is not properly set in some implementations, 1917 * but not testing against it breaks more machines than it fixes 1918 */ 1919 if (fadt->hdr_revision <= 1 || 1920 !(fadt->flags & FADT_RESET_REG_SUP) || fadt->reset_reg.address == 0) 1921 return; 1922 1923 value = fadt->reset_value; 1924 1925 reset_as = fadt->reset_reg.register_bit_width / 8; 1926 if (reset_as == 0) 1927 reset_as = 1; 1928 1929 reset_len = fadt->reset_reg.access_size; 1930 if (reset_len == 0) 1931 reset_len = reset_as; 1932 1933 acpi_gasio(sc, ACPI_IOWRITE, 1934 fadt->reset_reg.address_space_id, 1935 fadt->reset_reg.address, reset_as, reset_len, &value); 1936 1937 delay(100000); 1938} 1939 1940void 1941acpi_gpe_task(void *arg0, int gpe) 1942{ 1943 struct acpi_softc *sc = acpi_softc; 1944 struct gpe_block *pgpe = &sc->gpe_table[gpe]; 1945 1946 dnprintf(10, "handle gpe: %x\n", gpe); 1947 if (pgpe->handler && pgpe->active) { 1948 pgpe->active = 0; 1949 pgpe->handler(sc, gpe, pgpe->arg); 1950 } 1951} 1952 1953void 1954acpi_pbtn_task(void *arg0, int dummy) 1955{ 1956 struct acpi_softc *sc = arg0; 1957 uint16_t en; 1958 int s; 1959 1960 dnprintf(1,"power button pressed\n"); 1961 1962 /* Reset the latch and re-enable the GPE */ 1963 s = spltty(); 1964 en = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0); 1965 acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, 1966 en | ACPI_PM1_PWRBTN_EN); 1967 splx(s); 1968 1969 acpi_addtask(sc, acpi_powerdown_task, sc, 0); 1970} 1971 1972void 1973acpi_sbtn_task(void *arg0, int dummy) 1974{ 1975 struct acpi_softc *sc = arg0; 1976 uint16_t en; 1977 int s; 1978 1979 dnprintf(1,"sleep button pressed\n"); 1980 aml_notify_dev(ACPI_DEV_SBD, 0x80); 1981 1982 /* Reset the latch and re-enable the GPE */ 1983 s = spltty(); 1984 en = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0); 1985 acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, 1986 en | ACPI_PM1_SLPBTN_EN); 1987 splx(s); 1988} 1989 1990void 1991acpi_powerdown_task(void *arg0, int dummy) 1992{ 1993 extern int allowpowerdown; 1994 1995 if (allowpowerdown == 1) { 1996 allowpowerdown = 0; 1997 prsignal(initprocess, SIGUSR2); 1998 } 1999} 2000 2001int 2002acpi_interrupt(void *arg) 2003{ 2004 struct acpi_softc *sc = (struct acpi_softc *)arg; 2005 uint32_t processed = 0, idx, jdx; 2006 uint16_t sts, en; 2007 2008 dnprintf(40, "ACPI Interrupt\n"); 2009 for (idx = 0; idx < sc->sc_lastgpe; idx += 8) { 2010 sts = acpi_read_pmreg(sc, ACPIREG_GPE_STS, idx>>3); 2011 en = acpi_read_pmreg(sc, ACPIREG_GPE_EN, idx>>3); 2012 if (en & sts) { 2013 dnprintf(10, "GPE block: %.2x %.2x %.2x\n", idx, sts, 2014 en); 2015 /* Mask the GPE until it is serviced */ 2016 acpi_write_pmreg(sc, ACPIREG_GPE_EN, idx>>3, en & ~sts); 2017 for (jdx = 0; jdx < 8; jdx++) { 2018 if (en & sts & (1L << jdx)) { 2019 /* Signal this GPE */ 2020 sc->gpe_table[idx+jdx].active = 1; 2021 dnprintf(10, "queue gpe: %x\n", 2022 idx+jdx); 2023 acpi_addtask(sc, acpi_gpe_task, NULL, 2024 idx+jdx); 2025 2026 /* 2027 * Edge interrupts need their STS bits 2028 * cleared now. Level interrupts will 2029 * have their STS bits cleared just 2030 * before they are re-enabled. 2031 */ 2032 if (sc->gpe_table[idx+jdx].edge) 2033 acpi_write_pmreg(sc, 2034 ACPIREG_GPE_STS, idx>>3, 2035 1L << jdx); 2036 processed = 1; 2037 } 2038 } 2039 } 2040 } 2041 2042 sts = acpi_read_pmreg(sc, ACPIREG_PM1_STS, 0); 2043 en = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0); 2044 if (sts & en) { 2045 dnprintf(10,"GEN interrupt: %.4x\n", sts & en); 2046 sts &= en; 2047 if (sts & ACPI_PM1_PWRBTN_STS) { 2048 /* Mask and acknowledge */ 2049 en &= ~ACPI_PM1_PWRBTN_EN; 2050 acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en); 2051 acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, 2052 ACPI_PM1_PWRBTN_STS); 2053 sts &= ~ACPI_PM1_PWRBTN_STS; 2054 2055 acpi_addtask(sc, acpi_pbtn_task, sc, 0); 2056 } 2057 if (sts & ACPI_PM1_SLPBTN_STS) { 2058 /* Mask and acknowledge */ 2059 en &= ~ACPI_PM1_SLPBTN_EN; 2060 acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en); 2061 acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, 2062 ACPI_PM1_SLPBTN_STS); 2063 sts &= ~ACPI_PM1_SLPBTN_STS; 2064 2065 acpi_addtask(sc, acpi_sbtn_task, sc, 0); 2066 } 2067 if (sts) { 2068 printf("%s: PM1 stuck (en 0x%x st 0x%x), clearing\n", 2069 sc->sc_dev.dv_xname, en, sts); 2070 acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en & ~sts); 2071 acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, sts); 2072 } 2073 processed = 1; 2074 } 2075 2076 if (processed) { 2077 acpi_wakeup(sc); 2078 } 2079 2080 return (processed); 2081} 2082 2083int 2084acpi_add_device(struct aml_node *node, void *arg) 2085{ 2086 static int nacpicpus = 0; 2087 struct device *self = arg; 2088 struct acpi_softc *sc = arg; 2089 struct acpi_attach_args aaa; 2090 struct aml_value res; 2091 CPU_INFO_ITERATOR cii; 2092 struct cpu_info *ci; 2093 int proc_id = -1; 2094 2095 memset(&aaa, 0, sizeof(aaa)); 2096 aaa.aaa_node = node; 2097 aaa.aaa_iot = sc->sc_iot; 2098 aaa.aaa_memt = sc->sc_memt; 2099 if (node == NULL || node->value == NULL) 2100 return 0; 2101 2102 switch (node->value->type) { 2103 case AML_OBJTYPE_PROCESSOR: 2104 if (nacpicpus >= ncpus) 2105 return 0; 2106 if (aml_evalnode(sc, aaa.aaa_node, 0, NULL, &res) == 0) { 2107 if (res.type == AML_OBJTYPE_PROCESSOR) 2108 proc_id = res.v_processor.proc_id; 2109 aml_freevalue(&res); 2110 } 2111 CPU_INFO_FOREACH(cii, ci) { 2112 if (ci->ci_acpi_proc_id == proc_id) 2113 break; 2114 } 2115 if (ci == NULL) 2116 return 0; 2117 nacpicpus++; 2118 2119 aaa.aaa_name = "acpicpu"; 2120 break; 2121 case AML_OBJTYPE_THERMZONE: 2122 aaa.aaa_name = "acpitz"; 2123 break; 2124 case AML_OBJTYPE_POWERRSRC: 2125 aaa.aaa_name = "acpipwrres"; 2126 break; 2127 default: 2128 return 0; 2129 } 2130 config_found(self, &aaa, acpi_print); 2131 return 0; 2132} 2133 2134void 2135acpi_enable_onegpe(struct acpi_softc *sc, int gpe) 2136{ 2137 uint8_t mask, en; 2138 2139 /* Read enabled register */ 2140 mask = (1L << (gpe & 7)); 2141 en = acpi_read_pmreg(sc, ACPIREG_GPE_EN, gpe>>3); 2142 dnprintf(50, "enabling GPE %.2x (current: %sabled) %.2x\n", 2143 gpe, (en & mask) ? "en" : "dis", en); 2144 acpi_write_pmreg(sc, ACPIREG_GPE_EN, gpe>>3, en | mask); 2145} 2146 2147/* Clear all GPEs */ 2148void 2149acpi_disable_allgpes(struct acpi_softc *sc) 2150{ 2151 int idx; 2152 2153 for (idx = 0; idx < sc->sc_lastgpe; idx += 8) { 2154 acpi_write_pmreg(sc, ACPIREG_GPE_EN, idx >> 3, 0); 2155 acpi_write_pmreg(sc, ACPIREG_GPE_STS, idx >> 3, -1); 2156 } 2157} 2158 2159/* Enable runtime GPEs */ 2160void 2161acpi_enable_rungpes(struct acpi_softc *sc) 2162{ 2163 int idx; 2164 2165 for (idx = 0; idx < sc->sc_lastgpe; idx++) 2166 if (sc->gpe_table[idx].handler) 2167 acpi_enable_onegpe(sc, idx); 2168} 2169 2170/* Enable wakeup GPEs */ 2171void 2172acpi_enable_wakegpes(struct acpi_softc *sc, int state) 2173{ 2174 struct acpi_wakeq *wentry; 2175 2176 SIMPLEQ_FOREACH(wentry, &sc->sc_wakedevs, q_next) { 2177 dnprintf(10, "%.4s(S%d) gpe %.2x\n", wentry->q_node->name, 2178 wentry->q_state, 2179 wentry->q_gpe); 2180 if (state <= wentry->q_state) 2181 acpi_enable_onegpe(sc, wentry->q_gpe); 2182 } 2183} 2184 2185int 2186acpi_set_gpehandler(struct acpi_softc *sc, int gpe, int (*handler) 2187 (struct acpi_softc *, int, void *), void *arg, int edge) 2188{ 2189 struct gpe_block *ptbl; 2190 2191 ptbl = acpi_find_gpe(sc, gpe); 2192 if (ptbl == NULL || handler == NULL) 2193 return -EINVAL; 2194 if (ptbl->handler != NULL) 2195 printf("%s: GPE 0x%.2x already enabled\n", DEVNAME(sc), gpe); 2196 2197 dnprintf(50, "Adding GPE handler 0x%.2x (%s)\n", gpe, 2198 edge ? "edge" : "level"); 2199 ptbl->handler = handler; 2200 ptbl->arg = arg; 2201 ptbl->edge = edge; 2202 2203 return (0); 2204} 2205 2206int 2207acpi_gpe(struct acpi_softc *sc, int gpe, void *arg) 2208{ 2209 struct aml_node *node = arg; 2210 uint8_t mask, en; 2211 2212 dnprintf(10, "handling GPE %.2x\n", gpe); 2213 aml_evalnode(sc, node, 0, NULL, NULL); 2214 2215 mask = (1L << (gpe & 7)); 2216 if (!sc->gpe_table[gpe].edge) 2217 acpi_write_pmreg(sc, ACPIREG_GPE_STS, gpe>>3, mask); 2218 en = acpi_read_pmreg(sc, ACPIREG_GPE_EN, gpe>>3); 2219 acpi_write_pmreg(sc, ACPIREG_GPE_EN, gpe>>3, en | mask); 2220 return (0); 2221} 2222 2223/* Discover Devices that can wakeup the system 2224 * _PRW returns a package 2225 * pkg[0] = integer (FADT gpe bit) or package (gpe block,gpe bit) 2226 * pkg[1] = lowest sleep state 2227 * pkg[2+] = power resource devices (optional) 2228 * 2229 * To enable wakeup devices: 2230 * Evaluate _ON method in each power resource device 2231 * Evaluate _PSW method 2232 */ 2233int 2234acpi_foundprw(struct aml_node *node, void *arg) 2235{ 2236 struct acpi_softc *sc = arg; 2237 struct acpi_wakeq *wq; 2238 int64_t sta; 2239 2240 if (aml_evalinteger(sc, node->parent, "_STA", 0, NULL, &sta)) 2241 sta = STA_PRESENT | STA_ENABLED | STA_DEV_OK | 0x1000; 2242 2243 if ((sta & STA_PRESENT) == 0) 2244 return 0; 2245 2246 wq = malloc(sizeof(struct acpi_wakeq), M_DEVBUF, M_NOWAIT | M_ZERO); 2247 if (wq == NULL) 2248 return 0; 2249 2250 wq->q_wakepkg = malloc(sizeof(struct aml_value), M_DEVBUF, 2251 M_NOWAIT | M_ZERO); 2252 if (wq->q_wakepkg == NULL) { 2253 free(wq, M_DEVBUF, sizeof(*wq)); 2254 return 0; 2255 } 2256 dnprintf(10, "Found _PRW (%s)\n", node->parent->name); 2257 aml_evalnode(sc, node, 0, NULL, wq->q_wakepkg); 2258 wq->q_node = node->parent; 2259 wq->q_gpe = -1; 2260 2261 /* Get GPE of wakeup device, and lowest sleep level */ 2262 if (wq->q_wakepkg->type == AML_OBJTYPE_PACKAGE && 2263 wq->q_wakepkg->length >= 2) { 2264 if (wq->q_wakepkg->v_package[0]->type == AML_OBJTYPE_INTEGER) 2265 wq->q_gpe = wq->q_wakepkg->v_package[0]->v_integer; 2266 if (wq->q_wakepkg->v_package[1]->type == AML_OBJTYPE_INTEGER) 2267 wq->q_state = wq->q_wakepkg->v_package[1]->v_integer; 2268 } 2269 SIMPLEQ_INSERT_TAIL(&sc->sc_wakedevs, wq, q_next); 2270 return 0; 2271} 2272 2273struct gpe_block * 2274acpi_find_gpe(struct acpi_softc *sc, int gpe) 2275{ 2276 if (gpe >= sc->sc_lastgpe) 2277 return NULL; 2278 return &sc->gpe_table[gpe]; 2279} 2280 2281void 2282acpi_init_gpes(struct acpi_softc *sc) 2283{ 2284 struct aml_node *gpe; 2285 char name[12]; 2286 int idx, ngpe; 2287 2288 sc->sc_lastgpe = sc->sc_fadt->gpe0_blk_len << 2; 2289 if (sc->sc_fadt->gpe1_blk_len) { 2290 } 2291 dnprintf(50, "Last GPE: %.2x\n", sc->sc_lastgpe); 2292 2293 /* Allocate GPE table */ 2294 sc->gpe_table = mallocarray(sc->sc_lastgpe, sizeof(struct gpe_block), 2295 M_DEVBUF, M_WAITOK | M_ZERO); 2296 2297 ngpe = 0; 2298 2299 /* Clear GPE status */ 2300 acpi_disable_allgpes(sc); 2301 for (idx = 0; idx < sc->sc_lastgpe; idx++) { 2302 /* Search Level-sensitive GPES */ 2303 snprintf(name, sizeof(name), "\\_GPE._L%.2X", idx); 2304 gpe = aml_searchname(&aml_root, name); 2305 if (gpe != NULL) 2306 acpi_set_gpehandler(sc, idx, acpi_gpe, gpe, 0); 2307 if (gpe == NULL) { 2308 /* Search Edge-sensitive GPES */ 2309 snprintf(name, sizeof(name), "\\_GPE._E%.2X", idx); 2310 gpe = aml_searchname(&aml_root, name); 2311 if (gpe != NULL) 2312 acpi_set_gpehandler(sc, idx, acpi_gpe, gpe, 1); 2313 } 2314 } 2315 aml_find_node(&aml_root, "_PRW", acpi_foundprw, sc); 2316 sc->sc_maxgpe = ngpe; 2317} 2318 2319void 2320acpi_init_pm(struct acpi_softc *sc) 2321{ 2322 sc->sc_tts = aml_searchname(&aml_root, "_TTS"); 2323 sc->sc_pts = aml_searchname(&aml_root, "_PTS"); 2324 sc->sc_wak = aml_searchname(&aml_root, "_WAK"); 2325 sc->sc_bfs = aml_searchname(&aml_root, "_BFS"); 2326 sc->sc_gts = aml_searchname(&aml_root, "_GTS"); 2327 sc->sc_sst = aml_searchname(&aml_root, "_SI_._SST"); 2328} 2329 2330#ifndef SMALL_KERNEL 2331 2332void 2333acpi_init_states(struct acpi_softc *sc) 2334{ 2335 struct aml_value res; 2336 char name[8]; 2337 int i; 2338 2339 printf("\n%s: sleep states", DEVNAME(sc)); 2340 for (i = ACPI_STATE_S0; i <= ACPI_STATE_S5; i++) { 2341 snprintf(name, sizeof(name), "_S%d_", i); 2342 sc->sc_sleeptype[i].slp_typa = -1; 2343 sc->sc_sleeptype[i].slp_typb = -1; 2344 if (aml_evalname(sc, &aml_root, name, 0, NULL, &res) == 0) { 2345 if (res.type == AML_OBJTYPE_PACKAGE) { 2346 sc->sc_sleeptype[i].slp_typa = 2347 aml_val2int(res.v_package[0]); 2348 sc->sc_sleeptype[i].slp_typb = 2349 aml_val2int(res.v_package[1]); 2350 printf(" S%d", i); 2351 } 2352 aml_freevalue(&res); 2353 } 2354 } 2355} 2356 2357void 2358acpi_sleep_pm(struct acpi_softc *sc, int state) 2359{ 2360 uint16_t rega, regb, regra, regrb; 2361 int retry = 0; 2362 2363 intr_disable(); 2364 2365 /* Clear WAK_STS bit */ 2366 acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, ACPI_PM1_WAK_STS); 2367 2368 /* Disable BM arbitration at deep sleep and beyond */ 2369 if (state >= ACPI_STATE_S3 && 2370 sc->sc_fadt->pm2_cnt_blk && sc->sc_fadt->pm2_cnt_len) 2371 acpi_write_pmreg(sc, ACPIREG_PM2_CNT, 0, ACPI_PM2_ARB_DIS); 2372 2373 /* Write SLP_TYPx values */ 2374 rega = acpi_read_pmreg(sc, ACPIREG_PM1A_CNT, 0); 2375 regb = acpi_read_pmreg(sc, ACPIREG_PM1B_CNT, 0); 2376 rega &= ~(ACPI_PM1_SLP_TYPX_MASK | ACPI_PM1_SLP_EN); 2377 regb &= ~(ACPI_PM1_SLP_TYPX_MASK | ACPI_PM1_SLP_EN); 2378 rega |= ACPI_PM1_SLP_TYPX(sc->sc_sleeptype[state].slp_typa); 2379 regb |= ACPI_PM1_SLP_TYPX(sc->sc_sleeptype[state].slp_typb); 2380 acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, 0, rega); 2381 acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, 0, regb); 2382 2383 /* Loop on WAK_STS, setting the SLP_EN bits once in a while */ 2384 rega |= ACPI_PM1_SLP_EN; 2385 regb |= ACPI_PM1_SLP_EN; 2386 while (1) { 2387 if (retry == 0) { 2388 acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, 0, rega); 2389 acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, 0, regb); 2390 } 2391 retry = (retry + 1) % 100000; 2392 2393 regra = acpi_read_pmreg(sc, ACPIREG_PM1A_STS, 0); 2394 regrb = acpi_read_pmreg(sc, ACPIREG_PM1B_STS, 0); 2395 if ((regra & ACPI_PM1_WAK_STS) || 2396 (regrb & ACPI_PM1_WAK_STS)) 2397 break; 2398 } 2399} 2400 2401uint32_t acpi_force_bm; 2402 2403void 2404acpi_resume_pm(struct acpi_softc *sc, int fromstate) 2405{ 2406 uint16_t rega, regb, en; 2407 2408 /* Write SLP_TYPx values */ 2409 rega = acpi_read_pmreg(sc, ACPIREG_PM1A_CNT, 0); 2410 regb = acpi_read_pmreg(sc, ACPIREG_PM1B_CNT, 0); 2411 rega &= ~(ACPI_PM1_SLP_TYPX_MASK | ACPI_PM1_SLP_EN); 2412 regb &= ~(ACPI_PM1_SLP_TYPX_MASK | ACPI_PM1_SLP_EN); 2413 rega |= ACPI_PM1_SLP_TYPX(sc->sc_sleeptype[ACPI_STATE_S0].slp_typa); 2414 regb |= ACPI_PM1_SLP_TYPX(sc->sc_sleeptype[ACPI_STATE_S0].slp_typb); 2415 acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, 0, rega); 2416 acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, 0, regb); 2417 2418 /* Force SCI_EN on resume to fix horribly broken machines */ 2419 acpi_write_pmreg(sc, ACPIREG_PM1_CNT, 0, 2420 ACPI_PM1_SCI_EN | acpi_force_bm); 2421 2422 /* Clear fixed event status */ 2423 acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, ACPI_PM1_ALL_STS); 2424 2425 /* acpica-reference.pdf page 148 says do not call _BFS */ 2426 /* 1st resume AML step: _BFS(fromstate) */ 2427 aml_node_setval(sc, sc->sc_bfs, fromstate); 2428 2429 /* Enable runtime GPEs */ 2430 acpi_disable_allgpes(sc); 2431 acpi_enable_rungpes(sc); 2432 2433 acpi_indicator(sc, ACPI_SST_WAKING); 2434 2435 /* 2nd resume AML step: _WAK(fromstate) */ 2436 aml_node_setval(sc, sc->sc_wak, fromstate); 2437 2438 /* Clear WAK_STS bit */ 2439 acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, ACPI_PM1_WAK_STS); 2440 2441 en = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0); 2442 if (!(sc->sc_fadt->flags & FADT_PWR_BUTTON)) 2443 en |= ACPI_PM1_PWRBTN_EN; 2444 if (!(sc->sc_fadt->flags & FADT_SLP_BUTTON)) 2445 en |= ACPI_PM1_SLPBTN_EN; 2446 acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en); 2447 2448 /* 2449 * If PM2 exists, re-enable BM arbitration (reportedly some 2450 * BIOS forget to) 2451 */ 2452 if (sc->sc_fadt->pm2_cnt_blk && sc->sc_fadt->pm2_cnt_len) { 2453 rega = acpi_read_pmreg(sc, ACPIREG_PM2_CNT, 0); 2454 rega &= ~ACPI_PM2_ARB_DIS; 2455 acpi_write_pmreg(sc, ACPIREG_PM2_CNT, 0, rega); 2456 } 2457} 2458 2459/* Set the indicator light to some state */ 2460void 2461acpi_indicator(struct acpi_softc *sc, int led_state) 2462{ 2463 static int save_led_state = -1; 2464 2465 if (save_led_state != led_state) { 2466 aml_node_setval(sc, sc->sc_sst, led_state); 2467 save_led_state = led_state; 2468 } 2469} 2470 2471 2472int 2473acpi_sleep_state(struct acpi_softc *sc, int sleepmode) 2474{ 2475 extern int perflevel; 2476 extern int lid_action; 2477 int error = ENXIO; 2478 size_t rndbuflen = 0; 2479 char *rndbuf = NULL; 2480 int state, s; 2481#if NSOFTRAID > 0 2482 extern void sr_quiesce(void); 2483#endif 2484 2485 switch (sleepmode) { 2486 case ACPI_SLEEP_SUSPEND: 2487 state = ACPI_STATE_S3; 2488 break; 2489 case ACPI_SLEEP_HIBERNATE: 2490 state = ACPI_STATE_S4; 2491 break; 2492 default: 2493 return (EOPNOTSUPP); 2494 } 2495 2496 if (sc->sc_sleeptype[state].slp_typa == -1 || 2497 sc->sc_sleeptype[state].slp_typb == -1) { 2498 printf("%s: state S%d unavailable\n", 2499 sc->sc_dev.dv_xname, state); 2500 return (EOPNOTSUPP); 2501 } 2502 2503 /* 1st suspend AML step: _TTS(tostate) */ 2504 if (aml_node_setval(sc, sc->sc_tts, state) != 0) 2505 goto fail_tts; 2506 acpi_indicator(sc, ACPI_SST_WAKING); /* blink */ 2507 2508#if NWSDISPLAY > 0 2509 /* 2510 * Temporarily release the lock to prevent the X server from 2511 * blocking on setting the display brightness. 2512 */ 2513 rw_exit_write(&sc->sc_lck); 2514 wsdisplay_suspend(); 2515 rw_enter_write(&sc->sc_lck); 2516#endif /* NWSDISPLAY > 0 */ 2517 2518 stop_periodic_resettodr(); 2519 2520#ifdef HIBERNATE 2521 if (sleepmode == ACPI_SLEEP_HIBERNATE) { 2522 /* 2523 * Discard useless memory to reduce fragmentation, 2524 * and attempt to create a hibernate work area 2525 */ 2526 hibernate_suspend_bufcache(); 2527 uvmpd_hibernate(); 2528 if (hibernate_alloc()) { 2529 printf("%s: failed to allocate hibernate memory\n", 2530 sc->sc_dev.dv_xname); 2531 goto fail_alloc; 2532 } 2533 } 2534#endif /* HIBERNATE */ 2535 2536 sensor_quiesce(); 2537 if (config_suspend_all(DVACT_QUIESCE)) 2538 goto fail_quiesce; 2539 2540 vfs_stall(curproc, 1); 2541#if NSOFTRAID > 0 2542 sr_quiesce(); 2543#endif 2544 bufq_quiesce(); 2545 2546#ifdef MULTIPROCESSOR 2547 acpi_sleep_mp(); 2548#endif 2549 2550#ifdef HIBERNATE 2551 if (sleepmode == ACPI_SLEEP_HIBERNATE) { 2552 /* 2553 * We've just done various forms of syncing to disk 2554 * churned lots of memory dirty. We don't need to 2555 * save that dirty memory to hibernate, so release it. 2556 */ 2557 hibernate_suspend_bufcache(); 2558 uvmpd_hibernate(); 2559 } 2560#endif /* HIBERNATE */ 2561 2562 resettodr(); 2563 2564 s = splhigh(); 2565 intr_disable(); /* PSL_I for resume; PIC/APIC broken until repair */ 2566 cold = 2; /* Force other code to delay() instead of tsleep() */ 2567 2568 if (config_suspend_all(DVACT_SUSPEND) != 0) 2569 goto fail_suspend; 2570 acpi_sleep_clocks(sc, state); 2571 2572 suspend_randomness(); 2573 2574 /* 2nd suspend AML step: _PTS(tostate) */ 2575 if (aml_node_setval(sc, sc->sc_pts, state) != 0) 2576 goto fail_pts; 2577 2578 acpibtn_enable_psw(); /* enable _LID for wakeup */ 2579 acpi_indicator(sc, ACPI_SST_SLEEPING); 2580 2581 /* 3rd suspend AML step: _GTS(tostate) */ 2582 aml_node_setval(sc, sc->sc_gts, state); 2583 2584 /* Clear fixed event status */ 2585 acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, ACPI_PM1_ALL_STS); 2586 2587 /* Enable wake GPEs */ 2588 acpi_disable_allgpes(sc); 2589 acpi_enable_wakegpes(sc, state); 2590 2591 /* Sleep */ 2592 sc->sc_state = state; 2593 error = acpi_sleep_cpu(sc, state); 2594 sc->sc_state = ACPI_STATE_S0; 2595 /* Resume */ 2596 2597#ifdef HIBERNATE 2598 if (sleepmode == ACPI_SLEEP_HIBERNATE) { 2599 uvm_pmr_dirty_everything(); 2600 hib_getentropy(&rndbuf, &rndbuflen); 2601 } 2602#endif /* HIBERNATE */ 2603 2604 acpi_resume_clocks(sc); /* AML may need clocks */ 2605 acpi_resume_pm(sc, state); 2606 acpi_resume_cpu(sc); 2607 2608fail_pts: 2609 config_suspend_all(DVACT_RESUME); 2610 2611fail_suspend: 2612 cold = 0; 2613 intr_enable(); 2614 splx(s); 2615 2616 acpibtn_disable_psw(); /* disable _LID for wakeup */ 2617 inittodr(time_second); 2618 2619 /* 3rd resume AML step: _TTS(runstate) */ 2620 aml_node_setval(sc, sc->sc_tts, sc->sc_state); 2621 2622 /* force RNG upper level reseed */ 2623 resume_randomness(rndbuf, rndbuflen); 2624 2625#ifdef MULTIPROCESSOR 2626 acpi_resume_mp(); 2627#endif 2628 2629 vfs_stall(curproc, 0); 2630 bufq_restart(); 2631 2632fail_quiesce: 2633 config_suspend_all(DVACT_WAKEUP); 2634 sensor_restart(); 2635 2636#ifdef HIBERNATE 2637 if (sleepmode == ACPI_SLEEP_HIBERNATE) { 2638 hibernate_free(); 2639fail_alloc: 2640 hibernate_resume_bufcache(); 2641 } 2642#endif /* HIBERNATE */ 2643 2644 start_periodic_resettodr(); 2645 2646#if NWSDISPLAY > 0 2647 rw_exit_write(&sc->sc_lck); 2648 wsdisplay_resume(); 2649 rw_enter_write(&sc->sc_lck); 2650#endif /* NWSDISPLAY > 0 */ 2651 2652 sys_sync(curproc, NULL, NULL); 2653 2654 /* Restore hw.setperf */ 2655 if (cpu_setperf != NULL) 2656 cpu_setperf(perflevel); 2657 2658 acpi_record_event(sc, APM_NORMAL_RESUME); 2659 acpi_indicator(sc, ACPI_SST_WORKING); 2660 2661 /* If we woke up but all the lids are closed, go back to sleep */ 2662 if (acpibtn_numopenlids() == 0 && lid_action != 0) 2663 acpi_addtask(sc, acpi_sleep_task, sc, sleepmode); 2664 2665fail_tts: 2666 return (error); 2667} 2668 2669/* XXX 2670 * We are going to do AML execution but are not in the acpi thread. 2671 * We do not know if the acpi thread is sleeping on acpiec in some 2672 * intermediate context. Wish us luck. 2673 */ 2674void 2675acpi_powerdown(void) 2676{ 2677 int state = ACPI_STATE_S5, s; 2678 struct acpi_softc *sc = acpi_softc; 2679 2680 if (acpi_enabled == 0) 2681 return; 2682 2683 s = splhigh(); 2684 intr_disable(); 2685 cold = 1; 2686 2687 /* 1st powerdown AML step: _PTS(tostate) */ 2688 aml_node_setval(sc, sc->sc_pts, state); 2689 2690 acpi_disable_allgpes(sc); 2691 acpi_enable_wakegpes(sc, state); 2692 2693 /* 2nd powerdown AML step: _GTS(tostate) */ 2694 aml_node_setval(sc, sc->sc_gts, state); 2695 2696 acpi_sleep_pm(sc, state); 2697 panic("acpi S5 transition did not happen"); 2698 while (1) 2699 ; 2700} 2701 2702int 2703acpi_map_address(struct acpi_softc *sc, struct acpi_gas *gas, bus_addr_t base, 2704 bus_size_t size, bus_space_handle_t *pioh, bus_space_tag_t *piot) 2705{ 2706 int iospace = GAS_SYSTEM_IOSPACE; 2707 2708 /* No GAS structure, default to I/O space */ 2709 if (gas != NULL) { 2710 base += gas->address; 2711 iospace = gas->address_space_id; 2712 } 2713 switch (iospace) { 2714 case GAS_SYSTEM_MEMORY: 2715 *piot = sc->sc_memt; 2716 break; 2717 case GAS_SYSTEM_IOSPACE: 2718 *piot = sc->sc_iot; 2719 break; 2720 default: 2721 return -1; 2722 } 2723 if (bus_space_map(*piot, base, size, 0, pioh)) 2724 return -1; 2725 2726 return 0; 2727} 2728 2729#endif /* SMALL_KERNEL */ 2730 2731void 2732acpi_wakeup(void *arg) 2733{ 2734 struct acpi_softc *sc = (struct acpi_softc *)arg; 2735 2736 sc->sc_threadwaiting = 0; 2737 wakeup(sc); 2738} 2739 2740 2741void 2742acpi_thread(void *arg) 2743{ 2744 struct acpi_thread *thread = arg; 2745 struct acpi_softc *sc = thread->sc; 2746 extern int aml_busy; 2747 int s; 2748 2749 /* AML/SMI cannot be trusted -- only run on the BSP */ 2750 sched_peg_curproc(&cpu_info_primary); 2751 2752 rw_enter_write(&sc->sc_lck); 2753 2754 /* 2755 * If we have an interrupt handler, we can get notification 2756 * when certain status bits changes in the ACPI registers, 2757 * so let us enable some events we can forward to userland 2758 */ 2759 if (sc->sc_interrupt) { 2760 int16_t en; 2761 2762 dnprintf(1,"slpbtn:%c pwrbtn:%c\n", 2763 sc->sc_fadt->flags & FADT_SLP_BUTTON ? 'n' : 'y', 2764 sc->sc_fadt->flags & FADT_PWR_BUTTON ? 'n' : 'y'); 2765 dnprintf(10, "Enabling acpi interrupts...\n"); 2766 sc->sc_threadwaiting = 1; 2767 2768 /* Enable Sleep/Power buttons if they exist */ 2769 s = spltty(); 2770 en = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0); 2771 if (!(sc->sc_fadt->flags & FADT_PWR_BUTTON)) 2772 en |= ACPI_PM1_PWRBTN_EN; 2773 if (!(sc->sc_fadt->flags & FADT_SLP_BUTTON)) 2774 en |= ACPI_PM1_SLPBTN_EN; 2775 acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en); 2776 2777 /* Enable handled GPEs here */ 2778 acpi_enable_rungpes(sc); 2779 splx(s); 2780 } 2781 2782 while (thread->running) { 2783 s = spltty(); 2784 while (sc->sc_threadwaiting) { 2785 dnprintf(10, "acpi thread going to sleep...\n"); 2786 rw_exit_write(&sc->sc_lck); 2787 tsleep(sc, PWAIT, "acpi0", 0); 2788 rw_enter_write(&sc->sc_lck); 2789 } 2790 sc->sc_threadwaiting = 1; 2791 splx(s); 2792 if (aml_busy) { 2793 panic("thread woke up to find aml was busy"); 2794 continue; 2795 } 2796 2797 /* Run ACPI taskqueue */ 2798 while(acpi_dotask(acpi_softc)) 2799 ; 2800 } 2801 free(thread, M_DEVBUF, sizeof(*thread)); 2802 2803 kthread_exit(0); 2804} 2805 2806void 2807acpi_create_thread(void *arg) 2808{ 2809 struct acpi_softc *sc = arg; 2810 2811 if (kthread_create(acpi_thread, sc->sc_thread, NULL, DEVNAME(sc)) 2812 != 0) 2813 printf("%s: unable to create isr thread, GPEs disabled\n", 2814 DEVNAME(sc)); 2815} 2816 2817int 2818acpi_foundec(struct aml_node *node, void *arg) 2819{ 2820 struct acpi_softc *sc = (struct acpi_softc *)arg; 2821 struct device *self = (struct device *)arg; 2822 const char *dev; 2823 struct aml_value res; 2824 struct acpi_attach_args aaa; 2825 2826 if (aml_evalnode(sc, node, 0, NULL, &res) != 0) 2827 return 0; 2828 2829 switch (res.type) { 2830 case AML_OBJTYPE_STRING: 2831 dev = res.v_string; 2832 break; 2833 case AML_OBJTYPE_INTEGER: 2834 dev = aml_eisaid(aml_val2int(&res)); 2835 break; 2836 default: 2837 dev = "unknown"; 2838 break; 2839 } 2840 2841 if (strcmp(dev, ACPI_DEV_ECD)) 2842 return 0; 2843 2844 /* Check if we're already attached */ 2845 if (sc->sc_ec && sc->sc_ec->sc_devnode == node->parent) 2846 return 0; 2847 2848 memset(&aaa, 0, sizeof(aaa)); 2849 aaa.aaa_iot = sc->sc_iot; 2850 aaa.aaa_memt = sc->sc_memt; 2851 aaa.aaa_node = node->parent; 2852 aaa.aaa_dev = dev; 2853 aaa.aaa_name = "acpiec"; 2854 config_found(self, &aaa, acpi_print); 2855 aml_freevalue(&res); 2856 2857 return 0; 2858} 2859 2860int 2861acpi_foundsony(struct aml_node *node, void *arg) 2862{ 2863 struct acpi_softc *sc = (struct acpi_softc *)arg; 2864 struct device *self = (struct device *)arg; 2865 struct acpi_attach_args aaa; 2866 2867 memset(&aaa, 0, sizeof(aaa)); 2868 aaa.aaa_iot = sc->sc_iot; 2869 aaa.aaa_memt = sc->sc_memt; 2870 aaa.aaa_node = node->parent; 2871 aaa.aaa_name = "acpisony"; 2872 2873 config_found(self, &aaa, acpi_print); 2874 2875 return 0; 2876} 2877 2878/* Support for _DSD Device Properties. */ 2879 2880uint32_t 2881acpi_getpropint(struct aml_node *node, const char *prop, uint32_t defval) 2882{ 2883 struct aml_value dsd; 2884 int i; 2885 2886 /* daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */ 2887 static uint8_t prop_guid[] = { 2888 0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d, 2889 0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01, 2890 }; 2891 2892 if (aml_evalname(acpi_softc, node, "_DSD", 0, NULL, &dsd)) 2893 return defval; 2894 2895 if (dsd.type != AML_OBJTYPE_PACKAGE || dsd.length != 2 || 2896 dsd.v_package[0]->type != AML_OBJTYPE_BUFFER || 2897 dsd.v_package[1]->type != AML_OBJTYPE_PACKAGE) 2898 return defval; 2899 2900 /* Check UUID. */ 2901 if (dsd.v_package[0]->length != sizeof(prop_guid) || 2902 memcmp(dsd.v_package[0]->v_buffer, prop_guid, 2903 sizeof(prop_guid)) != 0) 2904 return defval; 2905 2906 /* Check properties. */ 2907 for (i = 0; i < dsd.v_package[1]->length; i++) { 2908 struct aml_value *res = dsd.v_package[1]->v_package[i]; 2909 2910 if (res->type != AML_OBJTYPE_PACKAGE || res->length != 2 || 2911 res->v_package[0]->type != AML_OBJTYPE_STRING || 2912 res->v_package[1]->type != AML_OBJTYPE_INTEGER) 2913 continue; 2914 2915 if (strcmp(res->v_package[0]->v_string, prop) == 0) 2916 return res->v_package[1]->v_integer; 2917 } 2918 2919 return defval; 2920} 2921 2922int 2923acpi_parsehid(struct aml_node *node, void *arg, char *outcdev, char *outdev, 2924 size_t devlen) 2925{ 2926 struct acpi_softc *sc = (struct acpi_softc *)arg; 2927 struct aml_value res; 2928 const char *dev; 2929 2930 /* NB aml_eisaid returns a static buffer, this must come first */ 2931 if (aml_evalname(acpi_softc, node->parent, "_CID", 0, NULL, &res) == 0) { 2932 switch (res.type) { 2933 case AML_OBJTYPE_STRING: 2934 dev = res.v_string; 2935 break; 2936 case AML_OBJTYPE_INTEGER: 2937 dev = aml_eisaid(aml_val2int(&res)); 2938 break; 2939 default: 2940 dev = "unknown"; 2941 break; 2942 } 2943 strlcpy(outcdev, dev, devlen); 2944 aml_freevalue(&res); 2945 2946 dnprintf(10, "compatible with device: %s\n", outcdev); 2947 } else { 2948 outcdev[0] = '\0'; 2949 } 2950 2951 dnprintf(10, "found hid device: %s ", node->parent->name); 2952 if (aml_evalnode(sc, node, 0, NULL, &res) != 0) 2953 return (1); 2954 2955 switch (res.type) { 2956 case AML_OBJTYPE_STRING: 2957 dev = res.v_string; 2958 break; 2959 case AML_OBJTYPE_INTEGER: 2960 dev = aml_eisaid(aml_val2int(&res)); 2961 break; 2962 default: 2963 dev = "unknown"; 2964 break; 2965 } 2966 dnprintf(10, " device: %s\n", dev); 2967 2968 strlcpy(outdev, dev, devlen); 2969 2970 aml_freevalue(&res); 2971 2972 return (0); 2973} 2974 2975/* Devices for which we don't want to attach a driver */ 2976const char *acpi_skip_hids[] = { 2977 "INT0800", /* Intel 82802Firmware Hub Device */ 2978 "PNP0000", /* 8259-compatible Programmable Interrupt Controller */ 2979 "PNP0001", /* EISA Interrupt Controller */ 2980 "PNP0100", /* PC-class System Timer */ 2981 "PNP0103", /* HPET System Timer */ 2982 "PNP0200", /* PC-class DMA Controller */ 2983 "PNP0201", /* EISA DMA Controller */ 2984 "PNP0800", /* Microsoft Sound System Compatible Device */ 2985 "PNP0C01", /* System Board */ 2986 "PNP0C02", /* PNP Motherboard Resources */ 2987 "PNP0C04", /* x87-compatible Floating Point Processing Unit */ 2988 "PNP0C09", /* Embedded Controller Device */ 2989 "PNP0C0F", /* PCI Interrupt Link Device */ 2990 NULL 2991}; 2992 2993/* ISA devices for which we attach a driver later */ 2994const char *acpi_isa_hids[] = { 2995 "PNP0303", /* IBM Enhanced Keyboard (101/102-key, PS/2 Mouse) */ 2996 "PNP0400", /* Standard LPT Parallel Port */ 2997 "PNP0401", /* ECP Parallel Port */ 2998 "PNP0501", /* 16550A-compatible COM Serial Port */ 2999 "PNP0700", /* PC-class Floppy Disk Controller */ 3000 "PNP0F03", /* Microsoft PS/2-style Mouse */ 3001 "PNP0F13", /* PS/2 Mouse */ 3002 NULL 3003}; 3004 3005void 3006acpi_attach_deps(struct acpi_softc *sc, struct aml_node *node) 3007{ 3008 struct aml_value res; 3009 struct aml_node *dep; 3010 int i; 3011 3012 if (aml_evalname(sc, node, "_DEP", 0, NULL, &res)) 3013 return; 3014 3015 if (res.type != AML_OBJTYPE_PACKAGE) 3016 return; 3017 3018 for (i = 0; i < res.length; i++) { 3019 if (res.v_package[i]->type != AML_OBJTYPE_STRING) 3020 continue; 3021 dep = aml_searchrel(node, res.v_package[i]->v_string); 3022 if (dep == NULL || dep->attached) 3023 continue; 3024 dep = aml_searchname(dep, "_HID"); 3025 if (dep) 3026 acpi_foundhid(dep, sc); 3027 } 3028 3029 aml_freevalue(&res); 3030} 3031 3032int 3033acpi_foundhid(struct aml_node *node, void *arg) 3034{ 3035 struct acpi_softc *sc = (struct acpi_softc *)arg; 3036 struct device *self = (struct device *)arg; 3037 char cdev[32]; 3038 char dev[32]; 3039 struct acpi_attach_args aaa; 3040 int64_t sta; 3041#ifndef SMALL_KERNEL 3042 int i; 3043#endif 3044 3045 if (acpi_parsehid(node, arg, cdev, dev, sizeof(dev)) != 0) 3046 return (0); 3047 3048 if (aml_evalinteger(sc, node->parent, "_STA", 0, NULL, &sta)) 3049 sta = STA_PRESENT | STA_ENABLED | STA_DEV_OK | 0x1000; 3050 3051 if ((sta & STA_PRESENT) == 0) 3052 return (0); 3053 3054 acpi_attach_deps(sc, node->parent); 3055 3056 memset(&aaa, 0, sizeof(aaa)); 3057 aaa.aaa_iot = sc->sc_iot; 3058 aaa.aaa_memt = sc->sc_memt; 3059 aaa.aaa_dmat = sc->sc_dmat; 3060 aaa.aaa_node = node->parent; 3061 aaa.aaa_dev = dev; 3062 aaa.aaa_cdev = cdev; 3063 3064#ifndef SMALL_KERNEL 3065 if (!strcmp(cdev, ACPI_DEV_MOUSE)) { 3066 for (i = 0; i < nitems(sbtn_pnp); i++) { 3067 if (!strcmp(dev, sbtn_pnp[i])) { 3068 mouse_has_softbtn = 1; 3069 break; 3070 } 3071 } 3072 } 3073#endif 3074 3075 if (acpi_matchhids(&aaa, acpi_skip_hids, "none") || 3076 acpi_matchhids(&aaa, acpi_isa_hids, "none")) 3077 return (0); 3078 3079 if (!node->parent->attached) { 3080 node->parent->attached = 1; 3081 config_found(self, &aaa, acpi_print); 3082 } 3083 3084 return (0); 3085} 3086 3087#ifndef SMALL_KERNEL 3088int 3089acpi_founddock(struct aml_node *node, void *arg) 3090{ 3091 struct acpi_softc *sc = (struct acpi_softc *)arg; 3092 struct device *self = (struct device *)arg; 3093 struct acpi_attach_args aaa; 3094 3095 dnprintf(10, "found dock entry: %s\n", node->parent->name); 3096 3097 memset(&aaa, 0, sizeof(aaa)); 3098 aaa.aaa_iot = sc->sc_iot; 3099 aaa.aaa_memt = sc->sc_memt; 3100 aaa.aaa_node = node->parent; 3101 aaa.aaa_name = "acpidock"; 3102 3103 config_found(self, &aaa, acpi_print); 3104 3105 return 0; 3106} 3107 3108int 3109acpi_foundvideo(struct aml_node *node, void *arg) 3110{ 3111 struct acpi_softc *sc = (struct acpi_softc *)arg; 3112 struct device *self = (struct device *)arg; 3113 struct acpi_attach_args aaa; 3114 3115 memset(&aaa, 0, sizeof(aaa)); 3116 aaa.aaa_iot = sc->sc_iot; 3117 aaa.aaa_memt = sc->sc_memt; 3118 aaa.aaa_node = node->parent; 3119 aaa.aaa_name = "acpivideo"; 3120 3121 config_found(self, &aaa, acpi_print); 3122 3123 return (0); 3124} 3125 3126int 3127acpi_foundsbs(struct aml_node *node, void *arg) 3128{ 3129 struct acpi_softc *sc = (struct acpi_softc *)arg; 3130 struct device *self = (struct device *)arg; 3131 char cdev[32], dev[32]; 3132 struct acpi_attach_args aaa; 3133 int64_t sta; 3134 3135 if (acpi_parsehid(node, arg, cdev, dev, sizeof(dev)) != 0) 3136 return (0); 3137 3138 if (aml_evalinteger(sc, node->parent, "_STA", 0, NULL, &sta)) 3139 sta = STA_PRESENT | STA_ENABLED | STA_DEV_OK | 0x1000; 3140 3141 if ((sta & STA_PRESENT) == 0) 3142 return (0); 3143 3144 acpi_attach_deps(sc, node->parent); 3145 3146 if (strcmp(dev, ACPI_DEV_SBS) != 0) 3147 return (0); 3148 3149 if (node->parent->attached) 3150 return (0); 3151 3152 memset(&aaa, 0, sizeof(aaa)); 3153 aaa.aaa_iot = sc->sc_iot; 3154 aaa.aaa_memt = sc->sc_memt; 3155 aaa.aaa_node = node->parent; 3156 aaa.aaa_dev = dev; 3157 aaa.aaa_cdev = cdev; 3158 3159 config_found(self, &aaa, acpi_print); 3160 node->parent->attached = 1; 3161 3162 return (0); 3163} 3164 3165int 3166acpiopen(dev_t dev, int flag, int mode, struct proc *p) 3167{ 3168 int error = 0; 3169 struct acpi_softc *sc; 3170 int s; 3171 3172 if (!acpi_cd.cd_ndevs || APMUNIT(dev) != 0 || 3173 !(sc = acpi_cd.cd_devs[APMUNIT(dev)])) 3174 return (ENXIO); 3175 3176 s = spltty(); 3177 switch (APMDEV(dev)) { 3178 case APMDEV_CTL: 3179 if (!(flag & FWRITE)) { 3180 error = EINVAL; 3181 break; 3182 } 3183 if (sc->sc_flags & SCFLAG_OWRITE) { 3184 error = EBUSY; 3185 break; 3186 } 3187 sc->sc_flags |= SCFLAG_OWRITE; 3188 break; 3189 case APMDEV_NORMAL: 3190 if (!(flag & FREAD) || (flag & FWRITE)) { 3191 error = EINVAL; 3192 break; 3193 } 3194 sc->sc_flags |= SCFLAG_OREAD; 3195 break; 3196 default: 3197 error = ENXIO; 3198 break; 3199 } 3200 splx(s); 3201 return (error); 3202} 3203 3204int 3205acpiclose(dev_t dev, int flag, int mode, struct proc *p) 3206{ 3207 int error = 0; 3208 struct acpi_softc *sc; 3209 int s; 3210 3211 if (!acpi_cd.cd_ndevs || APMUNIT(dev) != 0 || 3212 !(sc = acpi_cd.cd_devs[APMUNIT(dev)])) 3213 return (ENXIO); 3214 3215 s = spltty(); 3216 switch (APMDEV(dev)) { 3217 case APMDEV_CTL: 3218 sc->sc_flags &= ~SCFLAG_OWRITE; 3219 break; 3220 case APMDEV_NORMAL: 3221 sc->sc_flags &= ~SCFLAG_OREAD; 3222 break; 3223 default: 3224 error = ENXIO; 3225 break; 3226 } 3227 splx(s); 3228 return (error); 3229} 3230 3231int 3232acpiioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 3233{ 3234 int error = 0; 3235 struct acpi_softc *sc; 3236 struct acpi_ac *ac; 3237 struct acpi_bat *bat; 3238 struct acpi_sbs *sbs; 3239 struct apm_power_info *pi = (struct apm_power_info *)data; 3240 int bats; 3241 unsigned int remaining, rem, minutes, rate; 3242 int s; 3243 3244 if (!acpi_cd.cd_ndevs || APMUNIT(dev) != 0 || 3245 !(sc = acpi_cd.cd_devs[APMUNIT(dev)])) 3246 return (ENXIO); 3247 3248 s = spltty(); 3249 /* fake APM */ 3250 switch (cmd) { 3251 case APM_IOC_SUSPEND: 3252 case APM_IOC_STANDBY: 3253 if ((flag & FWRITE) == 0) { 3254 error = EBADF; 3255 break; 3256 } 3257 acpi_addtask(sc, acpi_sleep_task, sc, ACPI_SLEEP_SUSPEND); 3258 acpi_wakeup(sc); 3259 break; 3260#ifdef HIBERNATE 3261 case APM_IOC_HIBERNATE: 3262 if ((error = suser(p)) != 0) 3263 break; 3264 if ((flag & FWRITE) == 0) { 3265 error = EBADF; 3266 break; 3267 } 3268 if (get_hibernate_io_function(swdevt[0].sw_dev) == NULL) { 3269 error = EOPNOTSUPP; 3270 break; 3271 } 3272 acpi_addtask(sc, acpi_sleep_task, sc, ACPI_SLEEP_HIBERNATE); 3273 acpi_wakeup(sc); 3274 break; 3275#endif 3276 case APM_IOC_GETPOWER: 3277 /* A/C */ 3278 pi->ac_state = APM_AC_UNKNOWN; 3279 SLIST_FOREACH(ac, &sc->sc_ac, aac_link) { 3280 if (ac->aac_softc->sc_ac_stat == PSR_ONLINE) 3281 pi->ac_state = APM_AC_ON; 3282 else if (ac->aac_softc->sc_ac_stat == PSR_OFFLINE) 3283 if (pi->ac_state == APM_AC_UNKNOWN) 3284 pi->ac_state = APM_AC_OFF; 3285 } 3286 3287 /* battery */ 3288 pi->battery_state = APM_BATT_UNKNOWN; 3289 pi->battery_life = 0; 3290 pi->minutes_left = 0; 3291 bats = 0; 3292 remaining = rem = 0; 3293 minutes = 0; 3294 rate = 0; 3295 SLIST_FOREACH(bat, &sc->sc_bat, aba_link) { 3296 if (bat->aba_softc->sc_bat_present == 0) 3297 continue; 3298 3299 if (bat->aba_softc->sc_bix.bix_last_capacity == 0) 3300 continue; 3301 3302 bats++; 3303 rem = (bat->aba_softc->sc_bst.bst_capacity * 100) / 3304 bat->aba_softc->sc_bix.bix_last_capacity; 3305 if (rem > 100) 3306 rem = 100; 3307 remaining += rem; 3308 3309 if (bat->aba_softc->sc_bst.bst_rate == BST_UNKNOWN) 3310 continue; 3311 else if (bat->aba_softc->sc_bst.bst_rate > 1) 3312 rate = bat->aba_softc->sc_bst.bst_rate; 3313 3314 minutes += bat->aba_softc->sc_bst.bst_capacity; 3315 } 3316 3317 SLIST_FOREACH(sbs, &sc->sc_sbs, asbs_link) { 3318 if (sbs->asbs_softc->sc_batteries_present == 0) 3319 continue; 3320 3321 if (sbs->asbs_softc->sc_battery.rel_charge == 0) 3322 continue; 3323 3324 bats++; 3325 rem = sbs->asbs_softc->sc_battery.rel_charge; 3326 if (rem > 100) 3327 rem = 100; 3328 remaining += rem; 3329 3330 if (sbs->asbs_softc->sc_battery.run_time == 3331 ACPISBS_VALUE_UNKNOWN) 3332 continue; 3333 3334 rate = 60; /* XXX */ 3335 minutes += sbs->asbs_softc->sc_battery.run_time; 3336 } 3337 3338 if (bats == 0) { 3339 pi->battery_state = APM_BATTERY_ABSENT; 3340 pi->battery_life = 0; 3341 pi->minutes_left = (unsigned int)-1; 3342 break; 3343 } 3344 3345 if (pi->ac_state == APM_AC_ON || rate == 0) 3346 pi->minutes_left = (unsigned int)-1; 3347 else 3348 pi->minutes_left = 60 * minutes / rate; 3349 3350 /* running on battery */ 3351 pi->battery_life = remaining / bats; 3352 if (pi->battery_life > 50) 3353 pi->battery_state = APM_BATT_HIGH; 3354 else if (pi->battery_life > 25) 3355 pi->battery_state = APM_BATT_LOW; 3356 else 3357 pi->battery_state = APM_BATT_CRITICAL; 3358 3359 break; 3360 3361 default: 3362 error = ENOTTY; 3363 } 3364 3365 splx(s); 3366 return (error); 3367} 3368 3369void acpi_filtdetach(struct knote *); 3370int acpi_filtread(struct knote *, long); 3371 3372struct filterops acpiread_filtops = { 3373 1, NULL, acpi_filtdetach, acpi_filtread 3374}; 3375 3376int acpi_evindex; 3377 3378int 3379acpi_record_event(struct acpi_softc *sc, u_int type) 3380{ 3381 if ((sc->sc_flags & SCFLAG_OPEN) == 0) 3382 return (1); 3383 3384 acpi_evindex++; 3385 KNOTE(sc->sc_note, APM_EVENT_COMPOSE(type, acpi_evindex)); 3386 return (0); 3387} 3388 3389void 3390acpi_filtdetach(struct knote *kn) 3391{ 3392 struct acpi_softc *sc = kn->kn_hook; 3393 int s; 3394 3395 s = spltty(); 3396 SLIST_REMOVE(sc->sc_note, kn, knote, kn_selnext); 3397 splx(s); 3398} 3399 3400int 3401acpi_filtread(struct knote *kn, long hint) 3402{ 3403 /* XXX weird kqueue_scan() semantics */ 3404 if (hint && !kn->kn_data) 3405 kn->kn_data = hint; 3406 return (1); 3407} 3408 3409int 3410acpikqfilter(dev_t dev, struct knote *kn) 3411{ 3412 struct acpi_softc *sc; 3413 int s; 3414 3415 if (!acpi_cd.cd_ndevs || APMUNIT(dev) != 0 || 3416 !(sc = acpi_cd.cd_devs[APMUNIT(dev)])) 3417 return (ENXIO); 3418 3419 switch (kn->kn_filter) { 3420 case EVFILT_READ: 3421 kn->kn_fop = &acpiread_filtops; 3422 break; 3423 default: 3424 return (EINVAL); 3425 } 3426 3427 kn->kn_hook = sc; 3428 3429 s = spltty(); 3430 SLIST_INSERT_HEAD(sc->sc_note, kn, kn_selnext); 3431 splx(s); 3432 3433 return (0); 3434} 3435 3436#else /* SMALL_KERNEL */ 3437 3438int 3439acpiopen(dev_t dev, int flag, int mode, struct proc *p) 3440{ 3441 return (ENXIO); 3442} 3443 3444int 3445acpiclose(dev_t dev, int flag, int mode, struct proc *p) 3446{ 3447 return (ENXIO); 3448} 3449 3450int 3451acpiioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 3452{ 3453 return (ENXIO); 3454} 3455 3456int 3457acpikqfilter(dev_t dev, struct knote *kn) 3458{ 3459 return (ENXIO); 3460} 3461 3462#endif /* SMALL_KERNEL */ 3463