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