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