root/dev/acpi/acpi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. acpi_delay
  2. acpi_gasio
  3. acpi_inidev
  4. acpi_foundprt
  5. acpi_match
  6. acpi_add_device
  7. acpi_attach
  8. acpi_submatch
  9. acpi_print
  10. acpi_loadtables
  11. acpi_load_table
  12. acpi_load_dsdt
  13. acpiopen
  14. acpiclose
  15. acpiioctl
  16. acpi_filtdetach
  17. acpi_filtread
  18. acpikqfilter
  19. acpi_interrupt
  20. acpi_enable_onegpe
  21. acpi_set_gpehandler
  22. acpi_gpe_level
  23. acpi_gpe_edge
  24. acpi_init_gpes
  25. acpi_init_states
  26. acpi_init_pm
  27. acpi_enter_sleep_state
  28. acpi_resume
  29. acpi_powerdown
  30. acpi_isr_thread
  31. acpi_create_thread
  32. acpi_map_address
  33. acpi_map_pmregs
  34. acpi_read_pmreg
  35. acpi_write_pmreg
  36. acpi_foundec
  37. acpi_foundhid
  38. acpi_founddock

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

/* [<][>][^][v][top][bottom][index][help] */