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];
58 if((p = malloc(n)) == nil)
59 panic("amlalloc: no memory");
71 return p[1]<<8 | p[0];
76 return p[3]<<24 | p[2]<<16 | p[1]<<8 | p[0];
84 return u<<32 | get32(p);
89 return get32(t->len) - Tblsz;
102 if((uvlong)pa != xpa || pa == 0)
104 if(ntblpa >= nelem(tblpa) || ntblmap >= nelem(tblmap))
107 for(i=0; i<ntblpa; i++){
111 tblpa[ntblpa++] = pa;
113 if((t = vmap(pa, 8)) == nil)
121 if((t = vmap(pa, l)) == nil)
127 tblmap[ntblmap++] = t;
131 if(memcmp("RSDT", t->sig, 4) == 0){
132 for(p = t->data; p+3 < e; p += 4)
136 if(memcmp("XSDT", t->sig, 4) == 0){
137 for(p = t->data; p+7 < e; p += 8)
141 if(memcmp("FACP", t->sig, 4) == 0){
144 maptable(get32(p + 40));
147 maptable(get64(p + 140));
155 if(rsd == nil || ntblmap > 0 || ntblpa > 0)
157 if(!checksum(rsd, 20))
158 maptable(get32(rsd->raddr));
160 if(!checksum(rsd, 36))
161 maptable(get64(rsd->xaddr));
165 findapic(int gsi, int *pintin)
170 for(i=0; i<=MaxAPICNO; i++){
171 if((a = mpioapic[i]) == nil)
173 if((a->flags & PcmpEN) == 0)
175 if(gsi >= a->gsibase && gsi <= a->gsibase+a->mre){
177 *pintin = gsi - a->gsibase;
181 print("findapic: no ioapic found for gsi %d\n", gsi);
186 addirq(int gsi, int type, int busno, int irq, int flags)
194 if((a = findapic(gsi, &intin)) == nil)
197 for(bus = mpbus; bus; bus = bus->next)
198 if(bus->type == type && bus->busno == busno)
201 if((bus = xalloc(sizeof(Bus))) == nil)
202 panic("addirq: no memory for Bus");
215 mpbuslast->next = bus;
221 for(ai = bus->aintr; ai; ai = ai->next)
222 if(ai->intr->irq == irq)
225 if((pi = xalloc(sizeof(PCMPintr))) == nil)
226 panic("addirq: no memory for PCMPintr");
227 pi->type = PcmpIOINTR;
229 pi->flags = flags & (PcmpPOMASK|PcmpELMASK);
232 pi->apicno = a->apicno;
235 if((ai = xalloc(sizeof(Aintr))) == nil)
236 panic("addirq: no memory for Aintr");
239 ai->next = bus->aintr;
253 for(l = 0, i=24; i>=0; i -= 8, b >>= 8)
254 l |= (b & 0xFF) << i;
256 for(i=6; i>=3; i--, l >>= 4)
257 id[i] = "0123456789ABCDEF"[l & 0xF];
258 for(i=2; i>=0; i--, l >>= 5)
259 id[i] = '@' + (l & 0x1F);
272 if(x = amlwalk(dot, "^_HID")){
274 if(amleval(x, "", &p) == 0)
277 if((x = amlwalk(dot, "^_BBN")) == nil)
278 if((x = amlwalk(dot, "^_ADR")) == nil)
281 if(amleval(x, "", &p) < 0)
284 /* if root bridge, then we are done here */
285 if(id && (strcmp(id, "PNP0A03")==0 || strcmp(id, "PNP0A08")==0))
287 x = amlwalk(dot, "^");
288 if(x == nil || x == dot)
290 if((bno = pcibusno(x)) < 0)
292 tbdf = MKBUS(BusPCI, bno, adr>>16, adr&0xFFFF);
293 pdev = pcimatchtbdf(tbdf);
294 if(pdev == nil || pdev->bridge == nil)
296 return BUSBNO(pdev->bridge->tbdf);
300 enumprt(void *dot, void *)
310 /* evalulate _PRT method */
312 if(amleval(dot, "", &p) < 0)
320 if(amltag(a[i]) != 'p')
322 if(amllen(a[i]) != 4)
325 dno = amlint(b[0])>>16;
327 if(amltag(b[2]) == 'N' || amlint(b[2])){
328 print("enumprt: interrupt link not handled %V\n", b[2]);
331 addirq(amlint(b[3]), BusPCI, bno, (dno<<2)|pin, 0);
351 for(i=0; i<ntblmap; i++){
353 if(memcmp(t->sig, "DSDT", 4) == 0){
354 amlload(t->data, tbldlen(t));
359 /* load SSDT, there can be multiple tables */
360 for(i=0; i<ntblmap; i++){
362 if(memcmp(t->sig, "SSDT", 4) == 0)
363 amlload(t->data, tbldlen(t));
367 amleval(amlwalk(amlroot, "_PIC"), "i", 1, nil);
369 for(i=0; i<ntblmap; i++){
371 if(memcmp(t->sig, "APIC", 4) == 0)
374 panic("acpiinit: no MADT (APIC) table");
380 lapicbase = get32(p); p += 8;
381 va = vmap(lapicbase, 1024);
382 print("LAPIC: %.8lux %.8lux\n", lapicbase, (ulong)va);
384 panic("acpiinit: cannot map lapic %.8lux", lapicbase);
387 for(; p < e; p += c){
389 if(c < 2 || (p+c) > e)
392 case 0x00: /* Processor Local APIC */
395 if((a = xalloc(sizeof(Apic))) == nil)
396 panic("acpiinit: no memory for Apic");
397 a->type = PcmpPROCESSOR;
399 a->paddr = lapicbase;
401 a->lintr[0] = ApicIMASK;
402 a->lintr[1] = ApicIMASK;
403 a->flags = p[4] & PcmpEN;
404 if(a->flags & PcmpEN){
405 a->machno = machno++;
408 * platform firmware should list the boot processor
409 * as the first processor entry in the MADT
414 mpapic[a->apicno] = a;
416 case 0x01: /* I/O APIC */
419 if((a = xalloc(sizeof(Apic))) == nil)
420 panic("acpiinit: no memory for io Apic");
421 a->type = PcmpIOAPIC;
423 a->paddr = get32(p+4);
424 if((a->addr = vmap(a->paddr, 1024)) == nil)
425 panic("acpiinit: cannot map ioapic %.8lux", a->paddr);
426 a->gsibase = get32(p+8);
428 mpioapic[a->apicno] = a;
429 ioapicinit(a, a->apicno);
431 case 0x02: /* Interrupt Source Override */
432 addirq(get32(p+4), BusISA, 0, p[3], get16(p+8));
434 case 0x03: /* NMI Source */
435 case 0x04: /* Local APIC NMI */
436 case 0x05: /* Local APIC Address Override */
437 case 0x06: /* I/O SAPIC */
438 case 0x07: /* Local SAPIC */
439 case 0x08: /* Platform Interrupt Sources */
440 case 0x09: /* Processor Local x2APIC */
441 case 0x0A: /* x2APIC NMI */
443 case 0x0C: /* GICD */
448 /* look for PCI interrupt mappings */
449 amlenum(amlroot, "_PRT", enumprt, nil);
451 /* add identity mapped legacy isa interrupts */
453 addirq(i, BusISA, 0, i, 0);
455 /* free the AML interpreter */
459 * Ininitalize local APIC and start application processors.
464 static int identify(void);
471 .intrenable= mpintrenable,
472 .intron= lapicintron,
473 .introff= lapicintroff,
474 .fastclock= i8253read,
475 .timerset= lapictimerset,
479 readtbls(Chan*, void *v, long n, vlong o)
488 for(i=0; n > 0 && i < ntblmap; i++){
498 memmove(p, (uchar*)t + o, m);
503 return p - (uchar*)v;
511 if((cp = getconf("*acpi")) == nil)
513 if((rsd = sigsearch("RSD PTR ")) == nil)
515 if(checksum(rsd, 20) && checksum(rsd, 36))
517 addarchfile("acpitbls", 0444, readtbls, nil);
518 if(strcmp(cp, "0") == 0)
520 if((cp = getconf("*nomp")) != nil && strcmp(cp, "0") != 0)
523 archacpi.fastclock = tscticks;