Add a bit more info to the print, we can now see introvr flags and what they mean.
[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 *polarity[4] = {
939         "polarity/trigger like in ISA",
940         "active high",
941         "BOGUS POLARITY",
942         "active low"
943 };
944
945 static char *trigger[] = {
946         "BOGUS TRIGGER",
947         "edge",
948         "BOGUS TRIGGER",
949         "level"
950 };
951
952 static char *printiflags(char *start, char *end, int flags)
953 {
954
955         return seprintf(start, end, "[%s,%s]",
956                 polarity[flags & AFpmask], 
957                 trigger[(flags & AFtmask)>>2]);
958 }
959 static char *
960 dumpmadt(char *start, char *end, struct Madt *apics)
961 {
962         struct Apicst *st;
963
964         start = seprintf(start, end, "acpi: madt lapic paddr %llux pcat %d:\n", apics->lapicpa, apics->pcat);
965         for(st = apics->st; st != NULL; st = st->next)
966                 switch(st->type){
967                 case ASlapic:
968                         start = seprintf(start, end, "\tlapic pid %d id %d\n", st->lapic.pid, st->lapic.id);
969                         break;
970                 case ASioapic:
971                 case ASiosapic:
972                         start = seprintf(start, end, "\tioapic id %d addr %#llux ibase %d\n",
973                                          st->ioapic.id, st->ioapic.addr, st->ioapic.ibase);
974                         break;
975                 case ASintovr:
976                         start = seprintf(start, end, "\tintovr irq %d intr %d flags $%p",
977                                          st->intovr.irq, st->intovr.intr,st->intovr.flags);
978                         start = printiflags(start, end, st->intovr.flags);
979                         start = seprintf(start, end, "\n");
980                         break;
981                 case ASnmi:
982                         start = seprintf(start, end, "\tnmi intr %d flags $%p\n",
983                                 st->nmi.intr, st->nmi.flags);
984                         break;
985                 case ASlnmi:
986                         start = seprintf(start, end, "\tlnmi pid %d lint %d flags $%p\n",
987                                 st->lnmi.pid, st->lnmi.lint, st->lnmi.flags);
988                         break;
989                 case ASlsapic:
990                         start = seprintf(start, end, "\tlsapic pid %d id %d eid %d puid %d puids %s\n",
991                                 st->lsapic.pid, st->lsapic.id,
992                                 st->lsapic.eid, st->lsapic.puid,
993                                 st->lsapic.puids);
994                         break;
995                 case ASintsrc:
996                         start = seprintf(start, end, "\tintr type %d pid %d peid %d iosv %d intr %d %#x\n",
997                                 st->type, st->intsrc.pid,
998                                 st->intsrc.peid, st->intsrc.iosv,
999                                 st->intsrc.intr, st->intsrc.flags);
1000                         start = printiflags(start, end, st->intsrc.flags);
1001                         start = seprintf(start, end, "\n");
1002                         break;
1003                 case ASlx2apic:
1004                         start = seprintf(start, end, "\tlx2apic puid %d id %d\n", st->lx2apic.puid, st->lx2apic.id);
1005                         break;
1006                 case ASlx2nmi:
1007                         start = seprintf(start, end, "\tlx2nmi puid %d intr %d flags $%p\n",
1008                                 st->lx2nmi.puid, st->lx2nmi.intr, st->lx2nmi.flags);
1009                         break;
1010                 default:
1011                         start = seprintf(start, end, "\t<unknown madt entry>\n");
1012                 }
1013         start = seprintf(start, end, "\n");
1014         return start;
1015 }
1016
1017 static struct Atable*
1018 acpimadt(uint8_t *p, int len)
1019 {
1020
1021         uint8_t *pe;
1022         struct Apicst *st, *l, **stl;
1023         int stlen, id;
1024
1025         apics = kzmalloc(sizeof(struct Madt), 1);
1026         apics->lapicpa = l32get(p+36);
1027         apics->pcat = l32get(p+40);
1028         apics->st = NULL;
1029         stl = &apics->st;
1030         pe = p + len;
1031         for(p += 44; p < pe; p += stlen){
1032                 st = kzmalloc(sizeof(struct Apicst), 1);
1033                 st->type = p[0];
1034                 st->next = NULL;
1035                 stlen = p[1];
1036                 switch(st->type){
1037                 case ASlapic:
1038                         st->lapic.pid = p[2];
1039                         st->lapic.id = p[3];
1040                         if(l32get(p+4) == 0){
1041                                 kfree(st);
1042                                 st = NULL;
1043                         }
1044                         break;
1045                 case ASioapic:
1046                         st->ioapic.id = id = p[2];
1047                         st->ioapic.addr = l32get(p+4);
1048                         st->ioapic.ibase = l32get(p+8);
1049                         /* iosapic overrides any ioapic entry for the same id */
1050                         for(l = apics->st; l != NULL; l = l->next)
1051                                 if(l->type == ASiosapic && l->iosapic.id == id){
1052                                         st->ioapic = l->iosapic;
1053                                         /* we leave it linked; could be removed */
1054                                         break;
1055                                 }
1056                         break;
1057                 case ASintovr:
1058                         st->intovr.irq = p[3];
1059                         st->intovr.intr = l32get(p+4);
1060                         st->intovr.flags = l16get(p+8);
1061                         break;
1062                 case ASnmi:
1063                         st->nmi.flags = l16get(p+2);
1064                         st->nmi.intr = l32get(p+4);
1065                         break;
1066                 case ASlnmi:
1067                         st->lnmi.pid = p[2];
1068                         st->lnmi.flags = l16get(p+3);
1069                         st->lnmi.lint = p[5];
1070                         break;
1071                 case ASladdr:
1072                         /* This is for 64 bits, perhaps we should not
1073                          * honor it on 32 bits.
1074                          */
1075                         apics->lapicpa = l64get(p+8);
1076                         break;
1077                 case ASiosapic:
1078                         id = st->iosapic.id = p[2];
1079                         st->iosapic.ibase = l32get(p+4);
1080                         st->iosapic.addr = l64get(p+8);
1081                         /* iosapic overrides any ioapic entry for the same id */
1082                         for(l = apics->st; l != NULL; l = l->next)
1083                                 if(l->type == ASioapic && l->ioapic.id == id){
1084                                         l->ioapic = st->iosapic;
1085                                         kfree(st);
1086                                         st = NULL;
1087                                         break;
1088                                 }
1089                         break;
1090                 case ASlsapic:
1091                         st->lsapic.pid = p[2];
1092                         st->lsapic.id = p[3];
1093                         st->lsapic.eid = p[4];
1094                         st->lsapic.puid = l32get(p+12);
1095                         if(l32get(p+8) == 0){
1096                                 kfree(st);
1097                                 st = NULL;
1098                         }else
1099                                 kstrdup(&st->lsapic.puids, (char *)p+16);
1100                         break;
1101                 case ASintsrc:
1102                         st->intsrc.flags = l16get(p+2);
1103                         st->type = p[4];
1104                         st->intsrc.pid = p[5];
1105                         st->intsrc.peid = p[6];
1106                         st->intsrc.iosv = p[7];
1107                         st->intsrc.intr = l32get(p+8);
1108                         st->intsrc.any = l32get(p+12);
1109                         break;
1110                 case ASlx2apic:
1111                         st->lx2apic.id = l32get(p+4);
1112                         st->lx2apic.puid = l32get(p+12);
1113                         if(l32get(p+8) == 0){
1114                                 kfree(st);
1115                                 st = NULL;
1116                         }
1117                         break;
1118                 case ASlx2nmi:
1119                         st->lx2nmi.flags = l16get(p+2);
1120                         st->lx2nmi.puid = l32get(p+4);
1121                         st->lx2nmi.intr = p[8];
1122                         break;
1123                 default:
1124                         printd("unknown APIC structure\n");
1125                         kfree(st);
1126                         st = NULL;
1127                 }
1128                 if(st != NULL){
1129                         *stl = st;
1130                         stl = &st->next;
1131                 }
1132         }
1133 #if 0
1134         char *dump;
1135         dump = kzmalloc(8192, KMALLOC_WAIT);
1136         dumpmadt(dump, &dump[8191], apics);
1137         printk("%s\n", dump);
1138         kfree(dump);
1139 #endif
1140         return NULL;    /* can be unmapped once parsed */
1141 }
1142
1143 /*
1144  * Map the table and keep it there.
1145  */
1146 static struct Atable*
1147 acpitable(uint8_t *p, int len)
1148 {
1149         if(len < Sdthdrsz) {
1150                 return NULL;
1151         }
1152         return newtable(p);
1153 }
1154
1155 static char *
1156 dumptable(char *start, char *end, char *sig, uint8_t *p, int l)
1157 {
1158         int n, i;
1159
1160         if(2 > 1){
1161                 start = seprintf(start, end, "%s @ %#p\n", sig, p);
1162                 if(2 > 2)
1163                         n = l;
1164                 else
1165                         n = 256;
1166                 for(i = 0; i < n; i++){
1167                         if((i % 16) == 0)
1168                                 start = seprintf(start, end, "%x: ", i);
1169                         start = seprintf(start, end, " %2.2ux", p[i]);
1170                         if((i % 16) == 15)
1171                                 start = seprintf(start, end, "\n");
1172                 }
1173                 start = seprintf(start, end, "\n");
1174                 start = seprintf(start, end, "\n");
1175         }
1176         return start;
1177 }
1178
1179 static char*
1180 seprinttable(char *s, char *e, struct Atable *t)
1181 {
1182         uint8_t *p;
1183         int i, n;
1184
1185         p = ( uint8_t *)t->tbl; /* include header */
1186         n = Sdthdrsz + t->dlen;
1187         s = seprintf(s, e, "%s @ %#p\n", t->sig, p);
1188         for(i = 0; i < n; i++){
1189                 if((i % 16) == 0)
1190                         s = seprintf(s, e, "%x: ", i);
1191                 s = seprintf(s, e, " %2.2ux", p[i]);
1192                 if((i % 16) == 15)
1193                         s = seprintf(s, e, "\n");
1194         }
1195         return seprintf(s, e, "\n\n");
1196 }
1197
1198 /*
1199  * process xsdt table and load tables with sig, or all if NULL.
1200  * (XXX: should be able to search for sig, oemid, oemtblid)
1201  */
1202 static int
1203 acpixsdtload(char *sig)
1204 {
1205         int i, l, t, unmap, found;
1206         uintptr_t dhpa;
1207         uint8_t *sdt;
1208         char tsig[5];
1209         char table[128];
1210
1211         found = 0;
1212         for(i = 0; i < xsdt->len; i += xsdt->asize){
1213                 if(xsdt->asize == 8)
1214                         dhpa = l64get(xsdt->p+i);
1215                 else
1216                         dhpa = l32get(xsdt->p+i);
1217                 if((sdt = sdtmap(dhpa, &l, 1)) == NULL)
1218                         continue;
1219                 unmap = 1;
1220                 memmove(tsig, sdt, 4);
1221                 tsig[4] = 0;
1222                 if(sig == NULL || strcmp(sig, tsig) == 0){
1223                         printk("acpi: %s addr %#p\n", tsig, sdt);
1224                         for(t = 0; t < ARRAY_SIZE(ptables); t++)
1225                                 if(strcmp(tsig, ptables[t].sig) == 0){
1226                                         //dumptable(table, &table[127], tsig, sdt, l);
1227                                         unmap = ptables[t].f(sdt, l) == NULL;
1228                                         found = 1;
1229                                         break;
1230                                 }
1231                 }
1232 //              if(unmap)
1233 //                      vunmap(sdt, l);
1234         }
1235         return found;
1236 }
1237
1238 static void*
1239 rsdscan(uint8_t* addr, int len, char* signature)
1240 {
1241         int sl;
1242         uint8_t *e, *p;
1243
1244         printk("SCANNNNNNNNNNNNNNNNNNNNNNNNNNNNN\n");
1245         e = addr+len;
1246         sl = strlen(signature);
1247         for(p = addr; p+sl < e; p += 16){
1248                 if (p == (void *)0xf15c0)
1249                         printk("CHECK F15C0!!!!!!!!!!!!!!!\n");
1250                 if(memcmp(p, signature, sl))
1251                         continue;
1252                 printk("WE GOT %p\n", p);
1253                 return p;
1254         }
1255
1256         return NULL;
1257 }
1258
1259 static void*
1260 rsdsearch(char* signature)
1261 {
1262         uintptr_t p;
1263         uint8_t *bda;
1264         void *rsd;
1265
1266         /*
1267          * Search for the data structure signature:
1268          * 1) in the BIOS ROM between 0xE0000 and 0xFFFFF.
1269          */
1270         return rsdscan(KADDR(0xE0000), 0x20000, signature);
1271 }
1272
1273 static void
1274 acpirsdptr(void)
1275 {
1276         struct Rsdp *rsd;
1277         int asize;
1278         uintptr_t sdtpa;
1279
1280         if((rsd = rsdsearch("RSD PTR ")) == NULL) {
1281                 return;
1282         }
1283
1284         assert(sizeof(struct Sdthdr) == 36);
1285
1286         printk("acpi: RSD PTR@ %#p, physaddr $%p length %ud %#llux rev %d\n",
1287                 rsd, l32get(rsd->raddr), l32get(rsd->length),
1288                 l64get(rsd->xaddr), rsd->revision);
1289
1290         if(rsd->revision >= 2){
1291                 if(sdtchecksum(rsd, 36) == NULL){
1292                         printk("acpi: RSD: bad checksum\n");
1293                         return;
1294                 }
1295                 sdtpa = l64get(rsd->xaddr);
1296                 asize = 8;
1297         }
1298         else{
1299                 if(sdtchecksum(rsd, 20) == NULL){
1300                         printk("acpi: RSD: bad checksum\n");
1301                         return;
1302                 }
1303                 sdtpa = l32get(rsd->raddr);
1304                 asize = 4;
1305         }
1306
1307         /*
1308          * process the RSDT or XSDT table.
1309          */
1310         xsdt = kzmalloc(sizeof(struct Xsdt), 0);
1311         if(xsdt == NULL){
1312                 printk("acpi: malloc failed\n");
1313                 return;
1314         }
1315         if((xsdt->p = sdtmap(sdtpa, &xsdt->len, 1)) == NULL){
1316                 printk("acpi: sdtmap failed\n");
1317                 return;
1318         }
1319         if((xsdt->p[0] != 'R' && xsdt->p[0] != 'X') || memcmp(xsdt->p+1, "SDT", 3) != 0){
1320                 printk("acpi: xsdt sig: %c%c%c%c\n",
1321                         xsdt->p[0], xsdt->p[1], xsdt->p[2], xsdt->p[3]);
1322                 kfree(xsdt);
1323                 xsdt = NULL;
1324                 //vunmap(xsdt, xsdt->len);
1325                 return;
1326         }
1327         xsdt->p += sizeof(struct Sdthdr);
1328         xsdt->len -= sizeof(struct Sdthdr);
1329         xsdt->asize = asize;
1330         printk("acpi: XSDT %#p\n", xsdt);
1331         acpixsdtload(NULL);
1332         /* xsdt is kept and not unmapped */
1333
1334 }
1335
1336 static int
1337 acpigen(struct chan *c, char *unused_char_p_t, struct dirtab *tab, int ntab, int i,
1338         struct dir *dp)
1339 {
1340         struct qid qid;
1341
1342         if(i == DEVDOTDOT){
1343                 mkqid(&qid, Qdir, 0, QTDIR);
1344                 devdir(c, qid, ".", 0, eve, 0555, dp);
1345                 return 1;
1346         }
1347         i++; /* skip first element for . itself */
1348         if(tab==0 || i>=ntab) {
1349                 return -1;
1350         }
1351         tab += i;
1352         qid = tab->qid;
1353         qid.path &= ~Qdir;
1354         qid.vers = 0;
1355         devdir(c, qid, tab->name, tab->length, eve, tab->perm, dp);
1356         return 1;
1357 }
1358
1359 static char *
1360 dumpGas(char *start, char *end, char *prefix, struct Gas *g)
1361 {
1362         static char* rnames[] = {
1363                         "mem", "io", "pcicfg", "embed",
1364                         "smb", "cmos", "pcibar", "ipmi"};
1365         start = seprintf(start, end, "%s", prefix);
1366
1367         switch(g->spc){
1368         case Rsysmem:
1369         case Rsysio:
1370         case Rembed:
1371         case Rsmbus:
1372         case Rcmos:
1373         case Rpcibar:
1374         case Ripmi:
1375                 start = seprintf(start, end, "[%s ", rnames[g->spc]);
1376                 break;
1377         case Rpcicfg:
1378                 start = seprintf(start, end, "[pci ");
1379                 start = seprintf(start, end, "dev %#p ", (uint32_t)(g->addr >> 32) & 0xFFFF);
1380                 start = seprintf(start, end, "fn %#p ", (uint32_t)(g->addr & 0xFFFF0000) >> 16);
1381                 start = seprintf(start, end, "adr %#p ", (uint32_t)(g->addr &0xFFFF));
1382                 break;
1383         case Rfixedhw:
1384                 start = seprintf(start, end, "[hw ");
1385                 break;
1386         default:
1387                 start = seprintf(start, end, "[spc=%#p ", g->spc);
1388         }
1389         start = seprintf(start, end, "off %d len %d addr %#p sz%d]",
1390                 g->off, g->len, g->addr, g->accsz);
1391         start = seprintf(start, end, "\n");
1392         return start;
1393 }
1394
1395 static unsigned int
1396 getbanked(uintptr_t ra, uintptr_t rb, int sz)
1397 {
1398         unsigned int r;
1399
1400         r = 0;
1401         switch(sz){
1402         case 1:
1403                 if(ra != 0)
1404                         r |= inb(ra);
1405                 if(rb != 0)
1406                         r |= inb(rb);
1407                 break;
1408         case 2:
1409                 if(ra != 0)
1410                         r |= inw(ra);
1411                 if(rb != 0)
1412                         r |= inw(rb);
1413                 break;
1414         case 4:
1415                 if(ra != 0)
1416                         r |= inl(ra);
1417                 if(rb != 0)
1418                         r |= inl(rb);
1419                 break;
1420         default:
1421                 printd("getbanked: wrong size\n");
1422         }
1423         return r;
1424 }
1425
1426 static unsigned int
1427 setbanked(uintptr_t ra, uintptr_t rb, int sz, int v)
1428 {
1429         unsigned int r;
1430
1431         r = -1;
1432         switch(sz){
1433         case 1:
1434                 if(ra != 0)
1435                         outb(ra, v);
1436                 if(rb != 0)
1437                         outb(rb, v);
1438                 break;
1439         case 2:
1440                 if(ra != 0)
1441                         outw(ra, v);
1442                 if(rb != 0)
1443                         outw(rb, v);
1444                 break;
1445         case 4:
1446                 if(ra != 0)
1447                         outl(ra, v);
1448                 if(rb != 0)
1449                         outl(rb, v);
1450                 break;
1451         default:
1452                 printd("setbanked: wrong size\n");
1453         }
1454         return r;
1455 }
1456
1457 static unsigned int
1458 getpm1ctl(void)
1459 {
1460         return getbanked(fadt.pm1acntblk, fadt.pm1bcntblk, fadt.pm1cntlen);
1461 }
1462
1463 static void
1464 setpm1sts(unsigned int v)
1465 {
1466         printk("acpi: setpm1sts %#p\n", v);
1467         setbanked(fadt.pm1aevtblk, fadt.pm1bevtblk, fadt.pm1evtlen/2, v);
1468 }
1469
1470 static unsigned int
1471 getpm1sts(void)
1472 {
1473         return getbanked(fadt.pm1aevtblk, fadt.pm1bevtblk, fadt.pm1evtlen/2);
1474 }
1475
1476 static unsigned int
1477 getpm1en(void)
1478 {
1479         int sz;
1480
1481         sz = fadt.pm1evtlen/2;
1482         return getbanked(fadt.pm1aevtblk+sz, fadt.pm1bevtblk+sz, sz);
1483 }
1484
1485 static int
1486 getgpeen(int n)
1487 {
1488         return inb(gpes[n].enio) & 1<<gpes[n].enbit;
1489 }
1490
1491 static void
1492 setgpeen(int n, unsigned int v)
1493 {
1494         int old;
1495
1496         printk("acpi: setgpe %d %d\n", n, v);
1497         old = inb(gpes[n].enio);
1498         if(v)
1499                 outb(gpes[n].enio, old | 1<<gpes[n].enbit);
1500         else
1501                 outb(gpes[n].enio, old & ~(1<<gpes[n].enbit));
1502 }
1503
1504 static void
1505 clrgpests(int n)
1506 {
1507         outb(gpes[n].stsio, 1<<gpes[n].stsbit);
1508 }
1509
1510 static unsigned int
1511 getgpests(int n)
1512 {
1513         return inb(gpes[n].stsio) & 1<<gpes[n].stsbit;
1514 }
1515
1516 #warning "no acpi interrupts yet"
1517 #if 0
1518 static void
1519 acpiintr(Ureg*, void*)
1520 {
1521         int i;
1522         unsigned int sts, en;
1523
1524         printd("acpi: intr\n");
1525
1526         for(i = 0; i < ngpes; i++)
1527                 if(getgpests(i)){
1528                         printd("gpe %d on\n", i);
1529                         en = getgpeen(i);
1530                         setgpeen(i, 0);
1531                         clrgpests(i);
1532                         if(en != 0)
1533                                 printd("acpiitr: calling gpe %d\n", i);
1534                 //      queue gpe for calling gpe->ho in the
1535                 //      aml process.
1536                 //      enable it again when it returns.
1537                 }
1538         sts = getpm1sts();
1539         en = getpm1en();
1540         printd("acpiitr: pm1sts %#p pm1en %#p\n", sts, en);
1541         if(sts&en)
1542                 printd("have enabled events\n");
1543         if(sts&1)
1544                 printd("power button\n");
1545         // XXX serve other interrupts here.
1546         setpm1sts(sts); 
1547 }
1548 #endif
1549 static void
1550 initgpes(void)
1551 {
1552         int i, n0, n1;
1553
1554         n0 = fadt.gpe0blklen/2;
1555         n1 = fadt.gpe1blklen/2;
1556         ngpes = n0 + n1;
1557         gpes = kzmalloc(sizeof(struct Gpe) * ngpes, 1);
1558         for(i = 0; i < n0; i++){
1559                 gpes[i].nb = i;
1560                 gpes[i].stsbit = i&7;
1561                 gpes[i].stsio = fadt.gpe0blk + (i>>3);
1562                 gpes[i].enbit = (n0 + i)&7;
1563                 gpes[i].enio = fadt.gpe0blk + ((n0 + i)>>3);
1564         }
1565         for(i = 0; i + n0 < ngpes; i++){
1566                 gpes[i + n0].nb = fadt.gp1base + i;
1567                 gpes[i + n0].stsbit = i&7;
1568                 gpes[i + n0].stsio = fadt.gpe1blk + (i>>3);
1569                 gpes[i + n0].enbit = (n1 + i)&7;
1570                 gpes[i + n0].enio = fadt.gpe1blk + ((n1 + i)>>3);
1571         }
1572         for(i = 0; i < ngpes; i++){
1573                 setgpeen(i, 0);
1574                 clrgpests(i);
1575         }
1576 }
1577
1578 static void
1579 acpiioalloc(unsigned int addr, int len)
1580 {
1581         if(addr != 0){
1582                 printk("Just TAKING port %016lx to %016lx\n", 
1583                        addr, addr + len);
1584                 //ioalloc(addr, len, 0, "acpi");
1585         }
1586 }
1587
1588 int
1589 acpiinit(void)
1590 {
1591         /* this smicmd test implements 'run once' for now. */
1592         if(fadt.smicmd == 0){
1593                 //fmtinstall('G', Gfmt);
1594                 acpirsdptr();
1595                 if(fadt.smicmd == 0) {
1596                         printk("acpiinit returns -1\n");
1597                         return -1;
1598                 }
1599                 int mpacpi(int ncleft);
1600                 printk("mpacpi(32) is %d\n", mpacpi(32));
1601
1602         }
1603         return 0;
1604 }
1605
1606 static struct chan*
1607 acpiattach(char *spec)
1608 {
1609         int i;
1610
1611         printk("ACPI attach\n");
1612         /*
1613          * This was written for the stock kernel.
1614          * This code must use 64 registers to be acpi ready in nix.
1615          */
1616         if(acpiinit() < 0){
1617                 printk("ACPIINIT is called\n");
1618                 error("no acpi");
1619         }
1620
1621         /*
1622          * should use fadt->xpm* and fadt->xgpe* registers for 64 bits.
1623          * We are not ready in this kernel for that.
1624          */
1625         printk("acpi io alloc\n");
1626         acpiioalloc(fadt.smicmd, 1);
1627         acpiioalloc(fadt.pm1aevtblk, fadt.pm1evtlen);
1628         acpiioalloc(fadt.pm1bevtblk, fadt.pm1evtlen );
1629         acpiioalloc(fadt.pm1acntblk, fadt.pm1cntlen);
1630         acpiioalloc(fadt.pm1bcntblk, fadt.pm1cntlen);
1631         acpiioalloc(fadt.pm2cntblk, fadt.pm2cntlen);
1632         acpiioalloc(fadt.pmtmrblk, fadt.pmtmrlen);
1633         acpiioalloc(fadt.gpe0blk, fadt.gpe0blklen);
1634         acpiioalloc(fadt.gpe1blk, fadt.gpe1blklen);
1635
1636         printk("acpi init gpes\n");
1637         initgpes();
1638
1639         /*
1640          * This starts ACPI, which may require we handle
1641          * power mgmt events ourselves. Use with care.
1642          */
1643         outb(fadt.smicmd, fadt.acpienable);
1644         for(i = 0; i < 10; i++)
1645                 if(getpm1ctl() & Pm1SciEn)
1646                         break;
1647         if(i == 10)
1648                 error("acpi: failed to enable\n");
1649 //      if(fadt.sciint != 0)
1650 //              intrenable(fadt.sciint, acpiintr, 0, BUSUNKNOWN, "acpi");
1651         return devattach('a', spec);
1652 }
1653
1654 static struct walkqid*
1655 acpiwalk(struct chan *c, struct chan *nc, char **name, int nname)
1656 {
1657         return devwalk(c, nc, name, nname, acpidir, ARRAY_SIZE(acpidir), acpigen);
1658 }
1659
1660 static int
1661 acpistat(struct chan *c, uint8_t *dp, int n)
1662 {
1663         return devstat(c, dp, n, acpidir, ARRAY_SIZE(acpidir), acpigen);
1664 }
1665
1666 static struct chan*
1667 acpiopen(struct chan *c, int omode)
1668 {
1669         return devopen(c, omode, acpidir, ARRAY_SIZE(acpidir), acpigen);
1670 }
1671
1672 static void
1673 acpiclose(struct chan *unused)
1674 {
1675 }
1676
1677 static char*ttext;
1678 static int tlen;
1679
1680 static long
1681 acpiread(struct chan *c, void *a, long n, int64_t off)
1682 {
1683         long q;
1684         struct Atable *t;
1685         char *ns, *s, *e, *ntext;
1686
1687         q = c->qid.path;
1688         switch(q){
1689         case Qdir:
1690                 return devdirread(c, a, n, acpidir, ARRAY_SIZE(acpidir), acpigen);
1691         case Qtbl:
1692                 if(ttext == NULL){ // XXXXXX
1693                         tlen = 32768;
1694                         ttext = kzmalloc(tlen, 0);
1695                         if(ttext == NULL){
1696                                 printd("acpi: no memory\n");
1697                                 return 0;
1698                         }
1699                         s = ttext;
1700                         e = ttext + tlen;
1701                         strncpy(s,  "no tables\n", sizeof(s));
1702                         for(t = tfirst; t != NULL; t = t->next){
1703                                 ns = seprinttable(s, e, t);
1704                                 while(ns == e - 1){
1705                                         printk("acpiread: allocated %d\n", tlen*2);
1706                                         ntext = krealloc(ttext, tlen*2, 0);
1707                                         if(ntext == NULL)
1708                                                 panic("acpi: no memory\n");
1709                                         s = ntext + (ttext - s);
1710                                         ttext = ntext;
1711                                         tlen *= 2;
1712                                         e = ttext + tlen;
1713                                         ns = seprinttable(s, e, t);
1714                                 }
1715                                 s = ns;
1716                         }
1717                                         
1718                 }
1719                 return readstr(off, a, n, ttext);
1720         case Qpretty:
1721                 if(ttext == NULL){
1722                         tlen = 32768;
1723                         ttext = kzmalloc(tlen, 0);
1724                         if(ttext == NULL){
1725                                 printd("acpi: no memory\n");
1726                                 return 0;
1727                         }
1728                         s = ttext;
1729                         e = ttext + tlen;
1730                         s = dumpfadt(s, e, &fadt);
1731                         s = dumpmadt(s, e, apics);
1732                         s = dumpslit(s, e, slit);
1733                         s = dumpsrat(s, e, srat);
1734                         dumpmsct(s, e, msct);
1735                 }
1736                 return readstr(off, a, n, ttext);
1737         case Qio:
1738                 if(reg == NULL)
1739                         error("region not configured");
1740                 return regio(reg, a, n, off, 0);
1741         }
1742         error(Eperm);
1743         return -1;
1744 }
1745
1746 static long
1747 acpiwrite(struct chan *c, void *a, long n, int64_t off)
1748 {
1749         ERRSTACK(2);
1750         struct cmdtab *ct;
1751         struct cmdbuf *cb;
1752         struct Reg *r;
1753         unsigned int rno, fun, dev, bus, i;
1754
1755         if(c->qid.path == Qio){
1756                 if(reg == NULL)
1757                         error("region not configured");
1758                 return regio(reg, a, n, off, 1);
1759         }
1760         if(c->qid.path != Qctl)
1761                 error(Eperm);
1762
1763         cb = parsecmd(a, n);
1764         if(waserror()){
1765                 kfree(cb);
1766                 nexterror();
1767         }
1768         ct = lookupcmd(cb, ctls, ARRAY_SIZE(ctls));
1769         printk("acpi ctl %s\n", cb->f[0]);
1770         switch(ct->index){
1771         case CMregion:
1772                 r = reg;
1773                 if(r == NULL){
1774                         r = kzmalloc(sizeof(struct Reg), 0);
1775                         r->name = NULL;
1776                 }
1777                 kstrdup(&r->name, cb->f[1]);
1778                 r->spc = acpiregid(cb->f[2]);
1779                 if(r->spc < 0){
1780                         kfree(r);
1781                         reg = NULL;
1782                         error("bad region type");
1783                 }
1784                 if(r->spc == Rpcicfg || r->spc == Rpcibar){
1785                         rno = r->base>>Rpciregshift & Rpciregmask;
1786                         fun = r->base>>Rpcifunshift & Rpcifunmask;
1787                         dev = r->base>>Rpcidevshift & Rpcidevmask;
1788                         bus = r->base>>Rpcibusshift & Rpcibusmask;
1789 #define MKBUS(t,b,d,f)  (((t)<<24)|(((b)&0xFF)<<16)|(((d)&0x1F)<<11)|(((f)&0x07)<<8))
1790                         r->tbdf = MKBUS(0/*BusPCI*/, bus, dev, fun);
1791                         r->base = rno;  /* register ~ our base addr */
1792                 }
1793                 r->base = strtoul(cb->f[3], NULL, 0);
1794                 r->len = strtoul(cb->f[4], NULL, 0);
1795                 r->accsz = strtoul(cb->f[5], NULL, 0);
1796                 if(r->accsz < 1 || r->accsz > 4){
1797                         kfree(r);
1798                         reg = NULL;
1799                         error("bad region access size");
1800                 }
1801                 reg = r;
1802                 printk("region %s %s %p %p sz%d",
1803                         r->name, acpiregstr(r->spc), r->base, r->len, r->accsz);
1804                 break;
1805         case CMgpe:
1806                 i = strtoul(cb->f[1], NULL, 0);
1807                 if(i >= ngpes)
1808                         error("gpe out of range");
1809                 kstrdup(&gpes[i].obj, cb->f[2]);
1810                 printk("gpe %d %s\n", i, gpes[i].obj);
1811                 setgpeen(i, 1);
1812                 break;
1813         default:
1814                 panic("acpi: unknown ctl");
1815         }
1816         poperror();
1817         kfree(cb);
1818         return n;
1819 }
1820
1821
1822 struct dev acpidevtab __devtab = {
1823         'a',
1824         "acpi",
1825
1826         devreset,
1827         devinit,
1828         devshutdown,
1829         acpiattach,
1830         acpiwalk,
1831         acpistat,
1832         acpiopen,
1833         devcreate,
1834         acpiclose,
1835         acpiread,
1836         devbread,
1837         acpiwrite,
1838         devbwrite,
1839         devremove,
1840         devwstat,
1841 };