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