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