ref: 1359ede6a1956e26c7be7b01464777dcac17216b
parent: fd61eda91227e9f363a415546ee98a1c23c69d58
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Fri Jun 7 14:03:44 EDT 2013
archacpi: handle multiple SSDT tables we cannot assume theres only one instance of an acpi table. some bios have multiple SSDT tables and we would only find the first one. now, we keep a second array to record the physical address of the table visited by maptable(). load all instances to the SSDT.
--- a/sys/src/9/pc/archacpi.c
+++ b/sys/src/9/pc/archacpi.c
@@ -38,9 +38,15 @@
};
static Rsd *rsd;
-static int ntbltab;
-static Tbl *tbltab[64];
+/* physical addresses visited by maptable() */
+static int ntblpa;
+static uintptr tblpa[64];
+
+/* successfully mapped tables */
+static int ntblmap;
+static Tbl *tblmap[64];
+
void*
amlalloc(int n){void *p;
@@ -79,16 +85,6 @@
return get32(t->len) - sizeof(Tbl);
}
-
-static Tbl*
-findtable(void *sig){- int i;
- for(i=0; i<ntbltab; i++)
- if(memcmp(tbltab[i]->sig, sig, 4) == 0)
- return tbltab[i];
- return nil;
-}
-
static void
maptable(uvlong xpa)
{@@ -96,16 +92,24 @@
uintptr pa;
u32int l;
Tbl *t;
+ int i;
pa = xpa;
if((uvlong)pa != xpa || pa == 0)
return;
- if(ntbltab >= nelem(tbltab))
+ if(ntblpa >= nelem(tblpa) || ntblmap >= nelem(tblmap))
return;
+
+ for(i=0; i<ntblpa; i++){+ if(pa == tblpa[i])
+ return;
+ }
+ tblpa[ntblpa++] = pa;
+
if((t = vmap(pa, 8)) == nil)
return;
l = get32(t->len);
- if(l < sizeof(Tbl) || findtable(t->sig)){+ if(l < sizeof(Tbl)){vunmap(t, 8);
return;
}
@@ -116,9 +120,8 @@
vunmap(t, l);
return;
}
+ tblmap[ntblmap++] = t;
- tbltab[ntbltab++] = t;
-
p = (uchar*)t;
e = p + l;
if(memcmp("RSDT", t->sig, 4) == 0){@@ -145,7 +148,7 @@
static void
maptables(void)
{- if(rsd == nil || ntbltab > 0)
+ if(rsd == nil || ntblmap > 0 || ntblpa > 0)
return;
if(!checksum(rsd, 20))
maptable(get32(rsd->raddr));
@@ -340,17 +343,34 @@
amlinit();
- if(t = findtable("DSDT"))- amlload(t->data, tbldlen(t));
- if(t = findtable("SSDT"))- amlload(t->data, tbldlen(t));
+ /* load DSDT */
+ for(i=0; i<ntblmap; i++){+ t = tblmap[i];
+ if(memcmp(t->sig, "DSDT", 4) == 0){+ amlload(t->data, tbldlen(t));
+ break;
+ }
+ }
+ /* load SSDT, there can be multiple tables */
+ for(i=0; i<ntblmap; i++){+ t = tblmap[i];
+ if(memcmp(t->sig, "SSDT", 4) == 0)
+ amlload(t->data, tbldlen(t));
+ }
+
/* set APIC mode */
amleval(amlwalk(amlroot, "_PIC"), "i", 1, nil);
- if((t = findtable("APIC")) == nil)- panic("acpiinit: no MADT table");+ for(i=0; i<ntblmap; i++){+ t = tblmap[i];
+ if(memcmp(t->sig, "APIC", 4) == 0)
+ goto Foundapic;
+ }
+ panic("acpiinit: no MADT (APIC) table");+ return;
+Foundapic:
p = t->data;
e = p + tbldlen(t);
lapicbase = get32(p); p += 8;
@@ -461,8 +481,8 @@
maptables();
p = v;
- for(i=0; n > 0 && i < ntbltab; i++){- t = tbltab[i];
+ for(i=0; n > 0 && i < ntblmap; i++){+ t = tblmap[i];
l = get32(t->len);
if(o >= l){o -= l;
--
⑨