archacpi: optionally export acpi memory regions; properly initialize environment

This commit is contained in:
ftrvxmtrx 2016-10-18 23:04:19 +02:00
parent 06dd182695
commit e01577f8f6

View file

@ -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];
@ -457,6 +466,29 @@ enumprt(void *dot, void *)
return 1;
}
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 *)
{
@ -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();
@ -766,6 +856,42 @@ readpcicfg(Amlio *io, void *data, int n, int offset)
return i;
}
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)
{
@ -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;