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