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