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