9ns: Fix devtab function pointer signatures
[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 <net/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.name, DMDIR | 0555,
1658                        dp);
1659                 return 1;
1660         }
1661         return devgen(c, name, a->cdirs, a->nchildren + NQtypes, i, dp);
1662 }
1663
1664 /*
1665  * Print the contents of the XSDT.
1666  */
1667 static void dumpxsdt(void)
1668 {
1669         printk("xsdt: len = %lu, asize = %lu, p = %p\n",
1670                xsdt->len, xsdt->asize, xsdt->p);
1671 }
1672
1673 static char *dumpGas(char *start, char *end, char *prefix, struct Gas *g)
1674 {
1675         start = seprintf(start, end, "%s", prefix);
1676
1677         switch (g->spc) {
1678                 case Rsysmem:
1679                 case Rsysio:
1680                 case Rembed:
1681                 case Rsmbus:
1682                 case Rcmos:
1683                 case Rpcibar:
1684                 case Ripmi:
1685                         start = seprintf(start, end, "[%s ", regnames[g->spc]);
1686                         break;
1687                 case Rpcicfg:
1688                         start = seprintf(start, end, "[pci ");
1689                         start =
1690                                 seprintf(start, end, "dev %#p ",
1691                                                  (uint32_t)(g->addr >> 32) & 0xFFFF);
1692                         start =
1693                                 seprintf(start, end, "fn %#p ",
1694                                                  (uint32_t)(g->addr & 0xFFFF0000) >> 16);
1695                         start =
1696                                 seprintf(start, end, "adr %#p ", (uint32_t)(g->addr & 0xFFFF));
1697                         break;
1698                 case Rfixedhw:
1699                         start = seprintf(start, end, "[hw ");
1700                         break;
1701                 default:
1702                         start = seprintf(start, end, "[spc=%#p ", g->spc);
1703         }
1704         start = seprintf(start, end, "off %d len %d addr %#p sz%d]",
1705                                          g->off, g->len, g->addr, g->accsz);
1706         start = seprintf(start, end, "\n");
1707         return start;
1708 }
1709
1710 static unsigned int getbanked(uintptr_t ra, uintptr_t rb, int sz)
1711 {
1712         unsigned int r;
1713
1714         r = 0;
1715         switch (sz) {
1716                 case 1:
1717                         if (ra != 0)
1718                                 r |= inb(ra);
1719                         if (rb != 0)
1720                                 r |= inb(rb);
1721                         break;
1722                 case 2:
1723                         if (ra != 0)
1724                                 r |= inw(ra);
1725                         if (rb != 0)
1726                                 r |= inw(rb);
1727                         break;
1728                 case 4:
1729                         if (ra != 0)
1730                                 r |= inl(ra);
1731                         if (rb != 0)
1732                                 r |= inl(rb);
1733                         break;
1734                 default:
1735                         printd("getbanked: wrong size\n");
1736         }
1737         return r;
1738 }
1739
1740 static unsigned int setbanked(uintptr_t ra, uintptr_t rb, int sz, int v)
1741 {
1742         unsigned int r;
1743
1744         r = -1;
1745         switch (sz) {
1746                 case 1:
1747                         if (ra != 0)
1748                                 outb(ra, v);
1749                         if (rb != 0)
1750                                 outb(rb, v);
1751                         break;
1752                 case 2:
1753                         if (ra != 0)
1754                                 outw(ra, v);
1755                         if (rb != 0)
1756                                 outw(rb, v);
1757                         break;
1758                 case 4:
1759                         if (ra != 0)
1760                                 outl(ra, v);
1761                         if (rb != 0)
1762                                 outl(rb, v);
1763                         break;
1764                 default:
1765                         printd("setbanked: wrong size\n");
1766         }
1767         return r;
1768 }
1769
1770 static unsigned int getpm1ctl(void)
1771 {
1772         assert(fadt != NULL);
1773         return getbanked(fadt->pm1acntblk, fadt->pm1bcntblk, fadt->pm1cntlen);
1774 }
1775
1776 static void setpm1sts(unsigned int v)
1777 {
1778         assert(fadt != NULL);
1779         setbanked(fadt->pm1aevtblk, fadt->pm1bevtblk, fadt->pm1evtlen / 2, v);
1780 }
1781
1782 static unsigned int getpm1sts(void)
1783 {
1784         assert(fadt != NULL);
1785         return getbanked(fadt->pm1aevtblk, fadt->pm1bevtblk, fadt->pm1evtlen / 2);
1786 }
1787
1788 static unsigned int getpm1en(void)
1789 {
1790         int sz;
1791
1792         assert(fadt != NULL);
1793         sz = fadt->pm1evtlen / 2;
1794         return getbanked(fadt->pm1aevtblk + sz, fadt->pm1bevtblk + sz, sz);
1795 }
1796
1797 static int getgpeen(int n)
1798 {
1799         return inb(gpes[n].enio) & 1 << gpes[n].enbit;
1800 }
1801
1802 static void setgpeen(int n, unsigned int v)
1803 {
1804         int old;
1805
1806         old = inb(gpes[n].enio);
1807         if (v)
1808                 outb(gpes[n].enio, old | 1 << gpes[n].enbit);
1809         else
1810                 outb(gpes[n].enio, old & ~(1 << gpes[n].enbit));
1811 }
1812
1813 static void clrgpests(int n)
1814 {
1815         outb(gpes[n].stsio, 1 << gpes[n].stsbit);
1816 }
1817
1818 static unsigned int getgpests(int n)
1819 {
1820         return inb(gpes[n].stsio) & 1 << gpes[n].stsbit;
1821 }
1822
1823 #if 0
1824 static void acpiintr(Ureg *, void *)
1825 {
1826         int i;
1827         unsigned int sts, en;
1828
1829         printd("acpi: intr\n");
1830
1831         for (i = 0; i < ngpes; i++)
1832                 if (getgpests(i)) {
1833                         printd("gpe %d on\n", i);
1834                         en = getgpeen(i);
1835                         setgpeen(i, 0);
1836                         clrgpests(i);
1837                         if (en != 0)
1838                                 printd("acpiitr: calling gpe %d\n", i);
1839                         //  queue gpe for calling gpe->ho in the
1840                         //  aml process.
1841                         //  enable it again when it returns.
1842                 }
1843         sts = getpm1sts();
1844         en = getpm1en();
1845         printd("acpiitr: pm1sts %#p pm1en %#p\n", sts, en);
1846         if (sts & en)
1847                 printd("have enabled events\n");
1848         if (sts & 1)
1849                 printd("power button\n");
1850         // XXX serve other interrupts here.
1851         setpm1sts(sts);
1852 }
1853 #endif
1854
1855 static void initgpes(void)
1856 {
1857         int i, n0, n1;
1858
1859         assert(fadt != NULL);
1860         n0 = fadt->gpe0blklen / 2;
1861         n1 = fadt->gpe1blklen / 2;
1862         ngpes = n0 + n1;
1863         gpes = kzmalloc(sizeof(struct Gpe) * ngpes, 1);
1864         for (i = 0; i < n0; i++) {
1865                 gpes[i].nb = i;
1866                 gpes[i].stsbit = i & 7;
1867                 gpes[i].stsio = fadt->gpe0blk + (i >> 3);
1868                 gpes[i].enbit = (n0 + i) & 7;
1869                 gpes[i].enio = fadt->gpe0blk + ((n0 + i) >> 3);
1870         }
1871         for (i = 0; i + n0 < ngpes; i++) {
1872                 gpes[i + n0].nb = fadt->gp1base + i;
1873                 gpes[i + n0].stsbit = i & 7;
1874                 gpes[i + n0].stsio = fadt->gpe1blk + (i >> 3);
1875                 gpes[i + n0].enbit = (n1 + i) & 7;
1876                 gpes[i + n0].enio = fadt->gpe1blk + ((n1 + i) >> 3);
1877         }
1878         for (i = 0; i < ngpes; i++) {
1879                 setgpeen(i, 0);
1880                 clrgpests(i);
1881         }
1882 }
1883
1884 static void acpiioalloc(unsigned int addr, int len)
1885 {
1886         if (addr != 0)
1887                 printd("Just TAKING port %016lx to %016lx\n", addr, addr + len);
1888 }
1889
1890 static void acpiinitonce(void)
1891 {
1892         parsersdptr();
1893         if (root != NULL)
1894                 printk("ACPI initialized\n");
1895 }
1896
1897 int acpiinit(void)
1898 {
1899         run_once(acpiinitonce());
1900         return (root == NULL) ? -1 : 0;
1901 }
1902
1903 static struct chan *acpiattach(char *spec)
1904 {
1905         int i;
1906         struct chan *c;
1907         /*
1908          * This was written for the stock kernel.
1909          * This code must use 64 registers to be acpi ready in nix.
1910          */
1911         if (acpiinit() < 0)
1912                 error(ENOSYS, "no acpi");
1913
1914         /*
1915          * should use fadt->xpm* and fadt->xgpe* registers for 64 bits.
1916          * We are not ready in this kernel for that.
1917          */
1918         assert(fadt != NULL);
1919         acpiioalloc(fadt->smicmd, 1);
1920         acpiioalloc(fadt->pm1aevtblk, fadt->pm1evtlen);
1921         acpiioalloc(fadt->pm1bevtblk, fadt->pm1evtlen);
1922         acpiioalloc(fadt->pm1acntblk, fadt->pm1cntlen);
1923         acpiioalloc(fadt->pm1bcntblk, fadt->pm1cntlen);
1924         acpiioalloc(fadt->pm2cntblk, fadt->pm2cntlen);
1925         acpiioalloc(fadt->pmtmrblk, fadt->pmtmrlen);
1926         acpiioalloc(fadt->gpe0blk, fadt->gpe0blklen);
1927         acpiioalloc(fadt->gpe1blk, fadt->gpe1blklen);
1928
1929         initgpes();
1930 #ifdef RON_SAYS_CONFIG_WE_ARE_NOT_WORTHY
1931         /* this is frightening. SMI: just say no. Although we will almost
1932          * certainly find that we have no choice.
1933          *
1934          * This starts ACPI, which may require we handle
1935          * power mgmt events ourselves. Use with care.
1936          */
1937         outb(fadt->smicmd, fadt->acpienable);
1938         for (i = 0; i < 10; i++)
1939                 if (getpm1ctl() & Pm1SciEn)
1940                         break;
1941         if (i == 10)
1942                 error(EFAIL, "acpi: failed to enable\n");
1943         if (fadt->sciint != 0)
1944                 intrenable(fadt->sciint, acpiintr, 0, BUSUNKNOWN, "acpi");
1945 #endif
1946         c = devattach(devname(), spec);
1947
1948         return c;
1949 }
1950
1951 static struct walkqid *acpiwalk(struct chan *c, struct chan *nc, char **name,
1952                                                                 unsigned int nname)
1953 {
1954         /*
1955          * Note that devwalk hard-codes a test against the location of 'devgen',
1956          * so we pretty much have to not pass it here.
1957          */
1958         return devwalk(c, nc, name, nname, NULL, 0, acpigen);
1959 }
1960
1961 static size_t acpistat(struct chan *c, uint8_t *dp, size_t n)
1962 {
1963         struct Atable *a = genatable(c);
1964
1965         if (c->qid.type == QTDIR)
1966                 a = a->parent;
1967         assert(a != NULL);
1968
1969         /* TODO(dcross): make acpigen work here. */
1970         return devstat(c, dp, n, a->cdirs, a->nchildren + NQtypes, devgen);
1971 }
1972
1973 static struct chan *acpiopen(struct chan *c, int omode)
1974 {
1975         return devopen(c, omode, NULL, 0, acpigen);
1976 }
1977
1978 static void acpiclose(struct chan *unused)
1979 {
1980 }
1981
1982 static char *ttext;
1983 static int tlen;
1984
1985 // Get the table from the qid.
1986 // Read that one table using the pointers.
1987 static size_t acpiread(struct chan *c, void *a, size_t n, off64_t off)
1988 {
1989         long q;
1990         struct Atable *t;
1991         char *ns, *s, *e, *ntext;
1992
1993         if (ttext == NULL) {
1994                 tlen = 32768;
1995                 ttext = kzmalloc(tlen, 0);
1996         }
1997         if (ttext == NULL)
1998                 error(ENOMEM, "acpiread: no memory");
1999         q = c->qid.path & QIndexMask;
2000         switch (q) {
2001         case Qdir:
2002                 return devdirread(c, a, n, NULL, 0, acpigen);
2003         case Qraw:
2004                 return readmem(off, a, n, ttext, tlen);
2005         case Qtbl:
2006                 s = ttext;
2007                 e = ttext + tlen;
2008                 strlcpy(s, "no tables\n", tlen);
2009                 for (t = tfirst; t != NULL; t = t->next) {
2010                         ns = seprinttable(s, e, t);
2011                         while (ns == e - 1) {
2012                                 ntext = krealloc(ttext, tlen * 2, 0);
2013                                 if (ntext == NULL)
2014                                         panic("acpi: no memory\n");
2015                                 s = ntext + (ttext - s);
2016                                 ttext = ntext;
2017                                 tlen *= 2;
2018                                 e = ttext + tlen;
2019                                 ns = seprinttable(s, e, t);
2020                         }
2021                         s = ns;
2022                 }
2023                 return readstr(off, a, n, ttext);
2024         case Qpretty:
2025                 s = ttext;
2026                 e = ttext + tlen;
2027                 s = dumpfadt(s, e, fadt);
2028                 s = dumpmadt(s, e, apics);
2029                 s = dumpslit(s, e, slit);
2030                 s = dumpsrat(s, e, srat);
2031                 s = dumpdmar(s, e, dmar);
2032                 dumpmsct(s, e, mscttbl);
2033                 return readstr(off, a, n, ttext);
2034         default:
2035                 error(EINVAL, "acpiread: bad path %d\n", q);
2036         }
2037         error(EPERM, ERROR_FIXME);
2038
2039         return -1;
2040 }
2041
2042 static size_t acpiwrite(struct chan *c, void *a, size_t n, off64_t off)
2043 {
2044         error(EFAIL, "acpiwrite: not until we can figure out what it's for");
2045 #if 0
2046         ERRSTACK(2);
2047         struct cmdtab *ct;
2048         struct cmdbuf *cb;
2049         struct Reg *r;
2050         unsigned int rno, fun, dev, bus, i;
2051
2052         if (c->qid.path == Qio) {
2053                 if (reg == NULL)
2054                         error(EFAIL, "region not configured");
2055                 return regio(reg, a, n, off, 1);
2056         }
2057         if (c->qid.path != Qctl)
2058                 error(EPERM, ERROR_FIXME);
2059
2060         cb = parsecmd(a, n);
2061         if (waserror()) {
2062                 kfree(cb);
2063                 nexterror();
2064         }
2065         ct = lookupcmd(cb, ctls, ARRAY_SIZE(ctls));
2066         switch (ct->index) {
2067                 case CMregion:
2068                         /* TODO: this block is racy on reg (global) */
2069                         r = reg;
2070                         if (r == NULL) {
2071                                 r = kzmalloc(sizeof(struct Reg), 0);
2072                                 r->name = NULL;
2073                         }
2074                         kstrdup(&r->name, cb->f[1]);
2075                         r->spc = acpiregid(cb->f[2]);
2076                         if (r->spc < 0) {
2077                                 kfree(r);
2078                                 reg = NULL;
2079                                 error(EFAIL, "bad region type");
2080                         }
2081                         if (r->spc == Rpcicfg || r->spc == Rpcibar) {
2082                                 rno = r->base >> Rpciregshift & Rpciregmask;
2083                                 fun = r->base >> Rpcifunshift & Rpcifunmask;
2084                                 dev = r->base >> Rpcidevshift & Rpcidevmask;
2085                                 bus = r->base >> Rpcibusshift & Rpcibusmask;
2086 #ifdef CONFIG_X86
2087                                 r->tbdf = MKBUS(BusPCI, bus, dev, fun);
2088 #else
2089                                 r->tbdf = 0
2090 #endif
2091                                 r->base = rno;  /* register ~ our base addr */
2092                         }
2093                         r->base = strtoul(cb->f[3], NULL, 0);
2094                         r->len = strtoul(cb->f[4], NULL, 0);
2095                         r->accsz = strtoul(cb->f[5], NULL, 0);
2096                         if (r->accsz < 1 || r->accsz > 4) {
2097                                 kfree(r);
2098                                 reg = NULL;
2099                                 error(EFAIL, "bad region access size");
2100                         }
2101                         reg = r;
2102                         printd("region %s %s %p %p sz%d",
2103                                    r->name, acpiregstr(r->spc), r->base, r->len, r->accsz);
2104                         break;
2105                 case CMgpe:
2106                         i = strtoul(cb->f[1], NULL, 0);
2107                         if (i >= ngpes)
2108                                 error(ERANGE, "gpe out of range");
2109                         kstrdup(&gpes[i].obj, cb->f[2]);
2110                         setgpeen(i, 1);
2111                         break;
2112                 default:
2113                         panic("acpi: unknown ctl");
2114         }
2115         poperror();
2116         kfree(cb);
2117         return n;
2118 #endif
2119 }
2120
2121 struct {
2122         char *(*pretty)(struct Atable *atbl, char *start, char *end, void *arg);
2123 } acpisw[NACPITBLS] = {
2124 };
2125
2126 static char *pretty(struct Atable *atbl, char *start, char *end, void *arg)
2127 {
2128         int type;
2129
2130         type = atbl->type;
2131         if (type < 0 || NACPITBLS < type)
2132                 return start;
2133         if (acpisw[type].pretty == NULL)
2134                 return seprintf(start, end, "\"\"\n");
2135         return acpisw[type].pretty(atbl, start, end, arg);
2136 }
2137
2138 static char *raw(struct Atable *atbl, char *start, char *end, void *unused_arg)
2139 {
2140         size_t len = MIN(end - start, atbl->rawsize);
2141
2142         memmove(start, atbl->raw, len);
2143
2144         return start + len;
2145 }
2146
2147 struct dev acpidevtab __devtab = {
2148         .name = "acpi",
2149
2150         .reset = devreset,
2151         .init = devinit,
2152         .shutdown = devshutdown,
2153         .attach = acpiattach,
2154         .walk = acpiwalk,
2155         .stat = acpistat,
2156         .open = acpiopen,
2157         .create = devcreate,
2158         .close = acpiclose,
2159         .read = acpiread,
2160         .bread = devbread,
2161         .write = acpiwrite,
2162         .bwrite = devbwrite,
2163         .remove = devremove,
2164         .wstat = devwstat,
2165 };