65de22538ed12a07c9c8f9a30b4e464d03977759
[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 <acpi.h>
24
25 #include "../timers/hpet.h"
26
27 #ifdef CONFIG_X86
28 #include <arch/pci.h>
29 #endif
30
31 struct dev acpidevtab;
32
33 static char *devname(void)
34 {
35         return acpidevtab.name;
36 }
37
38 /*
39  * ACPI 4.0 Support.
40  * Still WIP.
41  *
42  * This driver locates tables and parses only the FADT
43  * and the XSDT. All other tables are mapped and kept there
44  * for the user-level interpreter.
45  */
46
47 static struct Atable *acpifadt(uint8_t *, int);
48 static struct Atable *acpitable(uint8_t *, int);
49 static struct Atable *acpimadt(uint8_t *, int);
50 static struct Atable *acpimsct(uint8_t *, int);
51 static struct Atable *acpisrat(uint8_t *, int);
52 static struct Atable *acpislit(uint8_t *, int);
53
54 static struct cmdtab ctls[] = {
55         {CMregion, "region", 6},
56         {CMgpe, "gpe", 3},
57 };
58
59 static struct dirtab acpidir[] = {
60         {".", {Qdir, 0, QTDIR}, 0, DMDIR | 0555},
61         {"acpictl", {Qctl}, 0, 0666},
62         {"acpitbl", {Qtbl}, 0, 0444},
63         {"acpiregio", {Qio}, 0, 0666},
64         {"acpipretty", {Qpretty}, 0, 0444},
65         {"ioapic", {Qioapic}, 0, 0444},
66         {"apic", {Qapic}, 0, 0444},
67 };
68
69 /*
70  * The DSDT is always given to the user interpreter.
71  * Tables listed here are also loaded from the XSDT:
72  * MSCT, MADT, and FADT are processed by us, because they are
73  * required to do early initialization before we have user processes.
74  * Other tables are given to the user level interpreter for
75  * execution.
76  *
77  * These historically returned a value to tell acpi whether or not it was okay
78  * to unmap the table.  (return 0 means there was no table, meaning it was okay
79  * to unmap).  We just use the kernbase mapping, so it's irrelevant. */
80 static struct Parse ptables[] = {
81         {"FACP", acpifadt},
82         {"APIC", acpimadt,},
83         {"SRAT", acpisrat,},
84         {"SLIT", acpislit,},
85         {"MSCT", acpimsct,},
86         {"SSDT", acpitable,},
87         {"HPET", acpihpet,},
88 };
89
90 static struct Facs *facs;               /* Firmware ACPI control structure */
91 static struct Fadt fadt;                /* Fixed ACPI description. To reach ACPI registers */
92 static struct Xsdt *xsdt;               /* XSDT table */
93 static struct Atable *tfirst;   /* loaded DSDT/SSDT/... tables */
94 static struct Atable *tlast;    /* pointer to last table */
95 struct Madt *apics;                             /* APIC info */
96 struct Srat *srat;                              /* System resource affinity, used by physalloc */
97 static struct Slit *slit;               /* System locality information table used by the scheduler */
98 static struct Msct *msct;               /* Maximum system characteristics table */
99 static struct Reg *reg;                 /* region used for I/O */
100 static struct Gpe *gpes;                /* General purpose events */
101 static int ngpes;
102
103 static char *regnames[] = {
104         "mem", "io", "pcicfg", "embed",
105         "smb", "cmos", "pcibar",
106 };
107
108 static char *dumpGas(char *start, char *end, char *prefix, struct Gas *g);
109
110 static char *acpiregstr(int id)
111 {
112         static char buf[20];            /* BUG */
113
114         if (id >= 0 && id < ARRAY_SIZE(regnames)) {
115                 return regnames[id];
116         }
117         seprintf(buf, buf + sizeof(buf), "spc:%#x", id);
118         return buf;
119 }
120
121 static int acpiregid(char *s)
122 {
123         int i;
124
125         for (i = 0; i < ARRAY_SIZE(regnames); i++)
126                 if (strcmp(regnames[i], s) == 0) {
127                         return i;
128                 }
129         return -1;
130 }
131
132 static uint8_t mget8(uintptr_t p, void *unused)
133 {
134         uint8_t *cp = (uint8_t *) p;
135         return *cp;
136 }
137
138 static void mset8(uintptr_t p, uint8_t v, void *unused)
139 {
140         uint8_t *cp = (uint8_t *) p;
141         *cp = v;
142 }
143
144 static uint16_t mget16(uintptr_t p, void *unused)
145 {
146         uint16_t *cp = (uint16_t *) p;
147         return *cp;
148 }
149
150 static void mset16(uintptr_t p, uint16_t v, void *unused)
151 {
152         uint16_t *cp = (uint16_t *) p;
153         *cp = v;
154 }
155
156 static uint32_t mget32(uintptr_t p, void *unused)
157 {
158         uint32_t *cp = (uint32_t *) p;
159         return *cp;
160 }
161
162 static void mset32(uintptr_t p, uint32_t v, void *unused)
163 {
164         uint32_t *cp = (uint32_t *) p;
165         *cp = v;
166 }
167
168 static uint64_t mget64(uintptr_t p, void *unused)
169 {
170         uint64_t *cp = (uint64_t *) p;
171         return *cp;
172 }
173
174 static void mset64(uintptr_t p, uint64_t v, void *unused)
175 {
176         uint64_t *cp = (uint64_t *) p;
177         *cp = v;
178 }
179
180 static uint8_t ioget8(uintptr_t p, void *unused)
181 {
182         return inb(p);
183 }
184
185 static void ioset8(uintptr_t p, uint8_t v, void *unused)
186 {
187         outb(p, v);
188 }
189
190 static uint16_t ioget16(uintptr_t p, void *unused)
191 {
192         return inw(p);
193 }
194
195 static void ioset16(uintptr_t p, uint16_t v, void *unused)
196 {
197         outw(p, v);
198 }
199
200 static uint32_t ioget32(uintptr_t p, void *unused)
201 {
202         return inl(p);
203 }
204
205 static void ioset32(uintptr_t p, uint32_t v, void *unused)
206 {
207         outl(p, v);
208 }
209
210 /* TODO: these cfgs are hacky.  maybe all the struct Reg should have struct
211  * pci_device or something? */
212 static uint8_t cfgget8(uintptr_t p, void *r)
213 {
214         struct Reg *ro = r;
215         struct pci_device pcidev;
216
217         explode_tbdf(ro->tbdf);
218         return pcidev_read8(&pcidev, p);
219 }
220
221 static void cfgset8(uintptr_t p, uint8_t v, void *r)
222 {
223         struct Reg *ro = r;
224         struct pci_device pcidev;
225
226         explode_tbdf(ro->tbdf);
227         pcidev_write8(&pcidev, p, v);
228 }
229
230 static uint16_t cfgget16(uintptr_t p, void *r)
231 {
232         struct Reg *ro = r;
233         struct pci_device pcidev;
234
235         explode_tbdf(ro->tbdf);
236         return pcidev_read16(&pcidev, p);
237 }
238
239 static void cfgset16(uintptr_t p, uint16_t v, void *r)
240 {
241         struct Reg *ro = r;
242         struct pci_device pcidev;
243
244         explode_tbdf(ro->tbdf);
245         pcidev_write16(&pcidev, p, v);
246 }
247
248 static uint32_t cfgget32(uintptr_t p, void *r)
249 {
250         struct Reg *ro = r;
251         struct pci_device pcidev;
252
253         explode_tbdf(ro->tbdf);
254         return pcidev_read32(&pcidev, p);
255 }
256
257 static void cfgset32(uintptr_t p, uint32_t v, void *r)
258 {
259         struct Reg *ro = r;
260         struct pci_device pcidev;
261
262         explode_tbdf(ro->tbdf);
263         pcidev_write32(&pcidev, p, v);
264 }
265
266 static struct Regio memio = {
267         NULL,
268         mget8, mset8, mget16, mset16,
269         mget32, mset32, mget64, mset64
270 };
271
272 static struct Regio ioio = {
273         NULL,
274         ioget8, ioset8, ioget16, ioset16,
275         ioget32, ioset32, NULL, NULL
276 };
277
278 static struct Regio cfgio = {
279         NULL,
280         cfgget8, cfgset8, cfgget16, cfgset16,
281         cfgget32, cfgset32, NULL, NULL
282 };
283
284 /*
285  * Copy memory, 1/2/4/8-bytes at a time, to/from a region.
286  */
287 static long
288 regcpy(struct Regio *dio, uintptr_t da, struct Regio *sio,
289            uintptr_t sa, long len, int align)
290 {
291         int n, i;
292
293         printd("regcpy %#p %#p %#p %#p\n", da, sa, len, align);
294         if ((len % align) != 0)
295                 printd("regcpy: bug: copy not aligned. truncated\n");
296         n = len / align;
297         for (i = 0; i < n; i++) {
298                 switch (align) {
299                         case 1:
300                                 printd("cpy8 %#p %#p\n", da, sa);
301                                 dio->set8(da, sio->get8(sa, sio->arg), dio->arg);
302                                 break;
303                         case 2:
304                                 printd("cpy16 %#p %#p\n", da, sa);
305                                 dio->set16(da, sio->get16(sa, sio->arg), dio->arg);
306                                 break;
307                         case 4:
308                                 printd("cpy32 %#p %#p\n", da, sa);
309                                 dio->set32(da, sio->get32(sa, sio->arg), dio->arg);
310                                 break;
311                         case 8:
312                                 printd("cpy64 %#p %#p\n", da, sa);
313                                 warn("Not doing set64 for some reason, fix me!");
314                                 //  dio->set64(da, sio->get64(sa, sio->arg), dio->arg);
315                                 break;
316                         default:
317                                 panic("regcpy: align bug");
318                 }
319                 da += align;
320                 sa += align;
321         }
322         return n * align;
323 }
324
325 /*
326  * Perform I/O within region in access units of accsz bytes.
327  * All units in bytes.
328  */
329 static long regio(struct Reg *r, void *p, uint32_t len, uintptr_t off, int iswr)
330 {
331         struct Regio rio;
332         uintptr_t rp;
333
334         printd("reg%s %s %#p %#p %#lx sz=%d\n",
335                    iswr ? "out" : "in", r->name, p, off, len, r->accsz);
336         rp = 0;
337         if (off + len > r->len) {
338                 printd("regio: access outside limits");
339                 len = r->len - off;
340         }
341         if (len <= 0) {
342                 printd("regio: zero len\n");
343                 return 0;
344         }
345         switch (r->spc) {
346                 case Rsysmem:
347                         if (r->p == NULL)
348                                 r->p = KADDR_NOCHECK(r->base);
349                         if (r->p == NULL)
350                                 error("regio: vmap/KADDR failed");
351                         rp = (uintptr_t) r->p + off;
352                         rio = memio;
353                         break;
354                 case Rsysio:
355                         rp = r->base + off;
356                         rio = ioio;
357                         break;
358                 case Rpcicfg:
359                         rp = r->base + off;
360                         rio = cfgio;
361                         rio.arg = r;
362                         break;
363                 case Rpcibar:
364                 case Rembed:
365                 case Rsmbus:
366                 case Rcmos:
367                 case Ripmi:
368                 case Rfixedhw:
369                         printd("regio: reg %s not supported\n", acpiregstr(r->spc));
370                         error("region not supported");
371         }
372         if (iswr)
373                 regcpy(&rio, rp, &memio, (uintptr_t) p, len, r->accsz);
374         else
375                 regcpy(&memio, (uintptr_t) p, &rio, rp, len, r->accsz);
376         return len;
377 }
378
379 struct Atable *new_acpi_table(uint8_t * p)
380 {
381         struct Atable *t;
382         struct Sdthdr *h;
383
384         t = kzmalloc(sizeof(struct Atable), 0);
385         if (t == NULL)
386                 panic("no memory for more aml tables");
387         t->tbl = p;
388         h = (struct Sdthdr *)t->tbl;
389         t->is64 = h->rev >= 2;
390         t->dlen = l32get(h->length) - Sdthdrsz;
391         memmove(t->sig, h->sig, sizeof(h->sig));
392         t->sig[sizeof(t->sig) - 1] = 0;
393         memmove(t->oemid, h->oemid, sizeof(h->oemid));
394         t->oemtblid[sizeof(t->oemtblid) - 1] = 0;
395         memmove(t->oemtblid, h->oemtblid, sizeof(h->oemtblid));
396         t->oemtblid[sizeof(t->oemtblid) - 1] = 0;
397         t->next = NULL;
398         if (tfirst == NULL)
399                 tfirst = tlast = t;
400         else {
401                 tlast->next = t;
402                 tlast = t;
403         }
404         return t;
405 }
406
407 static void *sdtchecksum(void *addr, int len)
408 {
409         uint8_t *p, sum;
410
411         sum = 0;
412         for (p = addr; len-- > 0; p++)
413                 sum += *p;
414         if (sum == 0) {
415                 return addr;
416         }
417
418         return NULL;
419 }
420
421 static void *sdtmap(uintptr_t pa, int *n, int cksum)
422 {
423         struct Sdthdr *sdt;
424
425         if (!pa) {
426                 printk("sdtmap: NULL pa\n");
427                 return NULL;
428         }
429         sdt = KADDR_NOCHECK(pa);
430         if (sdt == NULL) {
431                 printk("acpi: vmap1: NULL\n");
432                 return NULL;
433         }
434         *n = l32get(sdt->length);
435         if (!*n) {
436                 printk("sdt has zero length!\n");
437                 return NULL;
438         }
439         if ((sdt = KADDR_NOCHECK(pa)) == NULL) {
440                 printk("acpi: NULL vmap\n");
441                 return NULL;
442         }
443         if (cksum != 0 && sdtchecksum(sdt, *n) == NULL) {
444                 printk("acpi: SDT: bad checksum\n");
445                 return NULL;
446         }
447         return sdt;
448 }
449
450 static int loadfacs(uintptr_t pa)
451 {
452         int n;
453
454         facs = sdtmap(pa, &n, 0);
455         if (facs == NULL) {
456                 return -1;
457         }
458         if (memcmp(facs, "FACS", 4) != 0) {
459                 facs = NULL;
460                 return -1;
461         }
462         /* no unmap */
463
464         printd("acpi: facs: hwsig: %#p\n", facs->hwsig);
465         printd("acpi: facs: wakingv: %#p\n", facs->wakingv);
466         printd("acpi: facs: flags: %#p\n", facs->flags);
467         printd("acpi: facs: glock: %#p\n", facs->glock);
468         printd("acpi: facs: xwakingv: %#p\n", facs->xwakingv);
469         printd("acpi: facs: vers: %#p\n", facs->vers);
470         printd("acpi: facs: ospmflags: %#p\n", facs->ospmflags);
471         return 0;
472 }
473
474 static void loaddsdt(uintptr_t pa)
475 {
476         int n;
477         uint8_t *dsdtp;
478
479         dsdtp = sdtmap(pa, &n, 1);
480         if (dsdtp == NULL) {
481                 return;
482         }
483 }
484
485 static void gasget(struct Gas *gas, uint8_t * p)
486 {
487         gas->spc = p[0];
488         gas->len = p[1];
489         gas->off = p[2];
490         gas->accsz = p[3];
491         gas->addr = l64get(p + 4);
492 }
493
494 static char *dumpfadt(char *start, char *end, struct Fadt *fp)
495 {
496         if (2 == 0) {
497                 return NULL;
498         }
499
500         start = seprintf(start, end, "acpi: fadt: facs: $%p\n", fp->facs);
501         start = seprintf(start, end, "acpi: fadt: dsdt: $%p\n", fp->dsdt);
502         start = seprintf(start, end, "acpi: fadt: pmprofile: $%p\n", fp->pmprofile);
503         start = seprintf(start, end, "acpi: fadt: sciint: $%p\n", fp->sciint);
504         start = seprintf(start, end, "acpi: fadt: smicmd: $%p\n", fp->smicmd);
505         start =
506                 seprintf(start, end, "acpi: fadt: acpienable: $%p\n", fp->acpienable);
507         start =
508                 seprintf(start, end, "acpi: fadt: acpidisable: $%p\n", fp->acpidisable);
509         start = seprintf(start, end, "acpi: fadt: s4biosreq: $%p\n", fp->s4biosreq);
510         start = seprintf(start, end, "acpi: fadt: pstatecnt: $%p\n", fp->pstatecnt);
511         start =
512                 seprintf(start, end, "acpi: fadt: pm1aevtblk: $%p\n", fp->pm1aevtblk);
513         start =
514                 seprintf(start, end, "acpi: fadt: pm1bevtblk: $%p\n", fp->pm1bevtblk);
515         start =
516                 seprintf(start, end, "acpi: fadt: pm1acntblk: $%p\n", fp->pm1acntblk);
517         start =
518                 seprintf(start, end, "acpi: fadt: pm1bcntblk: $%p\n", fp->pm1bcntblk);
519         start = seprintf(start, end, "acpi: fadt: pm2cntblk: $%p\n", fp->pm2cntblk);
520         start = seprintf(start, end, "acpi: fadt: pmtmrblk: $%p\n", fp->pmtmrblk);
521         start = seprintf(start, end, "acpi: fadt: gpe0blk: $%p\n", fp->gpe0blk);
522         start = seprintf(start, end, "acpi: fadt: gpe1blk: $%p\n", fp->gpe1blk);
523         start = seprintf(start, end, "acpi: fadt: pm1evtlen: $%p\n", fp->pm1evtlen);
524         start = seprintf(start, end, "acpi: fadt: pm1cntlen: $%p\n", fp->pm1cntlen);
525         start = seprintf(start, end, "acpi: fadt: pm2cntlen: $%p\n", fp->pm2cntlen);
526         start = seprintf(start, end, "acpi: fadt: pmtmrlen: $%p\n", fp->pmtmrlen);
527         start =
528                 seprintf(start, end, "acpi: fadt: gpe0blklen: $%p\n", fp->gpe0blklen);
529         start =
530                 seprintf(start, end, "acpi: fadt: gpe1blklen: $%p\n", fp->gpe1blklen);
531         start = seprintf(start, end, "acpi: fadt: gp1base: $%p\n", fp->gp1base);
532         start = seprintf(start, end, "acpi: fadt: cstcnt: $%p\n", fp->cstcnt);
533         start = seprintf(start, end, "acpi: fadt: plvl2lat: $%p\n", fp->plvl2lat);
534         start = seprintf(start, end, "acpi: fadt: plvl3lat: $%p\n", fp->plvl3lat);
535         start = seprintf(start, end, "acpi: fadt: flushsz: $%p\n", fp->flushsz);
536         start =
537                 seprintf(start, end, "acpi: fadt: flushstride: $%p\n", fp->flushstride);
538         start = seprintf(start, end, "acpi: fadt: dutyoff: $%p\n", fp->dutyoff);
539         start = seprintf(start, end, "acpi: fadt: dutywidth: $%p\n", fp->dutywidth);
540         start = seprintf(start, end, "acpi: fadt: dayalrm: $%p\n", fp->dayalrm);
541         start = seprintf(start, end, "acpi: fadt: monalrm: $%p\n", fp->monalrm);
542         start = seprintf(start, end, "acpi: fadt: century: $%p\n", fp->century);
543         start =
544                 seprintf(start, end, "acpi: fadt: iapcbootarch: $%p\n",
545                                  fp->iapcbootarch);
546         start = seprintf(start, end, "acpi: fadt: flags: $%p\n", fp->flags);
547         start = dumpGas(start, end, "acpi: fadt: resetreg: ", &fp->resetreg);
548         start = seprintf(start, end, "acpi: fadt: resetval: $%p\n", fp->resetval);
549         start = seprintf(start, end, "acpi: fadt: xfacs: %p\n", fp->xfacs);
550         start = seprintf(start, end, "acpi: fadt: xdsdt: %p\n", fp->xdsdt);
551         start = dumpGas(start, end, "acpi: fadt: xpm1aevtblk:", &fp->xpm1aevtblk);
552         start = dumpGas(start, end, "acpi: fadt: xpm1bevtblk:", &fp->xpm1bevtblk);
553         start = dumpGas(start, end, "acpi: fadt: xpm1acntblk:", &fp->xpm1acntblk);
554         start = dumpGas(start, end, "acpi: fadt: xpm1bcntblk:", &fp->xpm1bcntblk);
555         start = dumpGas(start, end, "acpi: fadt: xpm2cntblk:", &fp->xpm2cntblk);
556         start = dumpGas(start, end, "acpi: fadt: xpmtmrblk:", &fp->xpmtmrblk);
557         start = dumpGas(start, end, "acpi: fadt: xgpe0blk:", &fp->xgpe0blk);
558         start = dumpGas(start, end, "acpi: fadt: xgpe1blk:", &fp->xgpe1blk);
559         return start;
560 }
561
562 static struct Atable *acpifadt(uint8_t * p, int len)
563 {
564         struct Fadt *fp;
565
566         if (len < 116) {
567                 printk("ACPI: unusually short FADT, aborting!\n");
568                 return 0;
569         }
570         fp = &fadt;
571         fp->facs = l32get(p + 36);
572         fp->dsdt = l32get(p + 40);
573         fp->pmprofile = p[45];
574         fp->sciint = l16get(p + 46);
575         fp->smicmd = l32get(p + 48);
576         fp->acpienable = p[52];
577         fp->acpidisable = p[53];
578         fp->s4biosreq = p[54];
579         fp->pstatecnt = p[55];
580         fp->pm1aevtblk = l32get(p + 56);
581         fp->pm1bevtblk = l32get(p + 60);
582         fp->pm1acntblk = l32get(p + 64);
583         fp->pm1bcntblk = l32get(p + 68);
584         fp->pm2cntblk = l32get(p + 72);
585         fp->pmtmrblk = l32get(p + 76);
586         fp->gpe0blk = l32get(p + 80);
587         fp->gpe1blk = l32get(p + 84);
588         fp->pm1evtlen = p[88];
589         fp->pm1cntlen = p[89];
590         fp->pm2cntlen = p[90];
591         fp->pmtmrlen = p[91];
592         fp->gpe0blklen = p[92];
593         fp->gpe1blklen = p[93];
594         fp->gp1base = p[94];
595         fp->cstcnt = p[95];
596         fp->plvl2lat = l16get(p + 96);
597         fp->plvl3lat = l16get(p + 98);
598         fp->flushsz = l16get(p + 100);
599         fp->flushstride = l16get(p + 102);
600         fp->dutyoff = p[104];
601         fp->dutywidth = p[105];
602         fp->dayalrm = p[106];
603         fp->monalrm = p[107];
604         fp->century = p[108];
605         fp->iapcbootarch = l16get(p + 109);
606         fp->flags = l32get(p + 112);
607
608         /* qemu gives us a 116 byte fadt, though i haven't seen any HW do that. */
609         if (len < 244)
610                 return 0;
611
612         gasget(&fp->resetreg, p + 116);
613         fp->resetval = p[128];
614         fp->xfacs = l64get(p + 132);
615         fp->xdsdt = l64get(p + 140);
616         gasget(&fp->xpm1aevtblk, p + 148);
617         gasget(&fp->xpm1bevtblk, p + 160);
618         gasget(&fp->xpm1acntblk, p + 172);
619         gasget(&fp->xpm1bcntblk, p + 184);
620         gasget(&fp->xpm2cntblk, p + 196);
621         gasget(&fp->xpmtmrblk, p + 208);
622         gasget(&fp->xgpe0blk, p + 220);
623         gasget(&fp->xgpe1blk, p + 232);
624
625         if (fp->xfacs != 0)
626                 loadfacs(fp->xfacs);
627         else
628                 loadfacs(fp->facs);
629
630         if (fp->xdsdt == ((uint64_t) fp->dsdt)) /* acpica */
631                 loaddsdt(fp->xdsdt);
632         else
633                 loaddsdt(fp->dsdt);
634
635         return NULL;    /* can be unmapped once parsed */
636 }
637
638 static char *dumpmsct(char *start, char *end, struct Msct *msct)
639 {
640         struct Mdom *st;
641
642         if (!msct)
643                 return start;
644         start = seprintf(start, end, "acpi: msct: %d doms %d clkdoms %#p maxpa\n",
645                                          msct->ndoms, msct->nclkdoms, msct->maxpa);
646         for (st = msct->dom; st != NULL; st = st->next)
647                 start = seprintf(start, end, "\t[%d:%d] %d maxproc %#p maxmmem\n",
648                                                  st->start, st->end, st->maxproc, st->maxmem);
649         start = seprintf(start, end, "\n");
650         return start;
651 }
652
653 /*
654  * XXX: should perhaps update our idea of available memory.
655  * Else we should remove this code.
656  */
657 static struct Atable *acpimsct(uint8_t * p, int len)
658 {
659         uint8_t *pe;
660         struct Mdom **stl, *st;
661         int off;
662
663         msct = kzmalloc(sizeof(struct Msct), 0);
664         msct->ndoms = l32get(p + 40) + 1;
665         msct->nclkdoms = l32get(p + 44) + 1;
666         msct->maxpa = l64get(p + 48);
667         msct->dom = NULL;
668         stl = &msct->dom;
669         pe = p + len;
670         off = l32get(p + 36);
671         for (p += off; p < pe; p += 22) {
672                 st = kzmalloc(sizeof(struct Mdom), 0);
673                 st->next = NULL;
674                 st->start = l32get(p + 2);
675                 st->end = l32get(p + 6);
676                 st->maxproc = l32get(p + 10);
677                 st->maxmem = l64get(p + 14);
678                 *stl = st;
679                 stl = &st->next;
680         }
681         return NULL;    /* can be unmapped once parsed */
682 }
683
684 static char *dumpsrat(char *start, char *end, struct Srat *st)
685 {
686         start = seprintf(start, end, "acpi: srat:\n");
687         for (; st != NULL; st = st->next)
688                 switch (st->type) {
689                         case SRlapic:
690                                 start =
691                                         seprintf(start, end,
692                                                          "\tlapic: dom %d apic %d sapic %d clk %d\n",
693                                                          st->lapic.dom, st->lapic.apic, st->lapic.sapic,
694                                                          st->lapic.clkdom);
695                                 break;
696                         case SRmem:
697                                 start = seprintf(start, end, "\tmem: dom %d %#p %#p %c%c\n",
698                                                                  st->mem.dom, st->mem.addr, st->mem.len,
699                                                                  st->mem.hplug ? 'h' : '-',
700                                                                  st->mem.nvram ? 'n' : '-');
701                                 break;
702                         case SRlx2apic:
703                                 start =
704                                         seprintf(start, end, "\tlx2apic: dom %d apic %d clk %d\n",
705                                                          st->lx2apic.dom, st->lx2apic.apic,
706                                                          st->lx2apic.clkdom);
707                                 break;
708                         default:
709                                 start = seprintf(start, end, "\t<unknown srat entry>\n");
710                 }
711         start = seprintf(start, end, "\n");
712         return start;
713 }
714
715 static struct Atable *acpisrat(uint8_t * p, int len)
716 {
717
718         struct Srat **stl, *st;
719         uint8_t *pe;
720         int stlen, flags;
721
722         if (srat != NULL) {
723                 printd("acpi: two SRATs?\n");
724                 return NULL;
725         }
726
727         stl = &srat;
728         pe = p + len;
729         for (p += 48; p < pe; p += stlen) {
730                 st = kzmalloc(sizeof(struct Srat), 1);
731                 st->type = p[0];
732                 st->next = NULL;
733                 stlen = p[1];
734                 switch (st->type) {
735                         case SRlapic:
736                                 st->lapic.dom = p[2] | p[9] << 24 | p[10] << 16 | p[11] << 8;
737                                 st->lapic.apic = p[3];
738                                 st->lapic.sapic = p[8];
739                                 st->lapic.clkdom = l32get(p + 12);
740                                 if (l32get(p + 4) == 0) {
741                                         kfree(st);
742                                         st = NULL;
743                                 }
744                                 break;
745                         case SRmem:
746                                 st->mem.dom = l32get(p + 2);
747                                 st->mem.addr = l64get(p + 8);
748                                 st->mem.len = l64get(p + 16);
749                                 flags = l32get(p + 28);
750                                 if ((flags & 1) == 0) { /* not enabled */
751                                         kfree(st);
752                                         st = NULL;
753                                 } else {
754                                         st->mem.hplug = flags & 2;
755                                         st->mem.nvram = flags & 4;
756                                 }
757                                 break;
758                         case SRlx2apic:
759                                 st->lx2apic.dom = l32get(p + 4);
760                                 st->lx2apic.apic = l32get(p + 8);
761                                 st->lx2apic.clkdom = l32get(p + 16);
762                                 if (l32get(p + 12) == 0) {
763                                         kfree(st);
764                                         st = NULL;
765                                 }
766                                 break;
767                         default:
768                                 printd("unknown SRAT structure\n");
769                                 kfree(st);
770                                 st = NULL;
771                 }
772                 if (st != NULL) {
773                         *stl = st;
774                         stl = &st->next;
775                 }
776         }
777         return NULL;    /* can be unmapped once parsed */
778 }
779
780 static char *dumpslit(char *start, char *end, struct Slit *sl)
781 {
782         int i;
783
784         if (!sl)
785                 return start;
786         start = seprintf(start, end, "acpi slit:\n");
787         for (i = 0; i < sl->rowlen * sl->rowlen; i++) {
788                 start = seprintf(start, end,
789                                                  "slit: %ux\n",
790                                                  sl->e[i / sl->rowlen][i % sl->rowlen].dist);
791         }
792         start = seprintf(start, end, "\n");
793         return start;
794 }
795
796 static int cmpslitent(void *v1, void *v2)
797 {
798         struct SlEntry *se1, *se2;
799
800         se1 = v1;
801         se2 = v2;
802         return se1->dist - se2->dist;
803 }
804
805 static struct Atable *acpislit(uint8_t * p, int len)
806 {
807
808         uint8_t *pe;
809         int i, j, k;
810         struct SlEntry *se;
811
812         pe = p + len;
813         slit = kzmalloc(sizeof(*slit), 0);
814         slit->rowlen = l64get(p + 36);
815         slit->e = kzmalloc(slit->rowlen * sizeof(struct SlEntry *), 0);
816         for (i = 0; i < slit->rowlen; i++)
817                 slit->e[i] = kzmalloc(sizeof(struct SlEntry) * slit->rowlen, 0);
818
819         i = 0;
820         for (p += 44; p < pe; p++, i++) {
821                 j = i / slit->rowlen;
822                 k = i % slit->rowlen;
823                 se = &slit->e[j][k];
824                 se->dom = k;
825                 se->dist = *p;
826         }
827 #if 0
828         /* TODO: might need to sort this shit */
829         for (i = 0; i < slit->rowlen; i++)
830                 qsort(slit->e[i], slit->rowlen, sizeof(slit->e[0][0]), cmpslitent);
831 #endif
832         return NULL;    /* can be unmapped once parsed */
833 }
834
835 uintptr_t acpimblocksize(uintptr_t addr, int *dom)
836 {
837         struct Srat *sl;
838
839         for (sl = srat; sl != NULL; sl = sl->next)
840                 if (sl->type == SRmem)
841                         if (sl->mem.addr <= addr && sl->mem.addr + sl->mem.len > addr) {
842                                 *dom = sl->mem.dom;
843                                 return sl->mem.len - (addr - sl->mem.addr);
844                         }
845         return 0;
846 }
847
848 int pickcore(int mycolor, int index)
849 {
850         int color;
851         int ncorepercol;
852
853         if (slit == NULL) {
854                 return 0;
855         }
856         ncorepercol = num_cores / slit->rowlen;
857         color = slit->e[mycolor][index / ncorepercol].dom;
858         return color * ncorepercol + index % ncorepercol;
859 }
860
861 static char *polarity[4] = {
862         "polarity/trigger like in ISA",
863         "active high",
864         "BOGUS POLARITY",
865         "active low"
866 };
867
868 static char *trigger[] = {
869         "BOGUS TRIGGER",
870         "edge",
871         "BOGUS TRIGGER",
872         "level"
873 };
874
875 static char *printiflags(char *start, char *end, int flags)
876 {
877
878         return seprintf(start, end, "[%s,%s]",
879                                         polarity[flags & AFpmask], trigger[(flags & AFtmask) >> 2]);
880 }
881
882 static char *dumpmadt(char *start, char *end, struct Madt *apics)
883 {
884         struct Apicst *st;
885
886         start =
887                 seprintf(start, end, "acpi: madt lapic paddr %llux pcat %d:\n",
888                                  apics->lapicpa, apics->pcat);
889         for (st = apics->st; st != NULL; st = st->next)
890
891                 switch (st->type) {
892                         case ASlapic:
893                                 start =
894                                         seprintf(start, end, "\tlapic pid %d id %d\n",
895                                                          st->lapic.pid, st->lapic.id);
896                                 break;
897                         case ASioapic:
898                         case ASiosapic:
899                                 start =
900                                         seprintf(start, end,
901                                                          "\tioapic id %d addr %#llux ibase %d\n",
902                                                          st->ioapic.id, st->ioapic.addr, st->ioapic.ibase);
903                                 break;
904                         case ASintovr:
905                                 start =
906                                         seprintf(start, end, "\tintovr irq %d intr %d flags $%p",
907                                                          st->intovr.irq, st->intovr.intr, st->intovr.flags);
908                                 start = printiflags(start, end, st->intovr.flags);
909                                 start = seprintf(start, end, "\n");
910                                 break;
911                         case ASnmi:
912                                 start = seprintf(start, end, "\tnmi intr %d flags $%p\n",
913                                                                  st->nmi.intr, st->nmi.flags);
914                                 break;
915                         case ASlnmi:
916                                 start =
917                                         seprintf(start, end, "\tlnmi pid %d lint %d flags $%p\n",
918                                                          st->lnmi.pid, st->lnmi.lint, st->lnmi.flags);
919                                 break;
920                         case ASlsapic:
921                                 start =
922                                         seprintf(start, end,
923                                                          "\tlsapic pid %d id %d eid %d puid %d puids %s\n",
924                                                          st->lsapic.pid, st->lsapic.id, st->lsapic.eid,
925                                                          st->lsapic.puid, st->lsapic.puids);
926                                 break;
927                         case ASintsrc:
928                                 start =
929                                         seprintf(start, end,
930                                                          "\tintr type %d pid %d peid %d iosv %d intr %d %#x\n",
931                                                          st->type, st->intsrc.pid, st->intsrc.peid,
932                                                          st->intsrc.iosv, st->intsrc.intr,
933                                                          st->intsrc.flags);
934                                 start = printiflags(start, end, st->intsrc.flags);
935                                 start = seprintf(start, end, "\n");
936                                 break;
937                         case ASlx2apic:
938                                 start =
939                                         seprintf(start, end, "\tlx2apic puid %d id %d\n",
940                                                          st->lx2apic.puid, st->lx2apic.id);
941                                 break;
942                         case ASlx2nmi:
943                                 start =
944                                         seprintf(start, end, "\tlx2nmi puid %d intr %d flags $%p\n",
945                                                          st->lx2nmi.puid, st->lx2nmi.intr,
946                                                          st->lx2nmi.flags);
947                                 break;
948                         default:
949                                 start = seprintf(start, end, "\t<unknown madt entry>\n");
950                 }
951         start = seprintf(start, end, "\n");
952         return start;
953 }
954
955 static struct Atable *acpimadt(uint8_t * p, int len)
956 {
957
958         uint8_t *pe;
959         struct Apicst *st, *l, **stl;
960         int stlen, id;
961
962         apics = kzmalloc(sizeof(struct Madt), 1);
963         apics->lapicpa = l32get(p + 36);
964         apics->pcat = l32get(p + 40);
965         apics->st = NULL;
966         stl = &apics->st;
967         pe = p + len;
968         for (p += 44; p < pe; p += stlen) {
969                 st = kzmalloc(sizeof(struct Apicst), 1);
970                 st->type = p[0];
971                 st->next = NULL;
972                 stlen = p[1];
973                 switch (st->type) {
974                         case ASlapic:
975                                 st->lapic.pid = p[2];
976                                 st->lapic.id = p[3];
977                                 if (l32get(p + 4) == 0) {
978                                         kfree(st);
979                                         st = NULL;
980                                 }
981                                 break;
982                         case ASioapic:
983                                 st->ioapic.id = id = p[2];
984                                 st->ioapic.addr = l32get(p + 4);
985                                 st->ioapic.ibase = l32get(p + 8);
986                                 /* ioapic overrides any ioapic entry for the same id */
987                                 for (l = apics->st; l != NULL; l = l->next)
988                                         if (l->type == ASiosapic && l->iosapic.id == id) {
989                                                 st->ioapic = l->iosapic;
990                                                 /* we leave it linked; could be removed */
991                                                 break;
992                                         }
993                                 break;
994                         case ASintovr:
995                                 st->intovr.irq = p[3];
996                                 st->intovr.intr = l32get(p + 4);
997                                 st->intovr.flags = l16get(p + 8);
998                                 break;
999                         case ASnmi:
1000                                 st->nmi.flags = l16get(p + 2);
1001                                 st->nmi.intr = l32get(p + 4);
1002                                 break;
1003                         case ASlnmi:
1004                                 st->lnmi.pid = p[2];
1005                                 st->lnmi.flags = l16get(p + 3);
1006                                 st->lnmi.lint = p[5];
1007                                 break;
1008                         case ASladdr:
1009                                 /* This is for 64 bits, perhaps we should not
1010                                  * honor it on 32 bits.
1011                                  */
1012                                 apics->lapicpa = l64get(p + 8);
1013                                 break;
1014                         case ASiosapic:
1015                                 id = st->iosapic.id = p[2];
1016                                 st->iosapic.ibase = l32get(p + 4);
1017                                 st->iosapic.addr = l64get(p + 8);
1018                                 /* iosapic overrides any ioapic entry for the same id */
1019                                 for (l = apics->st; l != NULL; l = l->next)
1020                                         if (l->type == ASioapic && l->ioapic.id == id) {
1021                                                 l->ioapic = st->iosapic;
1022                                                 kfree(st);
1023                                                 st = NULL;
1024                                                 break;
1025                                         }
1026                                 break;
1027                         case ASlsapic:
1028                                 st->lsapic.pid = p[2];
1029                                 st->lsapic.id = p[3];
1030                                 st->lsapic.eid = p[4];
1031                                 st->lsapic.puid = l32get(p + 12);
1032                                 if (l32get(p + 8) == 0) {
1033                                         kfree(st);
1034                                         st = NULL;
1035                                 } else
1036                                         kstrdup(&st->lsapic.puids, (char *)p + 16);
1037                                 break;
1038                         case ASintsrc:
1039                                 st->intsrc.flags = l16get(p + 2);
1040                                 st->type = p[4];
1041                                 st->intsrc.pid = p[5];
1042                                 st->intsrc.peid = p[6];
1043                                 st->intsrc.iosv = p[7];
1044                                 st->intsrc.intr = l32get(p + 8);
1045                                 st->intsrc.any = l32get(p + 12);
1046                                 break;
1047                         case ASlx2apic:
1048                                 st->lx2apic.id = l32get(p + 4);
1049                                 st->lx2apic.puid = l32get(p + 12);
1050                                 if (l32get(p + 8) == 0) {
1051                                         kfree(st);
1052                                         st = NULL;
1053                                 }
1054                                 break;
1055                         case ASlx2nmi:
1056                                 st->lx2nmi.flags = l16get(p + 2);
1057                                 st->lx2nmi.puid = l32get(p + 4);
1058                                 st->lx2nmi.intr = p[8];
1059                                 break;
1060                         default:
1061                                 printd("unknown APIC structure\n");
1062                                 kfree(st);
1063                                 st = NULL;
1064                 }
1065                 if (st != NULL) {
1066                         *stl = st;
1067                         stl = &st->next;
1068                 }
1069         }
1070         return NULL;    /* can be unmapped once parsed */
1071 }
1072
1073 /*
1074  * Map the table and keep it there.
1075  */
1076 static struct Atable *acpitable(uint8_t * p, int len)
1077 {
1078         if (len < Sdthdrsz) {
1079                 return NULL;
1080         }
1081         return new_acpi_table(p);
1082 }
1083
1084 static char *dumptable(char *start, char *end, char *sig, uint8_t * p, int l)
1085 {
1086         int n, i;
1087
1088         if (2 > 1) {
1089                 start = seprintf(start, end, "%s @ %#p\n", sig, p);
1090                 if (2 > 2)
1091                         n = l;
1092                 else
1093                         n = 256;
1094                 for (i = 0; i < n; i++) {
1095                         if ((i % 16) == 0)
1096                                 start = seprintf(start, end, "%x: ", i);
1097                         start = seprintf(start, end, " %2.2ux", p[i]);
1098                         if ((i % 16) == 15)
1099                                 start = seprintf(start, end, "\n");
1100                 }
1101                 start = seprintf(start, end, "\n");
1102                 start = seprintf(start, end, "\n");
1103         }
1104         return start;
1105 }
1106
1107 static char *seprinttable(char *s, char *e, struct Atable *t)
1108 {
1109         uint8_t *p;
1110         int i, n;
1111
1112         p = (uint8_t *) t->tbl; /* include header */
1113         n = Sdthdrsz + t->dlen;
1114         s = seprintf(s, e, "%s @ %#p\n", t->sig, p);
1115         for (i = 0; i < n; i++) {
1116                 if ((i % 16) == 0)
1117                         s = seprintf(s, e, "%x: ", i);
1118                 s = seprintf(s, e, " %2.2ux", p[i]);
1119                 if ((i % 16) == 15)
1120                         s = seprintf(s, e, "\n");
1121         }
1122         return seprintf(s, e, "\n\n");
1123 }
1124
1125 /*
1126  * process xsdt table and load tables with sig, or all if NULL.
1127  * (XXX: should be able to search for sig, oemid, oemtblid)
1128  */
1129 static int acpixsdtload(char *sig)
1130 {
1131         int i, l, t, found;
1132         uintptr_t dhpa;
1133         uint8_t *sdt;
1134         char tsig[5];
1135         char table[128];
1136
1137         found = 0;
1138         for (i = 0; i < xsdt->len; i += xsdt->asize) {
1139                 if (xsdt->asize == 8)
1140                         dhpa = l64get(xsdt->p + i);
1141                 else
1142                         dhpa = l32get(xsdt->p + i);
1143                 if ((sdt = sdtmap(dhpa, &l, 1)) == NULL)
1144                         continue;
1145                 memmove(tsig, sdt, 4);
1146                 tsig[4] = 0;
1147                 if (sig == NULL || strcmp(sig, tsig) == 0) {
1148                         printd("acpi: %s addr %#p\n", tsig, sdt);
1149                         for (t = 0; t < ARRAY_SIZE(ptables); t++)
1150                                 if (strcmp(tsig, ptables[t].sig) == 0) {
1151                                         //dumptable(table, &table[127], tsig, sdt, l);
1152                                         ptables[t].f(sdt, l);
1153                                         found = 1;
1154                                         break;
1155                                 }
1156                 }
1157         }
1158         return found;
1159 }
1160
1161 static void *rsdsearch(char *signature)
1162 {
1163         uintptr_t p;
1164         uint8_t *bda;
1165         void *rsd;
1166
1167         /*
1168          * Search for the data structure signature:
1169          * 1) in the BIOS ROM between 0xE0000 and 0xFFFFF.
1170          */
1171         return sigscan(KADDR(0xE0000), 0x20000, signature);
1172 }
1173
1174 static void acpirsdptr(void)
1175 {
1176         struct Rsdp *rsd;
1177         int asize;
1178         uintptr_t sdtpa;
1179
1180         if ((rsd = rsdsearch("RSD PTR ")) == NULL) {
1181                 return;
1182         }
1183
1184         assert(sizeof(struct Sdthdr) == 36);
1185
1186         printd("acpi: RSD PTR@ %#p, physaddr $%p length %ud %#llux rev %d\n",
1187                    rsd, l32get(rsd->raddr), l32get(rsd->length),
1188                    l64get(rsd->xaddr), rsd->revision);
1189
1190         if (rsd->revision >= 2) {
1191                 if (sdtchecksum(rsd, 36) == NULL) {
1192                         printk("acpi: RSD: bad checksum\n");
1193                         return;
1194                 }
1195                 sdtpa = l64get(rsd->xaddr);
1196                 asize = 8;
1197         } else {
1198                 if (sdtchecksum(rsd, 20) == NULL) {
1199                         printk("acpi: RSD: bad checksum\n");
1200                         return;
1201                 }
1202                 sdtpa = l32get(rsd->raddr);
1203                 asize = 4;
1204         }
1205
1206         /*
1207          * process the RSDT or XSDT table.
1208          */
1209         xsdt = kzmalloc(sizeof(struct Xsdt), 0);
1210         if (xsdt == NULL) {
1211                 printk("acpi: malloc failed\n");
1212                 return;
1213         }
1214         if ((xsdt->p = sdtmap(sdtpa, &xsdt->len, 1)) == NULL) {
1215                 printk("acpi: sdtmap failed\n");
1216                 return;
1217         }
1218         if ((xsdt->p[0] != 'R' && xsdt->p[0] != 'X')
1219                 || memcmp(xsdt->p + 1, "SDT", 3) != 0) {
1220                 printd("acpi: xsdt sig: %c%c%c%c\n", xsdt->p[0], xsdt->p[1], xsdt->p[2],
1221                            xsdt->p[3]);
1222                 kfree(xsdt);
1223                 xsdt = NULL;
1224                 return;
1225         }
1226         xsdt->p += sizeof(struct Sdthdr);
1227         xsdt->len -= sizeof(struct Sdthdr);
1228         xsdt->asize = asize;
1229         printd("acpi: XSDT %#p\n", xsdt);
1230         acpixsdtload(NULL);
1231         /* xsdt is kept and not unmapped */
1232
1233 }
1234
1235 static int
1236 acpigen(struct chan *c, char *unused_char_p_t, struct dirtab *tab, int ntab,
1237                 int i, struct dir *dp)
1238 {
1239         struct qid qid;
1240
1241         if (i == DEVDOTDOT) {
1242                 mkqid(&qid, Qdir, 0, QTDIR);
1243                 devdir(c, qid, devname(), 0, eve, 0555, dp);
1244                 return 1;
1245         }
1246         i++;    /* skip first element for . itself */
1247         if (tab == 0 || i >= ntab) {
1248                 return -1;
1249         }
1250         tab += i;
1251         qid = tab->qid;
1252         qid.path &= ~Qdir;
1253         qid.vers = 0;
1254         devdir(c, qid, tab->name, tab->length, eve, tab->perm, dp);
1255         return 1;
1256 }
1257
1258 static char *dumpGas(char *start, char *end, char *prefix, struct Gas *g)
1259 {
1260         static char *rnames[] = {
1261                 "mem", "io", "pcicfg", "embed",
1262                 "smb", "cmos", "pcibar", "ipmi"
1263         };
1264         start = seprintf(start, end, "%s", prefix);
1265
1266         switch (g->spc) {
1267                 case Rsysmem:
1268                 case Rsysio:
1269                 case Rembed:
1270                 case Rsmbus:
1271                 case Rcmos:
1272                 case Rpcibar:
1273                 case Ripmi:
1274                         start = seprintf(start, end, "[%s ", rnames[g->spc]);
1275                         break;
1276                 case Rpcicfg:
1277                         start = seprintf(start, end, "[pci ");
1278                         start =
1279                                 seprintf(start, end, "dev %#p ",
1280                                                  (uint32_t) (g->addr >> 32) & 0xFFFF);
1281                         start =
1282                                 seprintf(start, end, "fn %#p ",
1283                                                  (uint32_t) (g->addr & 0xFFFF0000) >> 16);
1284                         start =
1285                                 seprintf(start, end, "adr %#p ", (uint32_t) (g->addr & 0xFFFF));
1286                         break;
1287                 case Rfixedhw:
1288                         start = seprintf(start, end, "[hw ");
1289                         break;
1290                 default:
1291                         start = seprintf(start, end, "[spc=%#p ", g->spc);
1292         }
1293         start = seprintf(start, end, "off %d len %d addr %#p sz%d]",
1294                                          g->off, g->len, g->addr, g->accsz);
1295         start = seprintf(start, end, "\n");
1296         return start;
1297 }
1298
1299 static unsigned int getbanked(uintptr_t ra, uintptr_t rb, int sz)
1300 {
1301         unsigned int r;
1302
1303         r = 0;
1304         switch (sz) {
1305                 case 1:
1306                         if (ra != 0)
1307                                 r |= inb(ra);
1308                         if (rb != 0)
1309                                 r |= inb(rb);
1310                         break;
1311                 case 2:
1312                         if (ra != 0)
1313                                 r |= inw(ra);
1314                         if (rb != 0)
1315                                 r |= inw(rb);
1316                         break;
1317                 case 4:
1318                         if (ra != 0)
1319                                 r |= inl(ra);
1320                         if (rb != 0)
1321                                 r |= inl(rb);
1322                         break;
1323                 default:
1324                         printd("getbanked: wrong size\n");
1325         }
1326         return r;
1327 }
1328
1329 static unsigned int setbanked(uintptr_t ra, uintptr_t rb, int sz, int v)
1330 {
1331         unsigned int r;
1332
1333         r = -1;
1334         switch (sz) {
1335                 case 1:
1336                         if (ra != 0)
1337                                 outb(ra, v);
1338                         if (rb != 0)
1339                                 outb(rb, v);
1340                         break;
1341                 case 2:
1342                         if (ra != 0)
1343                                 outw(ra, v);
1344                         if (rb != 0)
1345                                 outw(rb, v);
1346                         break;
1347                 case 4:
1348                         if (ra != 0)
1349                                 outl(ra, v);
1350                         if (rb != 0)
1351                                 outl(rb, v);
1352                         break;
1353                 default:
1354                         printd("setbanked: wrong size\n");
1355         }
1356         return r;
1357 }
1358
1359 static unsigned int getpm1ctl(void)
1360 {
1361         return getbanked(fadt.pm1acntblk, fadt.pm1bcntblk, fadt.pm1cntlen);
1362 }
1363
1364 static void setpm1sts(unsigned int v)
1365 {
1366         setbanked(fadt.pm1aevtblk, fadt.pm1bevtblk, fadt.pm1evtlen / 2, v);
1367 }
1368
1369 static unsigned int getpm1sts(void)
1370 {
1371         return getbanked(fadt.pm1aevtblk, fadt.pm1bevtblk, fadt.pm1evtlen / 2);
1372 }
1373
1374 static unsigned int getpm1en(void)
1375 {
1376         int sz;
1377
1378         sz = fadt.pm1evtlen / 2;
1379         return getbanked(fadt.pm1aevtblk + sz, fadt.pm1bevtblk + sz, sz);
1380 }
1381
1382 static int getgpeen(int n)
1383 {
1384         return inb(gpes[n].enio) & 1 << gpes[n].enbit;
1385 }
1386
1387 static void setgpeen(int n, unsigned int v)
1388 {
1389         int old;
1390
1391         old = inb(gpes[n].enio);
1392         if (v)
1393                 outb(gpes[n].enio, old | 1 << gpes[n].enbit);
1394         else
1395                 outb(gpes[n].enio, old & ~(1 << gpes[n].enbit));
1396 }
1397
1398 static void clrgpests(int n)
1399 {
1400         outb(gpes[n].stsio, 1 << gpes[n].stsbit);
1401 }
1402
1403 static unsigned int getgpests(int n)
1404 {
1405         return inb(gpes[n].stsio) & 1 << gpes[n].stsbit;
1406 }
1407
1408 #if 0
1409 static void acpiintr(Ureg *, void *)
1410 {
1411         int i;
1412         unsigned int sts, en;
1413
1414         printd("acpi: intr\n");
1415
1416         for (i = 0; i < ngpes; i++)
1417                 if (getgpests(i)) {
1418                         printd("gpe %d on\n", i);
1419                         en = getgpeen(i);
1420                         setgpeen(i, 0);
1421                         clrgpests(i);
1422                         if (en != 0)
1423                                 printd("acpiitr: calling gpe %d\n", i);
1424                         //  queue gpe for calling gpe->ho in the
1425                         //  aml process.
1426                         //  enable it again when it returns.
1427                 }
1428         sts = getpm1sts();
1429         en = getpm1en();
1430         printd("acpiitr: pm1sts %#p pm1en %#p\n", sts, en);
1431         if (sts & en)
1432                 printd("have enabled events\n");
1433         if (sts & 1)
1434                 printd("power button\n");
1435         // XXX serve other interrupts here.
1436         setpm1sts(sts);
1437 }
1438 #endif
1439 static void initgpes(void)
1440 {
1441         int i, n0, n1;
1442
1443         n0 = fadt.gpe0blklen / 2;
1444         n1 = fadt.gpe1blklen / 2;
1445         ngpes = n0 + n1;
1446         gpes = kzmalloc(sizeof(struct Gpe) * ngpes, 1);
1447         for (i = 0; i < n0; i++) {
1448                 gpes[i].nb = i;
1449                 gpes[i].stsbit = i & 7;
1450                 gpes[i].stsio = fadt.gpe0blk + (i >> 3);
1451                 gpes[i].enbit = (n0 + i) & 7;
1452                 gpes[i].enio = fadt.gpe0blk + ((n0 + i) >> 3);
1453         }
1454         for (i = 0; i + n0 < ngpes; i++) {
1455                 gpes[i + n0].nb = fadt.gp1base + i;
1456                 gpes[i + n0].stsbit = i & 7;
1457                 gpes[i + n0].stsio = fadt.gpe1blk + (i >> 3);
1458                 gpes[i + n0].enbit = (n1 + i) & 7;
1459                 gpes[i + n0].enio = fadt.gpe1blk + ((n1 + i) >> 3);
1460         }
1461         for (i = 0; i < ngpes; i++) {
1462                 setgpeen(i, 0);
1463                 clrgpests(i);
1464         }
1465 }
1466
1467 static void acpiioalloc(unsigned int addr, int len)
1468 {
1469         if (addr != 0) {
1470                 printk("Just TAKING port %016lx to %016lx\n", addr, addr + len);
1471                 //ioalloc(addr, len, 0, "acpi");
1472         }
1473 }
1474
1475 int acpiinit(void)
1476 {
1477         /* this smicmd test implements 'run once' for now. */
1478         if (fadt.smicmd == 0) {
1479                 //fmtinstall('G', Gfmt);
1480                 acpirsdptr();
1481                 if (fadt.smicmd == 0) {
1482                         return -1;
1483                 }
1484         }
1485         printk("ACPI initialized\n");
1486         return 0;
1487 }
1488
1489 static struct chan *acpiattach(char *spec)
1490 {
1491         int i;
1492
1493         /*
1494          * This was written for the stock kernel.
1495          * This code must use 64 registers to be acpi ready in nix.
1496          */
1497         if (acpiinit() < 0) {
1498                 error("no acpi");
1499         }
1500
1501         /*
1502          * should use fadt->xpm* and fadt->xgpe* registers for 64 bits.
1503          * We are not ready in this kernel for that.
1504          */
1505         acpiioalloc(fadt.smicmd, 1);
1506         acpiioalloc(fadt.pm1aevtblk, fadt.pm1evtlen);
1507         acpiioalloc(fadt.pm1bevtblk, fadt.pm1evtlen);
1508         acpiioalloc(fadt.pm1acntblk, fadt.pm1cntlen);
1509         acpiioalloc(fadt.pm1bcntblk, fadt.pm1cntlen);
1510         acpiioalloc(fadt.pm2cntblk, fadt.pm2cntlen);
1511         acpiioalloc(fadt.pmtmrblk, fadt.pmtmrlen);
1512         acpiioalloc(fadt.gpe0blk, fadt.gpe0blklen);
1513         acpiioalloc(fadt.gpe1blk, fadt.gpe1blklen);
1514
1515         initgpes();
1516
1517         /*
1518          * This starts ACPI, which may require we handle
1519          * power mgmt events ourselves. Use with care.
1520          */
1521         outb(fadt.smicmd, fadt.acpienable);
1522         for (i = 0; i < 10; i++)
1523                 if (getpm1ctl() & Pm1SciEn)
1524                         break;
1525         if (i == 10)
1526                 error("acpi: failed to enable\n");
1527 //  if(fadt.sciint != 0)
1528 //      intrenable(fadt.sciint, acpiintr, 0, BUSUNKNOWN, "acpi");
1529         return devattach(devname(), spec);
1530 }
1531
1532 static struct walkqid *acpiwalk(struct chan *c, struct chan *nc, char **name,
1533                                                                 int nname)
1534 {
1535         return devwalk(c, nc, name, nname, acpidir, ARRAY_SIZE(acpidir), acpigen);
1536 }
1537
1538 static int acpistat(struct chan *c, uint8_t * dp, int n)
1539 {
1540         return devstat(c, dp, n, acpidir, ARRAY_SIZE(acpidir), acpigen);
1541 }
1542
1543 static struct chan *acpiopen(struct chan *c, int omode)
1544 {
1545         return devopen(c, omode, acpidir, ARRAY_SIZE(acpidir), acpigen);
1546 }
1547
1548 static void acpiclose(struct chan *unused)
1549 {
1550 }
1551
1552 static char *ttext;
1553 static int tlen;
1554
1555 static long acpiread(struct chan *c, void *a, long n, int64_t off)
1556 {
1557         long q;
1558         struct Atable *t;
1559         char *ns, *s, *e, *ntext;
1560
1561         if (ttext == NULL) {
1562                 tlen = 32768;
1563                 ttext = kzmalloc(tlen, 0);
1564         }
1565         if (ttext == NULL) {
1566                 error("acpiread: no memory");
1567         }
1568         q = c->qid.path;
1569         switch (q) {
1570                 case Qdir:
1571                         return devdirread(c, a, n, acpidir, ARRAY_SIZE(acpidir), acpigen);
1572                 case Qtbl:
1573                         s = ttext;
1574                         e = ttext + tlen;
1575                         strncpy(s, "no tables\n", sizeof(s));
1576                         for (t = tfirst; t != NULL; t = t->next) {
1577                                 ns = seprinttable(s, e, t);
1578                                 while (ns == e - 1) {
1579                                         ntext = krealloc(ttext, tlen * 2, 0);
1580                                         if (ntext == NULL)
1581                                                 panic("acpi: no memory\n");
1582                                         s = ntext + (ttext - s);
1583                                         ttext = ntext;
1584                                         tlen *= 2;
1585                                         e = ttext + tlen;
1586                                         ns = seprinttable(s, e, t);
1587                                 }
1588                                 s = ns;
1589                         }
1590                         return readstr(off, a, n, ttext);
1591                 case Qpretty:
1592                         s = ttext;
1593                         e = ttext + tlen;
1594                         s = dumpfadt(s, e, &fadt);
1595                         s = dumpmadt(s, e, apics);
1596                         s = dumpslit(s, e, slit);
1597                         s = dumpsrat(s, e, srat);
1598                         dumpmsct(s, e, msct);
1599                         return readstr(off, a, n, ttext);
1600                 case Qioapic:
1601                         s = ioapicdump(ttext, ttext + tlen);
1602                         return readstr(off, a, n, ttext);
1603                 case Qapic:
1604                         s = apicdump(ttext, ttext + tlen);
1605                         return readstr(off, a, n, ttext);
1606                 case Qio:
1607                         if (reg == NULL)
1608                                 error("region not configured");
1609                         return regio(reg, a, n, off, 0);
1610         }
1611         error(Eperm);
1612         return -1;
1613 }
1614
1615 static long acpiwrite(struct chan *c, void *a, long n, int64_t off)
1616 {
1617         ERRSTACK(2);
1618         struct cmdtab *ct;
1619         struct cmdbuf *cb;
1620         struct Reg *r;
1621         unsigned int rno, fun, dev, bus, i;
1622
1623         if (c->qid.path == Qio) {
1624                 if (reg == NULL)
1625                         error("region not configured");
1626                 return regio(reg, a, n, off, 1);
1627         }
1628         if (c->qid.path != Qctl)
1629                 error(Eperm);
1630
1631         cb = parsecmd(a, n);
1632         if (waserror()) {
1633                 kfree(cb);
1634                 nexterror();
1635         }
1636         ct = lookupcmd(cb, ctls, ARRAY_SIZE(ctls));
1637         switch (ct->index) {
1638                 case CMregion:
1639                         /* TODO: this block is racy on reg (global) */
1640                         r = reg;
1641                         if (r == NULL) {
1642                                 r = kzmalloc(sizeof(struct Reg), 0);
1643                                 r->name = NULL;
1644                         }
1645                         kstrdup(&r->name, cb->f[1]);
1646                         r->spc = acpiregid(cb->f[2]);
1647                         if (r->spc < 0) {
1648                                 kfree(r);
1649                                 reg = NULL;
1650                                 error("bad region type");
1651                         }
1652                         if (r->spc == Rpcicfg || r->spc == Rpcibar) {
1653                                 rno = r->base >> Rpciregshift & Rpciregmask;
1654                                 fun = r->base >> Rpcifunshift & Rpcifunmask;
1655                                 dev = r->base >> Rpcidevshift & Rpcidevmask;
1656                                 bus = r->base >> Rpcibusshift & Rpcibusmask;
1657                                 #ifdef CONFIG_X86
1658                                 r->tbdf = MKBUS(BusPCI, bus, dev, fun);
1659                                 #else
1660                                 r->tbdf = 0
1661                                 #endif
1662                                 r->base = rno;  /* register ~ our base addr */
1663                         }
1664                         r->base = strtoul(cb->f[3], NULL, 0);
1665                         r->len = strtoul(cb->f[4], NULL, 0);
1666                         r->accsz = strtoul(cb->f[5], NULL, 0);
1667                         if (r->accsz < 1 || r->accsz > 4) {
1668                                 kfree(r);
1669                                 reg = NULL;
1670                                 error("bad region access size");
1671                         }
1672                         reg = r;
1673                         printd("region %s %s %p %p sz%d",
1674                                    r->name, acpiregstr(r->spc), r->base, r->len, r->accsz);
1675                         break;
1676                 case CMgpe:
1677                         i = strtoul(cb->f[1], NULL, 0);
1678                         if (i >= ngpes)
1679                                 error("gpe out of range");
1680                         kstrdup(&gpes[i].obj, cb->f[2]);
1681                         setgpeen(i, 1);
1682                         break;
1683                 default:
1684                         panic("acpi: unknown ctl");
1685         }
1686         poperror();
1687         kfree(cb);
1688         return n;
1689 }
1690
1691 struct dev acpidevtab __devtab = {
1692         "acpi",
1693
1694         devreset,
1695         devinit,
1696         devshutdown,
1697         acpiattach,
1698         acpiwalk,
1699         acpistat,
1700         acpiopen,
1701         devcreate,
1702         acpiclose,
1703         acpiread,
1704         devbread,
1705         acpiwrite,
1706         devbwrite,
1707         devremove,
1708         devwstat,
1709 };