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