LCOV - code coverage report
Current view: top level - dev/acpi - acpi.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 1625 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 86 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13