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