Remove major stack consumers from procread()
[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, ERROR_FIXME);
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, ERROR_FIXME);
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         .name = "acpi",
1702
1703         .reset = devreset,
1704         .init = devinit,
1705         .shutdown = devshutdown,
1706         .attach = acpiattach,
1707         .walk = acpiwalk,
1708         .stat = acpistat,
1709         .open = acpiopen,
1710         .create = devcreate,
1711         .close = acpiclose,
1712         .read = acpiread,
1713         .bread = devbread,
1714         .write = acpiwrite,
1715         .bwrite = devbwrite,
1716         .remove = devremove,
1717         .wstat = devwstat,
1718 };