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