akaros/kern/drivers/dev/acpi.c
<<
>>
Prefs
   1/*
   2 * This file is part of the UCB release of Plan 9. It is subject to the license
   3 * terms in the LICENSE file found in the top-level directory of this
   4 * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
   5 * part of the UCB release of Plan 9, including this file, may be copied,
   6 * modified, propagated, or distributed except according to the terms contained
   7 * in the LICENSE file.
   8 */
   9
  10#include <acpi.h>
  11#include <assert.h>
  12#include <cpio.h>
  13#include <error.h>
  14#include <kmalloc.h>
  15#include <kref.h>
  16#include <net/ip.h>
  17#include <ns.h>
  18#include <pmap.h>
  19#include <slab.h>
  20#include <slice.h>
  21#include <smp.h>
  22#include <stdio.h>
  23#include <string.h>
  24
  25#include "../timers/hpet.h"
  26
  27#ifdef CONFIG_X86
  28#include <arch/pci.h>
  29#endif
  30
  31/* -----------------------------------------------------------------------------
  32 * Basic ACPI device.
  33 *
  34 * The qid.Path will be made unique by incrementing lastpath. lastpath starts
  35 * at Qroot.
  36 *
  37 * Qtbl will return a pointer to the Atable, which includes the signature, OEM
  38 * data, and so on.
  39 *
  40 * Raw, at any level, dumps the raw table at that level, which by the ACPI
  41 * flattened tree layout will include all descendents.
  42 *
  43 * Qpretty, at any level, will print the pretty form for that level and all
  44 * descendants.
  45 */
  46enum { Qroot = 0,
  47
  48       // The type is the qid.path mod NQtypes.
  49       Qdir = 0,
  50       Qpretty,
  51       Qraw,
  52       Qtbl,
  53       NQtypes,
  54
  55       QIndexShift = 8,
  56       QIndexMask = (1 << QIndexShift) - 1,
  57};
  58
  59#define ATABLEBUFSZ ROUNDUP(sizeof(struct Atable), KMALLOC_ALIGNMENT)
  60
  61static uint64_t lastpath;
  62static struct slice emptyslice;
  63static struct Atable **atableindex;
  64struct dev acpidevtab;
  65
  66static char *devname(void)
  67{
  68        return acpidevtab.name;
  69}
  70
  71/*
  72 * ACPI 4.0 Support.
  73 * Still WIP.
  74 *
  75 * This driver locates tables and parses only a small subset
  76 * of tables. All other tables are mapped and kept for the user-level
  77 * interpreter.
  78 */
  79static struct cmdtab ctls[] = {
  80    {CMregion, "region", 6},
  81    {CMgpe, "gpe", 3},
  82};
  83
  84static struct Facs *facs; /* Firmware ACPI control structure */
  85static struct Fadt *fadt; /* Fixed ACPI description to reach ACPI regs */
  86static struct Atable *root;
  87static struct Xsdt *xsdt;     /* XSDT table */
  88static struct Atable *tfirst; /* loaded DSDT/SSDT/... tables */
  89static struct Atable *tlast;  /* pointer to last table */
  90struct Atable *apics;         /* APIC info */
  91struct Atable *srat;          /* System resource affinity used by physalloc */
  92struct Atable *dmar;
  93static struct Slit *slit;      /* Sys locality info table used by scheduler */
  94static struct Atable *mscttbl; /* Maximum system characteristics table */
  95static struct Atable *mcfgtbl;
  96static struct Reg *reg;        /* region used for I/O */
  97static struct Gpe *gpes;       /* General purpose events */
  98static int ngpes;
  99
 100static char *regnames[] = {
 101    "mem", "io", "pcicfg", "embed", "smb", "cmos", "pcibar", "ipmi",
 102};
 103
 104/*
 105 * Lists to store RAM that we copy ACPI tables into. When we map a new
 106 * ACPI list into the kernel, we copy it into a specifically RAM buffer
 107 * (to make sure it's not coming from e.g. slow device memory). We store
 108 * pointers to those buffers on these lists.
 109 */
 110struct Acpilist {
 111        struct Acpilist *next;
 112        size_t size;
 113        int8_t raw[];
 114};
 115
 116static struct Acpilist *acpilists;
 117
 118/*
 119 * Produces an Atable at some level in the tree. Note that Atables are
 120 * isomorphic to directories in the file system namespace; this code
 121 * ensures that invariant.
 122 */
 123struct Atable *mkatable(struct Atable *parent, int type, char *name,
 124                        uint8_t *raw, size_t rawsize, size_t addsize)
 125{
 126        void *m;
 127        struct Atable *t;
 128
 129        m = kzmalloc(ATABLEBUFSZ + addsize, MEM_WAIT);
 130        if (m == NULL)
 131                panic("no memory for more aml tables");
 132        t = m;
 133        t->parent = parent;
 134        t->tbl = NULL;
 135        if (addsize != 0)
 136                t->tbl = m + ATABLEBUFSZ;
 137        t->rawsize = rawsize;
 138        t->raw = raw;
 139        strlcpy(t->name, name, sizeof(t->name));
 140        mkqid(&t->qid, (lastpath << QIndexShift) + Qdir, 0, QTDIR);
 141        mkqid(&t->rqid, (lastpath << QIndexShift) + Qraw, 0, 0);
 142        mkqid(&t->pqid, (lastpath << QIndexShift) + Qpretty, 0, 0);
 143        mkqid(&t->tqid, (lastpath << QIndexShift) + Qtbl, 0, 0);
 144        lastpath++;
 145
 146        return t;
 147}
 148
 149struct Atable *finatable(struct Atable *t, struct slice *slice)
 150{
 151        size_t n;
 152        struct Atable *tail;
 153        struct dirtab *dirs;
 154
 155        n = slice_len(slice);
 156        t->nchildren = n;
 157        t->children = (struct Atable **)slice_finalize(slice);
 158        dirs =
 159            kreallocarray(NULL, n + NQtypes, sizeof(struct dirtab), MEM_WAIT);
 160        assert(dirs != NULL);
 161        dirs[0] = (struct dirtab){".", t->qid, 0, 0555};
 162        dirs[1] = (struct dirtab){"pretty", t->pqid, 0, 0444};
 163        dirs[2] = (struct dirtab){"raw", t->rqid, 0, 0444};
 164        dirs[3] = (struct dirtab){"table", t->tqid, 0, 0444};
 165        for (size_t i = 0; i < n; i++) {
 166                strlcpy(dirs[i + NQtypes].name, t->children[i]->name, KNAMELEN);
 167                dirs[i + NQtypes].qid = t->children[i]->qid;
 168                dirs[i + NQtypes].length = 0;
 169                dirs[i + NQtypes].perm = DMDIR | 0555;
 170        }
 171        t->cdirs = dirs;
 172        tail = NULL;
 173        while (n-- > 0) {
 174                t->children[n]->next = tail;
 175                tail = t->children[n];
 176        }
 177
 178        return t;
 179}
 180
 181struct Atable *finatable_nochildren(struct Atable *t)
 182{
 183        return finatable(t, &emptyslice);
 184}
 185
 186static char *dumpGas(char *start, char *end, char *prefix, struct Gas *g);
 187static void dumpxsdt(void);
 188
 189static char *acpiregstr(int id)
 190{
 191        static char buf[20]; /* BUG */
 192
 193        if (id >= 0 && id < ARRAY_SIZE(regnames))
 194                return regnames[id];
 195        seprintf(buf, buf + sizeof(buf), "spc:%#x", id);
 196        return buf;
 197}
 198
 199static int acpiregid(char *s)
 200{
 201        for (int i = 0; i < ARRAY_SIZE(regnames); i++)
 202                if (strcmp(regnames[i], s) == 0)
 203                        return i;
 204        return -1;
 205}
 206
 207/*
 208 * TODO(rminnich): Fix these if we're ever on a different-endian machine.
 209 * They are specific to little-endian processors and are not portable.
 210 */
 211static uint8_t mget8(uintptr_t p, void *unused)
 212{
 213        uint8_t *cp = (uint8_t *)p;
 214        return *cp;
 215}
 216
 217static void mset8(uintptr_t p, uint8_t v, void *unused)
 218{
 219        uint8_t *cp = (uint8_t *)p;
 220        *cp = v;
 221}
 222
 223static uint16_t mget16(uintptr_t p, void *unused)
 224{
 225        uint16_t *cp = (uint16_t *)p;
 226        return *cp;
 227}
 228
 229static void mset16(uintptr_t p, uint16_t v, void *unused)
 230{
 231        uint16_t *cp = (uint16_t *)p;
 232        *cp = v;
 233}
 234
 235static uint32_t mget32(uintptr_t p, void *unused)
 236{
 237        uint32_t *cp = (uint32_t *)p;
 238        return *cp;
 239}
 240
 241static void mset32(uintptr_t p, uint32_t v, void *unused)
 242{
 243        uint32_t *cp = (uint32_t *)p;
 244        *cp = v;
 245}
 246
 247static uint64_t mget64(uintptr_t p, void *unused)
 248{
 249        uint64_t *cp = (uint64_t *)p;
 250        return *cp;
 251}
 252
 253static void mset64(uintptr_t p, uint64_t v, void *unused)
 254{
 255        uint64_t *cp = (uint64_t *)p;
 256        *cp = v;
 257}
 258
 259static uint8_t ioget8(uintptr_t p, void *unused)
 260{
 261        return inb(p);
 262}
 263
 264static void ioset8(uintptr_t p, uint8_t v, void *unused)
 265{
 266        outb(p, v);
 267}
 268
 269static uint16_t ioget16(uintptr_t p, void *unused)
 270{
 271        return inw(p);
 272}
 273
 274static void ioset16(uintptr_t p, uint16_t v, void *unused)
 275{
 276        outw(p, v);
 277}
 278
 279static uint32_t ioget32(uintptr_t p, void *unused)
 280{
 281        return inl(p);
 282}
 283
 284static void ioset32(uintptr_t p, uint32_t v, void *unused)
 285{
 286        outl(p, v);
 287}
 288
 289/*
 290 * TODO(rminnich): these cfgs are hacky. Maybe all the struct Reg should have
 291 * struct pci_device or something?
 292 */
 293static uint8_t cfgget8(uintptr_t p, void *r)
 294{
 295        struct Reg *ro = r;
 296        struct pci_device pcidev;
 297
 298        explode_tbdf(ro->tbdf);
 299        return pcidev_read8(&pcidev, p);
 300}
 301
 302static void cfgset8(uintptr_t p, uint8_t v, void *r)
 303{
 304        struct Reg *ro = r;
 305        struct pci_device pcidev;
 306
 307        explode_tbdf(ro->tbdf);
 308        pcidev_write8(&pcidev, p, v);
 309}
 310
 311static uint16_t cfgget16(uintptr_t p, void *r)
 312{
 313        struct Reg *ro = r;
 314        struct pci_device pcidev;
 315
 316        explode_tbdf(ro->tbdf);
 317        return pcidev_read16(&pcidev, p);
 318}
 319
 320static void cfgset16(uintptr_t p, uint16_t v, void *r)
 321{
 322        struct Reg *ro = r;
 323        struct pci_device pcidev;
 324
 325        explode_tbdf(ro->tbdf);
 326        pcidev_write16(&pcidev, p, v);
 327}
 328
 329static uint32_t cfgget32(uintptr_t p, void *r)
 330{
 331        struct Reg *ro = r;
 332        struct pci_device pcidev;
 333
 334        explode_tbdf(ro->tbdf);
 335        return pcidev_read32(&pcidev, p);
 336}
 337
 338static void cfgset32(uintptr_t p, uint32_t v, void *r)
 339{
 340        struct Reg *ro = r;
 341        struct pci_device pcidev;
 342
 343        explode_tbdf(ro->tbdf);
 344        pcidev_write32(&pcidev, p, v);
 345}
 346
 347static struct Regio memio = {NULL,   mget8,  mset8,  mget16, mset16,
 348                             mget32, mset32, mget64, mset64};
 349
 350static struct Regio ioio = {NULL,    ioget8,  ioset8, ioget16, ioset16,
 351                            ioget32, ioset32, NULL,   NULL};
 352
 353static struct Regio cfgio = {NULL,     cfgget8,  cfgset8, cfgget16, cfgset16,
 354                             cfgget32, cfgset32, NULL,    NULL};
 355
 356/*
 357 * Copy memory, 1/2/4/8-bytes at a time, to/from a region.
 358 */
 359static long regcpy(struct Regio *dio, uintptr_t da, struct Regio *sio,
 360                   uintptr_t sa, long len, int align)
 361{
 362        int n, i;
 363
 364        printd("regcpy %#p %#p %#p %#p\n", da, sa, len, align);
 365        if ((len % align) != 0)
 366                printd("regcpy: bug: copy not aligned. truncated\n");
 367        n = len / align;
 368        for (i = 0; i < n; i++) {
 369                switch (align) {
 370                case 1:
 371                        printd("cpy8 %#p %#p\n", da, sa);
 372                        dio->set8(da, sio->get8(sa, sio->arg), dio->arg);
 373                        break;
 374                case 2:
 375                        printd("cpy16 %#p %#p\n", da, sa);
 376                        dio->set16(da, sio->get16(sa, sio->arg), dio->arg);
 377                        break;
 378                case 4:
 379                        printd("cpy32 %#p %#p\n", da, sa);
 380                        dio->set32(da, sio->get32(sa, sio->arg), dio->arg);
 381                        break;
 382                case 8:
 383                        printd("cpy64 %#p %#p\n", da, sa);
 384                        warn("Not doing set64 for some reason, fix me!");
 385                        //  dio->set64(da, sio->get64(sa, sio->arg), dio->arg);
 386                        break;
 387                default:
 388                        panic("regcpy: align bug");
 389                }
 390                da += align;
 391                sa += align;
 392        }
 393        return n * align;
 394}
 395
 396/*
 397 * Perform I/O within region in access units of accsz bytes.
 398 * All units in bytes.
 399 */
 400static long regio(struct Reg *r, void *p, uint32_t len, uintptr_t off, int iswr)
 401{
 402        struct Regio rio;
 403        uintptr_t rp;
 404
 405        printd("reg%s %s %#p %#p %#lx sz=%d\n", iswr ? "out" : "in", r->name, p,
 406               off, len, r->accsz);
 407        rp = 0;
 408        if (off + len > r->len) {
 409                printd("regio: access outside limits");
 410                len = r->len - off;
 411        }
 412        if (len <= 0) {
 413                printd("regio: zero len\n");
 414                return 0;
 415        }
 416        switch (r->spc) {
 417        case Rsysmem:
 418                if (r->p == NULL)
 419                        r->p = KADDR_NOCHECK(r->base);
 420                if (r->p == NULL)
 421                        error(EFAIL, "regio: vmap/KADDR failed");
 422                rp = (uintptr_t)r->p + off;
 423                rio = memio;
 424                break;
 425        case Rsysio:
 426                rp = r->base + off;
 427                rio = ioio;
 428                break;
 429        case Rpcicfg:
 430                rp = r->base + off;
 431                rio = cfgio;
 432                rio.arg = r;
 433                break;
 434        case Rpcibar:
 435        case Rembed:
 436        case Rsmbus:
 437        case Rcmos:
 438        case Ripmi:
 439        case Rfixedhw:
 440                printd("regio: reg %s not supported\n", acpiregstr(r->spc));
 441                error(EFAIL, "region not supported");
 442        }
 443        if (iswr)
 444                regcpy(&rio, rp, &memio, (uintptr_t)p, len, r->accsz);
 445        else
 446                regcpy(&memio, (uintptr_t)p, &rio, rp, len, r->accsz);
 447        return len;
 448}
 449
 450/*
 451 * Compute and return SDT checksum: '0' is a correct sum.
 452 */
 453static uint8_t sdtchecksum(void *addr, int len)
 454{
 455        uint8_t *p, sum;
 456
 457        sum = 0;
 458        for (p = addr; len-- > 0; p++)
 459                sum += *p;
 460
 461        return sum;
 462}
 463
 464static void *sdtmap(uintptr_t pa, size_t *n, int cksum)
 465{
 466        struct Sdthdr *sdt;
 467        struct Acpilist *p;
 468
 469        if (!pa) {
 470                printk("sdtmap: NULL pa\n");
 471                return NULL;
 472        }
 473        sdt = KADDR_NOCHECK(pa);
 474        if (sdt == NULL) {
 475                printk("acpi: vmap: NULL\n");
 476                return NULL;
 477        }
 478        *n = l32get(sdt->length);
 479        if (!*n) {
 480                printk("sdt has zero length: pa = %p, sig = %.4s\n", pa,
 481                       sdt->sig);
 482                return NULL;
 483        }
 484        if (cksum != 0 && sdtchecksum(sdt, *n) != 0) {
 485                printk("acpi: SDT: bad checksum. pa = %p, len = %lu\n", pa, *n);
 486                return NULL;
 487        }
 488        p = kzmalloc(sizeof(struct Acpilist) + *n, MEM_WAIT);
 489        if (p == NULL)
 490                panic("sdtmap: memory allocation failed for %lu bytes", *n);
 491        memmove(p->raw, (void *)sdt, *n);
 492        p->size = *n;
 493        p->next = acpilists;
 494        acpilists = p;
 495
 496        return p->raw;
 497}
 498
 499static int loadfacs(uintptr_t pa)
 500{
 501        size_t n;
 502
 503        facs = sdtmap(pa, &n, 0);
 504        if (facs == NULL)
 505                return -1;
 506        if (memcmp(facs->sig, "FACS", 4) != 0) {
 507                facs = NULL;
 508                return -1;
 509        }
 510
 511        /* no unmap */
 512        printd("acpi: facs: hwsig: %#p\n", facs->hwsig);
 513        printd("acpi: facs: wakingv: %#p\n", facs->wakingv);
 514        printd("acpi: facs: flags: %#p\n", facs->flags);
 515        printd("acpi: facs: glock: %#p\n", facs->glock);
 516        printd("acpi: facs: xwakingv: %#p\n", facs->xwakingv);
 517        printd("acpi: facs: vers: %#p\n", facs->vers);
 518        printd("acpi: facs: ospmflags: %#p\n", facs->ospmflags);
 519
 520        return 0;
 521}
 522
 523static void loaddsdt(uintptr_t pa)
 524{
 525        size_t n;
 526        uint8_t *dsdtp;
 527
 528        dsdtp = sdtmap(pa, &n, 1);
 529        if (dsdtp == NULL) {
 530                printk("acpi: Failed to map dsdtp.\n");
 531                return;
 532        }
 533}
 534
 535static void gasget(struct Gas *gas, uint8_t *p)
 536{
 537        gas->spc = p[0];
 538        gas->len = p[1];
 539        gas->off = p[2];
 540        gas->accsz = p[3];
 541        gas->addr = l64get(p + 4);
 542}
 543
 544static char *dumpfadt(char *start, char *end, struct Fadt *fp)
 545{
 546        if (fp == NULL)
 547                return start;
 548
 549        start = seprintf(start, end, "acpi: FADT@%p\n", fp);
 550        start = seprintf(start, end, "acpi: fadt: facs: $%p\n", fp->facs);
 551        start = seprintf(start, end, "acpi: fadt: dsdt: $%p\n", fp->dsdt);
 552        start =
 553            seprintf(start, end, "acpi: fadt: pmprofile: $%p\n", fp->pmprofile);
 554        start = seprintf(start, end, "acpi: fadt: sciint: $%p\n", fp->sciint);
 555        start = seprintf(start, end, "acpi: fadt: smicmd: $%p\n", fp->smicmd);
 556        start = seprintf(start, end, "acpi: fadt: acpienable: $%p\n",
 557                         fp->acpienable);
 558        start = seprintf(start, end, "acpi: fadt: acpidisable: $%p\n",
 559                         fp->acpidisable);
 560        start =
 561            seprintf(start, end, "acpi: fadt: s4biosreq: $%p\n", fp->s4biosreq);
 562        start =
 563            seprintf(start, end, "acpi: fadt: pstatecnt: $%p\n", fp->pstatecnt);
 564        start = seprintf(start, end, "acpi: fadt: pm1aevtblk: $%p\n",
 565                         fp->pm1aevtblk);
 566        start = seprintf(start, end, "acpi: fadt: pm1bevtblk: $%p\n",
 567                         fp->pm1bevtblk);
 568        start = seprintf(start, end, "acpi: fadt: pm1acntblk: $%p\n",
 569                         fp->pm1acntblk);
 570        start = seprintf(start, end, "acpi: fadt: pm1bcntblk: $%p\n",
 571                         fp->pm1bcntblk);
 572        start =
 573            seprintf(start, end, "acpi: fadt: pm2cntblk: $%p\n", fp->pm2cntblk);
 574        start =
 575            seprintf(start, end, "acpi: fadt: pmtmrblk: $%p\n", fp->pmtmrblk);
 576        start = seprintf(start, end, "acpi: fadt: gpe0blk: $%p\n", fp->gpe0blk);
 577        start = seprintf(start, end, "acpi: fadt: gpe1blk: $%p\n", fp->gpe1blk);
 578        start =
 579            seprintf(start, end, "acpi: fadt: pm1evtlen: $%p\n", fp->pm1evtlen);
 580        start =
 581            seprintf(start, end, "acpi: fadt: pm1cntlen: $%p\n", fp->pm1cntlen);
 582        start =
 583            seprintf(start, end, "acpi: fadt: pm2cntlen: $%p\n", fp->pm2cntlen);
 584        start =
 585            seprintf(start, end, "acpi: fadt: pmtmrlen: $%p\n", fp->pmtmrlen);
 586        start = seprintf(start, end, "acpi: fadt: gpe0blklen: $%p\n",
 587                         fp->gpe0blklen);
 588        start = seprintf(start, end, "acpi: fadt: gpe1blklen: $%p\n",
 589                         fp->gpe1blklen);
 590        start = seprintf(start, end, "acpi: fadt: gp1base: $%p\n", fp->gp1base);
 591        start = seprintf(start, end, "acpi: fadt: cstcnt: $%p\n", fp->cstcnt);
 592        start =
 593            seprintf(start, end, "acpi: fadt: plvl2lat: $%p\n", fp->plvl2lat);
 594        start =
 595            seprintf(start, end, "acpi: fadt: plvl3lat: $%p\n", fp->plvl3lat);
 596        start = seprintf(start, end, "acpi: fadt: flushsz: $%p\n", fp->flushsz);
 597        start = seprintf(start, end, "acpi: fadt: flushstride: $%p\n",
 598                         fp->flushstride);
 599        start = seprintf(start, end, "acpi: fadt: dutyoff: $%p\n", fp->dutyoff);
 600        start =
 601            seprintf(start, end, "acpi: fadt: dutywidth: $%p\n", fp->dutywidth);
 602        start = seprintf(start, end, "acpi: fadt: dayalrm: $%p\n", fp->dayalrm);
 603        start = seprintf(start, end, "acpi: fadt: monalrm: $%p\n", fp->monalrm);
 604        start = seprintf(start, end, "acpi: fadt: century: $%p\n", fp->century);
 605        start = seprintf(start, end, "acpi: fadt: iapcbootarch: $%p\n",
 606                         fp->iapcbootarch);
 607        start = seprintf(start, end, "acpi: fadt: flags: $%p\n", fp->flags);
 608        start = dumpGas(start, end, "acpi: fadt: resetreg: ", &fp->resetreg);
 609        start =
 610            seprintf(start, end, "acpi: fadt: resetval: $%p\n", fp->resetval);
 611        start = seprintf(start, end, "acpi: fadt: xfacs: %p\n", fp->xfacs);
 612        start = seprintf(start, end, "acpi: fadt: xdsdt: %p\n", fp->xdsdt);
 613        start =
 614            dumpGas(start, end, "acpi: fadt: xpm1aevtblk:", &fp->xpm1aevtblk);
 615        start =
 616            dumpGas(start, end, "acpi: fadt: xpm1bevtblk:", &fp->xpm1bevtblk);
 617        start =
 618            dumpGas(start, end, "acpi: fadt: xpm1acntblk:", &fp->xpm1acntblk);
 619        start =
 620            dumpGas(start, end, "acpi: fadt: xpm1bcntblk:", &fp->xpm1bcntblk);
 621        start = dumpGas(start, end, "acpi: fadt: xpm2cntblk:", &fp->xpm2cntblk);
 622        start = dumpGas(start, end, "acpi: fadt: xpmtmrblk:", &fp->xpmtmrblk);
 623        start = dumpGas(start, end, "acpi: fadt: xgpe0blk:", &fp->xgpe0blk);
 624        start = dumpGas(start, end, "acpi: fadt: xgpe1blk:", &fp->xgpe1blk);
 625        return start;
 626}
 627
 628static struct Atable *parsefadt(struct Atable *parent, char *name, uint8_t *p,
 629                                size_t rawsize)
 630{
 631        struct Atable *t;
 632        struct Fadt *fp;
 633
 634        t = mkatable(parent, FADT, name, p, rawsize, sizeof(struct Fadt));
 635
 636        if (rawsize < 116) {
 637                printk("ACPI: unusually short FADT, aborting!\n");
 638                return t;
 639        }
 640        /* for now, keep the globals. We'll get rid of them later. */
 641        fp = t->tbl;
 642        fadt = fp;
 643        fp->facs = l32get(p + 36);
 644        fp->dsdt = l32get(p + 40);
 645        fp->pmprofile = p[45];
 646        fp->sciint = l16get(p + 46);
 647        fp->smicmd = l32get(p + 48);
 648        fp->acpienable = p[52];
 649        fp->acpidisable = p[53];
 650        fp->s4biosreq = p[54];
 651        fp->pstatecnt = p[55];
 652        fp->pm1aevtblk = l32get(p + 56);
 653        fp->pm1bevtblk = l32get(p + 60);
 654        fp->pm1acntblk = l32get(p + 64);
 655        fp->pm1bcntblk = l32get(p + 68);
 656        fp->pm2cntblk = l32get(p + 72);
 657        fp->pmtmrblk = l32get(p + 76);
 658        fp->gpe0blk = l32get(p + 80);
 659        fp->gpe1blk = l32get(p + 84);
 660        fp->pm1evtlen = p[88];
 661        fp->pm1cntlen = p[89];
 662        fp->pm2cntlen = p[90];
 663        fp->pmtmrlen = p[91];
 664        fp->gpe0blklen = p[92];
 665        fp->gpe1blklen = p[93];
 666        fp->gp1base = p[94];
 667        fp->cstcnt = p[95];
 668        fp->plvl2lat = l16get(p + 96);
 669        fp->plvl3lat = l16get(p + 98);
 670        fp->flushsz = l16get(p + 100);
 671        fp->flushstride = l16get(p + 102);
 672        fp->dutyoff = p[104];
 673        fp->dutywidth = p[105];
 674        fp->dayalrm = p[106];
 675        fp->monalrm = p[107];
 676        fp->century = p[108];
 677        fp->iapcbootarch = l16get(p + 109);
 678        fp->flags = l32get(p + 112);
 679
 680        /*
 681         * qemu gives us a 116 byte fadt, though i haven't seen any HW do that.
 682         * The right way to do this is to realloc the table and fake it out.
 683         */
 684        if (rawsize < 244)
 685                return finatable_nochildren(t);
 686
 687        gasget(&fp->resetreg, p + 116);
 688        fp->resetval = p[128];
 689        fp->xfacs = l64get(p + 132);
 690        fp->xdsdt = l64get(p + 140);
 691        gasget(&fp->xpm1aevtblk, p + 148);
 692        gasget(&fp->xpm1bevtblk, p + 160);
 693        gasget(&fp->xpm1acntblk, p + 172);
 694        gasget(&fp->xpm1bcntblk, p + 184);
 695        gasget(&fp->xpm2cntblk, p + 196);
 696        gasget(&fp->xpmtmrblk, p + 208);
 697        gasget(&fp->xgpe0blk, p + 220);
 698        gasget(&fp->xgpe1blk, p + 232);
 699
 700        if (fp->xfacs != 0)
 701                loadfacs(fp->xfacs);
 702        else
 703                loadfacs(fp->facs);
 704
 705        if (fp->xdsdt == (uint64_t)fp->dsdt) /* acpica */
 706                loaddsdt(fp->xdsdt);
 707        else
 708                loaddsdt(fp->dsdt);
 709
 710        return finatable_nochildren(t);
 711}
 712
 713static char *dumpmsct(char *start, char *end, struct Atable *table)
 714{
 715        struct Msct *msct;
 716
 717        if (!table)
 718                return start;
 719
 720        msct = table->tbl;
 721        if (!msct)
 722                return start;
 723
 724        start =
 725            seprintf(start, end, "acpi: msct: %d doms %d clkdoms %#p maxpa\n",
 726                     msct->ndoms, msct->nclkdoms, msct->maxpa);
 727        for (int i = 0; i < table->nchildren; i++) {
 728                struct Atable *domtbl = table->children[i]->tbl;
 729                struct Mdom *st = domtbl->tbl;
 730
 731                start =
 732                    seprintf(start, end, "\t[%d:%d] %d maxproc %#p maxmmem\n",
 733                             st->start, st->end, st->maxproc, st->maxmem);
 734        }
 735        start = seprintf(start, end, "\n");
 736
 737        return start;
 738}
 739
 740/*
 741 * XXX: should perhaps update our idea of available memory.
 742 * Else we should remove this code.
 743 */
 744static struct Atable *parsemsct(struct Atable *parent, char *name, uint8_t *raw,
 745                                size_t rawsize)
 746{
 747        struct Atable *t;
 748        uint8_t *r, *re;
 749        struct Msct *msct;
 750        struct Mdom **stl, *st;
 751        size_t off, nmdom;
 752        int i;
 753
 754        re = raw + rawsize;
 755        off = l32get(raw + 36);
 756        nmdom = 0;
 757        for (r = raw + off, re = raw + rawsize; r < re; r += 22)
 758                nmdom++;
 759        t = mkatable(parent, MSCT, name, raw, rawsize,
 760                     sizeof(struct Msct) + nmdom * sizeof(struct Mdom));
 761        msct = t->tbl;
 762        msct->ndoms = l32get(raw + 40) + 1;
 763        msct->nclkdoms = l32get(raw + 44) + 1;
 764        msct->maxpa = l64get(raw + 48);
 765        msct->nmdom = nmdom;
 766        msct->dom = NULL;
 767        if (nmdom != 0)
 768                msct->dom = (void *)msct + sizeof(struct Msct);
 769        for (i = 0, r = raw; i < nmdom; i++, r += 22) {
 770                msct->dom[i].start = l32get(r + 2);
 771                msct->dom[i].end = l32get(r + 6);
 772                msct->dom[i].maxproc = l32get(r + 10);
 773                msct->dom[i].maxmem = l64get(r + 14);
 774        }
 775        mscttbl = finatable_nochildren(t);
 776
 777        return mscttbl;
 778}
 779
 780/* TODO(rminnich): only handles on IOMMU for now. */
 781static char *dumpdmar(char *start, char *end, struct Atable *dmar)
 782{
 783        struct Dmar *dt;
 784
 785        if (dmar == NULL)
 786                return start;
 787
 788        dt = dmar->tbl;
 789        start = seprintf(start, end, "acpi: DMAR addr %p:\n", dt);
 790        start = seprintf(start, end, "\tdmar: intr_remap %d haw %d\n",
 791                         dt->intr_remap, dt->haw);
 792        for (int i = 0; i < dmar->nchildren; i++) {
 793                struct Atable *at = dmar->children[i];
 794                struct Drhd *drhd = at->tbl;
 795
 796                start = seprintf(start, end, "\tDRHD: ");
 797                start = seprintf(start, end, "%s 0x%02x 0x%016x ",
 798                                 drhd->all & 1 ? "INCLUDE_PCI_ALL" : "Scoped",
 799                                 drhd->segment, drhd->rba);
 800                start = seprintf(start, end, "iommu: %p\n", &drhd->iommu);
 801        }
 802
 803        return start;
 804}
 805
 806static char *dumpsrat(char *start, char *end, struct Atable *table)
 807{
 808        if (table == NULL)
 809                return seprintf(start, end, "NO SRAT\n");
 810        start = seprintf(start, end, "acpi: SRAT@%p:\n", table->tbl);
 811        for (; table != NULL; table = table->next) {
 812                struct Srat *st = table->tbl;
 813
 814                if (st == NULL)
 815                        continue;
 816                switch (st->type) {
 817                case SRlapic:
 818                        start = seprintf(
 819                            start, end,
 820                            "\tlapic: dom %d apic %d sapic %d clk %d\n",
 821                            st->lapic.dom, st->lapic.apic, st->lapic.sapic,
 822                            st->lapic.clkdom);
 823                        break;
 824                case SRmem:
 825                        start =
 826                            seprintf(start, end, "\tmem: dom %d %#p %#p %c%c\n",
 827                                     st->mem.dom, st->mem.addr, st->mem.len,
 828                                     st->mem.hplug ? 'h' : '-',
 829                                     st->mem.nvram ? 'n' : '-');
 830                        break;
 831                case SRlx2apic:
 832                        start = seprintf(start, end,
 833                                         "\tlx2apic: dom %d apic %d clk %d\n",
 834                                         st->lx2apic.dom, st->lx2apic.apic,
 835                                         st->lx2apic.clkdom);
 836                        break;
 837                default:
 838                        start =
 839                            seprintf(start, end, "\t<unknown srat entry>\n");
 840                }
 841        }
 842        start = seprintf(start, end, "\n");
 843        return start;
 844}
 845
 846static struct Atable *parsesrat(struct Atable *parent, char *name, uint8_t *p,
 847                                size_t rawsize)
 848{
 849
 850        struct Atable *t, *tt, *tail;
 851        uint8_t *pe;
 852        int stlen, flags;
 853        struct slice slice;
 854        char buf[16];
 855        int i;
 856        struct Srat *st;
 857
 858        /* TODO: Parse the second SRAT */
 859        if (srat != NULL) {
 860                warn("Multiple SRATs detected and ignored!");
 861                return NULL;
 862        }
 863
 864        t = mkatable(parent, SRAT, name, p, rawsize, 0);
 865        slice_init(&slice);
 866        pe = p + rawsize;
 867        for (p += 48, i = 0; p < pe; p += stlen, i++) {
 868                snprintf(buf, sizeof(buf), "%d", i);
 869                stlen = p[1];
 870                tt = mkatable(t, SRAT, buf, p, stlen, sizeof(struct Srat));
 871                st = tt->tbl;
 872                st->type = p[0];
 873                switch (st->type) {
 874                case SRlapic:
 875                        st->lapic.dom =
 876                            p[2] | p[9] << 24 | p[10] << 16 | p[11] << 8;
 877                        st->lapic.apic = p[3];
 878                        st->lapic.sapic = p[8];
 879                        st->lapic.clkdom = l32get(p + 12);
 880                        if (l32get(p + 4) == 0) {
 881                                kfree(tt);
 882                                tt = NULL;
 883                        }
 884                        break;
 885                case SRmem:
 886                        st->mem.dom = l32get(p + 2);
 887                        st->mem.addr = l64get(p + 8);
 888                        st->mem.len = l64get(p + 16);
 889                        flags = l32get(p + 28);
 890                        if ((flags & 1) == 0) { /* not enabled */
 891                                kfree(tt);
 892                                tt = NULL;
 893                        } else {
 894                                st->mem.hplug = flags & 2;
 895                                st->mem.nvram = flags & 4;
 896                        }
 897                        break;
 898                case SRlx2apic:
 899                        st->lx2apic.dom = l32get(p + 4);
 900                        st->lx2apic.apic = l32get(p + 8);
 901                        st->lx2apic.clkdom = l32get(p + 16);
 902                        if (l32get(p + 12) == 0) {
 903                                kfree(tt);
 904                                tt = NULL;
 905                        }
 906                        break;
 907                default:
 908                        printd("unknown SRAT structure\n");
 909                        kfree(tt);
 910                        tt = NULL;
 911                        break;
 912                }
 913                if (tt != NULL) {
 914                        finatable_nochildren(tt);
 915                        slice_append(&slice, tt);
 916                }
 917        }
 918        srat = finatable(t, &slice);
 919
 920        return srat;
 921}
 922
 923static char *dumpslit(char *start, char *end, struct Slit *sl)
 924{
 925        int i;
 926
 927        if (sl == NULL)
 928                return start;
 929        start = seprintf(start, end, "acpi slit:\n");
 930        for (i = 0; i < sl->rowlen * sl->rowlen; i++) {
 931                start = seprintf(start, end, "slit: %ux\n",
 932                                 sl->e[i / sl->rowlen][i % sl->rowlen].dist);
 933        }
 934        start = seprintf(start, end, "\n");
 935        return start;
 936}
 937
 938static int cmpslitent(void *v1, void *v2)
 939{
 940        struct SlEntry *se1, *se2;
 941
 942        se1 = v1;
 943        se2 = v2;
 944        return se1->dist - se2->dist;
 945}
 946
 947static struct Atable *parseslit(struct Atable *parent, char *name, uint8_t *raw,
 948                                size_t rawsize)
 949{
 950        struct Atable *t;
 951        uint8_t *r, *re;
 952        int i, j, k;
 953        struct SlEntry *se;
 954        size_t addsize, rowlen;
 955        void *p;
 956
 957        addsize = sizeof(*slit);
 958        rowlen = l64get(raw + 36);
 959        addsize += rowlen * sizeof(struct SlEntry *);
 960        addsize += sizeof(struct SlEntry) * rowlen * rowlen;
 961
 962        t = mkatable(parent, SLIT, name, raw, rawsize, addsize);
 963        slit = t->tbl;
 964        slit->rowlen = rowlen;
 965        p = (void *)slit + sizeof(*slit);
 966        slit->e = p;
 967        p += rowlen * sizeof(struct SlEntry *);
 968        for (i = 0; i < rowlen; i++) {
 969                slit->e[i] = p;
 970                p += sizeof(struct SlEntry) * rowlen;
 971        }
 972        for (i = 0, r = raw + 44, re = raw + rawsize; r < re; r++, i++) {
 973                int j = i / rowlen;
 974                int k = i % rowlen;
 975
 976                se = &slit->e[j][k];
 977                se->dom = k;
 978                se->dist = *r;
 979        }
 980
 981#if 0
 982        /* TODO: might need to sort this shit */
 983        for (i = 0; i < slit->rowlen; i++)
 984                qsort(slit->e[i], slit->rowlen, sizeof(slit->e[0][0]), cmpslitent);
 985#endif
 986
 987        return finatable_nochildren(t);
 988}
 989
 990int pickcore(int mycolor, int index)
 991{
 992        int color;
 993        int ncorepercol;
 994
 995        if (slit == NULL)
 996                return 0;
 997        ncorepercol = num_cores / slit->rowlen;
 998        color = slit->e[mycolor][index / ncorepercol].dom;
 999        return color * ncorepercol + index % ncorepercol;
1000}
1001
1002static char *polarity[4] = {"polarity/trigger like in ISA", "active high",
1003                            "BOGUS POLARITY", "active low"};
1004
1005static char *trigger[] = {"BOGUS TRIGGER", "edge", "BOGUS TRIGGER", "level"};
1006
1007static char *printiflags(char *start, char *end, int flags)
1008{
1009
1010        return seprintf(start, end, "[%s,%s]", polarity[flags & AFpmask],
1011                        trigger[(flags & AFtmask) >> 2]);
1012}
1013
1014static char *dumpmadt(char *start, char *end, struct Atable *apics)
1015{
1016        struct Madt *mt;
1017
1018        if (apics == NULL)
1019                return start;
1020
1021        mt = apics->tbl;
1022        if (mt == NULL)
1023                return seprintf(start, end, "acpi: no MADT");
1024        start = seprintf(start, end, "acpi: MADT@%p: lapic paddr %p pcat %d:\n",
1025                         mt, mt->lapicpa, mt->pcat);
1026        for (int i = 0; i < apics->nchildren; i++) {
1027                struct Atable *apic = apics->children[i];
1028                struct Apicst *st = apic->tbl;
1029
1030                switch (st->type) {
1031                case ASlapic:
1032                        start = seprintf(start, end, "\tlapic pid %d id %d\n",
1033                                         st->lapic.pid, st->lapic.id);
1034                        break;
1035                case ASioapic:
1036                case ASiosapic:
1037                        start = seprintf(
1038                            start, end, "\tioapic id %d addr %p ibase %d\n",
1039                            st->ioapic.id, st->ioapic.addr, st->ioapic.ibase);
1040                        break;
1041                case ASintovr:
1042                        start = seprintf(
1043                            start, end, "\tintovr irq %d intr %d flags $%p",
1044                            st->intovr.irq, st->intovr.intr, st->intovr.flags);
1045                        start = printiflags(start, end, st->intovr.flags);
1046                        start = seprintf(start, end, "\n");
1047                        break;
1048                case ASnmi:
1049                        start =
1050                            seprintf(start, end, "\tnmi intr %d flags $%p\n",
1051                                     st->nmi.intr, st->nmi.flags);
1052                        break;
1053                case ASlnmi:
1054                        start = seprintf(
1055                            start, end, "\tlnmi pid %d lint %d flags $%p\n",
1056                            st->lnmi.pid, st->lnmi.lint, st->lnmi.flags);
1057                        break;
1058                case ASlsapic:
1059                        start = seprintf(
1060                            start, end,
1061                            "\tlsapic pid %d id %d eid %d puid %d puids %s\n",
1062                            st->lsapic.pid, st->lsapic.id, st->lsapic.eid,
1063                            st->lsapic.puid, st->lsapic.puids);
1064                        break;
1065                case ASintsrc:
1066                        start = seprintf(start, end,
1067                                         "\tintr type %d pid %d peid %d iosv "
1068                                         "%d intr %d %#x\n",
1069                                         st->type, st->intsrc.pid,
1070                                         st->intsrc.peid, st->intsrc.iosv,
1071                                         st->intsrc.intr, st->intsrc.flags);
1072                        start = printiflags(start, end, st->intsrc.flags);
1073                        start = seprintf(start, end, "\n");
1074                        break;
1075                case ASlx2apic:
1076                        start =
1077                            seprintf(start, end, "\tlx2apic puid %d id %d\n",
1078                                     st->lx2apic.puid, st->lx2apic.id);
1079                        break;
1080                case ASlx2nmi:
1081                        start = seprintf(
1082                            start, end, "\tlx2nmi puid %d intr %d flags $%p\n",
1083                            st->lx2nmi.puid, st->lx2nmi.intr, st->lx2nmi.flags);
1084                        break;
1085                default:
1086                        start =
1087                            seprintf(start, end, "\t<unknown madt entry>\n");
1088                }
1089        }
1090        start = seprintf(start, end, "\n");
1091        return start;
1092}
1093
1094static struct Atable *parsemadt(struct Atable *parent, char *name, uint8_t *p,
1095                                size_t size)
1096{
1097        struct Atable *t, *tt, *tail;
1098        uint8_t *pe;
1099        struct Madt *mt;
1100        struct Apicst *st, *l;
1101        int id;
1102        size_t stlen;
1103        char buf[16];
1104        int i;
1105        struct slice slice;
1106
1107        slice_init(&slice);
1108        t = mkatable(parent, MADT, name, p, size, sizeof(struct Madt));
1109        mt = t->tbl;
1110        mt->lapicpa = l32get(p + 36);
1111        mt->pcat = l32get(p + 40);
1112        pe = p + size;
1113        for (p += 44, i = 0; p < pe; p += stlen, i++) {
1114                snprintf(buf, sizeof(buf), "%d", i);
1115                stlen = p[1];
1116                tt = mkatable(t, APIC, buf, p, stlen, sizeof(struct Apicst));
1117                st = tt->tbl;
1118                st->type = p[0];
1119                switch (st->type) {
1120                case ASlapic:
1121                        st->lapic.pid = p[2];
1122                        st->lapic.id = p[3];
1123                        if (l32get(p + 4) == 0) {
1124                                kfree(tt);
1125                                tt = NULL;
1126                        }
1127                        break;
1128                case ASioapic:
1129                        st->ioapic.id = id = p[2];
1130                        st->ioapic.addr = l32get(p + 4);
1131                        st->ioapic.ibase = l32get(p + 8);
1132                        /* ioapic overrides any ioapic entry for the same id */
1133                        for (int i = 0; i < slice_len(&slice); i++) {
1134                                l = ((struct Atable *)slice_get(&slice, i))
1135                                        ->tbl;
1136                                if (l->type == ASiosapic &&
1137                                    l->iosapic.id == id) {
1138                                        st->ioapic = l->iosapic;
1139                                        /* we leave it linked; could be removed
1140                                         */
1141                                        break;
1142                                }
1143                        }
1144                        break;
1145                case ASintovr:
1146                        st->intovr.irq = p[3];
1147                        st->intovr.intr = l32get(p + 4);
1148                        st->intovr.flags = l16get(p + 8);
1149                        break;
1150                case ASnmi:
1151                        st->nmi.flags = l16get(p + 2);
1152                        st->nmi.intr = l32get(p + 4);
1153                        break;
1154                case ASlnmi:
1155                        st->lnmi.pid = p[2];
1156                        st->lnmi.flags = l16get(p + 3);
1157                        st->lnmi.lint = p[5];
1158                        break;
1159                case ASladdr:
1160                        /* This is for 64 bits, perhaps we should not
1161                         * honor it on 32 bits.
1162                         */
1163                        mt->lapicpa = l64get(p + 8);
1164                        break;
1165                case ASiosapic:
1166                        id = st->iosapic.id = p[2];
1167                        st->iosapic.ibase = l32get(p + 4);
1168                        st->iosapic.addr = l64get(p + 8);
1169                        /* iosapic overrides any ioapic entry for the same id */
1170                        for (int i = 0; i < slice_len(&slice); i++) {
1171                                l = ((struct Atable *)slice_get(&slice, i))
1172                                        ->tbl;
1173                                if (l->type == ASioapic && l->ioapic.id == id) {
1174                                        l->ioapic = st->iosapic;
1175                                        kfree(tt);
1176                                        tt = NULL;
1177                                        break;
1178                                }
1179                        }
1180                        break;
1181                case ASlsapic:
1182                        st->lsapic.pid = p[2];
1183                        st->lsapic.id = p[3];
1184                        st->lsapic.eid = p[4];
1185                        st->lsapic.puid = l32get(p + 12);
1186                        if (l32get(p + 8) == 0) {
1187                                kfree(tt);
1188                                tt = NULL;
1189                        } else
1190                                kstrdup(&st->lsapic.puids, (char *)p + 16);
1191                        break;
1192                case ASintsrc:
1193                        st->intsrc.flags = l16get(p + 2);
1194                        st->type = p[4];
1195                        st->intsrc.pid = p[5];
1196                        st->intsrc.peid = p[6];
1197                        st->intsrc.iosv = p[7];
1198                        st->intsrc.intr = l32get(p + 8);
1199                        st->intsrc.any = l32get(p + 12);
1200                        break;
1201                case ASlx2apic:
1202                        st->lx2apic.id = l32get(p + 4);
1203                        st->lx2apic.puid = l32get(p + 12);
1204                        if (l32get(p + 8) == 0) {
1205                                kfree(tt);
1206                                tt = NULL;
1207                        }
1208                        break;
1209                case ASlx2nmi:
1210                        st->lx2nmi.flags = l16get(p + 2);
1211                        st->lx2nmi.puid = l32get(p + 4);
1212                        st->lx2nmi.intr = p[8];
1213                        break;
1214                default:
1215                        printd("unknown APIC structure\n");
1216                        kfree(tt);
1217                        tt = NULL;
1218                }
1219                if (tt != NULL) {
1220                        finatable_nochildren(tt);
1221                        slice_append(&slice, tt);
1222                }
1223        }
1224        apics = finatable(t, &slice);
1225
1226        return apics;
1227}
1228
1229static struct Atable *parsedmar(struct Atable *parent, char *name, uint8_t *raw,
1230                                size_t rawsize)
1231{
1232        struct Atable *t, *tt;
1233        int i;
1234        int baselen = MIN(rawsize, 38);
1235        int nentry, nscope, npath, off, dslen, dhlen, len, type, flags;
1236        void *pathp;
1237        char buf[16];
1238        struct slice drhds;
1239        struct Drhd *drhd;
1240        struct Dmar *dt;
1241
1242        /* count the entries */
1243        for (nentry = 0, off = 48; off < rawsize; nentry++) {
1244                dslen = l16get(raw + off + 2);
1245                printk("acpi DMAR: entry %d is addr %p (0x%x/0x%x)\n", nentry,
1246                       raw + off, l16get(raw + off), dslen);
1247                off = off + dslen;
1248        }
1249        printk("DMAR: %d entries\n", nentry);
1250
1251        t = mkatable(parent, DMAR, name, raw, rawsize, sizeof(*dmar));
1252        dt = t->tbl;
1253        /* The table can be only partly filled. */
1254        if (baselen >= 38 && raw[37] & 1)
1255                dt->intr_remap = 1;
1256        if (baselen >= 37)
1257                dt->haw = raw[36] + 1;
1258
1259        /* Now we walk all the DMAR entries. */
1260        slice_init(&drhds);
1261        for (off = 48, i = 0; i < nentry; i++, off += dslen) {
1262                snprintf(buf, sizeof(buf), "%d", i);
1263                dslen = l16get(raw + off + 2);
1264                type = l16get(raw + off);
1265                // TODO(dcross): Introduce sensible symbolic constants
1266                // for DMAR entry types. For right now, type 0 => DRHD.
1267                // We skip everything else.
1268                if (type != 0)
1269                        continue;
1270                npath = 0;
1271                nscope = 0;
1272                for (int o = off + 16; o < (off + dslen); o += dhlen) {
1273                        nscope++;
1274                        dhlen = *(raw + o + 1); // Single byte length.
1275                        npath += ((dhlen - 6) / 2);
1276                }
1277                tt = mkatable(t, DRHD, buf, raw + off, dslen,
1278                              sizeof(struct Drhd) + 2 * npath +
1279                                  nscope * sizeof(struct DevScope));
1280                flags = *(raw + off + 4);
1281                drhd = tt->tbl;
1282                drhd->all = flags & 1;
1283                drhd->segment = l16get(raw + off + 6);
1284                drhd->rba = l64get(raw + off + 8);
1285                drhd->nscope = nscope;
1286                drhd->scopes = (void *)drhd + sizeof(struct Drhd);
1287                pathp = (void *)drhd + sizeof(struct Drhd) +
1288                        nscope * sizeof(struct DevScope);
1289                for (int i = 0, o = off + 16; i < nscope; i++) {
1290                        struct DevScope *ds = &drhd->scopes[i];
1291
1292                        dhlen = *(raw + o + 1);
1293                        ds->enumeration_id = *(raw + o + 4);
1294                        ds->start_bus_number = *(raw + o + 5);
1295                        ds->npath = (dhlen - 6) / 2;
1296                        ds->paths = pathp;
1297                        for (int j = 0; j < ds->npath; j++)
1298                                ds->paths[j] = l16get(raw + o + 6 + 2 * j);
1299                        pathp += 2 * ds->npath;
1300                        o += dhlen;
1301                }
1302
1303                iommu_initialize(&drhd->iommu, dt->haw, drhd->rba);
1304
1305                /*
1306                 * NOTE: if all is set, there should be no scopes of type
1307                 * This being ACPI, where vendors randomly copy tables
1308                 * from one system to another, and creating breakage,
1309                 * anything is possible. But we'll warn them.
1310                 */
1311                finatable_nochildren(tt);
1312                slice_append(&drhds, tt);
1313        }
1314        iommu_initialize_global();
1315        dmar = finatable(t, &drhds);
1316
1317        return dmar;
1318}
1319
1320/*
1321 * Map the table and keep it there.
1322 */
1323static struct Atable *parsessdt(struct Atable *parent, char *name, uint8_t *raw,
1324                                size_t size)
1325{
1326        struct Atable *t;
1327        struct Sdthdr *h;
1328
1329        /*
1330         * We found it and it is too small.
1331         * Simply return with no side effect.
1332         */
1333        if (size < Sdthdrsz)
1334                return NULL;
1335        t = mkatable(parent, SSDT, name, raw, size, 0);
1336        h = (struct Sdthdr *)raw;
1337        memmove(t->name, h->sig, sizeof(h->sig));
1338        t->name[sizeof(h->sig)] = '\0';
1339
1340        return finatable_nochildren(t);
1341}
1342
1343static struct Atable *parsemcfg(struct Atable *parent, char *name, uint8_t *raw,
1344                                size_t rawsize)
1345{
1346        struct Atable *t;
1347        struct acpi_mcfg *mcfg = (struct acpi_mcfg *)raw;
1348        struct acpi_mcfg_data *tbl;
1349        size_t nr_mcfg_entries;
1350        uint8_t *p;
1351
1352        if (rawsize < 36)
1353                return NULL;
1354        t = mkatable(parent, MCFG, name, raw, rawsize, 0);
1355
1356        nr_mcfg_entries = (l32get(mcfg->length) - 36) / 16;
1357        tbl = kmalloc(sizeof(struct acpi_mcfg_data)
1358                      + sizeof(struct acpi_mcfg_entry) * nr_mcfg_entries,
1359                      MEM_WAIT);
1360        tbl->nr_entries = nr_mcfg_entries;
1361        p = mcfg->entries;
1362        for (int i = 0; i < tbl->nr_entries; i++) {
1363                tbl->entries[i].addr = l64get(p + 0);
1364                tbl->entries[i].segment = l16get(p + 8);
1365                tbl->entries[i].start_bus = p[10];
1366                tbl->entries[i].end_bus = p[11];
1367                p += 16;
1368        }
1369        t->tbl = tbl;
1370
1371        mcfgtbl = finatable_nochildren(t);
1372
1373        return mcfgtbl;
1374}
1375
1376static char *dumpmcfg(char *start, char *end, struct Atable *table)
1377{
1378        struct acpi_mcfg *mcfg;
1379        struct acpi_mcfg_data *tbl;
1380
1381        if (!table)
1382                return start;
1383
1384        mcfg = (struct acpi_mcfg*)table->raw;
1385        tbl = table->tbl;
1386
1387        start = seprintf(start, end, "mcfg: oem id: %c%c%c%c%c%c\n",
1388                         mcfg->oemid[0], mcfg->oemid[1], mcfg->oemid[2],
1389                         mcfg->oemid[3], mcfg->oemid[4], mcfg->oemid[5]);
1390        start = seprintf(start, end, "mcfg: oem table id: %c%c%c%c%c%c%c%c\n",
1391                         mcfg->oemtblid[0], mcfg->oemtblid[1],
1392                         mcfg->oemtblid[2], mcfg->oemtblid[3],
1393                         mcfg->oemtblid[4], mcfg->oemtblid[5],
1394                         mcfg->oemtblid[6], mcfg->oemtblid[7]);
1395        start = seprintf(start, end, "mcfg: oem rev: 0x%x\n",
1396                         l32get(mcfg->oemrev));
1397        start = seprintf(start, end, "mcfg: creator id: %c%c%c%c\n",
1398                         mcfg->creatorid[0], mcfg->creatorid[1],
1399                         mcfg->creatorid[2], mcfg->creatorid[3]);
1400        start = seprintf(start, end, "mcfg: creator rev: 0x%x\n",
1401                         l32get(mcfg->creatorrev));
1402
1403        start = seprintf(start, end, "mcfg: nr_entries %d\n", tbl->nr_entries);
1404        for (int i = 0; i < tbl->nr_entries; i++) {
1405                start = seprintf(start, end, "\tSeg: %d Bus: %d-%d Addr: %p\n",
1406                                 tbl->entries[i].segment,
1407                                 tbl->entries[i].start_bus,
1408                                 tbl->entries[i].end_bus,
1409                                 tbl->entries[i].addr);
1410        }
1411
1412        return start;
1413}
1414
1415physaddr_t acpi_pci_get_mmio_cfg_addr(int segment, int bus, int dev, int func)
1416{
1417        struct acpi_mcfg_data *tbl;
1418
1419        if (!mcfgtbl)
1420                return 0;
1421        tbl = mcfgtbl->tbl;
1422
1423        for (int i = 0; i < tbl->nr_entries; i++) {
1424                if (segment == tbl->entries[i].segment &&
1425                    tbl->entries[i].start_bus <= bus &&
1426                    bus <= tbl->entries[i].end_bus)
1427                        return tbl->entries[i].addr
1428                                + (((bus - tbl->entries[i].start_bus) << 20)
1429                                   | (dev << 15)
1430                                   | (func << 12)
1431                                  );
1432        }
1433        return 0;
1434}
1435
1436static char *dumptable(char *start, char *end, char *sig, uint8_t *p, int l)
1437{
1438        int n, i;
1439
1440        if (2 > 1) {
1441                start = seprintf(start, end, "%s @ %#p\n", sig, p);
1442                if (2 > 2)
1443                        n = l;
1444                else
1445                        n = 256;
1446                for (i = 0; i < n; i++) {
1447                        if ((i % 16) == 0)
1448                                start = seprintf(start, end, "%x: ", i);
1449                        start = seprintf(start, end, " %2.2ux", p[i]);
1450                        if ((i % 16) == 15)
1451                                start = seprintf(start, end, "\n");
1452                }
1453                start = seprintf(start, end, "\n");
1454                start = seprintf(start, end, "\n");
1455        }
1456        return start;
1457}
1458
1459static char *seprinttable(char *s, char *e, struct Atable *t)
1460{
1461        uint8_t *p;
1462        int i, n;
1463
1464        p = (uint8_t *)t->tbl; /* include header */
1465        n = t->rawsize;
1466        s = seprintf(s, e, "%s @ %#p\n", t->name, p);
1467        for (i = 0; i < n; i++) {
1468                if ((i % 16) == 0)
1469                        s = seprintf(s, e, "%x: ", i);
1470                s = seprintf(s, e, " %2.2ux", p[i]);
1471                if ((i % 16) == 15)
1472                        s = seprintf(s, e, "\n");
1473        }
1474        return seprintf(s, e, "\n\n");
1475}
1476
1477static void *rsdsearch(char *signature)
1478{
1479        uintptr_t p;
1480        uint8_t *bda;
1481        void *rsd;
1482
1483        /*
1484         * Search for the data structure signature:
1485         * 1) in the BIOS ROM between 0xE0000 and 0xFFFFF.
1486         */
1487        return sigscan(KADDR_NOCHECK(0xE0000), 0x20000, signature);
1488}
1489
1490/*
1491 * Note: some of this comment is from the unfinished user interpreter.
1492 *
1493 * The DSDT is always given to the user interpreter.
1494 * Tables listed here are also loaded from the XSDT:
1495 * MSCT, MADT, and FADT are processed by us, because they are
1496 * required to do early initialization before we have user processes.
1497 * Other tables are given to the user level interpreter for
1498 * execution.
1499 *
1500 * These historically returned a value to tell acpi whether or not it was okay
1501 * to unmap the table.  (return 0 means there was no table, meaning it was okay
1502 * to unmap).  We just use the kernbase mapping, so it's irrelevant.
1503 *
1504 * N.B. The intel source code defines the constants for ACPI in a
1505 * non-endian-independent manner. Rather than bring in the huge wad o' code
1506 * that represents, we just the names.
1507 */
1508struct Parser {
1509        char *sig;
1510        struct Atable *(*parse)(struct Atable *parent, char *name, uint8_t *raw,
1511                                size_t rawsize);
1512};
1513
1514static struct Parser ptable[] = {
1515    {"FACP", parsefadt}, {"APIC", parsemadt}, {"DMAR", parsedmar},
1516    {"SRAT", parsesrat}, {"SLIT", parseslit}, {"MSCT", parsemsct},
1517    {"SSDT", parsessdt}, {"HPET", parsehpet}, {"MCFG", parsemcfg},
1518};
1519
1520/*
1521 * process xsdt table and load tables with sig, or all if NULL.
1522 * (XXX: should be able to search for sig, oemid, oemtblid)
1523 */
1524static void parsexsdt(struct Atable *root)
1525{
1526        ERRSTACK(1);
1527        struct Sdthdr *sdt;
1528        struct Atable *table;
1529        struct slice slice;
1530        size_t l, end;
1531        uintptr_t dhpa;
1532        struct Atable *n;
1533        uint8_t *tbl;
1534
1535        slice_init(&slice);
1536        if (waserror()) {
1537                slice_destroy(&slice);
1538                return;
1539        }
1540
1541        tbl = xsdt->p + sizeof(struct Sdthdr);
1542        end = xsdt->len - sizeof(struct Sdthdr);
1543        for (int i = 0; i < end; i += xsdt->asize) {
1544                dhpa = (xsdt->asize == 8) ? l64get(tbl + i) : l32get(tbl + i);
1545                sdt = sdtmap(dhpa, &l, 1);
1546                if (sdt == NULL)
1547                        continue;
1548                printd("acpi: %s addr %#p\n", tsig, sdt);
1549                for (int j = 0; j < ARRAY_SIZE(ptable); j++) {
1550                        if (memcmp(sdt->sig, ptable[j].sig, sizeof(sdt->sig)) ==
1551                            0) {
1552                                table = ptable[j].parse(root, ptable[j].sig,
1553                                                        (void *)sdt, l);
1554                                if (table != NULL)
1555                                        slice_append(&slice, table);
1556                                break;
1557                        }
1558                }
1559        }
1560        finatable(root, &slice);
1561}
1562
1563void makeindex(struct Atable *root)
1564{
1565        uint64_t index;
1566
1567        if (root == NULL)
1568                return;
1569        index = root->qid.path >> QIndexShift;
1570        atableindex[index] = root;
1571        for (int k = 0; k < root->nchildren; k++)
1572                makeindex(root->children[k]);
1573}
1574
1575static void parsersdptr(void)
1576{
1577        struct Rsdp *rsd;
1578        int asize, cksum;
1579        uintptr_t sdtpa;
1580
1581        static_assert(sizeof(struct Sdthdr) == 36);
1582
1583        /* Find the root pointer. */
1584        rsd = rsdsearch("RSD PTR ");
1585        if (rsd == NULL) {
1586                printk("NO RSDP\n");
1587                return;
1588        }
1589
1590        /*
1591         * Initialize the root of ACPI parse tree.
1592         */
1593        lastpath = Qroot;
1594        root = mkatable(NULL, XSDT, devname(), NULL, 0, sizeof(struct Xsdt));
1595        root->parent = root;
1596
1597        printd(
1598            "/* RSDP */ struct Rsdp = {%08c, %x, %06c, %x, %p, %d, %p, %x}\n",
1599            rsd->signature, rsd->rchecksum, rsd->oemid, rsd->revision,
1600            *(uint32_t *)rsd->raddr, *(uint32_t *)rsd->length,
1601            *(uint32_t *)rsd->xaddr, rsd->xchecksum);
1602
1603        printd("acpi: RSD PTR@ %#p, physaddr $%p length %ud %#llux rev %d\n",
1604               rsd, l32get(rsd->raddr), l32get(rsd->length), l64get(rsd->xaddr),
1605               rsd->revision);
1606
1607        if (rsd->revision >= 2) {
1608                cksum = sdtchecksum(rsd, 36);
1609                if (cksum != 0) {
1610                        printk("acpi: bad RSD checksum %d, 64 bit parser "
1611                               "aborted\n",
1612                               cksum);
1613                        return;
1614                }
1615                sdtpa = l64get(rsd->xaddr);
1616                asize = 8;
1617        } else {
1618                cksum = sdtchecksum(rsd, 20);
1619                if (cksum != 0) {
1620                        printk("acpi: bad RSD checksum %d, 32 bit parser "
1621                               "aborted\n",
1622                               cksum);
1623                        return;
1624                }
1625                sdtpa = l32get(rsd->raddr);
1626                asize = 4;
1627        }
1628
1629        /*
1630         * process the RSDT or XSDT table.
1631         */
1632        xsdt = root->tbl;
1633        xsdt->p = sdtmap(sdtpa, &xsdt->len, 1);
1634        if (xsdt->p == NULL) {
1635                printk("acpi: sdtmap failed\n");
1636                return;
1637        }
1638        if ((xsdt->p[0] != 'R' && xsdt->p[0] != 'X') ||
1639            memcmp(xsdt->p + 1, "SDT", 3) != 0) {
1640                printd("acpi: xsdt sig: %c%c%c%c\n", xsdt->p[0], xsdt->p[1],
1641                       xsdt->p[2], xsdt->p[3]);
1642                xsdt = NULL;
1643                return;
1644        }
1645        xsdt->asize = asize;
1646        printd("acpi: XSDT %#p\n", xsdt);
1647        parsexsdt(root);
1648        atableindex =
1649            kreallocarray(NULL, lastpath, sizeof(struct Atable *), MEM_WAIT);
1650        assert(atableindex != NULL);
1651        makeindex(root);
1652}
1653
1654/* Given an xsdt, find the table matching 'sig', if any. */
1655static struct Sdthdr *xsdt_find_tbl(struct Sdthdr *xsdt, const char *sig,
1656                                    int addr_size)
1657{
1658        uint8_t *ptr_tbl;
1659        size_t ptr_tbl_len;
1660        physaddr_t sdt_pa;
1661        struct Sdthdr *sdt;
1662
1663        ptr_tbl = (uint8_t *)xsdt + sizeof(struct Sdthdr);
1664        ptr_tbl_len = l32get(xsdt->length) - sizeof(struct Sdthdr);
1665        for (int i = 0; i < ptr_tbl_len; i += addr_size) {
1666                sdt_pa = (addr_size == 8) ? l64get(ptr_tbl + i)
1667                                          : l32get(ptr_tbl + i);
1668                sdt = KADDR_NOCHECK(sdt_pa);
1669                if (memcmp(sdt->sig, sig, sizeof(sdt->sig)) == 0)
1670                        return sdt;
1671        }
1672        return NULL;
1673}
1674
1675/* This may be an overestimate, if some LAPICS are present but disabled */
1676static int madt_get_nr_cores(struct Sdthdr *madt)
1677{
1678        uint8_t *p, *madt_end;
1679        size_t entry_len;
1680        int nr_cores = 0;
1681
1682        p = (uint8_t *)madt;
1683        madt_end = p + l32get(madt->length);
1684        for (p += 44; p < madt_end; p += entry_len) {
1685                entry_len = p[1];
1686                switch (p[0]) {
1687                case ASlapic:
1688                        nr_cores++;
1689                        break;
1690                default:
1691                        break;
1692                }
1693        }
1694        return nr_cores;
1695}
1696
1697int get_early_num_cores(void)
1698{
1699        struct Rsdp *rsd;
1700        int asize;
1701        physaddr_t sdtpa;
1702        struct Sdthdr *xsdt, *madt;
1703        uint8_t *xsdt_buf;
1704        int nr_cores;
1705
1706        rsd = rsdsearch("RSD PTR ");
1707        assert(rsd);
1708        if (rsd->revision >= 2) {
1709                sdtpa = l64get(rsd->xaddr);
1710                asize = 8;
1711        } else {
1712                sdtpa = l32get(rsd->raddr);
1713                asize = 4;
1714        }
1715
1716        xsdt = KADDR_NOCHECK(sdtpa);
1717        xsdt_buf = (uint8_t *)xsdt;
1718        if ((xsdt_buf[0] != 'R' && xsdt_buf[0] != 'X') ||
1719            memcmp(xsdt_buf + 1, "SDT", 3) != 0) {
1720                panic("acpi: xsdt sig: %c%c%c%c\n", xsdt_buf[0], xsdt_buf[1],
1721                      xsdt_buf[2], xsdt_buf[3]);
1722        }
1723        madt = xsdt_find_tbl(xsdt, "APIC", asize);
1724        assert(madt);
1725        nr_cores = madt_get_nr_cores(madt);
1726        if (nr_cores == 0) {
1727                warn("MADT parsing found 0 cores!");
1728                nr_cores = 1;
1729        }
1730        return nr_cores;
1731}
1732
1733/*
1734 * The invariant that each level in the tree has an associated
1735 * Atable implies that each chan can be mapped to an Atable.
1736 * The assertions here enforce that invariant.
1737 */
1738static struct Atable *genatable(struct chan *c)
1739{
1740        struct Atable *a;
1741        uint64_t ai;
1742
1743        ai = c->qid.path >> QIndexShift;
1744        assert(ai < lastpath);
1745        a = atableindex[ai];
1746        assert(a != NULL);
1747
1748        return a;
1749}
1750
1751static int acpigen(struct chan *c, char *name, struct dirtab *tab, int ntab,
1752                   int i, struct dir *dp)
1753{
1754        struct Atable *a = genatable(c);
1755
1756        if (i == DEVDOTDOT) {
1757                assert((c->qid.path & QIndexMask) == Qdir);
1758                devdir(c, a->parent->qid, a->parent->name, 0, eve.name,
1759                       DMDIR | 0555, dp);
1760                return 1;
1761        }
1762        return devgen(c, name, a->cdirs, a->nchildren + NQtypes, i, dp);
1763}
1764
1765/*
1766 * Print the contents of the XSDT.
1767 */
1768static void dumpxsdt(void)
1769{
1770        printk("xsdt: len = %lu, asize = %lu, p = %p\n", xsdt->len, xsdt->asize,
1771               xsdt->p);
1772}
1773
1774static char *dumpGas(char *start, char *end, char *prefix, struct Gas *g)
1775{
1776        start = seprintf(start, end, "%s", prefix);
1777
1778        switch (g->spc) {
1779        case Rsysmem:
1780        case Rsysio:
1781        case Rembed:
1782        case Rsmbus:
1783        case Rcmos:
1784        case Rpcibar:
1785        case Ripmi:
1786                start = seprintf(start, end, "[%s ", regnames[g->spc]);
1787                break;
1788        case Rpcicfg:
1789                start = seprintf(start, end, "[pci ");
1790                start = seprintf(start, end, "dev %#p ",
1791                                 (uint32_t)(g->addr >> 32) & 0xFFFF);
1792                start = seprintf(start, end, "fn %#p ",
1793                                 (uint32_t)(g->addr & 0xFFFF0000) >> 16);
1794                start = seprintf(start, end, "adr %#p ",
1795                                 (uint32_t)(g->addr & 0xFFFF));
1796                break;
1797        case Rfixedhw:
1798                start = seprintf(start, end, "[hw ");
1799                break;
1800        default:
1801                start = seprintf(start, end, "[spc=%#p ", g->spc);
1802        }
1803        start = seprintf(start, end, "off %d len %d addr %#p sz%d]", g->off,
1804                         g->len, g->addr, g->accsz);
1805        start = seprintf(start, end, "\n");
1806        return start;
1807}
1808
1809static unsigned int getbanked(uintptr_t ra, uintptr_t rb, int sz)
1810{
1811        unsigned int r;
1812
1813        r = 0;
1814        switch (sz) {
1815        case 1:
1816                if (ra != 0)
1817                        r |= inb(ra);
1818                if (rb != 0)
1819                        r |= inb(rb);
1820                break;
1821        case 2:
1822                if (ra != 0)
1823                        r |= inw(ra);
1824                if (rb != 0)
1825                        r |= inw(rb);
1826                break;
1827        case 4:
1828                if (ra != 0)
1829                        r |= inl(ra);
1830                if (rb != 0)
1831                        r |= inl(rb);
1832                break;
1833        default:
1834                printd("getbanked: wrong size\n");
1835        }
1836        return r;
1837}
1838
1839static unsigned int setbanked(uintptr_t ra, uintptr_t rb, int sz, int v)
1840{
1841        unsigned int r;
1842
1843        r = -1;
1844        switch (sz) {
1845        case 1:
1846                if (ra != 0)
1847                        outb(ra, v);
1848                if (rb != 0)
1849                        outb(rb, v);
1850                break;
1851        case 2:
1852                if (ra != 0)
1853                        outw(ra, v);
1854                if (rb != 0)
1855                        outw(rb, v);
1856                break;
1857        case 4:
1858                if (ra != 0)
1859                        outl(ra, v);
1860                if (rb != 0)
1861                        outl(rb, v);
1862                break;
1863        default:
1864                printd("setbanked: wrong size\n");
1865        }
1866        return r;
1867}
1868
1869static unsigned int getpm1ctl(void)
1870{
1871        assert(fadt != NULL);
1872        return getbanked(fadt->pm1acntblk, fadt->pm1bcntblk, fadt->pm1cntlen);
1873}
1874
1875static void setpm1sts(unsigned int v)
1876{
1877        assert(fadt != NULL);
1878        setbanked(fadt->pm1aevtblk, fadt->pm1bevtblk, fadt->pm1evtlen / 2, v);
1879}
1880
1881static unsigned int getpm1sts(void)
1882{
1883        assert(fadt != NULL);
1884        return getbanked(fadt->pm1aevtblk, fadt->pm1bevtblk,
1885                         fadt->pm1evtlen / 2);
1886}
1887
1888static unsigned int getpm1en(void)
1889{
1890        int sz;
1891
1892        assert(fadt != NULL);
1893        sz = fadt->pm1evtlen / 2;
1894        return getbanked(fadt->pm1aevtblk + sz, fadt->pm1bevtblk + sz, sz);
1895}
1896
1897static int getgpeen(int n)
1898{
1899        return inb(gpes[n].enio) & 1 << gpes[n].enbit;
1900}
1901
1902static void setgpeen(int n, unsigned int v)
1903{
1904        int old;
1905
1906        old = inb(gpes[n].enio);
1907        if (v)
1908                outb(gpes[n].enio, old | 1 << gpes[n].enbit);
1909        else
1910                outb(gpes[n].enio, old & ~(1 << gpes[n].enbit));
1911}
1912
1913static void clrgpests(int n)
1914{
1915        outb(gpes[n].stsio, 1 << gpes[n].stsbit);
1916}
1917
1918static unsigned int getgpests(int n)
1919{
1920        return inb(gpes[n].stsio) & 1 << gpes[n].stsbit;
1921}
1922
1923#if 0
1924static void acpiintr(Ureg *, void *)
1925{
1926        int i;
1927        unsigned int sts, en;
1928
1929        printd("acpi: intr\n");
1930
1931        for (i = 0; i < ngpes; i++)
1932                if (getgpests(i)) {
1933                        printd("gpe %d on\n", i);
1934                        en = getgpeen(i);
1935                        setgpeen(i, 0);
1936                        clrgpests(i);
1937                        if (en != 0)
1938                                printd("acpiitr: calling gpe %d\n", i);
1939                        //  queue gpe for calling gpe->ho in the
1940                        //  aml process.
1941                        //  enable it again when it returns.
1942                }
1943        sts = getpm1sts();
1944        en = getpm1en();
1945        printd("acpiitr: pm1sts %#p pm1en %#p\n", sts, en);
1946        if (sts & en)
1947                printd("have enabled events\n");
1948        if (sts & 1)
1949                printd("power button\n");
1950        // XXX serve other interrupts here.
1951        setpm1sts(sts);
1952}
1953#endif
1954
1955static void initgpes(void)
1956{
1957        int i, n0, n1;
1958
1959        assert(fadt != NULL);
1960        n0 = fadt->gpe0blklen / 2;
1961        n1 = fadt->gpe1blklen / 2;
1962        ngpes = n0 + n1;
1963        gpes = kzmalloc(sizeof(struct Gpe) * ngpes, 1);
1964        for (i = 0; i < n0; i++) {
1965                gpes[i].nb = i;
1966                gpes[i].stsbit = i & 7;
1967                gpes[i].stsio = fadt->gpe0blk + (i >> 3);
1968                gpes[i].enbit = (n0 + i) & 7;
1969                gpes[i].enio = fadt->gpe0blk + ((n0 + i) >> 3);
1970        }
1971        for (i = 0; i + n0 < ngpes; i++) {
1972                gpes[i + n0].nb = fadt->gp1base + i;
1973                gpes[i + n0].stsbit = i & 7;
1974                gpes[i + n0].stsio = fadt->gpe1blk + (i >> 3);
1975                gpes[i + n0].enbit = (n1 + i) & 7;
1976                gpes[i + n0].enio = fadt->gpe1blk + ((n1 + i) >> 3);
1977        }
1978        for (i = 0; i < ngpes; i++) {
1979                setgpeen(i, 0);
1980                clrgpests(i);
1981        }
1982}
1983
1984static void acpiioalloc(unsigned int addr, int len)
1985{
1986        if (addr != 0)
1987                printd("Just TAKING port %016lx to %016lx\n", addr, addr + len);
1988}
1989
1990static void acpiinitonce(void)
1991{
1992        parsersdptr();
1993        if (root != NULL)
1994                printk("ACPI initialized\n");
1995}
1996
1997int acpiinit(void)
1998{
1999        run_once(acpiinitonce());
2000        return (root == NULL) ? -1 : 0;
2001}
2002
2003static struct chan *acpiattach(char *spec)
2004{
2005        int i;
2006        struct chan *c;
2007        /*
2008         * This was written for the stock kernel.
2009         * This code must use 64 registers to be acpi ready in nix.
2010         */
2011        if (acpiinit() < 0)
2012                error(ENOSYS, "no acpi");
2013
2014        /*
2015         * should use fadt->xpm* and fadt->xgpe* registers for 64 bits.
2016         * We are not ready in this kernel for that.
2017         */
2018        assert(fadt != NULL);
2019        acpiioalloc(fadt->smicmd, 1);
2020        acpiioalloc(fadt->pm1aevtblk, fadt->pm1evtlen);
2021        acpiioalloc(fadt->pm1bevtblk, fadt->pm1evtlen);
2022        acpiioalloc(fadt->pm1acntblk, fadt->pm1cntlen);
2023        acpiioalloc(fadt->pm1bcntblk, fadt->pm1cntlen);
2024        acpiioalloc(fadt->pm2cntblk, fadt->pm2cntlen);
2025        acpiioalloc(fadt->pmtmrblk, fadt->pmtmrlen);
2026        acpiioalloc(fadt->gpe0blk, fadt->gpe0blklen);
2027        acpiioalloc(fadt->gpe1blk, fadt->gpe1blklen);
2028
2029        initgpes();
2030#ifdef RON_SAYS_CONFIG_WE_ARE_NOT_WORTHY
2031        /* this is frightening. SMI: just say no. Although we will almost
2032         * certainly find that we have no choice.
2033         *
2034         * This starts ACPI, which may require we handle
2035         * power mgmt events ourselves. Use with care.
2036         */
2037        outb(fadt->smicmd, fadt->acpienable);
2038        for (i = 0; i < 10; i++)
2039                if (getpm1ctl() & Pm1SciEn)
2040                        break;
2041        if (i == 10)
2042                error(EFAIL, "acpi: failed to enable\n");
2043        if (fadt->sciint != 0)
2044                intrenable(fadt->sciint, acpiintr, 0, BUSUNKNOWN, "acpi");
2045#endif
2046        c = devattach(devname(), spec);
2047
2048        return c;
2049}
2050
2051static struct walkqid *acpiwalk(struct chan *c, struct chan *nc, char **name,
2052                                unsigned int nname)
2053{
2054        /*
2055         * Note that devwalk hard-codes a test against the location of 'devgen',
2056         * so we pretty much have to not pass it here.
2057         */
2058        return devwalk(c, nc, name, nname, NULL, 0, acpigen);
2059}
2060
2061static size_t acpistat(struct chan *c, uint8_t *dp, size_t n)
2062{
2063        struct Atable *a = genatable(c);
2064
2065        if (c->qid.type == QTDIR)
2066                a = a->parent;
2067        assert(a != NULL);
2068
2069        /* TODO(dcross): make acpigen work here. */
2070        return devstat(c, dp, n, a->cdirs, a->nchildren + NQtypes, devgen);
2071}
2072
2073static struct chan *acpiopen(struct chan *c, int omode)
2074{
2075        return devopen(c, omode, NULL, 0, acpigen);
2076}
2077
2078static void acpiclose(struct chan *unused)
2079{
2080}
2081
2082static char *ttext;
2083static int tlen;
2084
2085// Get the table from the qid.
2086// Read that one table using the pointers.
2087static size_t acpiread(struct chan *c, void *a, size_t n, off64_t off)
2088{
2089        long q;
2090        struct Atable *t;
2091        char *ns, *s, *e, *ntext;
2092
2093        if (ttext == NULL) {
2094                tlen = 32768;
2095                ttext = kzmalloc(tlen, 0);
2096        }
2097        if (ttext == NULL)
2098                error(ENOMEM, "acpiread: no memory");
2099        q = c->qid.path & QIndexMask;
2100        switch (q) {
2101        case Qdir:
2102                return devdirread(c, a, n, NULL, 0, acpigen);
2103        case Qraw:
2104                return readmem(off, a, n, ttext, tlen);
2105        case Qtbl:
2106                s = ttext;
2107                e = ttext + tlen;
2108                strlcpy(s, "no tables\n", tlen);
2109                for (t = tfirst; t != NULL; t = t->next) {
2110                        ns = seprinttable(s, e, t);
2111                        while (ns == e - 1) {
2112                                ntext = krealloc(ttext, tlen * 2, 0);
2113                                if (ntext == NULL)
2114                                        panic("acpi: no memory\n");
2115                                s = ntext + (ttext - s);
2116                                ttext = ntext;
2117                                tlen *= 2;
2118                                e = ttext + tlen;
2119                                ns = seprinttable(s, e, t);
2120                        }
2121                        s = ns;
2122                }
2123                return readstr(off, a, n, ttext);
2124        case Qpretty:
2125                s = ttext;
2126                e = ttext + tlen;
2127                s = dumpfadt(s, e, fadt);
2128                s = dumpmadt(s, e, apics);
2129                s = dumpslit(s, e, slit);
2130                s = dumpsrat(s, e, srat);
2131                s = dumpdmar(s, e, dmar);
2132                s = dumpmsct(s, e, mscttbl);
2133                s = dumpmcfg(s, e, mcfgtbl);
2134                return readstr(off, a, n, ttext);
2135        default:
2136                error(EINVAL, "acpiread: bad path %d\n", q);
2137        }
2138        error(EPERM, ERROR_FIXME);
2139
2140        return -1;
2141}
2142
2143static size_t acpiwrite(struct chan *c, void *a, size_t n, off64_t off)
2144{
2145        error(EFAIL, "acpiwrite: not until we can figure out what it's for");
2146#if 0
2147        ERRSTACK(2);
2148        struct cmdtab *ct;
2149        struct cmdbuf *cb;
2150        struct Reg *r;
2151        unsigned int rno, fun, dev, bus, i;
2152
2153        if (c->qid.path == Qio) {
2154                if (reg == NULL)
2155                        error(EFAIL, "region not configured");
2156                return regio(reg, a, n, off, 1);
2157        }
2158        if (c->qid.path != Qctl)
2159                error(EPERM, ERROR_FIXME);
2160
2161        cb = parsecmd(a, n);
2162        if (waserror()) {
2163                kfree(cb);
2164                nexterror();
2165        }
2166        ct = lookupcmd(cb, ctls, ARRAY_SIZE(ctls));
2167        switch (ct->index) {
2168                case CMregion:
2169                        /* TODO: this block is racy on reg (global) */
2170                        r = reg;
2171                        if (r == NULL) {
2172                                r = kzmalloc(sizeof(struct Reg), 0);
2173                                r->name = NULL;
2174                        }
2175                        kstrdup(&r->name, cb->f[1]);
2176                        r->spc = acpiregid(cb->f[2]);
2177                        if (r->spc < 0) {
2178                                kfree(r);
2179                                reg = NULL;
2180                                error(EFAIL, "bad region type");
2181                        }
2182                        if (r->spc == Rpcicfg || r->spc == Rpcibar) {
2183                                rno = r->base >> Rpciregshift & Rpciregmask;
2184                                fun = r->base >> Rpcifunshift & Rpcifunmask;
2185                                dev = r->base >> Rpcidevshift & Rpcidevmask;
2186                                bus = r->base >> Rpcibusshift & Rpcibusmask;
2187#ifdef CONFIG_X86
2188                                r->tbdf = MKBUS(BusPCI, bus, dev, fun);
2189#else
2190                                r->tbdf = 0
2191#endif
2192                                r->base = rno;  /* register ~ our base addr */
2193                        }
2194                        r->base = strtoul(cb->f[3], NULL, 0);
2195                        r->len = strtoul(cb->f[4], NULL, 0);
2196                        r->accsz = strtoul(cb->f[5], NULL, 0);
2197                        if (r->accsz < 1 || r->accsz > 4) {
2198                                kfree(r);
2199                                reg = NULL;
2200                                error(EFAIL, "bad region access size");
2201                        }
2202                        reg = r;
2203                        printd("region %s %s %p %p sz%d",
2204                                   r->name, acpiregstr(r->spc), r->base, r->len, r->accsz);
2205                        break;
2206                case CMgpe:
2207                        i = strtoul(cb->f[1], NULL, 0);
2208                        if (i >= ngpes)
2209                                error(ERANGE, "gpe out of range");
2210                        kstrdup(&gpes[i].obj, cb->f[2]);
2211                        setgpeen(i, 1);
2212                        break;
2213                default:
2214                        panic("acpi: unknown ctl");
2215        }
2216        poperror();
2217        kfree(cb);
2218        return n;
2219#endif
2220}
2221
2222struct {
2223        char *(*pretty)(struct Atable *atbl, char *start, char *end, void *arg);
2224} acpisw[NACPITBLS] = {};
2225
2226static char *pretty(struct Atable *atbl, char *start, char *end, void *arg)
2227{
2228        int type;
2229
2230        type = atbl->type;
2231        if (type < 0 || NACPITBLS < type)
2232                return start;
2233        if (acpisw[type].pretty == NULL)
2234                return seprintf(start, end, "\"\"\n");
2235        return acpisw[type].pretty(atbl, start, end, arg);
2236}
2237
2238static char *raw(struct Atable *atbl, char *start, char *end, void *unused_arg)
2239{
2240        size_t len = MIN(end - start, atbl->rawsize);
2241
2242        memmove(start, atbl->raw, len);
2243
2244        return start + len;
2245}
2246
2247struct dev acpidevtab __devtab = {
2248    .name = "acpi",
2249
2250    .reset = devreset,
2251    .init = devinit,
2252    .shutdown = devshutdown,
2253    .attach = acpiattach,
2254    .walk = acpiwalk,
2255    .stat = acpistat,
2256    .open = acpiopen,
2257    .create = devcreate,
2258    .close = acpiclose,
2259    .read = acpiread,
2260    .bread = devbread,
2261    .write = acpiwrite,
2262    .bwrite = devbwrite,
2263    .remove = devremove,
2264    .wstat = devwstat,
2265};
2266