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