diff -r 1d2fc4425c99 sys/include/aml.h
--- a/sys/include/aml.h	Sat Jun 01 13:44:07 2013 -0400
+++ b/sys/include/aml.h	Mon Jun 03 21:23:02 2013 +0000
@@ -33,4 +33,7 @@
 
 /* to be provided by operating system */
 extern void*	amlalloc(int);
-extern void	amlfree(void*);
+extern void		amlfree(void*);
+extern void 	acpi_read(int, int, int, uvlong *);
+extern void 	acpi_write(int, int, int, uvlong);
+extern void 	acpi_delay(int);
\ No newline at end of file
diff -r 1d2fc4425c99 sys/src/9/pc/acpiec.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/9/pc/acpiec.c	Mon Jun 03 21:23:02 2013 +0000
@@ -0,0 +1,238 @@
+#include <u.h>
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "mp.h"
+
+#include <aml.h>
+
+struct Gas {
+	uchar 	space;
+	uchar 	bw;
+	uchar	bo;
+	uchar 	size;
+	uchar	addr[8];
+};
+
+struct Ecdt {
+	struct Gas	ec_cmd;
+	struct Gas 	ec_data;
+	uchar 		uid[4];
+	uchar 		gpe;
+	uchar 		id[1];
+};
+
+struct ec {
+	int cmd;
+	int data;
+	int ready;
+} ec;
+
+enum { 
+	/* status bits */
+	OutBufFull = 0x01, 
+	InBufFull  = 0x02,
+	DataIsCmd  = 0x08,
+	Burst      = 0x10,
+	SciEvt     = 0x20,
+	SmiEvt     = 0x40,
+	/* commands */
+	EcRead 	   = 0x80,
+	EcWrite    = 0x81,
+	EcBurstEn  = 0x82,
+	EcBurstDis = 0x83,
+	EcQuery	   = 0x84,
+};
+
+static void
+acpiec_wait(uchar mask, uchar val)
+{
+	uchar stat;
+
+	while((stat = inb(ec.cmd) & mask) != val) {
+		if (stat & Burst)
+			delay(1);
+	}
+}
+
+static uchar
+acpiec_read_data(void)
+{
+	acpiec_wait(OutBufFull, OutBufFull);
+	return inb(ec.data);
+}
+
+static void
+acpiec_write_data(uchar val)
+{
+	acpiec_wait(InBufFull, 0);
+	outb(ec.data, val);
+}
+
+static void
+acpiec_write_cmd(uchar val)
+{
+	acpiec_wait(InBufFull, 0);
+	outb(ec.cmd, val);
+}
+
+uchar
+acpiec_read(uchar addr)
+{
+	if (!ec.ready)
+		return 0;
+	acpiec_write_cmd(EcRead);
+	acpiec_write_data(addr);
+	
+	return acpiec_read_data();
+}
+
+void
+acpiec_write(uchar addr, uvlong val)
+{
+	int i;
+	uchar *v = (uchar*)&val;
+
+	if (!ec.ready)
+		return;
+
+	for(i = 0; i < sizeof(uvlong); i++) {
+		acpiec_write_cmd(EcWrite);
+		acpiec_write_data(addr + i); // ?
+		acpiec_write_data(v[i]);
+	}
+}
+
+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 uint
+get32(uchar *p){
+	return p[3]<<24 | p[2]<<16 | p[1]<<8 | p[0];
+}
+
+static uvlong
+get64(uchar *p){
+	uvlong u;
+
+	u = get32(p+4);
+	return u<<32 | get32(p);
+}
+
+void
+acpiec_init(void *dot, void *tbl) 
+{
+	void *m;
+	char *buf;
+	void *p;
+	int gpe;
+	int rv, size, t;
+	int ec_sc, ec_data;
+	struct Ecdt *ecdt = tbl;
+
+	if(ec.ready)
+		return;
+	if(ecdt != nil) {
+		ecdt = (struct Ecdt*)tbl;
+		ec_sc = get64(ecdt->ec_cmd.addr);
+		ec_data = get64(ecdt->ec_data.addr);
+		gpe = ecdt->gpe;
+		goto done;
+	}
+
+	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");
+	}
+
+	/* 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;
+	}	
+done:
+	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");
+	print("ec: status: %d gpe: %d data: 0x%x s/c: 0x%x \n",
+		inb(ec_sc), gpe, ec_data, ec_sc);	
+	ec.cmd = ec_sc;
+	ec.data = ec_data;
+	ec.ready = 1;
+}
\ No newline at end of file
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	Mon Jun 03 21:23:02 2013 +0000
@@ -41,6 +41,10 @@
 static int ntbltab;
 static Tbl *tbltab[64];
 
+extern void acpiec_init(void *, void *);
+extern uchar acpiec_read(uchar);
+extern void acpiec_write(uchar, uvlong);
+
 void*
 amlalloc(int n){
 	void *p;
@@ -289,6 +293,25 @@
 	return BUSBNO(pdev->bridge->tbdf);
 }
 
+static int 
+findec(void *dot, void *)
+{
+	void *p;
+	char *id;
+
+	id = nil;
+	p = nil;
+	if(amleval(dot, "", &p) == 0)
+		id = eisaid(p);
+
+	/* EC is all we care about */
+	if(id && (!strcmp(id, "PNP0C09"))) {
+		acpiec_init(dot, nil);
+		return 0;
+	}
+	return -1;
+}
+
 static int
 enumprt(void *dot, void *)
 {
@@ -326,6 +349,32 @@
 	return 1;
 }
 
+void 
+acpi_read(int space, int off, int, uvlong *buf)
+{
+	if (space != 0x03) { // EbctlSpace 
+		*buf = 0;
+		return;
+	}
+	//print("acpiec_read: off 0x%x len %d\n", off, len);
+	*buf = acpiec_read(off);
+}
+
+void 
+acpi_write(int space, int off, int, uvlong val)
+{
+	if (space != 0x03) { // EbctlSpace 
+		return;
+	}
+	//print("acpiec_write: off 0x%x len %d\n", off, len);
+	acpiec_write(off, val);
+}
+
+void acpi_delay(int n)
+{
+	microdelay(n);
+}
+
 static void
 acpiinit(void)
 {
@@ -344,7 +393,9 @@
 		amlload(t->data, tbldlen(t));
 	if(t = findtable("SSDT"))
 		amlload(t->data, tbldlen(t));
-
+	if(t = findtable("ECDT"))
+		acpiec_init(nil, t->data);
+		
 	/* set APIC mode */
 	amleval(amlwalk(amlroot, "_PIC"), "i", 1, nil);
 
@@ -428,6 +479,9 @@
 	for(i=0; i<16; i++)
 		addirq(i, BusISA, 0, i, 0);
 
+	/* look for EC if not yet found */
+	amlenum(amlroot, "_HID", findec, nil);
+
 	/* free the AML interpreter */
 	amlexit();
 
@@ -479,6 +533,20 @@
 	return p - (uchar*)v;
 }
 
+static long
+writeacpiec(Chan*, void *a, long n, vlong off)
+{
+	acpi_write(0x03, off, n, *((uvlong*)a));
+	return n;
+}
+
+static long
+readacpiec(Chan*, void *v, long n, vlong off)
+{
+	acpi_read(0x03, off, n, v);
+	return 1;
+}
+
 static int
 identify(void)
 {
@@ -491,6 +559,7 @@
 	if(checksum(rsd, 20) && checksum(rsd, 36))
 		return 1;
 	addarchfile("acpitbls", 0444, readtbls, nil);
+	addarchfile("acpiec", 0664, readacpiec, writeacpiec);
 	if(strcmp(cp, "0") == 0)
 		return 1;
 	if((cp = getconf("*nomp")) != nil && strcmp(cp, "0") != 0)
diff -r 1d2fc4425c99 sys/src/9/pc/pcf
--- a/sys/src/9/pc/pcf	Sat Jun 01 13:44:07 2013 -0400
+++ b/sys/src/9/pc/pcf	Mon Jun 03 21:23:02 2013 +0000
@@ -83,6 +83,7 @@
 
 misc
 	archacpi	mp apic
+	acpiec 		mp apic
 	archmp		mp apic
 	mtrr
 
diff -r 1d2fc4425c99 sys/src/libaml/aml.c
--- a/sys/src/libaml/aml.c	Sat Jun 01 13:44:07 2013 -0400
+++ b/sys/src/libaml/aml.c	Mon Jun 03 21:23:02 2013 +0000
@@ -138,10 +138,12 @@
 	void	*arg[8];
 };
 
+enum { CondPrev, CondCur };
+
 struct Interp {
 	uchar	*pc;
 	Frame	*fp;
-	int	cond;
+	int	cond[2];
 };
 
 static Interp	interp;
@@ -167,7 +169,7 @@
 	Ocfld, Ocfld0, Ocfld1, Ocfld2, Ocfld4, Ocfld8,
 	Oif, Oelse, Owhile, Obreak, Oret, Ocall, 
 	Ostore, Oderef, Osize, Oref, Ocref,
-	Oacq, Orel,
+	Oacq, Orel, Olgte, Ollte, Oneq, Oslp
 };
 
 static Op optab[];
@@ -441,6 +443,7 @@
 	Region *r;
 	uchar *p;
 	int i;
+	uvlong ret = 0;
 
 	switch(TAG(reg)){
 	case 'b':
@@ -461,13 +464,18 @@
 		r = reg;
 		if((off+len) > r->len)
 			break;
+		if(write)
+			acpi_write(r->space, off, len, v);
+		else
+			acpi_read(r->space, off, len, &ret);
+
 		if(amldebug){
-			print("rwreg: %s %-8s [%llux+%x]/%d %llux\n", 
+			print("rwreg: %s %-8s [%llux+%x]/%d %llux ret=%llux\n", 
 				write ? "W" : "R", 
 				spacename[r->space],
-				r->off, off, len, v);
+				r->off, off, len, v, write ? v : ret);
 		}
-		break;
+		return (write ? v : ret);
 	}
 
 	return ~0;
@@ -812,7 +820,7 @@
 		if((++loop & 127) == 0)
 			gc();
 		if(amldebug)
-			print("\n%.8p.%.2lx %-8s %d\t%N\t", PC, FP - FB, FP->phase, interp.cond, FP->dot);
+			print("\n%.8p.%.2lx %-8s %d\t%N\t", PC, FP - FB, FP->phase, interp.cond[CondCur], FP->dot);
 		r = nil;
 		c = *FP->phase++;
 		switch(c){
@@ -834,6 +842,27 @@
 			FP->start = PC;
 			c = *PC++;
 			if(amldebug) print("%.2X", c);
+			if((c == 0x5b) && (*PC == 0x22)) {
+				print("sleep\n");
+				FP->op = &optab[Oslp];
+				PC++;
+			} else
+			if((c == 0x92) && ((*PC == 0x93) || (*PC == 0x94) || (*PC == 0x95))) {
+				switch (*PC) {
+				case 0x93:
+					FP->op = &optab[Oneq];
+					PC++;
+					break;
+				case 0x94:
+					FP->op = &optab[Ollte];
+					PC++;
+					break;
+				case 0x95:
+					FP->op = &optab[Olgte];
+					PC++;
+					break;
+				}
+			} else {
 			if(c == '['){
 				if(PC >= FP->end)
 					goto Overrun;
@@ -843,6 +872,7 @@
 			}else
 				c = octab1[c];
 			FP->op = &optab[c];
+			}
 			FP->narg = 0;
 			FP->phase = FP->op->sequence;
 			if(amldebug) print("\t%s %s", FP->op->name, FP->phase);
@@ -1040,6 +1070,7 @@
 		n = sizeof(Package)+ival(FP->arg[0])*sizeof(void*);
 		p = mk('p', n);
 		FP->ref = p;
+		p->n = ival(FP->arg[0]);
 	}
 	return p;
 }
@@ -1244,12 +1275,12 @@
 evalcond(void){
 	switch(FP->op - optab){
 	case Oif:
-		interp.cond = ival(FP->arg[0]) != 0;
-		if(!interp.cond)
+		interp.cond[CondCur] = ival(FP->arg[0]) != 0;
+		if(!interp.cond[1])
 			PC = FP->end;
 		break;
 	case Oelse:
-		if(interp.cond)
+		if(interp.cond[CondCur])
 			PC = FP->end;
 		break;
 	case Owhile:
@@ -1259,11 +1290,16 @@
 				FP->aux = nil;
 			}
 			return nil;
+		} else {
+			//print("Entering while, saving cond\n");
+			interp.cond[CondPrev] = interp.cond[CondCur];
 		}
 		FP->aux = FP->end;
-		interp.cond = ival(FP->arg[0]) != 0;
-		if(!interp.cond){
+		interp.cond[CondCur] = ival(FP->arg[0]) != 0;
+		if(!interp.cond[CondCur]){
 			PC = FP->end;
+			//print("Leaving while, restoring cond\n");
+			interp.cond[CondCur] = interp.cond[CondPrev];
 			break;
 		}
 		return nil;
@@ -1308,6 +1344,15 @@
 	case Olgt:
 		if(c > 0) return mki(1);
 		break;
+	case Olgte:
+		if(c >= 0) return mki(1);
+		break;
+	case Ollte:
+		if(c <= 0) return mki(1);
+		break;
+	case Oneq:
+		if(c != 0) return mki(1);
+		break;
 	case Ollt:
 		if(c < 0) return mki(1);
 		break;
@@ -1317,6 +1362,12 @@
 }
 
 static void*
+evalslp(void){
+	acpi_delay((int)amlint(FP->arg[0]));
+	return nil;
+}
+
+static void*
 evalcall(void){
 	Method *m;
 	Env *e;
@@ -1378,6 +1429,7 @@
 
 	if((e = FP->env) == nil)
 		return nil;
+
 	c = FP->start[0];
 	if(c >= 0x60 && c <= 0x67){
 		r = mk('L', sizeof(Ref));
@@ -1616,6 +1668,10 @@
 
 	[Oacq]		"Acquire",		"@2",		evalnop,
 	[Orel]		"Release",		"@",		evalnop,
+	[Olgte]     "GreaterEqual", "**", 		evalcmp,
+	[Ollte]     "LessEqual", 	"**", 		evalcmp,
+	[Oneq]     	"NotEqual", 	"**", 		evalcmp,
+	[Oslp] 		"Sleep", 		"*", 		evalslp,
 };
 
 static uchar octab1[] = {
@@ -1637,7 +1693,7 @@
 /* 78 */	Odiv,	Oshl,	Oshr,	Oand,	Onand,	Oor,	Onor,	Oxor,
 /* 80 */	Onot,	Obad,	Obad,	Oderef,	Obad,	Omod,	Obad,	Osize,
 /* 88 */	Oindex,	Obad,	Ocfld4,	Ocfld2,	Ocfld1,	Ocfld0,	Obad,	Ocfld8,
-/* 90 */	Oland,	Olor,	Olnot,	Oleq,	Olgt,	Ollt,	Obad,	Obad,
+/* 90 */	Oland,	Olor,	Olnot,	Oleq,	Olgt, 	Ollt,	Obad,	Obad,
 /* 98 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
 /* A0 */	Oif,	Oelse,	Owhile,	Onop,	Oret,	Obreak,	Obad,	Obad,
 /* A8 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
@@ -1724,6 +1780,23 @@
 	return 0;
 }
 
+static void*
+evalosi(void){
+	static char *w[] = { 
+		"Windows 2001",
+		"Windows 2001 SP1",
+		"Windows 2001 SP2",
+		"Windows 2006",
+	};
+	char *arg = (char*)(amlval(FP->arg[0]));
+	int i, res = 0;
+
+	for(i = 0; !res && (i < 4); i++)
+		res = !strcmp(w[i], arg);
+
+	return mki(res);
+}
+
 void
 amlinit(void){
 	Name *n;
@@ -1742,16 +1815,20 @@
 	getname(amlroot, "_TZ", 1);
 	getname(amlroot, "_SI", 1);
 
+	getname(amlroot, "_GL", 1);
+
 	if(n = getname(amlroot, "_REV", 1))
 		n->v = mki(2);
 	if(n = getname(amlroot, "_OS", 1))
+		n->v = mks("Microsoft Windows NT");
+	if(n = getname(amlroot, "_OS_", -1))
 		n->v = mks("Microsoft Windows");
 	if(n = getname(amlroot, "_OSI", 1)){
 		Method *m;
 
 		m = mk('m', sizeof(Method));
 		m->narg = 1;
-		m->eval = evalnop;
+		m->eval = evalosi;
 		m->name = n;
 		n->v = m;
 	}
@@ -1801,7 +1878,8 @@
 	int i;
 
 	va_start(a, fmt);
-	e = *fmt ? mk('E', sizeof(Env)) : nil;
+	//e = *fmt ? mk('E', sizeof(Env)) : nil;
+	e = mk('E', sizeof(Env));
 	for(i=0;*fmt;fmt++){
 		switch(*fmt){
 		case 's':
