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