ref: e01577f8f61023ab90d8022e75cb00027399428c
parent: 06dd182695dfee1549dfa2c6da0ce54edf198ef0
author: ftrvxmtrx <[email protected]>
date: Tue Oct 18 19:04:19 EDT 2016
archacpi: optionally export acpi memory regions; properly initialize environment
--- 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 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 @@
}
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 @@
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 @@
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 @@
}
}
+ /* 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 @@
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 @@
}
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 @@
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);
@@ -883,6 +1014,10 @@
io->aux = pdev;
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);