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