wire up the new acpi io functions so we can do io to pci space and io ports. adapted from cinap's work. Reference: /n/atom/patch/applied2013/nixacpiio Date: Fri Sep 20 04:47:29 CES 2013 Signed-off-by: quanstro@quanstro.net --- /sys/src/nix/k10/acpi.c Fri Sep 20 04:46:26 2013 +++ /sys/src/nix/k10/acpi.c Fri Sep 20 04:46:28 2013 @@ -60,30 +60,10 @@ return s; } -void* -amlalloc(usize n) -{ - void *p; - - if((p = malloc(n)) != nil){ - setmalloctag(&p, getcallerpc(&n)); - setrealloctag(&p, 0); - } - return p; -} - -void -amlfree(void *p) -{ - free(p); -} - #define get16(p) getle((p), 2) #define get32(p) getle((p), 4) #define get64(p) getle((p), 8) -extern uvlong getle(uchar*, int); - static uint tbldlen(Tbl *t) { @@ -347,24 +327,6 @@ } } -/* - * if we find a gsi for an i/o apic that does not exist, and the gsi - * belongs to a bus that does not exist, assume that both belong to - * a processor that does not exist, and do not complain. - */ -static int -havebus(int bustype, int busno) -{ - Pcidev *p; - - if(bustype != BusPCI) - return 1; - for(p = nil; p = pcimatch(p, 0, 0); ) - if(BUSBNO(p->tbdf) == busno) - return 1; - return 0; -} - static void addirq(int gsi, int bustype, int busno, int irq, int flags) { @@ -372,8 +334,7 @@ u32int i; if((apicno = gsitoapicid(gsi, &intin)) == -1){ - if(havebus(bustype, busno)) - print("acpi: addirq: no apic for gsi %d bus %d.%d\n", gsi, bustype, busno); + DBG("acpi: addirq: no apic for gsi %d bus type=%d busno %d\n", gsi, bustype, busno); return; } DBG("addirq: gsi %d %s busno %d irq %d flags %.8ux\n", @@ -410,7 +371,7 @@ return id; } -static int +/*static*/ int pcibusno(void *dot) { int bno, adr, tbdf; @@ -419,16 +380,13 @@ char *id; id = nil; - if(x = amlwalk(dot, "^_HID")){ - p = nil; - if(amleval(x, "", &p) == 0) + if((x = amlwalk(dot, "^_HID")) != nil) + if((p = amlval(x)) != nil) id = eisaid(p); - } if((x = amlwalk(dot, "^_BBN")) == nil) if((x = amlwalk(dot, "^_ADR")) == nil) return -1; - p = nil; - if(amleval(x, "", &p) < 0) + if((p = amlval(x)) == nil) return -1; adr = amlint(p); /* if root bridge, then we are done here */ @@ -441,23 +399,118 @@ return -1; tbdf = MKBUS(BusPCI, bno, adr>>16, adr&0xFFFF); pdev = pcimatchtbdf(tbdf); - if(pdev == nil){ - DBG("acpi: pcibusno: bridge not found: %T\n", tbdf); + if(pdev == nil) + return -1; + if(pdev->bridge == nil) + return bno; + return BUSBNO(pdev->bridge->tbdf); +} + +static int +getirqs(void *d, uchar pmask[32], int *pflags) +{ + int i, n, m; + uchar *p; + + *pflags = 0; + memset(pmask, 0, 32); + if(amltag(d) != 'b') return -1; + p = amlval(d); + if(amllen(d) >= 2 && (p[0] == 0x22 || p[0] == 0x23)){ + pmask[0] = p[1]; + pmask[1] = p[2]; + if(amllen(d) >= 3 && p[0] == 0x23) + *pflags = p[3]; + return 0; + } + if(amllen(d) >= 5 && p[0] == 0x89){ + n = p[4]; + if(amllen(d) < 5+n*4) + return -1; + for(i=0; i= 0 && m < 256) + pmask[m/8] |= 1<<(m%8); + } + *pflags = p[3]; + return 0; } - if(pdev->bridge == nil){ - DBG("acpi: pcibusno: nothing bridged: %T\n", tbdf); + return -1; +} + +static uchar* +setirq(void *d, uint irq) +{ + uchar *p; + + if(amltag(d) != 'b') + return nil; + p = amlnew('b', amllen(d)); + memmove(p, d, amllen(p)); + if(p[0] == 0x22 || p[0] == 0x23) + putle(p, 1<bridge->tbdf); + + if(gsi > 0 || getconf("*nopcirouting") != nil) + return gsi; + + for(i=0; i<256; i++){ + gsi = lastirq++ & 0xFF; /* round robin */ + im = 1<<(gsi%8); + if(pm[gsi/8] & im){ + if((c = setirq(r, gsi)) == nil) + break; + if(amleval(amlwalk(link, "_SRS"), "b", c, nil) < 0) + break; + return gsi; + } + } + return -1; } static int enumprt(void *dot, void *) { void *p, **a, **b; - int bno, dno, pin, gsi; - int n, i; + int bno, dno, pin, gsi, flags, n, i; bno = pcibusno(dot); if(bno < 0){ @@ -472,6 +525,7 @@ if(amltag(p) != 'p') return 1; + amltake(p); n = amllen(p); a = amlval(p); for(i=0; i>16; pin = amlint(b[1]); - if(amltag(b[2]) == 'N' || amlint(b[2]) != 0){ - print("enumprt: interrupt link not handled %V\n", b[2]); - continue; - } gsi = amlint(b[3]); + if(gsi == 0){ + print("acpi: gsi is zero ... setuplink\n"); + gsi = setuplink(b[2], &flags); + if(gsi <= 0) + continue; + } addirq(gsi, BusPCI, bno, (dno<<2)|pin, 0); } + amldrop(p); return 1; } @@ -508,6 +566,34 @@ } } +static long +readtbls(Chan*, void *v, long n, vlong o) +{ + int i, l, m; + uchar *p; + Tbl *t; + + maptables(); + + p = v; + for(i=0; n > 0 && i < ntblmap; i++){ + t = tblmap[i]; + l = get32(t->len); + if(o >= l){ + o -= l; + continue; + } + m = l - o; + if(m > n) + m = n; + memmove(p, (uchar*)t + o, m); + p += m; + n -= m; + o = 0; + } + return p - (uchar*)v; +} + enum { Lapicen = 1, }; @@ -522,6 +608,8 @@ Tbl *t; print("acpiinit\n"); +uvlong tk; +tk = rdtsc(); maptables(); amlinit(); loadtbls("DSDT", 0); @@ -586,4 +674,7 @@ amlexit(); print("acpiinit: %d maches\n", nmach); +tk += rdtsc(); +print("acpi: time %lld ms\n", tk*1000/m->cpuhz); + addarchfile("acpitbls", 0444, readtbls, nil); } --- /sys/src/nix/k10/acpiio.c Thu Jan 1 00:00:00 1970 +++ /sys/src/nix/k10/acpiio.c Fri Sep 20 04:46:29 2013 @@ -0,0 +1,234 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "adr.h" + +#include "apic.h" +#include + +extern int pcibusno(void*); + +static int +pciaddr(void *dot) +{ + int adr, bno; + void *x; + + for(;;){ + if((x = amlwalk(dot, "_ADR")) == nil){ + x = amlwalk(dot, "^"); + if(x == nil || x == dot) + break; + dot = x; + continue; + } + if((bno = pcibusno(x)) < 0) + break; + if((x = amlval(x)) == nil) + break; + adr = amlint(x); + return MKBUS(BusPCI, bno, adr>>16, adr&0xFFFF); + } + return -1; +} + +static int +readpcicfg(Amlio *io, void *data, int n, int offset) +{ + uchar *a; + int i; + uint r; + Pcidev *p; + + a = data; + p = io->aux; + if(p == nil) + return -1; + offset += io->off; + if(offset > 256) + return 0; + if(n+offset > 256) + n = 256-offset; + r = offset; + if(!(r & 3) && n == 4){ + putle(a, pcicfgr32(p, r), 4); + return 4; + } + if(!(r & 1) && n == 2){ + putle(a, pcicfgr16(p, r), 2); + return 2; + } + for(i = 0; i < n; i++){ + putle(a, pcicfgr8(p, r), 1); + a++; + r++; + } + return i; +} + +static int +writepcicfg(Amlio *io, void *data, int n, int offset) +{ + uchar *a; + int i; + uint r; + Pcidev *p; + + a = data; + p = io->aux; + if(p == nil) + return -1; + offset += io->off; + if(offset > 256) + return 0; + if(n+offset > 256) + n = 256-offset; + r = offset; + if(!(r & 3) && n == 4){ + pcicfgw32(p, r, getle(a, 4)); + return 4; + } + if(!(r & 1) && n == 2){ + pcicfgw16(p, r, getle(a, 2)); + return 2; + } + for(i = 0; i < n; i++){ + pcicfgw8(p, r, getle(a, 1)); + a++; + r++; + } + return i; +} + +static int +readioport(Amlio *io, void *data, int len, int port) +{ + uchar *a; + + a = data; + port += io->off; + switch(len){ + default: + return -1; + case 4: + putle(a, inl(port), 4); +print("aml: readioport: port %ux len %d %llux\n", port, len, getle(a, len)); + return 4; + case 2: + putle(a, ins(port), 2); +print("aml: readioport: port %ux len %d %llux\n", port, len, getle(a, len)); + return 2; + case 1: + putle(a, inb(port), 1); +print("aml: readioport: port %ux len %d %llux\n", port, len, getle(a, len)); + return 1; + } +} + +static int +writeioport(Amlio *io, void *data, int len, int port) +{ + uchar *a; + + a = data; + port += io->off; +print("aml: writeioport: port %ux len %d %llux\n", port, len, getle(a, len)); + switch(len){ + default: + return -1; + case 4: + outl(port, getle(a, 4)); + return 4; + case 2: + outs(port, getle(a, 2)); + return 2; + case 1: + outb(port, getle(a, 1)); + return 1; + } +} + +int +amlmapio(Amlio *io) +{ + char buf[64]; + int tbdf; + Pcidev *p; + + switch(io->space){ + default: + print("amlmapio: address space %x not implemented\n", io->space); + break; + case MemSpace: + if((io->va = vmap(io->off, io->len)) == nil){ + print("amlmapio: vmap failed\n"); + break; + } + return 0; + case IoSpace: + snprint(buf, sizeof(buf), "%N", io->name); + if(ioalloc(io->off, io->len, 0, buf) < 0){ + print("amlmapio: ioalloc failed\n"); + break; + } + io->read = readioport; + io->write = writeioport; + return 0; + case PcicfgSpace: + if((tbdf = pciaddr(io->name)) < 0){ + print("amlmapio: no address\n"); + break; + } + if((p = pcimatchtbdf(tbdf)) == nil){ + print("amlmapio: no device %T\n", tbdf); + break; + } + io->aux = p; + io->read = readpcicfg; + io->write = writepcicfg; + return 0; + } + print("amlmapio: mapping %N failed\n", io->name); + return -1; +} + +void +amlunmapio(Amlio *io) +{ + switch(io->space){ + case MemSpace: + vunmap(io->va, io->len); + break; + case IoSpace: + iofree(io->off); + break; + } +} + +void* +amlalloc(usize n) +{ + void *p; + + if((p = malloc(n)) == nil) + panic("amlalloc: no memory"); + memset(p, 0, n); + setmalloctag(&p, getcallerpc(&n)); + setrealloctag(&p, 0); + return p; +} + +void +amlfree(void *p) +{ + free(p); +} + +void +amldelay(int µs) +{ + microdelay(µs); +} --- /sys/src/nix/k10/cpu Fri Sep 20 04:46:31 2013 +++ /sys/src/nix/k10/cpu Fri Sep 20 04:46:32 2013 @@ -69,7 +69,7 @@ misc +dev # mp mpacpi lapic ioapic msi pci sipi - acpi lapic ioapic msi pci sipi + acpi acpiio lapic ioapic msi pci sipi boot cpu il --- /sys/src/nix/k10/term Fri Sep 20 04:46:34 2013 +++ /sys/src/nix/k10/term Fri Sep 20 04:46:35 2013 @@ -76,7 +76,7 @@ misc +dev # mp mpacpi lapic ioapic msi pci sipi - acpi lapic ioapic msi pci sipi + acpi acpiio lapic ioapic msi pci sipi boot terminal il