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