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