ACPI changes for DMAR and new directory hierarchy.
[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, KMALLOC_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                              KMALLOC_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, KMALLOC_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         if (srat != NULL)
851                 panic("acpi: two SRATs?\n");
852
853         t = mkatable(parent, SRAT, name, p, rawsize, 0);
854         slice_init(&slice);
855         pe = p + rawsize;
856         for (p += 48, i = 0; p < pe; p += stlen, i++) {
857                 snprintf(buf, sizeof(buf), "%d", i);
858                 stlen = p[1];
859                 tt = mkatable(t, SRAT, buf, p, stlen, sizeof(struct Srat));
860                 st = tt->tbl;
861                 st->type = p[0];
862                 switch (st->type) {
863                         case SRlapic:
864                                 st->lapic.dom = p[2] | p[9] << 24 | p[10] << 16 | p[11] << 8;
865                                 st->lapic.apic = p[3];
866                                 st->lapic.sapic = p[8];
867                                 st->lapic.clkdom = l32get(p + 12);
868                                 if (l32get(p + 4) == 0) {
869                                         kfree(tt);
870                                         tt = NULL;
871                                 }
872                                 break;
873                         case SRmem:
874                                 st->mem.dom = l32get(p + 2);
875                                 st->mem.addr = l64get(p + 8);
876                                 st->mem.len = l64get(p + 16);
877                                 flags = l32get(p + 28);
878                                 if ((flags & 1) == 0) { /* not enabled */
879                                         kfree(tt);
880                                         tt = NULL;
881                                 } else {
882                                         st->mem.hplug = flags & 2;
883                                         st->mem.nvram = flags & 4;
884                                 }
885                                 break;
886                         case SRlx2apic:
887                                 st->lx2apic.dom = l32get(p + 4);
888                                 st->lx2apic.apic = l32get(p + 8);
889                                 st->lx2apic.clkdom = l32get(p + 16);
890                                 if (l32get(p + 12) == 0) {
891                                         kfree(tt);
892                                         tt = NULL;
893                                 }
894                                 break;
895                         default:
896                                 printd("unknown SRAT structure\n");
897                                 kfree(tt);
898                                 tt = NULL;
899                                 break;
900                 }
901                 if (tt != NULL) {
902                         finatable_nochildren(tt);
903                         slice_append(&slice, tt);
904                 }
905         }
906         srat = finatable(t, &slice);
907
908         return srat;
909 }
910
911 static char *dumpslit(char *start, char *end, struct Slit *sl)
912 {
913         int i;
914
915         if (sl == NULL)
916                 return start;
917         start = seprintf(start, end, "acpi slit:\n");
918         for (i = 0; i < sl->rowlen * sl->rowlen; i++) {
919                 start = seprintf(start, end,
920                                                  "slit: %ux\n",
921                                                  sl->e[i / sl->rowlen][i % sl->rowlen].dist);
922         }
923         start = seprintf(start, end, "\n");
924         return start;
925 }
926
927 static int cmpslitent(void *v1, void *v2)
928 {
929         struct SlEntry *se1, *se2;
930
931         se1 = v1;
932         se2 = v2;
933         return se1->dist - se2->dist;
934 }
935
936 static struct Atable *parseslit(struct Atable *parent,
937                                 char *name, uint8_t *raw, size_t rawsize)
938 {
939         struct Atable *t;
940         uint8_t *r, *re;
941         int i, j, k;
942         struct SlEntry *se;
943         size_t addsize, rowlen;
944         void *p;
945
946         addsize = sizeof(*slit);
947         rowlen = l64get(raw + 36);
948         addsize += rowlen * sizeof(struct SlEntry *);
949         addsize += sizeof(struct SlEntry) * rowlen * rowlen;
950
951         t = mkatable(parent, SLIT, name, raw, rawsize, addsize);
952         slit = t->tbl;
953         slit->rowlen = rowlen;
954         p = (void *)slit + sizeof(*slit);
955         slit->e = p;
956         p += rowlen * sizeof(struct SlEntry *);
957         for (i = 0; i < rowlen; i++) {
958                 slit->e[i] = p;
959                 p += sizeof(struct SlEntry) * rowlen;
960         }
961         for (i = 0, r = raw + 44, re = raw + rawsize; r < re; r++, i++) {
962                 int j = i / rowlen;
963                 int k = i % rowlen;
964
965                 se = &slit->e[j][k];
966                 se->dom = k;
967                 se->dist = *r;
968         }
969
970 #if 0
971         /* TODO: might need to sort this shit */
972         for (i = 0; i < slit->rowlen; i++)
973                 qsort(slit->e[i], slit->rowlen, sizeof(slit->e[0][0]), cmpslitent);
974 #endif
975
976         return finatable_nochildren(t);
977 }
978
979 int pickcore(int mycolor, int index)
980 {
981         int color;
982         int ncorepercol;
983
984         if (slit == NULL)
985                 return 0;
986         ncorepercol = num_cores / slit->rowlen;
987         color = slit->e[mycolor][index / ncorepercol].dom;
988         return color * ncorepercol + index % ncorepercol;
989 }
990
991 static char *polarity[4] = {
992         "polarity/trigger like in ISA",
993         "active high",
994         "BOGUS POLARITY",
995         "active low"
996 };
997
998 static char *trigger[] = {
999         "BOGUS TRIGGER",
1000         "edge",
1001         "BOGUS TRIGGER",
1002         "level"
1003 };
1004
1005 static char *printiflags(char *start, char *end, int flags)
1006 {
1007
1008         return seprintf(start, end, "[%s,%s]",
1009                                         polarity[flags & AFpmask], trigger[(flags & AFtmask) >> 2]);
1010 }
1011
1012 static char *dumpmadt(char *start, char *end, struct Atable *apics)
1013 {
1014         struct Madt *mt;
1015
1016         if (apics == NULL)
1017                 return start;
1018
1019         mt = apics->tbl;
1020         if (mt == NULL)
1021                 return seprintf(start, end, "acpi: no MADT");
1022         start = seprintf(start, end, "acpi: MADT@%p: lapic paddr %p pcat %d:\n",
1023                          mt, mt->lapicpa, mt->pcat);
1024         for (int i = 0; i < apics->nchildren; i++) {
1025                 struct Atable *apic = apics->children[i];
1026                 struct Apicst *st = apic->tbl;
1027
1028                 switch (st->type) {
1029                         case ASlapic:
1030                                 start =
1031                                         seprintf(start, end, "\tlapic pid %d id %d\n",
1032                                                          st->lapic.pid, st->lapic.id);
1033                                 break;
1034                         case ASioapic:
1035                         case ASiosapic:
1036                                 start =
1037                                         seprintf(start, end,
1038                                                          "\tioapic id %d addr %p ibase %d\n",
1039                                                          st->ioapic.id, st->ioapic.addr, st->ioapic.ibase);
1040                                 break;
1041                         case ASintovr:
1042                                 start =
1043                                         seprintf(start, end, "\tintovr irq %d intr %d flags $%p",
1044                                                          st->intovr.irq, st->intovr.intr, st->intovr.flags);
1045                                 start = printiflags(start, end, st->intovr.flags);
1046                                 start = seprintf(start, end, "\n");
1047                                 break;
1048                         case ASnmi:
1049                                 start = seprintf(start, end, "\tnmi intr %d flags $%p\n",
1050                                                                  st->nmi.intr, st->nmi.flags);
1051                                 break;
1052                         case ASlnmi:
1053                                 start =
1054                                         seprintf(start, end, "\tlnmi pid %d lint %d flags $%p\n",
1055                                                          st->lnmi.pid, st->lnmi.lint, st->lnmi.flags);
1056                                 break;
1057                         case ASlsapic:
1058                                 start =
1059                                         seprintf(start, end,
1060                                                          "\tlsapic pid %d id %d eid %d puid %d puids %s\n",
1061                                                          st->lsapic.pid, st->lsapic.id, st->lsapic.eid,
1062                                                          st->lsapic.puid, st->lsapic.puids);
1063                                 break;
1064                         case ASintsrc:
1065                                 start =
1066                                         seprintf(start, end,
1067                                                          "\tintr type %d pid %d peid %d iosv %d intr %d %#x\n",
1068                                                          st->type, st->intsrc.pid, st->intsrc.peid,
1069                                                          st->intsrc.iosv, st->intsrc.intr,
1070                                                          st->intsrc.flags);
1071                                 start = printiflags(start, end, st->intsrc.flags);
1072                                 start = seprintf(start, end, "\n");
1073                                 break;
1074                         case ASlx2apic:
1075                                 start =
1076                                         seprintf(start, end, "\tlx2apic puid %d id %d\n",
1077                                                          st->lx2apic.puid, st->lx2apic.id);
1078                                 break;
1079                         case ASlx2nmi:
1080                                 start =
1081                                         seprintf(start, end, "\tlx2nmi puid %d intr %d flags $%p\n",
1082                                                          st->lx2nmi.puid, st->lx2nmi.intr,
1083                                                          st->lx2nmi.flags);
1084                                 break;
1085                         default:
1086                                 start = seprintf(start, end, "\t<unknown madt entry>\n");
1087                 }
1088         }
1089         start = seprintf(start, end, "\n");
1090         return start;
1091 }
1092
1093 static struct Atable *parsemadt(struct Atable *parent,
1094                                 char *name, uint8_t *p, size_t size)
1095 {
1096         struct Atable *t, *tt, *tail;
1097         uint8_t *pe;
1098         struct Madt *mt;
1099         struct Apicst *st, *l;
1100         int id;
1101         size_t stlen;
1102         char buf[16];
1103         int i;
1104         struct slice slice;
1105
1106         slice_init(&slice);
1107         t = mkatable(parent, MADT, name, p, size, sizeof(struct Madt));
1108         mt = t->tbl;
1109         mt->lapicpa = l32get(p + 36);
1110         mt->pcat = l32get(p + 40);
1111         pe = p + size;
1112         for (p += 44, i = 0; p < pe; p += stlen, i++) {
1113                 snprintf(buf, sizeof(buf), "%d", i);
1114                 stlen = p[1];
1115                 tt = mkatable(t, APIC, buf, p, stlen, sizeof(struct Apicst));
1116                 st = tt->tbl;
1117                 st->type = p[0];
1118                 switch (st->type) {
1119                         case ASlapic:
1120                                 st->lapic.pid = p[2];
1121                                 st->lapic.id = p[3];
1122                                 if (l32get(p + 4) == 0) {
1123                                         kfree(tt);
1124                                         tt = NULL;
1125                                 }
1126                                 break;
1127                         case ASioapic:
1128                                 st->ioapic.id = id = p[2];
1129                                 st->ioapic.addr = l32get(p + 4);
1130                                 st->ioapic.ibase = l32get(p + 8);
1131                                 /* ioapic overrides any ioapic entry for the same id */
1132                                 for (int i = 0; i < slice_len(&slice); i++) {
1133                                         l = ((struct Atable *)slice_get(&slice, i))->tbl;
1134                                         if (l->type == ASiosapic && l->iosapic.id == id) {
1135                                                 st->ioapic = l->iosapic;
1136                                                 /* we leave it linked; could be removed */
1137                                                 break;
1138                                         }
1139                                 }
1140                                 break;
1141                         case ASintovr:
1142                                 st->intovr.irq = p[3];
1143                                 st->intovr.intr = l32get(p + 4);
1144                                 st->intovr.flags = l16get(p + 8);
1145                                 break;
1146                         case ASnmi:
1147                                 st->nmi.flags = l16get(p + 2);
1148                                 st->nmi.intr = l32get(p + 4);
1149                                 break;
1150                         case ASlnmi:
1151                                 st->lnmi.pid = p[2];
1152                                 st->lnmi.flags = l16get(p + 3);
1153                                 st->lnmi.lint = p[5];
1154                                 break;
1155                         case ASladdr:
1156                                 /* This is for 64 bits, perhaps we should not
1157                                  * honor it on 32 bits.
1158                                  */
1159                                 mt->lapicpa = l64get(p + 8);
1160                                 break;
1161                         case ASiosapic:
1162                                 id = st->iosapic.id = p[2];
1163                                 st->iosapic.ibase = l32get(p + 4);
1164                                 st->iosapic.addr = l64get(p + 8);
1165                                 /* iosapic overrides any ioapic entry for the same id */
1166                                 for (int i = 0; i < slice_len(&slice); i++) {
1167                                         l = ((struct Atable*)slice_get(&slice, i))->tbl;
1168                                         if (l->type == ASioapic && l->ioapic.id == id) {
1169                                                 l->ioapic = st->iosapic;
1170                                                 kfree(tt);
1171                                                 tt = NULL;
1172                                                 break;
1173                                         }
1174                                 }
1175                                 break;
1176                         case ASlsapic:
1177                                 st->lsapic.pid = p[2];
1178                                 st->lsapic.id = p[3];
1179                                 st->lsapic.eid = p[4];
1180                                 st->lsapic.puid = l32get(p + 12);
1181                                 if (l32get(p + 8) == 0) {
1182                                         kfree(tt);
1183                                         tt = NULL;
1184                                 } else
1185                                         kstrdup(&st->lsapic.puids, (char *)p + 16);
1186                                 break;
1187                         case ASintsrc:
1188                                 st->intsrc.flags = l16get(p + 2);
1189                                 st->type = p[4];
1190                                 st->intsrc.pid = p[5];
1191                                 st->intsrc.peid = p[6];
1192                                 st->intsrc.iosv = p[7];
1193                                 st->intsrc.intr = l32get(p + 8);
1194                                 st->intsrc.any = l32get(p + 12);
1195                                 break;
1196                         case ASlx2apic:
1197                                 st->lx2apic.id = l32get(p + 4);
1198                                 st->lx2apic.puid = l32get(p + 12);
1199                                 if (l32get(p + 8) == 0) {
1200                                         kfree(tt);
1201                                         tt = NULL;
1202                                 }
1203                                 break;
1204                         case ASlx2nmi:
1205                                 st->lx2nmi.flags = l16get(p + 2);
1206                                 st->lx2nmi.puid = l32get(p + 4);
1207                                 st->lx2nmi.intr = p[8];
1208                                 break;
1209                         default:
1210                                 printd("unknown APIC structure\n");
1211                                 kfree(tt);
1212                                 tt = NULL;
1213                 }
1214                 if (tt != NULL) {
1215                         finatable_nochildren(tt);
1216                         slice_append(&slice, tt);
1217                 }
1218         }
1219         apics = finatable(t, &slice);
1220
1221         return apics;
1222 }
1223
1224 static struct Atable *parsedmar(struct Atable *parent,
1225                                 char *name, uint8_t *raw, size_t rawsize)
1226 {
1227         struct Atable *t, *tt;
1228         int i;
1229         int baselen = MIN(rawsize, 38);
1230         int nentry, nscope, npath, off, dslen, dhlen, len, type, flags;
1231         void *pathp;
1232         char buf[16];
1233         struct slice drhds;
1234         struct Drhd *drhd;
1235         struct Dmar *dt;
1236
1237         /* count the entries */
1238         for (nentry = 0, off = 48; off < rawsize; nentry++) {
1239                 dslen = l16get(raw + off + 2);
1240                 printk("acpi DMAR: entry %d is addr %p (0x%x/0x%x)\n",
1241                        nentry, raw + off, l16get(raw + off), dslen);
1242                 off = off + dslen;
1243         }
1244         printk("DMAR: %d entries\n", nentry);
1245
1246         t = mkatable(parent, DMAR, name, raw, rawsize, sizeof(*dmar));
1247         dt = t->tbl;
1248         /* The table can be only partly filled. */
1249         if (baselen >= 38 && raw[37] & 1)
1250                 dt->intr_remap = 1;
1251         if (baselen >= 37)
1252                 dt->haw = raw[36] + 1;
1253
1254         /* Now we walk all the DMAR entries. */
1255         slice_init(&drhds);
1256         for (off = 48, i = 0; i < nentry; i++, off += dslen) {
1257                 snprintf(buf, sizeof(buf), "%d", i);
1258                 dslen = l16get(raw + off + 2);
1259                 type = l16get(raw + off);
1260                 // TODO(dcross): Introduce sensible symbolic constants
1261                 // for DMAR entry types. For right now, type 0 => DRHD.
1262                 // We skip everything else.
1263                 if (type != 0)
1264                         continue;
1265                 npath = 0;
1266                 nscope = 0;
1267                 for (int o = off + 16; o < (off + dslen); o += dhlen) {
1268                         nscope++;
1269                         dhlen = *(raw + o + 1); // Single byte length.
1270                         npath += ((dhlen - 6) / 2);
1271                 }
1272                 tt = mkatable(t, DRHD, buf, raw + off, dslen,
1273                               sizeof(struct Drhd) + 2 * npath +
1274                               nscope * sizeof(struct DevScope));
1275                 flags = *(raw + off + 4);
1276                 drhd = tt->tbl;
1277                 drhd->all = flags & 1;
1278                 drhd->segment = l16get(raw + off + 6);
1279                 drhd->rba = l64get(raw + off + 8);
1280                 drhd->nscope = nscope;
1281                 drhd->scopes = (void *)drhd + sizeof(struct Drhd);
1282                 pathp = (void *)drhd +
1283                     sizeof(struct Drhd) + nscope * sizeof(struct DevScope);
1284                 for (int i = 0, o = off + 16; i < nscope; i++) {
1285                         struct DevScope *ds = &drhd->scopes[i];
1286
1287                         dhlen = *(raw + o + 1);
1288                         ds->enumeration_id = *(raw + o + 4);
1289                         ds->start_bus_number = *(raw + o + 5);
1290                         ds->npath = (dhlen - 6) / 2;
1291                         ds->paths = pathp;
1292                         for (int j = 0; j < ds->npath; j++)
1293                                 ds->paths[j] = l16get(raw + o + 6 + 2*j);
1294                         pathp += 2*ds->npath;
1295                         o += dhlen;
1296                 }
1297                 /*
1298                  * NOTE: if all is set, there should be no scopes of type
1299                  * This being ACPI, where vendors randomly copy tables
1300                  * from one system to another, and creating breakage,
1301                  * anything is possible. But we'll warn them.
1302                  */
1303                 finatable_nochildren(tt);
1304                 slice_append(&drhds, tt);
1305         }
1306         dmar = finatable(t, &drhds);
1307
1308         return dmar;
1309 }
1310
1311 /*
1312  * Map the table and keep it there.
1313  */
1314 static struct Atable *parsessdt(struct Atable *parent,
1315                                 char *name, uint8_t *raw, size_t size)
1316 {
1317         struct Atable *t;
1318         struct Sdthdr *h;
1319
1320         /*
1321          * We found it and it is too small.
1322          * Simply return with no side effect.
1323          */
1324         if (size < Sdthdrsz)
1325                 return NULL;
1326         t = mkatable(parent, SSDT, name, raw, size, 0);
1327         h = (struct Sdthdr *)raw;
1328         memmove(t->name, h->sig, sizeof(h->sig));
1329         t->name[sizeof(h->sig)] = '\0';
1330
1331         return finatable_nochildren(t);
1332 }
1333
1334 static char *dumptable(char *start, char *end, char *sig, uint8_t *p, int l)
1335 {
1336         int n, i;
1337
1338         if (2 > 1) {
1339                 start = seprintf(start, end, "%s @ %#p\n", sig, p);
1340                 if (2 > 2)
1341                         n = l;
1342                 else
1343                         n = 256;
1344                 for (i = 0; i < n; i++) {
1345                         if ((i % 16) == 0)
1346                                 start = seprintf(start, end, "%x: ", i);
1347                         start = seprintf(start, end, " %2.2ux", p[i]);
1348                         if ((i % 16) == 15)
1349                                 start = seprintf(start, end, "\n");
1350                 }
1351                 start = seprintf(start, end, "\n");
1352                 start = seprintf(start, end, "\n");
1353         }
1354         return start;
1355 }
1356
1357 static char *seprinttable(char *s, char *e, struct Atable *t)
1358 {
1359         uint8_t *p;
1360         int i, n;
1361
1362         p = (uint8_t *)t->tbl;  /* include header */
1363         n = t->rawsize;
1364         s = seprintf(s, e, "%s @ %#p\n", t->name, p);
1365         for (i = 0; i < n; i++) {
1366                 if ((i % 16) == 0)
1367                         s = seprintf(s, e, "%x: ", i);
1368                 s = seprintf(s, e, " %2.2ux", p[i]);
1369                 if ((i % 16) == 15)
1370                         s = seprintf(s, e, "\n");
1371         }
1372         return seprintf(s, e, "\n\n");
1373 }
1374
1375 static void *rsdsearch(char *signature)
1376 {
1377         uintptr_t p;
1378         uint8_t *bda;
1379         void *rsd;
1380
1381         /*
1382          * Search for the data structure signature:
1383          * 1) in the BIOS ROM between 0xE0000 and 0xFFFFF.
1384          */
1385         return sigscan(KADDR(0xE0000), 0x20000, signature);
1386 }
1387
1388 /*
1389  * Note: some of this comment is from the unfinished user interpreter.
1390  *
1391  * The DSDT is always given to the user interpreter.
1392  * Tables listed here are also loaded from the XSDT:
1393  * MSCT, MADT, and FADT are processed by us, because they are
1394  * required to do early initialization before we have user processes.
1395  * Other tables are given to the user level interpreter for
1396  * execution.
1397  *
1398  * These historically returned a value to tell acpi whether or not it was okay
1399  * to unmap the table.  (return 0 means there was no table, meaning it was okay
1400  * to unmap).  We just use the kernbase mapping, so it's irrelevant.
1401  *
1402  * N.B. The intel source code defines the constants for ACPI in a
1403  * non-endian-independent manner. Rather than bring in the huge wad o' code
1404  * that represents, we just the names.
1405  */
1406 struct Parser {
1407         char *sig;
1408         struct Atable *(*parse)(struct Atable *parent,
1409                                 char *name, uint8_t *raw, size_t rawsize);
1410 };
1411
1412
1413 static struct Parser ptable[] = {
1414         {"FACP", parsefadt},
1415         {"APIC", parsemadt},
1416         {"DMAR", parsedmar},
1417         {"SRAT", parsesrat},
1418         {"SLIT", parseslit},
1419         {"MSCT", parsemsct},
1420         {"SSDT", parsessdt},
1421         {"HPET", parsehpet},
1422 };
1423
1424 /*
1425  * process xsdt table and load tables with sig, or all if NULL.
1426  * (XXX: should be able to search for sig, oemid, oemtblid)
1427  */
1428 static void parsexsdt(struct Atable *root)
1429 {
1430         ERRSTACK(1);
1431         struct Sdthdr *sdt;
1432         struct Atable *table;
1433         struct slice slice;
1434         size_t l, end;
1435         uintptr_t dhpa;
1436         struct Atable *n;
1437         uint8_t *tbl;
1438
1439         slice_init(&slice);
1440         if (waserror()) {
1441                 slice_destroy(&slice);
1442                 return;
1443         }
1444
1445         tbl = xsdt->p + sizeof(struct Sdthdr);
1446         end = xsdt->len - sizeof(struct Sdthdr);
1447         for (int i = 0; i < end; i += xsdt->asize) {
1448                 dhpa = (xsdt->asize == 8) ? l64get(tbl + i) : l32get(tbl + i);
1449                 sdt = sdtmap(dhpa, &l, 1);
1450                 if (sdt == NULL)
1451                         continue;
1452                 printd("acpi: %s addr %#p\n", tsig, sdt);
1453                 for (int j = 0; j < ARRAY_SIZE(ptable); j++) {
1454                         if (memcmp(sdt->sig, ptable[j].sig, sizeof(sdt->sig)) == 0) {
1455                                 table = ptable[j].parse(root, ptable[j].sig, (void *)sdt, l);
1456                                 if (table != NULL)
1457                                         slice_append(&slice, table);
1458                                 break;
1459                         }
1460                 }
1461         }
1462         finatable(root, &slice);
1463 }
1464
1465 void makeindex(struct Atable *root)
1466 {
1467         uint64_t index;
1468
1469         if (root == NULL)
1470                 return;
1471         index = root->qid.path >> QIndexShift;
1472         atableindex[index] = root;
1473         for (int k = 0; k < root->nchildren; k++)
1474                 makeindex(root->children[k]);
1475 }
1476
1477 static void parsersdptr(void)
1478 {
1479         struct Rsdp *rsd;
1480         int asize, cksum;
1481         uintptr_t sdtpa;
1482
1483         static_assert(sizeof(struct Sdthdr) == 36);
1484
1485         /* Find the root pointer. */
1486         rsd = rsdsearch("RSD PTR ");
1487         if (rsd == NULL) {
1488                 printk("NO RSDP\n");
1489                 return;
1490         }
1491
1492         /*
1493          * Initialize the root of ACPI parse tree.
1494          */
1495         lastpath = Qroot;
1496         root = mkatable(NULL, XSDT, devname(), NULL, 0, sizeof(struct Xsdt));
1497         root->parent = root;
1498
1499         printd("/* RSDP */ struct Rsdp = {%08c, %x, %06c, %x, %p, %d, %p, %x}\n",
1500                    rsd->signature, rsd->rchecksum, rsd->oemid, rsd->revision,
1501                    *(uint32_t *)rsd->raddr, *(uint32_t *)rsd->length,
1502                    *(uint32_t *)rsd->xaddr, rsd->xchecksum);
1503
1504         printd("acpi: RSD PTR@ %#p, physaddr $%p length %ud %#llux rev %d\n",
1505                    rsd, l32get(rsd->raddr), l32get(rsd->length),
1506                    l64get(rsd->xaddr), rsd->revision);
1507
1508         if (rsd->revision >= 2) {
1509                 cksum = sdtchecksum(rsd, 36);
1510                 if (cksum != 0) {
1511                         printk("acpi: bad RSD checksum %d, 64 bit parser aborted\n", cksum);
1512                         return;
1513                 }
1514                 sdtpa = l64get(rsd->xaddr);
1515                 asize = 8;
1516         } else {
1517                 cksum = sdtchecksum(rsd, 20);
1518                 if (cksum != 0) {
1519                         printk("acpi: bad RSD checksum %d, 32 bit parser aborted\n", cksum);
1520                         return;
1521                 }
1522                 sdtpa = l32get(rsd->raddr);
1523                 asize = 4;
1524         }
1525
1526         /*
1527          * process the RSDT or XSDT table.
1528          */
1529         xsdt = root->tbl;
1530         xsdt->p = sdtmap(sdtpa, &xsdt->len, 1);
1531         if (xsdt->p == NULL) {
1532                 printk("acpi: sdtmap failed\n");
1533                 return;
1534         }
1535         if ((xsdt->p[0] != 'R' && xsdt->p[0] != 'X')
1536                 || memcmp(xsdt->p + 1, "SDT", 3) != 0) {
1537                 printd("acpi: xsdt sig: %c%c%c%c\n",
1538                        xsdt->p[0], xsdt->p[1], xsdt->p[2], xsdt->p[3]);
1539                 xsdt = NULL;
1540                 return;
1541         }
1542         xsdt->asize = asize;
1543         printd("acpi: XSDT %#p\n", xsdt);
1544         parsexsdt(root);
1545         atableindex = kreallocarray(NULL, lastpath, sizeof(struct Atable *),
1546                                     KMALLOC_WAIT);
1547         assert(atableindex != NULL);
1548         makeindex(root);
1549 }
1550
1551 /*
1552  * The invariant that each level in the tree has an associated
1553  * Atable implies that each chan can be mapped to an Atable.
1554  * The assertions here enforce that invariant.
1555  */
1556 static struct Atable *genatable(struct chan *c)
1557 {
1558         struct Atable *a;
1559         uint64_t ai;
1560
1561         ai = c->qid.path >> QIndexShift;
1562         assert(ai < lastpath);
1563         a = atableindex[ai];
1564         assert(a != NULL);
1565
1566         return a;
1567 }
1568
1569 static int acpigen(struct chan *c, char *name, struct dirtab *tab, int ntab,
1570                                    int i, struct dir *dp)
1571 {
1572         struct Atable *a = genatable(c);
1573
1574         if (i == DEVDOTDOT) {
1575                 assert((c->qid.path & QIndexMask) == Qdir);
1576                 devdir(c, a->parent->qid, a->parent->name, 0, eve, DMDIR|0555, dp);
1577                 return 1;
1578         }
1579         return devgen(c, name, a->cdirs, a->nchildren + NQtypes, i, dp);
1580 }
1581
1582 /*
1583  * Print the contents of the XSDT.
1584  */
1585 static void dumpxsdt(void)
1586 {
1587         printk("xsdt: len = %lu, asize = %lu, p = %p\n",
1588                xsdt->len, xsdt->asize, xsdt->p);
1589 }
1590
1591 static char *dumpGas(char *start, char *end, char *prefix, struct Gas *g)
1592 {
1593         start = seprintf(start, end, "%s", prefix);
1594
1595         switch (g->spc) {
1596                 case Rsysmem:
1597                 case Rsysio:
1598                 case Rembed:
1599                 case Rsmbus:
1600                 case Rcmos:
1601                 case Rpcibar:
1602                 case Ripmi:
1603                         start = seprintf(start, end, "[%s ", regnames[g->spc]);
1604                         break;
1605                 case Rpcicfg:
1606                         start = seprintf(start, end, "[pci ");
1607                         start =
1608                                 seprintf(start, end, "dev %#p ",
1609                                                  (uint32_t)(g->addr >> 32) & 0xFFFF);
1610                         start =
1611                                 seprintf(start, end, "fn %#p ",
1612                                                  (uint32_t)(g->addr & 0xFFFF0000) >> 16);
1613                         start =
1614                                 seprintf(start, end, "adr %#p ", (uint32_t)(g->addr & 0xFFFF));
1615                         break;
1616                 case Rfixedhw:
1617                         start = seprintf(start, end, "[hw ");
1618                         break;
1619                 default:
1620                         start = seprintf(start, end, "[spc=%#p ", g->spc);
1621         }
1622         start = seprintf(start, end, "off %d len %d addr %#p sz%d]",
1623                                          g->off, g->len, g->addr, g->accsz);
1624         start = seprintf(start, end, "\n");
1625         return start;
1626 }
1627
1628 static unsigned int getbanked(uintptr_t ra, uintptr_t rb, int sz)
1629 {
1630         unsigned int r;
1631
1632         r = 0;
1633         switch (sz) {
1634                 case 1:
1635                         if (ra != 0)
1636                                 r |= inb(ra);
1637                         if (rb != 0)
1638                                 r |= inb(rb);
1639                         break;
1640                 case 2:
1641                         if (ra != 0)
1642                                 r |= inw(ra);
1643                         if (rb != 0)
1644                                 r |= inw(rb);
1645                         break;
1646                 case 4:
1647                         if (ra != 0)
1648                                 r |= inl(ra);
1649                         if (rb != 0)
1650                                 r |= inl(rb);
1651                         break;
1652                 default:
1653                         printd("getbanked: wrong size\n");
1654         }
1655         return r;
1656 }
1657
1658 static unsigned int setbanked(uintptr_t ra, uintptr_t rb, int sz, int v)
1659 {
1660         unsigned int r;
1661
1662         r = -1;
1663         switch (sz) {
1664                 case 1:
1665                         if (ra != 0)
1666                                 outb(ra, v);
1667                         if (rb != 0)
1668                                 outb(rb, v);
1669                         break;
1670                 case 2:
1671                         if (ra != 0)
1672                                 outw(ra, v);
1673                         if (rb != 0)
1674                                 outw(rb, v);
1675                         break;
1676                 case 4:
1677                         if (ra != 0)
1678                                 outl(ra, v);
1679                         if (rb != 0)
1680                                 outl(rb, v);
1681                         break;
1682                 default:
1683                         printd("setbanked: wrong size\n");
1684         }
1685         return r;
1686 }
1687
1688 static unsigned int getpm1ctl(void)
1689 {
1690         assert(fadt != NULL);
1691         return getbanked(fadt->pm1acntblk, fadt->pm1bcntblk, fadt->pm1cntlen);
1692 }
1693
1694 static void setpm1sts(unsigned int v)
1695 {
1696         assert(fadt != NULL);
1697         setbanked(fadt->pm1aevtblk, fadt->pm1bevtblk, fadt->pm1evtlen / 2, v);
1698 }
1699
1700 static unsigned int getpm1sts(void)
1701 {
1702         assert(fadt != NULL);
1703         return getbanked(fadt->pm1aevtblk, fadt->pm1bevtblk, fadt->pm1evtlen / 2);
1704 }
1705
1706 static unsigned int getpm1en(void)
1707 {
1708         int sz;
1709
1710         assert(fadt != NULL);
1711         sz = fadt->pm1evtlen / 2;
1712         return getbanked(fadt->pm1aevtblk + sz, fadt->pm1bevtblk + sz, sz);
1713 }
1714
1715 static int getgpeen(int n)
1716 {
1717         return inb(gpes[n].enio) & 1 << gpes[n].enbit;
1718 }
1719
1720 static void setgpeen(int n, unsigned int v)
1721 {
1722         int old;
1723
1724         old = inb(gpes[n].enio);
1725         if (v)
1726                 outb(gpes[n].enio, old | 1 << gpes[n].enbit);
1727         else
1728                 outb(gpes[n].enio, old & ~(1 << gpes[n].enbit));
1729 }
1730
1731 static void clrgpests(int n)
1732 {
1733         outb(gpes[n].stsio, 1 << gpes[n].stsbit);
1734 }
1735
1736 static unsigned int getgpests(int n)
1737 {
1738         return inb(gpes[n].stsio) & 1 << gpes[n].stsbit;
1739 }
1740
1741 #if 0
1742 static void acpiintr(Ureg *, void *)
1743 {
1744         int i;
1745         unsigned int sts, en;
1746
1747         printd("acpi: intr\n");
1748
1749         for (i = 0; i < ngpes; i++)
1750                 if (getgpests(i)) {
1751                         printd("gpe %d on\n", i);
1752                         en = getgpeen(i);
1753                         setgpeen(i, 0);
1754                         clrgpests(i);
1755                         if (en != 0)
1756                                 printd("acpiitr: calling gpe %d\n", i);
1757                         //  queue gpe for calling gpe->ho in the
1758                         //  aml process.
1759                         //  enable it again when it returns.
1760                 }
1761         sts = getpm1sts();
1762         en = getpm1en();
1763         printd("acpiitr: pm1sts %#p pm1en %#p\n", sts, en);
1764         if (sts & en)
1765                 printd("have enabled events\n");
1766         if (sts & 1)
1767                 printd("power button\n");
1768         // XXX serve other interrupts here.
1769         setpm1sts(sts);
1770 }
1771 #endif
1772
1773 static void initgpes(void)
1774 {
1775         int i, n0, n1;
1776
1777         assert(fadt != NULL);
1778         n0 = fadt->gpe0blklen / 2;
1779         n1 = fadt->gpe1blklen / 2;
1780         ngpes = n0 + n1;
1781         gpes = kzmalloc(sizeof(struct Gpe) * ngpes, 1);
1782         for (i = 0; i < n0; i++) {
1783                 gpes[i].nb = i;
1784                 gpes[i].stsbit = i & 7;
1785                 gpes[i].stsio = fadt->gpe0blk + (i >> 3);
1786                 gpes[i].enbit = (n0 + i) & 7;
1787                 gpes[i].enio = fadt->gpe0blk + ((n0 + i) >> 3);
1788         }
1789         for (i = 0; i + n0 < ngpes; i++) {
1790                 gpes[i + n0].nb = fadt->gp1base + i;
1791                 gpes[i + n0].stsbit = i & 7;
1792                 gpes[i + n0].stsio = fadt->gpe1blk + (i >> 3);
1793                 gpes[i + n0].enbit = (n1 + i) & 7;
1794                 gpes[i + n0].enio = fadt->gpe1blk + ((n1 + i) >> 3);
1795         }
1796         for (i = 0; i < ngpes; i++) {
1797                 setgpeen(i, 0);
1798                 clrgpests(i);
1799         }
1800 }
1801
1802 static void acpiioalloc(unsigned int addr, int len)
1803 {
1804         if (addr != 0)
1805                 printd("Just TAKING port %016lx to %016lx\n", addr, addr + len);
1806 }
1807
1808 static void acpiinitonce(void)
1809 {
1810         parsersdptr();
1811         if (root != NULL)
1812                 printk("ACPI initialized\n");
1813 }
1814
1815 int acpiinit(void)
1816 {
1817         run_once(acpiinitonce());
1818         return (root == NULL) ? -1 : 0;
1819 }
1820
1821 static struct chan *acpiattach(char *spec)
1822 {
1823         int i;
1824         struct chan *c;
1825         /*
1826          * This was written for the stock kernel.
1827          * This code must use 64 registers to be acpi ready in nix.
1828          */
1829         if (acpiinit() < 0)
1830                 error(ENOSYS, "no acpi");
1831
1832         /*
1833          * should use fadt->xpm* and fadt->xgpe* registers for 64 bits.
1834          * We are not ready in this kernel for that.
1835          */
1836         assert(fadt != NULL);
1837         acpiioalloc(fadt->smicmd, 1);
1838         acpiioalloc(fadt->pm1aevtblk, fadt->pm1evtlen);
1839         acpiioalloc(fadt->pm1bevtblk, fadt->pm1evtlen);
1840         acpiioalloc(fadt->pm1acntblk, fadt->pm1cntlen);
1841         acpiioalloc(fadt->pm1bcntblk, fadt->pm1cntlen);
1842         acpiioalloc(fadt->pm2cntblk, fadt->pm2cntlen);
1843         acpiioalloc(fadt->pmtmrblk, fadt->pmtmrlen);
1844         acpiioalloc(fadt->gpe0blk, fadt->gpe0blklen);
1845         acpiioalloc(fadt->gpe1blk, fadt->gpe1blklen);
1846
1847         initgpes();
1848 #ifdef RON_SAYS_CONFIG_WE_ARE_NOT_WORTHY
1849         /* this is frightening. SMI: just say no. Although we will almost
1850          * certainly find that we have no choice.
1851          *
1852          * This starts ACPI, which may require we handle
1853          * power mgmt events ourselves. Use with care.
1854          */
1855         outb(fadt->smicmd, fadt->acpienable);
1856         for (i = 0; i < 10; i++)
1857                 if (getpm1ctl() & Pm1SciEn)
1858                         break;
1859         if (i == 10)
1860                 error(EFAIL, "acpi: failed to enable\n");
1861         if (fadt->sciint != 0)
1862                 intrenable(fadt->sciint, acpiintr, 0, BUSUNKNOWN, "acpi");
1863 #endif
1864         c = devattach(devname(), spec);
1865
1866         return c;
1867 }
1868
1869 static struct walkqid *acpiwalk(struct chan *c, struct chan *nc, char **name,
1870                                                                 int nname)
1871 {
1872         /*
1873          * Note that devwalk hard-codes a test against the location of 'devgen',
1874          * so we pretty much have to not pass it here.
1875          */
1876         return devwalk(c, nc, name, nname, NULL, 0, acpigen);
1877 }
1878
1879 static int acpistat(struct chan *c, uint8_t *dp, int n)
1880 {
1881         struct Atable *a = genatable(c);
1882
1883         if (c->qid.type == QTDIR)
1884                 a = a->parent;
1885         assert(a != NULL);
1886
1887         /* TODO(dcross): make acpigen work here. */
1888         return devstat(c, dp, n, a->cdirs, a->nchildren + NQtypes, devgen);
1889 }
1890
1891 static struct chan *acpiopen(struct chan *c, int omode)
1892 {
1893         return devopen(c, omode, NULL, 0, acpigen);
1894 }
1895
1896 static void acpiclose(struct chan *unused)
1897 {
1898 }
1899
1900 static char *ttext;
1901 static int tlen;
1902
1903 // Get the table from the qid.
1904 // Read that one table using the pointers.
1905 static long acpiread(struct chan *c, void *a, long n, int64_t off)
1906 {
1907         long q;
1908         struct Atable *t;
1909         char *ns, *s, *e, *ntext;
1910
1911         if (ttext == NULL) {
1912                 tlen = 32768;
1913                 ttext = kzmalloc(tlen, 0);
1914         }
1915         if (ttext == NULL)
1916                 error(ENOMEM, "acpiread: no memory");
1917         q = c->qid.path & QIndexMask;
1918         switch (q) {
1919         case Qdir:
1920                 return devdirread(c, a, n, NULL, 0, acpigen);
1921         case Qraw:
1922                 return readmem(off, a, n, ttext, tlen);
1923         case Qtbl:
1924                 s = ttext;
1925                 e = ttext + tlen;
1926                 strlcpy(s, "no tables\n", tlen);
1927                 for (t = tfirst; t != NULL; t = t->next) {
1928                         ns = seprinttable(s, e, t);
1929                         while (ns == e - 1) {
1930                                 ntext = krealloc(ttext, tlen * 2, 0);
1931                                 if (ntext == NULL)
1932                                         panic("acpi: no memory\n");
1933                                 s = ntext + (ttext - s);
1934                                 ttext = ntext;
1935                                 tlen *= 2;
1936                                 e = ttext + tlen;
1937                                 ns = seprinttable(s, e, t);
1938                         }
1939                         s = ns;
1940                 }
1941                 return readstr(off, a, n, ttext);
1942         case Qpretty:
1943                 s = ttext;
1944                 e = ttext + tlen;
1945                 s = dumpfadt(s, e, fadt);
1946                 s = dumpmadt(s, e, apics);
1947                 s = dumpslit(s, e, slit);
1948                 s = dumpsrat(s, e, srat);
1949                 s = dumpdmar(s, e, dmar);
1950                 dumpmsct(s, e, mscttbl);
1951                 return readstr(off, a, n, ttext);
1952         default:
1953                 error(EINVAL, "acpiread: bad path %d\n", q);
1954         }
1955         error(EPERM, ERROR_FIXME);
1956
1957         return -1;
1958 }
1959
1960 static long acpiwrite(struct chan *c, void *a, long n, int64_t off)
1961 {
1962         error(EFAIL, "acpiwrite: not until we can figure out what it's for");
1963 #if 0
1964         ERRSTACK(2);
1965         struct cmdtab *ct;
1966         struct cmdbuf *cb;
1967         struct Reg *r;
1968         unsigned int rno, fun, dev, bus, i;
1969
1970         if (c->qid.path == Qio) {
1971                 if (reg == NULL)
1972                         error(EFAIL, "region not configured");
1973                 return regio(reg, a, n, off, 1);
1974         }
1975         if (c->qid.path != Qctl)
1976                 error(EPERM, ERROR_FIXME);
1977
1978         cb = parsecmd(a, n);
1979         if (waserror()) {
1980                 kfree(cb);
1981                 nexterror();
1982         }
1983         ct = lookupcmd(cb, ctls, ARRAY_SIZE(ctls));
1984         switch (ct->index) {
1985                 case CMregion:
1986                         /* TODO: this block is racy on reg (global) */
1987                         r = reg;
1988                         if (r == NULL) {
1989                                 r = kzmalloc(sizeof(struct Reg), 0);
1990                                 r->name = NULL;
1991                         }
1992                         kstrdup(&r->name, cb->f[1]);
1993                         r->spc = acpiregid(cb->f[2]);
1994                         if (r->spc < 0) {
1995                                 kfree(r);
1996                                 reg = NULL;
1997                                 error(EFAIL, "bad region type");
1998                         }
1999                         if (r->spc == Rpcicfg || r->spc == Rpcibar) {
2000                                 rno = r->base >> Rpciregshift & Rpciregmask;
2001                                 fun = r->base >> Rpcifunshift & Rpcifunmask;
2002                                 dev = r->base >> Rpcidevshift & Rpcidevmask;
2003                                 bus = r->base >> Rpcibusshift & Rpcibusmask;
2004 #ifdef CONFIG_X86
2005                                 r->tbdf = MKBUS(BusPCI, bus, dev, fun);
2006 #else
2007                                 r->tbdf = 0
2008 #endif
2009                                 r->base = rno;  /* register ~ our base addr */
2010                         }
2011                         r->base = strtoul(cb->f[3], NULL, 0);
2012                         r->len = strtoul(cb->f[4], NULL, 0);
2013                         r->accsz = strtoul(cb->f[5], NULL, 0);
2014                         if (r->accsz < 1 || r->accsz > 4) {
2015                                 kfree(r);
2016                                 reg = NULL;
2017                                 error(EFAIL, "bad region access size");
2018                         }
2019                         reg = r;
2020                         printd("region %s %s %p %p sz%d",
2021                                    r->name, acpiregstr(r->spc), r->base, r->len, r->accsz);
2022                         break;
2023                 case CMgpe:
2024                         i = strtoul(cb->f[1], NULL, 0);
2025                         if (i >= ngpes)
2026                                 error(ERANGE, "gpe out of range");
2027                         kstrdup(&gpes[i].obj, cb->f[2]);
2028                         setgpeen(i, 1);
2029                         break;
2030                 default:
2031                         panic("acpi: unknown ctl");
2032         }
2033         poperror();
2034         kfree(cb);
2035         return n;
2036 #endif
2037 }
2038
2039 struct {
2040         char *(*pretty)(struct Atable *atbl, char *start, char *end, void *arg);
2041 } acpisw[NACPITBLS] = {
2042 };
2043
2044 static char *pretty(struct Atable *atbl, char *start, char *end, void *arg)
2045 {
2046         int type;
2047
2048         type = atbl->type;
2049         if (type < 0 || NACPITBLS < type)
2050                 return start;
2051         if (acpisw[type].pretty == NULL)
2052                 return seprintf(start, end, "\"\"\n");
2053         return acpisw[type].pretty(atbl, start, end, arg);
2054 }
2055
2056 static char *raw(struct Atable *atbl, char *start, char *end, void *unused_arg)
2057 {
2058         size_t len = MIN(end - start, atbl->rawsize);
2059
2060         memmove(start, atbl->raw, len);
2061
2062         return start + len;
2063 }
2064
2065 struct dev acpidevtab __devtab = {
2066         .name = "acpi",
2067
2068         .reset = devreset,
2069         .init = devinit,
2070         .shutdown = devshutdown,
2071         .attach = acpiattach,
2072         .walk = acpiwalk,
2073         .stat = acpistat,
2074         .open = acpiopen,
2075         .create = devcreate,
2076         .close = acpiclose,
2077         .read = acpiread,
2078         .bread = devbread,
2079         .write = acpiwrite,
2080         .bwrite = devbwrite,
2081         .remove = devremove,
2082         .wstat = devwstat,
2083 };