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