Set up ACPI interrupt configuration
[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 #if 0
632         static char buf[8192]; // XXX
633         char *out;
634         out = dumpfadt(buf, &buf[8191], fp);
635         printk("%s\n", out);
636 #endif
637         if(fp->xfacs != 0)
638                 loadfacs(fp->xfacs);
639         else
640                 loadfacs(fp->facs);
641
642         if(fp->xdsdt == ((uint64_t)fp->dsdt)) /* acpica */
643                 loaddsdt(fp->xdsdt);
644         else
645                 loaddsdt(fp->dsdt);
646
647         return NULL;    /* can be unmapped once parsed */
648 }
649
650 static char *
651 dumpmsct(char *start, char *end, struct Msct *msct)
652 {
653         struct Mdom *st;
654
655         if (! msct)
656                 return start;
657         start = seprintf(start, end, "acpi: msct: %d doms %d clkdoms %#p maxpa\n",
658                 msct->ndoms, msct->nclkdoms, msct->maxpa);
659         for(st = msct->dom; st != NULL; st = st->next)
660                 start = seprintf(start, end, "\t[%d:%d] %d maxproc %#p maxmmem\n",
661                         st->start, st->end, st->maxproc, st->maxmem);
662         start = seprintf(start, end, "\n");
663         return start;
664 }
665
666 /*
667  * XXX: should perhaps update our idea of available memory.
668  * Else we should remove this code.
669  */
670 static struct Atable*
671 acpimsct(uint8_t *p, int len)
672 {
673         uint8_t *pe;
674         struct Mdom **stl, *st;
675         int off;
676
677
678         msct = kzmalloc(sizeof(struct Msct), KMALLOC_WAIT);
679         msct->ndoms = l32get(p+40) + 1;
680         msct->nclkdoms = l32get(p+44) + 1;
681         msct->maxpa = l64get(p+48);
682         msct->dom = NULL;
683         stl = &msct->dom;
684         pe = p + len;
685         off = l32get(p+36);
686         for(p += off; p < pe; p += 22){
687                 st = kzmalloc(sizeof(struct Mdom), KMALLOC_WAIT);
688                 st->next = NULL;
689                 st->start = l32get(p+2);
690                 st->end = l32get(p+6);
691                 st->maxproc = l32get(p+10);
692                 st->maxmem = l64get(p+14);
693                 *stl = st;
694                 stl = &st->next;
695         }
696 #if 0
697         // no longer works if called from init.c
698         char *dump;
699         dump = kzmalloc(1024, KMALLOC_WAIT);
700         dumpmsct(dump, &dump[1023], msct);
701         printk("%s\n", dump);
702         kfree(dump);
703 #endif
704         return NULL;    /* can be unmapped once parsed */
705 }
706
707 static char *
708 dumpsrat(char *start, char *end, struct Srat *st)
709 {
710         start = seprintf(start, end, "acpi: srat:\n");
711         for(; st != NULL; st = st->next)
712                 switch(st->type){
713                 case SRlapic:
714                         start = seprintf(start, end, "\tlapic: dom %d apic %d sapic %d clk %d\n",
715                                 st->lapic.dom, st->lapic.apic,
716                                 st->lapic.sapic, st->lapic.clkdom);
717                         break;
718                 case SRmem:
719                         start = seprintf(start, end, "\tmem: dom %d %#p %#p %c%c\n",
720                                 st->mem.dom, st->mem.addr, st->mem.len,
721                                 st->mem.hplug?'h':'-',
722                                 st->mem.nvram?'n':'-');
723                         break;
724                 case SRlx2apic:
725                         start = seprintf(start, end, "\tlx2apic: dom %d apic %d clk %d\n",
726                                 st->lx2apic.dom, st->lx2apic.apic,
727                                 st->lx2apic.clkdom);
728                         break;
729                 default:
730                         start = seprintf(start, end, "\t<unknown srat entry>\n");
731                 }
732         start = seprintf(start, end, "\n");
733         return start;
734 }
735
736 static struct Atable*
737 acpisrat(uint8_t *p, int len)
738 {
739
740         struct Srat **stl, *st;
741         uint8_t *pe;
742         int stlen, flags;
743
744         if(srat != NULL){
745                 printd("acpi: two SRATs?\n");
746                 return NULL;
747         }
748
749         stl = &srat;
750         pe = p + len;
751         for(p += 48; p < pe; p += stlen){
752                 st = kzmalloc(sizeof(struct Srat), 1);
753                 st->type = p[0];
754                 st->next = NULL;
755                 stlen = p[1];
756                 switch(st->type){
757                 case SRlapic:
758                         st->lapic.dom = p[2] | p[9]<<24| p[10]<<16 | p[11]<<8;
759                         st->lapic.apic = p[3];
760                         st->lapic.sapic = p[8];
761                         st->lapic.clkdom = l32get(p+12);
762                         if(l32get(p+4) == 0){
763                                 kfree(st);
764                                 st = NULL;
765                         }
766                         break;
767                 case SRmem:
768                         st->mem.dom = l32get(p+2);
769                         st->mem.addr = l64get(p+8);
770                         st->mem.len = l64get(p+16);
771                         flags = l32get(p+28);
772                         if((flags&1) == 0){     /* not enabled */
773                                 kfree(st);
774                                 st = NULL;
775                         }else{
776                                 st->mem.hplug = flags & 2;
777                                 st->mem.nvram = flags & 4;
778                         }
779                         break;
780                 case SRlx2apic:
781                         st->lx2apic.dom = l32get(p+4);
782                         st->lx2apic.apic = l32get(p+8);
783                         st->lx2apic.clkdom = l32get(p+16);
784                         if(l32get(p+12) == 0){
785                                 kfree(st);
786                                 st = NULL;
787                         }
788                         break;
789                 default:
790                         printd("unknown SRAT structure\n");
791                         kfree(st);
792                         st = NULL;
793                 }
794                 if(st != NULL){
795                         *stl = st;
796                         stl = &st->next;
797                 }
798         }
799
800 #if 0
801         char *dump;
802         dump = kzmalloc(8192, KMALLOC_WAIT);
803         dumpsrat(dump, &dump[8192], srat);
804         printk("%s\n", dump);
805         kfree(dump);
806 #endif
807         return NULL;    /* can be unmapped once parsed */
808 }
809
810 static char *
811 dumpslit(char *start, char *end, struct Slit *sl)
812 {
813         int i;
814         
815         if (! sl)
816                 return start;
817         start = seprintf(start, end, "acpi slit:\n");
818         for(i = 0; i < sl->rowlen*sl->rowlen; i++){
819                 start = seprintf(start, end,
820                                 "slit: %ux\n", sl->e[i/sl->rowlen][i%sl->rowlen].dist);
821         }
822         start = seprintf(start, end, "\n");
823         return start;
824 }
825
826 static int
827 cmpslitent(void* v1, void* v2)
828 {
829         struct SlEntry *se1, *se2;
830
831         se1 = v1;
832         se2 = v2;
833         return se1->dist - se2->dist;
834 }
835
836 static struct Atable*
837 acpislit(uint8_t *p, int len)
838 {
839
840         uint8_t *pe;
841         int i, j, k;
842         struct SlEntry *se;
843
844         pe = p + len;
845         slit = kzmalloc(sizeof(*slit), 0);
846         slit->rowlen = l64get(p+36);
847         slit->e = kzmalloc(slit->rowlen * sizeof(struct SlEntry *), 0);
848         for(i = 0; i < slit->rowlen; i++)
849                 slit->e[i] = kzmalloc(sizeof(struct SlEntry) * slit->rowlen, 0);
850
851         i = 0;
852         for(p += 44; p < pe; p++, i++){
853                 j = i/slit->rowlen;
854                 k = i%slit->rowlen;
855                 se = &slit->e[j][k];
856                 se->dom = k;
857                 se->dist = *p;
858         }
859
860 #warning "no qsort"
861 #if 0
862         char *dump;
863         dump = kzmalloc(8192, KMALLOC_WAIT);
864         dumpslit(dump, &dump[8191], slit);
865         printk("%s", dump);
866         kfree(dump);
867         for(i = 0; i < slit->rowlen; i++)
868                 qsort(slit->e[i], slit->rowlen, sizeof(slit->e[0][0]), cmpslitent);
869         
870         dumpslit(slit);
871 #endif
872         return NULL;    /* can be unmapped once parsed */
873 }
874
875 uintptr_t
876 acpimblocksize(uintptr_t addr, int *dom)
877 {
878         struct Srat *sl;
879
880         for(sl = srat; sl != NULL; sl = sl->next)
881                 if(sl->type == SRmem)
882                 if(sl->mem.addr <= addr && sl->mem.addr + sl->mem.len > addr){
883                         *dom = sl->mem.dom;
884                         return sl->mem.len - (addr - sl->mem.addr);
885                 }
886         return 0;
887 }
888
889
890 /*
891  * we use mp->machno (or index in Mach array) as the identifier,
892  * but ACPI relies on the apic identifier.
893  */
894 int
895 corecolor(int core)
896 {
897 #warning "can't do core colors yet"
898 return -1;
899 #if 0
900         struct Srat *sl;
901         static int colors[32];
902
903         if(core < 0 || core >= num_cpus)
904                 return -1;
905         m = sys->machptr[core];
906         if(m == NULL)
907                 return -1;
908
909         if(core >= 0 && core < ARRAY_SIZE(colors) && colors[core] != 0)
910                 return colors[core] - 1;
911
912         for(sl = srat; sl != NULL; sl = sl->next)
913                 if(sl->type == SRlapic && sl->lapic.apic == m->apicno){
914                         if(core >= 0 && core < ARRAY_SIZE(colors))
915                                 colors[core] = 1 + sl->lapic.dom;
916                         return sl->lapic.dom;
917                 }
918         return -1;
919 #endif
920 }
921
922
923 int
924 pickcore(int mycolor, int index)
925 {
926         int color;
927         int ncorepercol;
928
929         if(slit == NULL) {
930                 return 0;
931         }
932         ncorepercol = num_cpus/slit->rowlen;
933         color = slit->e[mycolor][index/ncorepercol].dom;
934         return color * ncorepercol + index % ncorepercol;
935 }
936
937
938 static char *
939 dumpmadt(char *start, char *end, struct Madt *apics)
940 {
941         struct Apicst *st;
942
943         start = seprintf(start, end, "acpi: madt lapic paddr %llux pcat %d:\n", apics->lapicpa, apics->pcat);
944         for(st = apics->st; st != NULL; st = st->next)
945                 switch(st->type){
946                 case ASlapic:
947                         start = seprintf(start, end, "\tlapic pid %d id %d\n", st->lapic.pid, st->lapic.id);
948                         break;
949                 case ASioapic:
950                 case ASiosapic:
951                         start = seprintf(start, end, "\tioapic id %d addr %#llux ibase %d\n",
952                                 st->ioapic.id, st->ioapic.addr, st->ioapic.ibase);
953                         break;
954                 case ASintovr:
955                         start = seprintf(start, end, "\tintovr irq %d intr %d flags $%p\n",
956                                 st->intovr.irq, st->intovr.intr,st->intovr.flags);
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 = seprintf(start, end, "\tlnmi pid %d lint %d flags $%p\n",
964                                 st->lnmi.pid, st->lnmi.lint, st->lnmi.flags);
965                         break;
966                 case ASlsapic:
967                         start = seprintf(start, end, "\tlsapic pid %d id %d eid %d puid %d puids %s\n",
968                                 st->lsapic.pid, st->lsapic.id,
969                                 st->lsapic.eid, st->lsapic.puid,
970                                 st->lsapic.puids);
971                         break;
972                 case ASintsrc:
973                         start = seprintf(start, end, "\tintr type %d pid %d peid %d iosv %d intr %d %#x\n",
974                                 st->type, st->intsrc.pid,
975                                 st->intsrc.peid, st->intsrc.iosv,
976                                 st->intsrc.intr, st->intsrc.flags);
977                         break;
978                 case ASlx2apic:
979                         start = seprintf(start, end, "\tlx2apic puid %d id %d\n", st->lx2apic.puid, st->lx2apic.id);
980                         break;
981                 case ASlx2nmi:
982                         start = seprintf(start, end, "\tlx2nmi puid %d intr %d flags $%p\n",
983                                 st->lx2nmi.puid, st->lx2nmi.intr, st->lx2nmi.flags);
984                         break;
985                 default:
986                         start = seprintf(start, end, "\t<unknown madt entry>\n");
987                 }
988         start = seprintf(start, end, "\n");
989         return start;
990 }
991
992 static struct Atable*
993 acpimadt(uint8_t *p, int len)
994 {
995
996         uint8_t *pe;
997         struct Apicst *st, *l, **stl;
998         int stlen, id;
999
1000         apics = kzmalloc(sizeof(struct Madt), 1);
1001         apics->lapicpa = l32get(p+36);
1002         apics->pcat = l32get(p+40);
1003         apics->st = NULL;
1004         stl = &apics->st;
1005         pe = p + len;
1006         for(p += 44; p < pe; p += stlen){
1007                 st = kzmalloc(sizeof(struct Apicst), 1);
1008                 st->type = p[0];
1009                 st->next = NULL;
1010                 stlen = p[1];
1011                 switch(st->type){
1012                 case ASlapic:
1013                         st->lapic.pid = p[2];
1014                         st->lapic.id = p[3];
1015                         if(l32get(p+4) == 0){
1016                                 kfree(st);
1017                                 st = NULL;
1018                         }
1019                         break;
1020                 case ASioapic:
1021                         st->ioapic.id = id = p[2];
1022                         st->ioapic.addr = l32get(p+4);
1023                         st->ioapic.ibase = l32get(p+8);
1024                         /* iosapic overrides any ioapic entry for the same id */
1025                         for(l = apics->st; l != NULL; l = l->next)
1026                                 if(l->type == ASiosapic && l->iosapic.id == id){
1027                                         st->ioapic = l->iosapic;
1028                                         /* we leave it linked; could be removed */
1029                                         break;
1030                                 }
1031                         break;
1032                 case ASintovr:
1033                         st->intovr.irq = p[3];
1034                         st->intovr.intr = l32get(p+4);
1035                         st->intovr.flags = l16get(p+8);
1036                         break;
1037                 case ASnmi:
1038                         st->nmi.flags = l16get(p+2);
1039                         st->nmi.intr = l32get(p+4);
1040                         break;
1041                 case ASlnmi:
1042                         st->lnmi.pid = p[2];
1043                         st->lnmi.flags = l16get(p+3);
1044                         st->lnmi.lint = p[5];
1045                         break;
1046                 case ASladdr:
1047                         /* This is for 64 bits, perhaps we should not
1048                          * honor it on 32 bits.
1049                          */
1050                         apics->lapicpa = l64get(p+8);
1051                         break;
1052                 case ASiosapic:
1053                         id = st->iosapic.id = p[2];
1054                         st->iosapic.ibase = l32get(p+4);
1055                         st->iosapic.addr = l64get(p+8);
1056                         /* iosapic overrides any ioapic entry for the same id */
1057                         for(l = apics->st; l != NULL; l = l->next)
1058                                 if(l->type == ASioapic && l->ioapic.id == id){
1059                                         l->ioapic = st->iosapic;
1060                                         kfree(st);
1061                                         st = NULL;
1062                                         break;
1063                                 }
1064                         break;
1065                 case ASlsapic:
1066                         st->lsapic.pid = p[2];
1067                         st->lsapic.id = p[3];
1068                         st->lsapic.eid = p[4];
1069                         st->lsapic.puid = l32get(p+12);
1070                         if(l32get(p+8) == 0){
1071                                 kfree(st);
1072                                 st = NULL;
1073                         }else
1074                                 kstrdup(&st->lsapic.puids, (char *)p+16);
1075                         break;
1076                 case ASintsrc:
1077                         st->intsrc.flags = l16get(p+2);
1078                         st->type = p[4];
1079                         st->intsrc.pid = p[5];
1080                         st->intsrc.peid = p[6];
1081                         st->intsrc.iosv = p[7];
1082                         st->intsrc.intr = l32get(p+8);
1083                         st->intsrc.any = l32get(p+12);
1084                         break;
1085                 case ASlx2apic:
1086                         st->lx2apic.id = l32get(p+4);
1087                         st->lx2apic.puid = l32get(p+12);
1088                         if(l32get(p+8) == 0){
1089                                 kfree(st);
1090                                 st = NULL;
1091                         }
1092                         break;
1093                 case ASlx2nmi:
1094                         st->lx2nmi.flags = l16get(p+2);
1095                         st->lx2nmi.puid = l32get(p+4);
1096                         st->lx2nmi.intr = p[8];
1097                         break;
1098                 default:
1099                         printd("unknown APIC structure\n");
1100                         kfree(st);
1101                         st = NULL;
1102                 }
1103                 if(st != NULL){
1104                         *stl = st;
1105                         stl = &st->next;
1106                 }
1107         }
1108 #if 0
1109         char *dump;
1110         dump = kzmalloc(8192, KMALLOC_WAIT);
1111         dumpmadt(dump, &dump[8191], apics);
1112         printk("%s\n", dump);
1113         kfree(dump);
1114 #endif
1115         return NULL;    /* can be unmapped once parsed */
1116 }
1117
1118 /*
1119  * Map the table and keep it there.
1120  */
1121 static struct Atable*
1122 acpitable(uint8_t *p, int len)
1123 {
1124         if(len < Sdthdrsz) {
1125                 return NULL;
1126         }
1127         return newtable(p);
1128 }
1129
1130 static char *
1131 dumptable(char *start, char *end, char *sig, uint8_t *p, int l)
1132 {
1133         int n, i;
1134
1135         if(2 > 1){
1136                 start = seprintf(start, end, "%s @ %#p\n", sig, p);
1137                 if(2 > 2)
1138                         n = l;
1139                 else
1140                         n = 256;
1141                 for(i = 0; i < n; i++){
1142                         if((i % 16) == 0)
1143                                 start = seprintf(start, end, "%x: ", i);
1144                         start = seprintf(start, end, " %2.2ux", p[i]);
1145                         if((i % 16) == 15)
1146                                 start = seprintf(start, end, "\n");
1147                 }
1148                 start = seprintf(start, end, "\n");
1149                 start = seprintf(start, end, "\n");
1150         }
1151         return start;
1152 }
1153
1154 static char*
1155 seprinttable(char *s, char *e, struct Atable *t)
1156 {
1157         uint8_t *p;
1158         int i, n;
1159
1160         p = ( uint8_t *)t->tbl; /* include header */
1161         n = Sdthdrsz + t->dlen;
1162         s = seprintf(s, e, "%s @ %#p\n", t->sig, p);
1163         for(i = 0; i < n; i++){
1164                 if((i % 16) == 0)
1165                         s = seprintf(s, e, "%x: ", i);
1166                 s = seprintf(s, e, " %2.2ux", p[i]);
1167                 if((i % 16) == 15)
1168                         s = seprintf(s, e, "\n");
1169         }
1170         return seprintf(s, e, "\n\n");
1171 }
1172
1173 /*
1174  * process xsdt table and load tables with sig, or all if NULL.
1175  * (XXX: should be able to search for sig, oemid, oemtblid)
1176  */
1177 static int
1178 acpixsdtload(char *sig)
1179 {
1180         int i, l, t, unmap, found;
1181         uintptr_t dhpa;
1182         uint8_t *sdt;
1183         char tsig[5];
1184         char table[128];
1185
1186         found = 0;
1187         for(i = 0; i < xsdt->len; i += xsdt->asize){
1188                 if(xsdt->asize == 8)
1189                         dhpa = l64get(xsdt->p+i);
1190                 else
1191                         dhpa = l32get(xsdt->p+i);
1192                 if((sdt = sdtmap(dhpa, &l, 1)) == NULL)
1193                         continue;
1194                 unmap = 1;
1195                 memmove(tsig, sdt, 4);
1196                 tsig[4] = 0;
1197                 if(sig == NULL || strcmp(sig, tsig) == 0){
1198                         printk("acpi: %s addr %#p\n", tsig, sdt);
1199                         for(t = 0; t < ARRAY_SIZE(ptables); t++)
1200                                 if(strcmp(tsig, ptables[t].sig) == 0){
1201                                         //dumptable(table, &table[127], tsig, sdt, l);
1202                                         unmap = ptables[t].f(sdt, l) == NULL;
1203                                         found = 1;
1204                                         break;
1205                                 }
1206                 }
1207 //              if(unmap)
1208 //                      vunmap(sdt, l);
1209         }
1210         return found;
1211 }
1212
1213 static void*
1214 rsdscan(uint8_t* addr, int len, char* signature)
1215 {
1216         int sl;
1217         uint8_t *e, *p;
1218
1219         printk("SCANNNNNNNNNNNNNNNNNNNNNNNNNNNNN\n");
1220         e = addr+len;
1221         sl = strlen(signature);
1222         for(p = addr; p+sl < e; p += 16){
1223                 if (p == (void *)0xf15c0)
1224                         printk("CHECK F15C0!!!!!!!!!!!!!!!\n");
1225                 if(memcmp(p, signature, sl))
1226                         continue;
1227                 printk("WE GOT %p\n", p);
1228                 return p;
1229         }
1230
1231         return NULL;
1232 }
1233
1234 static void*
1235 rsdsearch(char* signature)
1236 {
1237         uintptr_t p;
1238         uint8_t *bda;
1239         void *rsd;
1240
1241         /*
1242          * Search for the data structure signature:
1243          * 1) in the BIOS ROM between 0xE0000 and 0xFFFFF.
1244          */
1245         return rsdscan(KADDR(0xE0000), 0x20000, signature);
1246 }
1247
1248 static void
1249 acpirsdptr(void)
1250 {
1251         struct Rsdp *rsd;
1252         int asize;
1253         uintptr_t sdtpa;
1254
1255         if((rsd = rsdsearch("RSD PTR ")) == NULL) {
1256                 return;
1257         }
1258
1259         assert(sizeof(struct Sdthdr) == 36);
1260
1261         printk("acpi: RSD PTR@ %#p, physaddr $%p length %ud %#llux rev %d\n",
1262                 rsd, l32get(rsd->raddr), l32get(rsd->length),
1263                 l64get(rsd->xaddr), rsd->revision);
1264
1265         if(rsd->revision >= 2){
1266                 if(sdtchecksum(rsd, 36) == NULL){
1267                         printk("acpi: RSD: bad checksum\n");
1268                         return;
1269                 }
1270                 sdtpa = l64get(rsd->xaddr);
1271                 asize = 8;
1272         }
1273         else{
1274                 if(sdtchecksum(rsd, 20) == NULL){
1275                         printk("acpi: RSD: bad checksum\n");
1276                         return;
1277                 }
1278                 sdtpa = l32get(rsd->raddr);
1279                 asize = 4;
1280         }
1281
1282         /*
1283          * process the RSDT or XSDT table.
1284          */
1285         xsdt = kzmalloc(sizeof(struct Xsdt), 0);
1286         if(xsdt == NULL){
1287                 printk("acpi: malloc failed\n");
1288                 return;
1289         }
1290         if((xsdt->p = sdtmap(sdtpa, &xsdt->len, 1)) == NULL){
1291                 printk("acpi: sdtmap failed\n");
1292                 return;
1293         }
1294         if((xsdt->p[0] != 'R' && xsdt->p[0] != 'X') || memcmp(xsdt->p+1, "SDT", 3) != 0){
1295                 printk("acpi: xsdt sig: %c%c%c%c\n",
1296                         xsdt->p[0], xsdt->p[1], xsdt->p[2], xsdt->p[3]);
1297                 kfree(xsdt);
1298                 xsdt = NULL;
1299                 //vunmap(xsdt, xsdt->len);
1300                 return;
1301         }
1302         xsdt->p += sizeof(struct Sdthdr);
1303         xsdt->len -= sizeof(struct Sdthdr);
1304         xsdt->asize = asize;
1305         printk("acpi: XSDT %#p\n", xsdt);
1306         acpixsdtload(NULL);
1307         /* xsdt is kept and not unmapped */
1308
1309 }
1310
1311 static int
1312 acpigen(struct chan *c, char *unused_char_p_t, struct dirtab *tab, int ntab, int i,
1313         struct dir *dp)
1314 {
1315         struct qid qid;
1316
1317         if(i == DEVDOTDOT){
1318                 mkqid(&qid, Qdir, 0, QTDIR);
1319                 devdir(c, qid, ".", 0, eve, 0555, dp);
1320                 return 1;
1321         }
1322         i++; /* skip first element for . itself */
1323         if(tab==0 || i>=ntab) {
1324                 return -1;
1325         }
1326         tab += i;
1327         qid = tab->qid;
1328         qid.path &= ~Qdir;
1329         qid.vers = 0;
1330         devdir(c, qid, tab->name, tab->length, eve, tab->perm, dp);
1331         return 1;
1332 }
1333
1334 static char *
1335 dumpGas(char *start, char *end, char *prefix, struct Gas *g)
1336 {
1337         static char* rnames[] = {
1338                         "mem", "io", "pcicfg", "embed",
1339                         "smb", "cmos", "pcibar", "ipmi"};
1340         start = seprintf(start, end, "%s", prefix);
1341
1342         switch(g->spc){
1343         case Rsysmem:
1344         case Rsysio:
1345         case Rembed:
1346         case Rsmbus:
1347         case Rcmos:
1348         case Rpcibar:
1349         case Ripmi:
1350                 start = seprintf(start, end, "[%s ", rnames[g->spc]);
1351                 break;
1352         case Rpcicfg:
1353                 start = seprintf(start, end, "[pci ");
1354                 start = seprintf(start, end, "dev %#p ", (uint32_t)(g->addr >> 32) & 0xFFFF);
1355                 start = seprintf(start, end, "fn %#p ", (uint32_t)(g->addr & 0xFFFF0000) >> 16);
1356                 start = seprintf(start, end, "adr %#p ", (uint32_t)(g->addr &0xFFFF));
1357                 break;
1358         case Rfixedhw:
1359                 start = seprintf(start, end, "[hw ");
1360                 break;
1361         default:
1362                 start = seprintf(start, end, "[spc=%#p ", g->spc);
1363         }
1364         start = seprintf(start, end, "off %d len %d addr %#p sz%d]",
1365                 g->off, g->len, g->addr, g->accsz);
1366         start = seprintf(start, end, "\n");
1367         return start;
1368 }
1369
1370 static unsigned int
1371 getbanked(uintptr_t ra, uintptr_t rb, int sz)
1372 {
1373         unsigned int r;
1374
1375         r = 0;
1376         switch(sz){
1377         case 1:
1378                 if(ra != 0)
1379                         r |= inb(ra);
1380                 if(rb != 0)
1381                         r |= inb(rb);
1382                 break;
1383         case 2:
1384                 if(ra != 0)
1385                         r |= inw(ra);
1386                 if(rb != 0)
1387                         r |= inw(rb);
1388                 break;
1389         case 4:
1390                 if(ra != 0)
1391                         r |= inl(ra);
1392                 if(rb != 0)
1393                         r |= inl(rb);
1394                 break;
1395         default:
1396                 printd("getbanked: wrong size\n");
1397         }
1398         return r;
1399 }
1400
1401 static unsigned int
1402 setbanked(uintptr_t ra, uintptr_t rb, int sz, int v)
1403 {
1404         unsigned int r;
1405
1406         r = -1;
1407         switch(sz){
1408         case 1:
1409                 if(ra != 0)
1410                         outb(ra, v);
1411                 if(rb != 0)
1412                         outb(rb, v);
1413                 break;
1414         case 2:
1415                 if(ra != 0)
1416                         outw(ra, v);
1417                 if(rb != 0)
1418                         outw(rb, v);
1419                 break;
1420         case 4:
1421                 if(ra != 0)
1422                         outl(ra, v);
1423                 if(rb != 0)
1424                         outl(rb, v);
1425                 break;
1426         default:
1427                 printd("setbanked: wrong size\n");
1428         }
1429         return r;
1430 }
1431
1432 static unsigned int
1433 getpm1ctl(void)
1434 {
1435         return getbanked(fadt.pm1acntblk, fadt.pm1bcntblk, fadt.pm1cntlen);
1436 }
1437
1438 static void
1439 setpm1sts(unsigned int v)
1440 {
1441         printk("acpi: setpm1sts %#p\n", v);
1442         setbanked(fadt.pm1aevtblk, fadt.pm1bevtblk, fadt.pm1evtlen/2, v);
1443 }
1444
1445 static unsigned int
1446 getpm1sts(void)
1447 {
1448         return getbanked(fadt.pm1aevtblk, fadt.pm1bevtblk, fadt.pm1evtlen/2);
1449 }
1450
1451 static unsigned int
1452 getpm1en(void)
1453 {
1454         int sz;
1455
1456         sz = fadt.pm1evtlen/2;
1457         return getbanked(fadt.pm1aevtblk+sz, fadt.pm1bevtblk+sz, sz);
1458 }
1459
1460 static int
1461 getgpeen(int n)
1462 {
1463         return inb(gpes[n].enio) & 1<<gpes[n].enbit;
1464 }
1465
1466 static void
1467 setgpeen(int n, unsigned int v)
1468 {
1469         int old;
1470
1471         printk("acpi: setgpe %d %d\n", n, v);
1472         old = inb(gpes[n].enio);
1473         if(v)
1474                 outb(gpes[n].enio, old | 1<<gpes[n].enbit);
1475         else
1476                 outb(gpes[n].enio, old & ~(1<<gpes[n].enbit));
1477 }
1478
1479 static void
1480 clrgpests(int n)
1481 {
1482         outb(gpes[n].stsio, 1<<gpes[n].stsbit);
1483 }
1484
1485 static unsigned int
1486 getgpests(int n)
1487 {
1488         return inb(gpes[n].stsio) & 1<<gpes[n].stsbit;
1489 }
1490
1491 #warning "no acpi interrupts yet"
1492 #if 0
1493 static void
1494 acpiintr(Ureg*, void*)
1495 {
1496         int i;
1497         unsigned int sts, en;
1498
1499         printd("acpi: intr\n");
1500
1501         for(i = 0; i < ngpes; i++)
1502                 if(getgpests(i)){
1503                         printd("gpe %d on\n", i);
1504                         en = getgpeen(i);
1505                         setgpeen(i, 0);
1506                         clrgpests(i);
1507                         if(en != 0)
1508                                 printd("acpiitr: calling gpe %d\n", i);
1509                 //      queue gpe for calling gpe->ho in the
1510                 //      aml process.
1511                 //      enable it again when it returns.
1512                 }
1513         sts = getpm1sts();
1514         en = getpm1en();
1515         printd("acpiitr: pm1sts %#p pm1en %#p\n", sts, en);
1516         if(sts&en)
1517                 printd("have enabled events\n");
1518         if(sts&1)
1519                 printd("power button\n");
1520         // XXX serve other interrupts here.
1521         setpm1sts(sts); 
1522 }
1523 #endif
1524 static void
1525 initgpes(void)
1526 {
1527         int i, n0, n1;
1528
1529         n0 = fadt.gpe0blklen/2;
1530         n1 = fadt.gpe1blklen/2;
1531         ngpes = n0 + n1;
1532         gpes = kzmalloc(sizeof(struct Gpe) * ngpes, 1);
1533         for(i = 0; i < n0; i++){
1534                 gpes[i].nb = i;
1535                 gpes[i].stsbit = i&7;
1536                 gpes[i].stsio = fadt.gpe0blk + (i>>3);
1537                 gpes[i].enbit = (n0 + i)&7;
1538                 gpes[i].enio = fadt.gpe0blk + ((n0 + i)>>3);
1539         }
1540         for(i = 0; i + n0 < ngpes; i++){
1541                 gpes[i + n0].nb = fadt.gp1base + i;
1542                 gpes[i + n0].stsbit = i&7;
1543                 gpes[i + n0].stsio = fadt.gpe1blk + (i>>3);
1544                 gpes[i + n0].enbit = (n1 + i)&7;
1545                 gpes[i + n0].enio = fadt.gpe1blk + ((n1 + i)>>3);
1546         }
1547         for(i = 0; i < ngpes; i++){
1548                 setgpeen(i, 0);
1549                 clrgpests(i);
1550         }
1551 }
1552
1553 static void
1554 acpiioalloc(unsigned int addr, int len)
1555 {
1556         if(addr != 0){
1557                 printk("Just TAKING port %016lx to %016lx\n", 
1558                        addr, addr + len);
1559                 //ioalloc(addr, len, 0, "acpi");
1560         }
1561 }
1562
1563 int
1564 acpiinit(void)
1565 {
1566         /* this smicmd test implements 'run once' for now. */
1567         if(fadt.smicmd == 0){
1568                 //fmtinstall('G', Gfmt);
1569                 acpirsdptr();
1570                 if(fadt.smicmd == 0) {
1571                         printk("acpiinit returns -1\n");
1572                         return -1;
1573                 }
1574                 int mpacpi(int ncleft);
1575                 printk("mpacpi(32) is %d\n", mpacpi(32));
1576
1577         }
1578         return 0;
1579 }
1580
1581 static struct chan*
1582 acpiattach(char *spec)
1583 {
1584         int i;
1585
1586         printk("ACPI attach\n");
1587         /*
1588          * This was written for the stock kernel.
1589          * This code must use 64 registers to be acpi ready in nix.
1590          */
1591         if(acpiinit() < 0){
1592                 printk("ACPIINIT is called\n");
1593                 error("no acpi");
1594         }
1595
1596         /*
1597          * should use fadt->xpm* and fadt->xgpe* registers for 64 bits.
1598          * We are not ready in this kernel for that.
1599          */
1600         printk("acpi io alloc\n");
1601         acpiioalloc(fadt.smicmd, 1);
1602         acpiioalloc(fadt.pm1aevtblk, fadt.pm1evtlen);
1603         acpiioalloc(fadt.pm1bevtblk, fadt.pm1evtlen );
1604         acpiioalloc(fadt.pm1acntblk, fadt.pm1cntlen);
1605         acpiioalloc(fadt.pm1bcntblk, fadt.pm1cntlen);
1606         acpiioalloc(fadt.pm2cntblk, fadt.pm2cntlen);
1607         acpiioalloc(fadt.pmtmrblk, fadt.pmtmrlen);
1608         acpiioalloc(fadt.gpe0blk, fadt.gpe0blklen);
1609         acpiioalloc(fadt.gpe1blk, fadt.gpe1blklen);
1610
1611         printk("acpi init gpes\n");
1612         initgpes();
1613
1614         /*
1615          * This starts ACPI, which may require we handle
1616          * power mgmt events ourselves. Use with care.
1617          */
1618         outb(fadt.smicmd, fadt.acpienable);
1619         for(i = 0; i < 10; i++)
1620                 if(getpm1ctl() & Pm1SciEn)
1621                         break;
1622         if(i == 10)
1623                 error("acpi: failed to enable\n");
1624 //      if(fadt.sciint != 0)
1625 //              intrenable(fadt.sciint, acpiintr, 0, BUSUNKNOWN, "acpi");
1626         return devattach('a', spec);
1627 }
1628
1629 static struct walkqid*
1630 acpiwalk(struct chan *c, struct chan *nc, char **name, int nname)
1631 {
1632         return devwalk(c, nc, name, nname, acpidir, ARRAY_SIZE(acpidir), acpigen);
1633 }
1634
1635 static int
1636 acpistat(struct chan *c, uint8_t *dp, int n)
1637 {
1638         return devstat(c, dp, n, acpidir, ARRAY_SIZE(acpidir), acpigen);
1639 }
1640
1641 static struct chan*
1642 acpiopen(struct chan *c, int omode)
1643 {
1644         return devopen(c, omode, acpidir, ARRAY_SIZE(acpidir), acpigen);
1645 }
1646
1647 static void
1648 acpiclose(struct chan *unused)
1649 {
1650 }
1651
1652 static char*ttext;
1653 static int tlen;
1654
1655 static long
1656 acpiread(struct chan *c, void *a, long n, int64_t off)
1657 {
1658         long q;
1659         struct Atable *t;
1660         char *ns, *s, *e, *ntext;
1661
1662         q = c->qid.path;
1663         switch(q){
1664         case Qdir:
1665                 return devdirread(c, a, n, acpidir, ARRAY_SIZE(acpidir), acpigen);
1666         case Qtbl:
1667                 if(ttext == NULL){ // XXXXXX
1668                         tlen = 32768;
1669                         ttext = kzmalloc(tlen, 0);
1670                         if(ttext == NULL){
1671                                 printd("acpi: no memory\n");
1672                                 return 0;
1673                         }
1674                         s = ttext;
1675                         e = ttext + tlen;
1676                         strncpy(s,  "no tables\n", sizeof(s));
1677                         for(t = tfirst; t != NULL; t = t->next){
1678                                 ns = seprinttable(s, e, t);
1679                                 while(ns == e - 1){
1680                                         printk("acpiread: allocated %d\n", tlen*2);
1681                                         ntext = krealloc(ttext, tlen*2, 0);
1682                                         if(ntext == NULL)
1683                                                 panic("acpi: no memory\n");
1684                                         s = ntext + (ttext - s);
1685                                         ttext = ntext;
1686                                         tlen *= 2;
1687                                         e = ttext + tlen;
1688                                         ns = seprinttable(s, e, t);
1689                                 }
1690                                 s = ns;
1691                         }
1692                                         
1693                 }
1694                 return readstr(off, a, n, ttext);
1695         case Qpretty:
1696                 if(ttext == NULL){
1697                         tlen = 32768;
1698                         ttext = kzmalloc(tlen, 0);
1699                         if(ttext == NULL){
1700                                 printd("acpi: no memory\n");
1701                                 return 0;
1702                         }
1703                         s = ttext;
1704                         e = ttext + tlen;
1705                         s = dumpfadt(s, e, &fadt);
1706                         s = dumpmadt(s, e, apics);
1707                         s = dumpslit(s, e, slit);
1708                         s = dumpsrat(s, e, srat);
1709                         dumpmsct(s, e, msct);
1710                 }
1711                 return readstr(off, a, n, ttext);
1712         case Qio:
1713                 if(reg == NULL)
1714                         error("region not configured");
1715                 return regio(reg, a, n, off, 0);
1716         }
1717         error(Eperm);
1718         return -1;
1719 }
1720
1721 static long
1722 acpiwrite(struct chan *c, void *a, long n, int64_t off)
1723 {
1724         ERRSTACK(2);
1725         struct cmdtab *ct;
1726         struct cmdbuf *cb;
1727         struct Reg *r;
1728         unsigned int rno, fun, dev, bus, i;
1729
1730         if(c->qid.path == Qio){
1731                 if(reg == NULL)
1732                         error("region not configured");
1733                 return regio(reg, a, n, off, 1);
1734         }
1735         if(c->qid.path != Qctl)
1736                 error(Eperm);
1737
1738         cb = parsecmd(a, n);
1739         if(waserror()){
1740                 kfree(cb);
1741                 nexterror();
1742         }
1743         ct = lookupcmd(cb, ctls, ARRAY_SIZE(ctls));
1744         printk("acpi ctl %s\n", cb->f[0]);
1745         switch(ct->index){
1746         case CMregion:
1747                 r = reg;
1748                 if(r == NULL){
1749                         r = kzmalloc(sizeof(struct Reg), 0);
1750                         r->name = NULL;
1751                 }
1752                 kstrdup(&r->name, cb->f[1]);
1753                 r->spc = acpiregid(cb->f[2]);
1754                 if(r->spc < 0){
1755                         kfree(r);
1756                         reg = NULL;
1757                         error("bad region type");
1758                 }
1759                 if(r->spc == Rpcicfg || r->spc == Rpcibar){
1760                         rno = r->base>>Rpciregshift & Rpciregmask;
1761                         fun = r->base>>Rpcifunshift & Rpcifunmask;
1762                         dev = r->base>>Rpcidevshift & Rpcidevmask;
1763                         bus = r->base>>Rpcibusshift & Rpcibusmask;
1764 #define MKBUS(t,b,d,f)  (((t)<<24)|(((b)&0xFF)<<16)|(((d)&0x1F)<<11)|(((f)&0x07)<<8))
1765                         r->tbdf = MKBUS(0/*BusPCI*/, bus, dev, fun);
1766                         r->base = rno;  /* register ~ our base addr */
1767                 }
1768                 r->base = strtoul(cb->f[3], NULL, 0);
1769                 r->len = strtoul(cb->f[4], NULL, 0);
1770                 r->accsz = strtoul(cb->f[5], NULL, 0);
1771                 if(r->accsz < 1 || r->accsz > 4){
1772                         kfree(r);
1773                         reg = NULL;
1774                         error("bad region access size");
1775                 }
1776                 reg = r;
1777                 printk("region %s %s %p %p sz%d",
1778                         r->name, acpiregstr(r->spc), r->base, r->len, r->accsz);
1779                 break;
1780         case CMgpe:
1781                 i = strtoul(cb->f[1], NULL, 0);
1782                 if(i >= ngpes)
1783                         error("gpe out of range");
1784                 kstrdup(&gpes[i].obj, cb->f[2]);
1785                 printk("gpe %d %s\n", i, gpes[i].obj);
1786                 setgpeen(i, 1);
1787                 break;
1788         default:
1789                 panic("acpi: unknown ctl");
1790         }
1791         poperror();
1792         kfree(cb);
1793         return n;
1794 }
1795
1796
1797 struct dev acpidevtab __devtab = {
1798         'a',
1799         "acpi",
1800
1801         devreset,
1802         devinit,
1803         devshutdown,
1804         acpiattach,
1805         acpiwalk,
1806         acpistat,
1807         acpiopen,
1808         devcreate,
1809         acpiclose,
1810         acpiread,
1811         devbread,
1812         acpiwrite,
1813         devbwrite,
1814         devremove,
1815         devwstat,
1816 };