2 #include "../port/lib.h"
12 typedef struct Rsd Rsd;
13 typedef struct Tbl Tbl;
41 Tblsz = 4+4+1+1+6+8+4+4+4,
46 /* physical addresses visited by maptable() */
48 static uintptr tblpa[64];
50 /* successfully mapped tables */
52 static Tbl *tblmap[64];
56 return p[1]<<8 | p[0];
61 return p[3]<<24 | p[2]<<16 | p[1]<<8 | p[0];
69 return u<<32 | get32(p);
74 return get32(t->len) - Tblsz;
87 if((uvlong)pa != xpa || pa == 0)
89 if(ntblpa >= nelem(tblpa) || ntblmap >= nelem(tblmap))
92 for(i=0; i<ntblpa; i++){
98 if((t = vmap(pa, 8)) == nil)
106 if((t = vmap(pa, l)) == nil)
112 tblmap[ntblmap++] = t;
116 if(memcmp("RSDT", t->sig, 4) == 0){
117 for(p = t->data; p+3 < e; p += 4)
121 if(memcmp("XSDT", t->sig, 4) == 0){
122 for(p = t->data; p+7 < e; p += 8)
126 if(memcmp("FACP", t->sig, 4) == 0){
129 maptable(get32(p + 40));
132 maptable(get64(p + 140));
140 if(rsd == nil || ntblmap > 0 || ntblpa > 0)
142 if(!checksum(rsd, 20))
143 maptable(get32(rsd->raddr));
145 if(!checksum(rsd, 36))
146 maptable(get64(rsd->xaddr));
150 findapic(int gsi, int *pintin)
155 for(i=0; i<=MaxAPICNO; i++){
156 if((a = mpioapic[i]) == nil)
158 if((a->flags & PcmpEN) == 0)
160 if(gsi >= a->gsibase && gsi <= a->gsibase+a->mre){
162 *pintin = gsi - a->gsibase;
166 print("findapic: no ioapic found for gsi %d\n", gsi);
171 addirq(int gsi, int type, int busno, int irq, int flags)
179 if((a = findapic(gsi, &intin)) == nil)
182 for(bus = mpbus; bus; bus = bus->next)
183 if(bus->type == type && bus->busno == busno)
186 if((bus = xalloc(sizeof(Bus))) == nil)
187 panic("addirq: no memory for Bus");
200 mpbuslast->next = bus;
206 for(ai = bus->aintr; ai; ai = ai->next)
207 if(ai->intr->irq == irq)
210 if((pi = xalloc(sizeof(PCMPintr))) == nil)
211 panic("addirq: no memory for PCMPintr");
212 pi->type = PcmpIOINTR;
214 pi->flags = flags & (PcmpPOMASK|PcmpELMASK);
217 pi->apicno = a->apicno;
220 if((ai = xalloc(sizeof(Aintr))) == nil)
221 panic("addirq: no memory for Aintr");
224 ai->next = bus->aintr;
238 for(l = 0, i=24; i>=0; i -= 8, b >>= 8)
239 l |= (b & 0xFF) << i;
241 for(i=6; i>=3; i--, l >>= 4)
242 id[i] = "0123456789ABCDEF"[l & 0xF];
243 for(i=2; i>=0; i--, l >>= 5)
244 id[i] = '@' + (l & 0x1F);
257 if((x = amlwalk(dot, "^_HID")) != nil)
258 if((p = amlval(x)) != nil)
260 if((x = amlwalk(dot, "^_BBN")) == nil)
261 if((x = amlwalk(dot, "^_ADR")) == nil)
263 if((p = amlval(x)) == nil)
266 /* if root bridge, then we are done here */
267 if(id != nil && (strcmp(id, "PNP0A03")==0 || strcmp(id, "PNP0A08")==0))
269 x = amlwalk(dot, "^");
270 if(x == nil || x == dot)
272 if((bno = pcibusno(x)) < 0)
274 tbdf = MKBUS(BusPCI, bno, adr>>16, adr&0xFFFF);
275 pdev = pcimatchtbdf(tbdf);
278 if(pdev->bridge == nil)
280 return BUSBNO(pdev->bridge->tbdf);
290 if((x = amlwalk(dot, "_ADR")) == nil){
291 x = amlwalk(dot, "^");
292 if(x == nil || x == dot)
297 if((bno = pcibusno(x)) < 0)
299 if((x = amlval(x)) == nil)
302 return MKBUS(BusPCI, bno, adr>>16, adr&0xFFFF);
308 getirqs(void *d, uchar pmask[32], int *pflags)
314 memset(pmask, 0, 32);
318 if(amllen(d) >= 2 && (p[0] == 0x22 || p[0] == 0x23)){
321 if(amllen(d) >= 3 && p[0] == 0x23)
322 *pflags = ((p[3] & (1<<0)) ? PcmpEDGE : PcmpLEVEL)
323 | ((p[3] & (1<<3)) ? PcmpLOW : PcmpHIGH);
326 if(amllen(d) >= 5 && p[0] == 0x89){
328 if(amllen(d) < 5+n*4)
331 m = get32(p+5 + i*4);
332 if(m >= 0 && m < 256)
333 pmask[m/8] |= 1<<(m%8);
335 *pflags = ((p[3] & (1<<1)) ? PcmpEDGE : PcmpLEVEL)
336 | ((p[3] & (1<<2)) ? PcmpLOW : PcmpHIGH);
343 setirq(void *d, uint irq)
349 p = amlnew('b', amllen(d));
350 memmove(p, d, amllen(p));
351 if(p[0] == 0x22 || p[0] == 0x23){
367 setuplink(void *link, int *pflags)
369 uchar im, pm[32], cm[32], *c;
370 static int lastirq = 1;
374 if(amltag(link) != 'N')
378 if(amleval(amlwalk(link, "_PRS"), "", &r) < 0)
380 if(getirqs(r, pm, pflags) < 0)
384 if(amleval(amlwalk(link, "_CRS"), "", &r) < 0)
386 if(getirqs(r, cm, pflags) < 0)
390 for(i=0; i<256; i++){
398 if(gsi > 0 || getconf("*nopcirouting") != nil)
401 for(i=0; i<256; i++){
402 gsi = lastirq++ & 0xFF; /* round robin */
405 if((c = setirq(r, gsi)) == nil)
407 if(amleval(amlwalk(link, "_SRS"), "b", c, nil) < 0)
416 enumprt(void *dot, void *)
419 int bno, dno, pin, gsi, flags;
426 /* evalulate _PRT method */
428 if(amleval(dot, "", &p) < 0)
437 if(amltag(a[i]) != 'p')
439 if(amllen(a[i]) != 4)
443 dno = amlint(b[0])>>16;
447 gsi = setuplink(b[2], &flags);
451 addirq(gsi, BusPCI, bno, (dno<<2)|pin, flags);
473 for(i=0; i<ntblmap; i++){
475 if(memcmp(t->sig, "DSDT", 4) == 0){
476 amlload(t->data, tbldlen(t));
481 /* load SSDT, there can be multiple tables */
482 for(i=0; i<ntblmap; i++){
484 if(memcmp(t->sig, "SSDT", 4) == 0)
485 amlload(t->data, tbldlen(t));
489 amleval(amlwalk(amlroot, "_PIC"), "i", 1, nil);
491 for(i=0; i<ntblmap; i++){
493 if(memcmp(t->sig, "APIC", 4) == 0)
496 panic("acpiinit: no MADT (APIC) table");
502 lapicbase = get32(s); s += 8;
503 va = vmap(lapicbase, 1024);
504 print("LAPIC: %.8lux %#p\n", lapicbase, va);
506 panic("acpiinit: cannot map lapic %.8lux", lapicbase);
509 for(p = s; p < e; p += c){
511 if(c < 2 || (p+c) > e)
514 case 0x00: /* Processor Local APIC */
517 if((a = xalloc(sizeof(Apic))) == nil)
518 panic("acpiinit: no memory for Apic");
519 a->type = PcmpPROCESSOR;
521 a->paddr = lapicbase;
523 a->lintr[0] = ApicIMASK;
524 a->lintr[1] = ApicIMASK;
525 a->flags = p[4] & PcmpEN;
527 /* skip disabled processors */
528 if((a->flags & PcmpEN) == 0 || mpapic[a->apicno] != nil){
532 a->machno = machno++;
535 * platform firmware should list the boot processor
536 * as the first processor entry in the MADT
541 mpapic[a->apicno] = a;
543 case 0x01: /* I/O APIC */
546 if((a = xalloc(sizeof(Apic))) == nil)
547 panic("acpiinit: no memory for io Apic");
548 a->type = PcmpIOAPIC;
550 a->paddr = get32(p+4);
551 if((a->addr = vmap(a->paddr, 1024)) == nil)
552 panic("acpiinit: cannot map ioapic %.8lux", a->paddr);
553 a->gsibase = get32(p+8);
555 mpioapic[a->apicno] = a;
556 ioapicinit(a, a->apicno);
562 * need 2nd pass as vbox puts interrupt overrides
563 * *before* the ioapic entries (!)
565 for(p = s; p < e; p += c){
567 if(c < 2 || (p+c) > e)
570 case 0x02: /* Interrupt Source Override */
571 addirq(get32(p+4), BusISA, 0, p[3], get16(p+8));
573 case 0x03: /* NMI Source */
574 case 0x04: /* Local APIC NMI */
575 case 0x05: /* Local APIC Address Override */
576 case 0x06: /* I/O SAPIC */
577 case 0x07: /* Local SAPIC */
578 case 0x08: /* Platform Interrupt Sources */
579 case 0x09: /* Processor Local x2APIC */
580 case 0x0A: /* x2APIC NMI */
582 case 0x0C: /* GICD */
587 /* look for PCI interrupt mappings */
588 amlenum(amlroot, "_PRT", enumprt, nil);
590 /* add identity mapped legacy isa interrupts */
592 addirq(i, BusISA, 0, i, 0);
594 /* free the AML interpreter */
598 * Ininitalize local APIC and start application processors.
603 static int identify(void);
610 .intrenable= mpintrenable,
611 .intron= lapicintron,
612 .introff= lapicintroff,
613 .fastclock= i8253read,
614 .timerset= lapictimerset,
618 readtbls(Chan*, void *v, long n, vlong o)
627 for(i=0; n > 0 && i < ntblmap; i++){
637 memmove(p, (uchar*)t + o, m);
642 return p - (uchar*)v;
651 if((cp = getconf("*acpi")) == nil)
653 pa = (uintptr)strtoull(cp, nil, 16);
655 rsd = sigsearch("RSD PTR ");
657 rsd = vmap(pa, sizeof(Rsd));
660 if(checksum(rsd, 20) && checksum(rsd, 36))
662 addarchfile("acpitbls", 0444, readtbls, nil);
663 if(strcmp(cp, "0") == 0)
665 if((cp = getconf("*nomp")) != nil && strcmp(cp, "0") != 0)
667 if(m->havetsc && getconf("*notsc") == nil)
668 archacpi.fastclock = tscticks;
673 readpcicfg(Amlio *io, void *data, int n, int offset)
690 if(!(r & 3) && n == 4){
695 if(!(r & 1) && n == 2){
700 for(i = 0; i < n; i++){
710 writepcicfg(Amlio *io, void *data, int n, int offset)
727 if(!(r & 3) && n == 4){
732 if(!(r & 1) && n == 2){
737 for(i = 0; i < n; i++){
747 readioport(Amlio *io, void *data, int len, int port)
755 PBIT32(a, inl(port));
758 PBIT16(a, ins(port));
768 writeioport(Amlio *io, void *data, int len, int port)
776 outl(port, GBIT32(a));
779 outs(port, GBIT16(a));
782 outb(port, GBIT8(a));
797 print("amlmapio: address space %x not implemented\n", io->space);
800 if((io->va = vmap(io->off, io->len)) == nil){
801 print("amlmapio: vmap failed\n");
806 snprint(buf, sizeof(buf), "%N", io->name);
807 if(ioalloc(io->off, io->len, 0, buf) < 0){
808 print("amlmapio: ioalloc failed\n");
811 io->read = readioport;
812 io->write = writeioport;
815 if((tbdf = pciaddr(io->name)) < 0){
816 print("amlmapio: no address\n");
819 if((pdev = pcimatchtbdf(tbdf)) == nil){
820 print("amlmapio: no device %T\n", tbdf);
824 io->read = readpcicfg;
825 io->write = writepcicfg;
828 print("amlmapio: mapping %N failed\n", io->name);
833 amlunmapio(Amlio *io)
837 vunmap(io->va, io->len);
849 if((p = malloc(n)) == nil)
850 panic("amlalloc: no memory");
867 * reset machine by writing acpi reset register.
876 for(i=0; i < ntblmap; i++){
878 if(memcmp(t->sig, "FACP", 4) != 0)
880 if(get32(t->len) <= 128)
883 if((get32(p + 112) & (1<<10)) == 0)
885 if(p[116+0] != IoSpace)
887 outb(get32(p+116+4), p[128]);