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