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