diff options
author | ftrvxmtrx <ftrvxmtrx@gmail.com> | 2016-10-18 23:04:19 +0200 |
---|---|---|
committer | ftrvxmtrx <ftrvxmtrx@gmail.com> | 2016-10-18 23:04:19 +0200 |
commit | e01577f8f61023ab90d8022e75cb00027399428c (patch) | |
tree | db4e4cb05da129c88e2e7e4c61932608aba73218 /sys/src/9/pc | |
parent | 06dd182695dfee1549dfa2c6da0ce54edf198ef0 (diff) |
archacpi: optionally export acpi memory regions; properly initialize environment
Diffstat (limited to 'sys/src/9/pc')
-rw-r--r-- | sys/src/9/pc/archacpi.c | 141 |
1 files changed, 138 insertions, 3 deletions
diff --git a/sys/src/9/pc/archacpi.c b/sys/src/9/pc/archacpi.c index 370905103..bebc66b7d 100644 --- a/sys/src/9/pc/archacpi.c +++ b/sys/src/9/pc/archacpi.c @@ -9,9 +9,15 @@ #include <aml.h> +typedef struct Memreg Memreg; typedef struct Rsd Rsd; typedef struct Tbl Tbl; +struct Memreg { + uintptr addr; + int size; +}; + struct Rsd { uchar sig[8]; uchar csum; @@ -51,6 +57,9 @@ static uintptr tblpa[64]; static int ntblmap; static Tbl *tblmap[64]; +static int nmemregs; +static Memreg memregs[16]; + static ushort get16(uchar *p){ return p[1]<<8 | p[0]; @@ -458,6 +467,29 @@ enumprt(void *dot, void *) } static int +enumini(void *dot, void *) +{ + void *p, *r; + int s; + + /* + * If there is no _STA (or it fails), device should be + * considered present and enabled. + */ + s = 0xff; + if((p = amlwalk(dot, "^_STA")) != nil){ + if(amleval(p, "", &r) >= 0) + s = amlint(r); + if((s & 1) == 0) /* return if not present */ + return 1; + } + if(s & 1) /* initialize everything present */ + amleval(dot, "", nil); + /* recurse if present, enabled and "ok" */ + return (s & 11) == 11 ? 0 : 1; +} + +static int enumec(void *dot, void *) { int cmdport, dataport; @@ -477,10 +509,62 @@ enumec(void *dot, void *) return 1; dataport = b[0+2] | b[0+3]<<8; cmdport = b[8+2] | b[8+3]<<8; + if((x = amlwalk(dot, "^_REG")) != nil) + amleval(x, "ii", 3, 1, nil); ecinit(cmdport, dataport); return 1; } +static long +readmem(Chan*, void *v, long n, vlong o) +{ + int i; + uchar *t; + uintptr start, end; + Memreg *mr; + + start = o; + end = start + n; + for(i = 0; n > 0 && i < nmemregs; i++){ + mr = &memregs[i]; + if(start >= mr->addr && start < mr->addr+mr->size){ + if(end > mr->addr+mr->size) + end = mr->addr+mr->size; + n = end - start; + t = vmap(mr->addr, n); + memmove(v, start - mr->addr + t, n); + vunmap(t, n); + return n; + } + } + return 0; +} + +static long +writemem(Chan*, void *v, long n, vlong o) +{ + int i; + uchar *t; + uintptr start, end; + Memreg *mr; + + start = o; + end = start + n; + for(i = 0; n > 0 && i < nmemregs; i++){ + mr = &memregs[i]; + if(start >= mr->addr && start < mr->addr+mr->size){ + if(end > mr->addr+mr->size) + end = mr->addr+mr->size; + n = end - start; + t = vmap(mr->addr, n); + memmove(start - mr->addr + t, v, n); + vunmap(t, n); + return n; + } + } + return 0; +} + static void acpiinit(void) { @@ -495,6 +579,9 @@ acpiinit(void) amlinit(); + if(getconf("*acpimem") != nil) + addarchfile("acpimem", 0660, readmem, writemem); + /* load DSDT */ for(i=0; i<ntblmap; i++){ t = tblmap[i]; @@ -611,6 +698,12 @@ Foundapic: } } + /* find embedded controller */ + amlenum(amlroot, "_HID", enumec, nil); + + /* init */ + amlenum(amlroot, "_INI", enumini, nil); + /* look for PCI interrupt mappings */ amlenum(amlroot, "_PRT", enumprt, nil); @@ -618,9 +711,6 @@ Foundapic: for(i=0; i<16; i++) addirq(i, BusISA, 0, i, 0); - /* find embedded controller */ - amlenum(amlroot, "_HID", enumec, nil); - /* free the AML interpreter */ amlexit(); @@ -767,6 +857,42 @@ readpcicfg(Amlio *io, void *data, int n, int offset) } static int +readec(Amlio *io, void *data, int n, int off) +{ + int port, v; + uchar *p; + + USED(io); + if(off < 0 || off >= 256) + return 0; + if(off+n > 256) + n = 256 - off; + p = data; + for(port = off; port < off+n; port++){ + if((v = ecread(port)) < 0) + break; + *p++ = v; + } + return n; +} + +static int +writeec(Amlio *io, void *data, int n, int off) +{ + int port; + uchar *p; + + USED(io); + if(off < 0 || off+n > 256) + return -1; + p = data; + for(port = off; port < off+n; port++) + if(ecwrite(port, *p++) < 0) + break; + return n; +} + +static int writepcicfg(Amlio *io, void *data, int n, int offset) { ulong r, x; @@ -861,6 +987,11 @@ amlmapio(Amlio *io) print("amlmapio: vmap failed\n"); break; } + if(nmemregs < nelem(memregs)){ + memregs[nmemregs].addr = io->off; + memregs[nmemregs].size = io->len; + nmemregs++; + } return 0; case IoSpace: snprint(buf, sizeof(buf), "%N", io->name); @@ -884,6 +1015,10 @@ amlmapio(Amlio *io) io->read = readpcicfg; io->write = writepcicfg; return 0; + case EbctlSpace: + io->read = readec; + io->write = writeec; + return 0; } print("amlmapio: mapping %N failed\n", io->name); return -1; |