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