wire up the new acpi io functions so we can do io to pci space and io ports. adapted from cinap's work. also pick irq for lonesome interrupts. Reference: /n/atom/patch/applied2013/fsacpiio Date: Fri Sep 20 04:49:42 CES 2013 Signed-off-by: quanstro@quanstro.net --- /sys/src/fs/amd64/acpi.c Fri Sep 20 04:49:07 2013 +++ /sys/src/fs/amd64/acpi.c Fri Sep 20 04:49:09 2013 @@ -57,34 +57,10 @@ return s; } -/* - * typical leakage ~40kb. - */ -void* -amlalloc(usize n) -{ - void *p; - - if((p = ialloc(n, 0)) != nil){ - // setmalloctag(&p, getcallerpc(&n)); - // setrealloctag(&p, 0); - } - return p; -} - -void -amlfree(void *p) -{ - USED(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) { @@ -348,24 +324,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) { @@ -373,8 +331,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 %d.%d\n", gsi, bustype, busno); return; } DBG("addirq: gsi %d %s busno %d irq %d flags %.8ux\n", @@ -413,7 +370,7 @@ return id; } -static int +/*static*/ int pcibusno(void *dot) { int bno, adr, tbdf; @@ -422,16 +379,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 */ @@ -444,23 +398,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(pdev->bridge == nil){ - DBG("acpi: pcibusno: nothing bridged: %T\n", tbdf); + 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; + } + 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){ @@ -475,6 +524,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; } --- /sys/src/fs/amd64/acpiio.c Thu Jan 1 00:00:00 1970 +++ /sys/src/fs/amd64/acpiio.c Fri Sep 20 04:49:10 2013 @@ -0,0 +1,226 @@ +#include "all.h" +#include "io.h" +#include "mp.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 = ialloc(n, 0)) == nil) + panic("amlalloc: no memory"); + memset(p, 0, n); + return p; +} + +void +amlfree(void*) +{ +} + +void +amldelay(int µs) +{ + microdelay(µs); +} --- /sys/src/fs/ivey/mkfile Fri Sep 20 04:49:12 2013 +++ /sys/src/fs/ivey/mkfile Fri Sep 20 04:49:13 2013 @@ -48,7 +48,6 @@ iobuf.$O\ lrand.$O\ main.$O\ - options.$O\ print.$O\ proc.$O\ rawcopy.$O\ @@ -63,7 +62,9 @@ l64cpuid.$O\ 8250.$O\ acpi.$O\ + acpiio.$O\ arch.$O\ + options.$O\ cga.$O\ dosfs.$O\ fpu.$O\ @@ -71,8 +72,8 @@ iasata.$O\ ioapic.$O\ lapic.$O\ - lock.$O\ -# tiklock.$O\ +# lock.$O\ + tiklock.$O\ malloc.$O\ mmu.$O\ # mp.$O\