diff -r 1d2fc4425c99 sys/src/9/pc/archacpi.c
--- a/sys/src/9/pc/archacpi.c	Sat Jun 01 13:44:07 2013 -0400
+++ b/sys/src/9/pc/archacpi.c	Sat Jun 01 19:56:34 2013 +0000
@@ -289,6 +289,232 @@
 	return BUSBNO(pdev->bridge->tbdf);
 }
 
+static void
+acpibat(void *dot)
+{	
+	uvlong sta;
+	void *m;
+	void *p, **a;
+	enum { BatteryPresent = (1L << 4) };
+	enum { BifUnknown = 0xffffffff };
+
+	if((m = amlwalk(dot, "_STA")) == 0) {
+		print("bat: no _STA\n");
+		return;
+	}
+	if(amleval(m, "", &p) < 0) {
+		print("bat: _STA not working\n");
+		return;
+	}
+	sta = amlint(p);
+	if((sta & BatteryPresent) != 0) {
+		print("bat:\n");
+
+		if((m = amlwalk(dot, "_BIF")) == 0) {
+			print("bat: no _BIF\n");
+			return;
+		}
+		if(amleval(m, "", &p) < 0) {
+			print("bat: _BIF not working\n");
+			return;
+		}
+
+		a = amlval(p);
+		print("\tpower unit: %ulld\n", amlint(a[0]));
+		print("\tcapacity: %ulld\n", amlint(a[1]));
+		print("\tlast capacity: %ulld\n", amlint(a[2]));
+		print("\tvoltage: %ulld\n", amlint(a[4]));
+		print("\tmodel: %s\n", (char*)amlval(a[9]));
+		print("\ttype: %s\n", (char*)amlval(a[11]));
+		print("\toem: %s\n", (char*)amlval(a[12]));
+
+		if((m = amlwalk(dot, "_BST")) == 0) {
+			print("bat: no _BST\n");
+			return;
+		}
+		if(amleval(m, "", &p) < 0) {
+			print("bat: _BST not working\n");
+			return;
+		}
+		a = amlval(p);
+		print("\tstate: %ulld\n", amlint(a[0]));
+		print("\trate: %ulld\n", amlint(a[1]));
+		print("\tcapacity: %ulld\n", amlint(a[2]));
+		print("\tvoltage: %ulld\n", amlint(a[3]));
+	}
+}
+
+static int
+acpiec_getreg(unsigned char *buf, int size, int *type, int *addr)
+{
+	enum { ResTypeMask = 0x80, ResLengthMask = 0x07,
+		   ResTypeIoPort = 0x47, ResTypeEndTag = 0x79 };
+
+	enum { SystemIoSpace = 1 };
+
+	int len, hlen;
+
+	if (size <= 0)
+		return 0;
+	if (*buf & ResTypeMask) {
+		/* large resource */
+		if (size < 3)
+			return 1;
+		len = (int)buf[1] + 256 * (int)buf[2];
+		hlen = 3;
+	} else {
+		/* small resource */
+		len = buf[0] & ResLengthMask;
+		hlen = 1;
+	}
+	if (*buf != ResTypeIoPort)
+		return 0;
+
+	if (size < hlen + len)
+		return 0;
+	
+	*type = SystemIoSpace;
+	*addr = (int)buf[2] + 256 * (int)buf[3];
+
+	return (hlen + len);
+}
+
+
+static void
+acpiec(void *dot) 
+{
+	void *m;
+	char *buf;
+	void *p;
+	int gpe;
+	int rv, size, t;
+
+	int ec_sc, ec_data;
+
+	if((m = amlwalk(dot, "_GPE")) == 0) {
+		print("ec: no _GPE\n");
+		return;
+	}
+	if(amleval(m, "", &p) < 0) {
+		print("ec: _GPE not working\n");
+		return;
+	}
+
+	gpe = amlint(amlval(p));
+
+	if((m = amlwalk(dot, "_CRS")) == 0) {
+		print("ec: no _CRS\n");
+		return;
+	}
+	if(amleval(m, "", &buf) < 0) {
+		print("ec: _CRS not working\n");
+		return;
+	}
+	if(amltag(buf) != 'b') {
+		print("ec: unknown _CRS type\n");
+		return;
+	}
+	size = amllen(buf);
+	rv = acpiec_getreg(amlval(buf), size, &t, &ec_data);
+	//print("getreg: rv=%d t=%d ec_data=0x%x\n", rv, t, ec_data);
+
+	buf += rv;
+	size -= rv;
+
+	rv = acpiec_getreg(amlval(buf), size, &t, &ec_sc);
+	//print("getreg: rv=%d t=%d ec_sc=0x%x\n", rv, t, ec_sc);
+
+	buf += rv;
+	size -= rv;
+
+	if(size != 2 || *buf != 0x79) {
+		print("no crs endtag\n");
+	}
+
+	if(ioalloc(ec_data, 1, 0, "ec_data") < 0)
+		print("ec: ec_data port space in use");
+	if (ioalloc(ec_sc, 1, 0, "ec_sc") < 0)
+		print("ec: ec_sc port space in use");
+
+	/* register */
+	enum { RegTypeEC = 3 };
+	if((m = amlwalk(dot, "_REG")) == 0) {
+		print("ec: no _REG\n");
+		return;
+	}
+	if(amleval(m, "ii", RegTypeEC, 1, nil) < 0) {
+		print("ec: _REG not working\n");
+		return;
+	}	
+	print("ec: status: %d gpe: %d data: 0x%x s/c: 0x%x \n",
+		inb(ec_sc), gpe, ec_data, ec_sc);	
+}
+
+static int
+acpiacstatus(void *mi) 
+{
+	void **p;
+	static void *m = nil;
+
+	if(mi != nil)
+		m = mi;
+
+	if(amleval(m, "", &p) < 0) {
+		print("ac: _PSR not working\n");
+		return 0;
+	}
+	return amlint(p);
+}
+
+static void
+acpiac(void *dot) 
+{
+	uvlong sta;
+	void *m;
+	void *p;
+	enum { Offline, Online };
+
+	if((m = amlwalk(dot, "_STA")) == 0) {
+		print("ac: no _STA\n");
+		return;
+	}
+	if(amleval(m, "", &p) < 0) {
+		print("ac: _STA not working\n");
+		return;
+	}
+	if((m = amlwalk(dot, "_PSR")) == 0) {
+		print("ac: no _PSR\n");
+		return;
+	}
+	sta = acpiacstatus(m);
+	if(sta == Online)
+		print("ac: AC online\n");
+	else if(sta == Offline)
+		print("ac: AC offline\n");
+	else
+		print("ac: status unknown\n");
+}	
+
+static int 
+enumhid(void *dot, void *)
+{
+	void *p;
+	char *id;
+
+	id = nil;
+	p = nil;
+	if(amleval(dot, "", &p) == 0)
+			id = eisaid(p);
+
+	if(id && (!strcmp(id, "PNP0C09")))
+		acpiec(dot);
+	if(id && (!strcmp(id, "PNP0C0A")))
+		acpibat(dot);
+	if(id && (!strcmp(id, "ACPI0003")))
+		acpiac(dot);
+	return -1;
+}
+
 static int
 enumprt(void *dot, void *)
 {
@@ -428,8 +654,11 @@
 	for(i=0; i<16; i++)
 		addirq(i, BusISA, 0, i, 0);
 
+	/* look for other ACPI devices */
+	amlenum(amlroot, "_HID", enumhid, nil);
+
 	/* free the AML interpreter */
-	amlexit();
+	//amlexit();
 
 	/*
 	 * Ininitalize local APIC and start application processors.
@@ -479,6 +708,18 @@
 	return p - (uchar*)v;
 }
 
+static long
+readacpi(Chan*, void *v, long n, vlong o)
+{
+	int m;
+
+	if (o >= 7)
+		return 0;
+	m = sprint((char*)v, "ac: %s\n", acpiacstatus(nil) ? "on" : "off");
+
+	return m;
+}
+
 static int
 identify(void)
 {
@@ -491,6 +732,7 @@
 	if(checksum(rsd, 20) && checksum(rsd, 36))
 		return 1;
 	addarchfile("acpitbls", 0444, readtbls, nil);
+	addarchfile("acpi", 0444, readacpi, nil);
 	if(strcmp(cp, "0") == 0)
 		return 1;
 	if((cp = getconf("*nomp")) != nil && strcmp(cp, "0") != 0)
