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