9front - general discussion about 9front
 help / color / mirror / Atom feed
* [9front] [PATCH] aux/acpi: support new ACPI 2.0 info for shutdown
@ 2023-05-20 23:17 mia soweli
  0 siblings, 0 replies; only message in thread
From: mia soweli @ 2023-05-20 23:17 UTC (permalink / raw)
  To: 9front


this involves a horrible mess, because the registers can be
in system memory, as io ports, on the embedded controller,
so we must engage aml io mapping.
---
diff f72335db09b994351eed11ec537b329903b6731a daeb5b0ab6d6342dd7d4a25ee6380f67082cfbed
--- a/sys/src/cmd/aux/acpi.c
+++ b/sys/src/cmd/aux/acpi.c
@@ -9,6 +9,7 @@
 typedef struct Bat Bat;
 typedef struct Tbl Tbl;
 typedef struct Therm Therm;
+typedef struct FACP FACP;
 
 struct Batstat {
 	int rate;
@@ -45,6 +46,31 @@
 	void *tmp;
 };
 
+struct FACP {
+	int ok;
+
+	uvlong pm1a;
+	int pm1aspace;
+	int pm1awid;
+
+	uvlong pm1b;
+	int pm1bspace;
+	int pm1bwid;
+
+	uvlong gpe0;
+	ulong gpe0len;
+	int gpe0space;
+	int gpe0wid;
+
+	uvlong gpe1;
+	ulong gpe1len;
+	int gpe1space;
+	int gpe1wid;
+
+	ulong slpa;
+	ulong slpb;
+};
+
 enum {
 	Tblsz = 4+4+1+1+6+8+4+4+4,
 
@@ -56,12 +82,11 @@
 	SLP_TM = 0x1c00,
 };
 
-static ulong PM1a_CNT_BLK, PM1b_CNT_BLK, SLP_TYPa, SLP_TYPb;
-static ulong GPE0_BLK, GPE1_BLK, GPE0_BLK_LEN, GPE1_BLK_LEN;
-static int ec, mem, iofd[5], nbats, ntherms, facp;
+static int ec, mem, iofd[5], nbats, ntherms;
 static char *uid = "pm", *units[] = {"mW", "mA"};
 static Therm therms[16];
 static Bat bats[4];
+static FACP facp;
 
 static int
 enumec(void *dot, void *)
@@ -240,25 +265,54 @@
 	close(ctl);
 }
 
+static ulong
+get32(uchar *p)
+{
+	return p[3]<<24 | p[2]<<16 | p[1]<<8 | p[0];
+}
+
+static uvlong
+get64(uchar *p)
+{
+	return ((uvlong)p[7]<<56) | ((uvlong)p[6]<<48)
+			| ((uvlong)p[5]<<40) | ((uvlong)p[4]<<32)
+			| ((uvlong)p[3]<<24) | ((uvlong)p[2]<<16)
+			| ((uvlong)p[1]<<8) | ((uvlong)p[0]);
+}
+
 static void
-outw(long addr, ushort val)
+put64(uchar *p, uvlong i)
 {
-	uchar buf[2];
+	p[0] = i; p[1] = i >> 8;
+	p[2] = i >> 16; p[3] = i >> 24;
+	p[4] = i >> 32; p[5] = i >> 40;
+	p[6] = i >> 48; p[7] = i >> 56;
+}
 
-	if(addr == 0)
-		return;
-	buf[0] = val;
-	buf[1] = val >> 8;
-	pwrite(iofd[2], buf, 2, addr);
+static int
+wid2len(int wid)
+{
+	if(wid == 1)
+		return 1;
+	if(wid == 2)
+		return 2;
+	if(wid == 3)
+		return 4;
+	if(wid == 4)
+		return 8;
+
+	return 0;
 }
 
 static void
 poweroff(void)
 {
-	int n;
+	int n, w;
 	void *tts, *pts;
+	Amlio ioa, iob;
+	uchar buf[8];
 
-	if(facp == 0){
+	if(facp.ok == 0){
 		werrstr("no FACP");
 		return;
 	}
@@ -276,17 +330,40 @@
 		amleval(tts, "i", 5, nil);
 
 	/* disable GPEs */
-	for(n = 0; GPE0_BLK > 0 && n < GPE0_BLK_LEN/2; n += 2){
-		outw(GPE0_BLK + GPE0_BLK_LEN/2 + n, 0); /* EN */
-		outw(GPE0_BLK + n, 0xffff); /* STS */
+	ioa.space = facp.gpe0space;
+	iob.space = facp.gpe1space;
+	ioa.off = facp.gpe0;
+	iob.off = facp.gpe1;
+	amlmapio(&ioa);
+	amlmapio(&iob);
+
+	w = wid2len(facp.gpe0wid);
+	for(n = 0; facp.gpe0 > 0 && n < facp.gpe0len/2; n += facp.gpe0wid){
+		memset(buf, 0, w); (*ioa.write)(&ioa, buf, w, facp.gpe0len/2 + n);
+		memset(buf, 0xff, w); (*ioa.write)(&ioa, buf, w, n);
 	}
-	for(n = 0; GPE1_BLK > 0 && n < GPE1_BLK_LEN/2; n += 2){
-		outw(GPE1_BLK + GPE1_BLK_LEN/2 + n, 0); /* EN */
-		outw(GPE1_BLK + n, 0xffff); /* STS */
+
+	w = wid2len(facp.gpe1wid);
+	for(n = 0; facp.gpe1 > 0 && n < facp.gpe1len/2; n += facp.gpe1wid){
+		memset(buf, 0, w); (*iob.write)(&iob, buf, w, facp.gpe1len/2 + n);
+		memset(buf, 0xff, w); (*iob.write)(&iob, buf, w, n);
 	}
 
-	outw(PM1a_CNT_BLK, ((SLP_TYPa << 10) & SLP_TM) | SLP_EN);
-	outw(PM1b_CNT_BLK, ((SLP_TYPb << 10) & SLP_TM) | SLP_EN);
+	ioa.space = facp.pm1aspace;
+	iob.space = facp.pm1bspace;
+	ioa.off = facp.pm1a;
+	iob.off = facp.pm1b;
+	amlmapio(&ioa);
+	amlmapio(&iob);
+
+	w = wid2len(facp.pm1awid);
+	put64(buf, ((facp.slpa << 10) & SLP_TM) | SLP_EN);
+	(*ioa.write)(&ioa, buf, w, 0);
+
+	w = wid2len(facp.pm1bwid);
+	put64(buf, ((facp.slpb << 10) & SLP_TM) | SLP_EN);
+	(*iob.write)(&iob, buf, w, 0);
+
 	sleep(100);
 
 	/*
@@ -298,9 +375,15 @@
 	 * PM1a_CNT_BLK seems to have no effect but 0x7 seems
 	 * to work fine. So trying the following as a last effort.
 	 */
-	SLP_TYPa |= SLP_TYPb;
-	outw(PM1a_CNT_BLK, ((SLP_TYPa << 10) & SLP_TM) | SLP_EN);
-	outw(PM1b_CNT_BLK, ((SLP_TYPa << 10) & SLP_TM) | SLP_EN);
+
+	facp.slpa |= facp.slpb;
+
+	w = wid2len(facp.pm1awid);
+	put64(buf, ((facp.slpa << 10) & SLP_TM) | SLP_EN);
+	(*ioa.write)(&ioa, buf, w, 0);
+	w = wid2len(facp.pm1bwid);
+	put64(buf, ((facp.slpa << 10) & SLP_TM) | SLP_EN);
+	(*iob.write)(&iob, buf, w, 0);
 	sleep(100);
 
 	werrstr("acpi failed");
@@ -371,12 +454,8 @@
 	.write = fswrite,
 };
 
-static ulong
-get32(uchar *p)
-{
-	return p[3]<<24 | p[2]<<16 | p[1]<<8 | p[0];
-}
 
+
 void
 threadmain(int argc, char **argv)
 {
@@ -442,19 +521,58 @@
 		}else if(memcmp("SSDT", t->sig, 4) == 0){
 			amlload(t->data, l);
 		}else if(memcmp("FACP", t->sig, 4) == 0){
-			facp = 1;
-			PM1a_CNT_BLK = get32(((uchar*)t) + 64);
-			PM1b_CNT_BLK = get32(((uchar*)t) + 68);
-			GPE0_BLK = get32(((uchar*)t) + 80);
-			GPE1_BLK = get32(((uchar*)t) + 84);
-			GPE0_BLK_LEN = *(((uchar*)t) + 92);
-			GPE1_BLK_LEN = *(((uchar*)t) + 93);
+			facp.ok = 1;
+			if(t->rev >= 2) {
+				/* try the 64 bit pointers from ACPI 2.0 */
+				facp.pm1aspace = *(((uchar*)t) + 172);
+				facp.pm1awid = *(((uchar*)t) + 175);
+				facp.pm1a = get64(((uchar*)t) + 176);
+
+				facp.pm1bspace = *(((uchar*)t) + 184);
+				facp.pm1bwid = *(((uchar*)t) + 187);
+				facp.pm1b = get64(((uchar*)t) + 188);
+
+				facp.gpe0space = *(((uchar*)t) + 220);
+				facp.gpe0wid = *(((uchar*)t) + 223);
+				facp.gpe0 = get64(((uchar*)t) + 224);
+
+				facp.gpe1space = *(((uchar*)t) + 232);
+				facp.gpe1wid = *(((uchar*)t) + 235);
+				facp.gpe1 = get64(((uchar*)t) + 236);
+			}
+
+			/* fall back to ACPI 1.0 io port method */
+			if(!facp.pm1a) {
+				facp.pm1aspace = IoSpace;
+				facp.pm1awid = 2;
+				facp.pm1a = get32(((uchar*)t) + 64);
+			}
+
+			if(!facp.pm1b) {
+				facp.pm1bspace = IoSpace;
+				facp.pm1bwid = 2;
+				facp.pm1b = get32(((uchar*)t) + 68);
+			}
+
+			if(!facp.gpe0) {
+				facp.gpe0space = IoSpace;
+				facp.gpe0wid = 2;
+				facp.gpe0 = get32(((uchar*)t) + 80);
+				facp.gpe0len = *(((uchar*)t) + 92);
+			}
+
+			if(!facp.gpe1) {
+				facp.gpe1space = IoSpace;
+				facp.gpe1wid = 2;
+				facp.gpe1 = get32(((uchar*)t) + 84);
+				facp.gpe1len = *(((uchar*)t) + 93);
+			}
 		}
 	}
 	if(amleval(amlwalk(amlroot, "_S5"), "", &r) >= 0 && amltag(r) == 'p' && amllen(r) >= 2){
 		rr = amlval(r);
-		SLP_TYPa = amlint(rr[0]);
-		SLP_TYPb = amlint(rr[1]);
+		facp.slpa = amlint(rr[0]);
+		facp.slpb = amlint(rr[1]);
 	}
 	close(fd);
 

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-05-21 13:54 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-20 23:17 [9front] [PATCH] aux/acpi: support new ACPI 2.0 info for shutdown mia soweli

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).