acpi shutdown

This commit is contained in:
aiju 2012-06-29 16:55:48 +02:00
parent 3500a4fafe
commit 1eff3709b4
2 changed files with 110 additions and 5 deletions

View file

@ -38,9 +38,12 @@ for (i in $k){
# for scram, don't scram other systems # for scram, don't scram other systems
bind -b '#P' /dev bind -b '#P' /dev
if (test -e '#P'/apm) if(! ~ $reboot yes){
if (! ~ $reboot yes) if (test -e '#P'/apm)
scram=yes scram=yes
if (test -e '#P'/acpitbls -a -e '#P'/iow)
scram=yes
}
# halting (binaries we run can't be on the fs we're halting) # halting (binaries we run can't be on the fs we're halting)
ramfs ramfs
@ -85,8 +88,10 @@ fn x {
echo rebooting... echo rebooting...
echo reboot >'#c/reboot' echo reboot >'#c/reboot'
} }
if (~ $scram yes) if (~ $scram yes){
scram scram
echo 'It''s now safe to turn off your computer'
}
} }
x x

View file

@ -1,9 +1,39 @@
#include <u.h> #include <u.h>
#include </386/include/ureg.h> #include </386/include/ureg.h>
#include <libc.h> #include <libc.h>
#include <aml.h>
struct Ureg u; struct Ureg u;
int fd; int fd, iofd, PM1A_CNT_BLK, PM1B_CNT_BLK, SLP_TYPa, SLP_TYPb;
typedef struct Tbl Tbl;
struct Tbl {
uchar sig[4];
uchar len[4];
uchar rev;
uchar csum;
uchar oemid[6];
uchar oemtid[8];
uchar oemrev[4];
uchar cid[4];
uchar crev[4];
uchar data[];
};
void*
amlalloc(int n){
return mallocz(n, 1);
}
void
amlfree(void *p){
free(p);
}
static uint
get32(uchar *p){
return p[3]<<24 | p[2]<<16 | p[1]<<8 | p[0];
}
void void
apm(void) apm(void)
@ -18,12 +48,67 @@ apm(void)
sysfatal("apm: %lux", (u.ax>>8) & 0xFF); sysfatal("apm: %lux", (u.ax>>8) & 0xFF);
} }
int
loadacpi(void)
{
void *r, **rr;
Tbl *t;
int n;
ulong l;
amlinit();
for(;;){
t = malloc(sizeof(*t));
if((n = readn(fd, t, sizeof(*t))) <= 0)
break;
if(n != sizeof(*t))
return -1;
l = *(ulong*)(t->len);
if(l < sizeof(*t))
return -1;
t = realloc(t, l);
l -= sizeof(*t);
if(readn(fd, t->data, l) != l)
return -1;
if(memcmp("DSDT", t->sig, 4) == 0)
amlload(t->data, l);
else if(memcmp("SSDT", t->sig, 4) == 0)
amlload(t->data, l);
else if(memcmp("FACP", t->sig, 4) == 0){
PM1A_CNT_BLK = get32(((uchar*)t) + 64);
PM1B_CNT_BLK = get32(((uchar*)t) + 68);
}
}
if(PM1A_CNT_BLK == 0)
return -1;
if(amleval(amlwalk(amlroot, "_S5"), "", &r) < 0)
return -1;
if(amltag(r) != 'p' || amllen(r) < 2)
return -1;
rr = amlval(r);
if(amltag(rr[1]) != 'i')
return -1;
SLP_TYPa = (amlint(rr[1]) & 0xFF) << 10;
SLP_TYPb = ((amlint(rr[1]) >> 8) & 0xFF) << 10;
return 0;
}
void
outw(long addr, short val)
{
char buf[2];
buf[0] = val;
buf[1] = val >> 8;
pwrite(iofd, buf, 2, addr);
}
void void
main() main()
{ {
if((fd = open("/dev/apm", ORDWR)) < 0) if((fd = open("/dev/apm", ORDWR)) < 0)
if((fd = open("#P/apm", ORDWR)) < 0) if((fd = open("#P/apm", ORDWR)) < 0)
sysfatal("open: %r"); goto tryacpi;
u.ax = 0x530E; u.ax = 0x530E;
u.bx = 0x0000; u.bx = 0x0000;
@ -33,4 +118,19 @@ main()
u.bx = 0x0001; u.bx = 0x0001;
u.cx = 0x0003; u.cx = 0x0003;
apm(); apm();
tryacpi:
if((fd = open("/dev/acpitbls", OREAD)) < 0)
if((fd = open("#P/acpitbls", OREAD)) < 0)
goto fail;
if((iofd = open("/dev/iow", OWRITE)) < 0)
if((iofd = open("#P/iow", OWRITE)) < 0)
goto fail;
if(loadacpi() < 0)
goto fail;
outw(PM1A_CNT_BLK, SLP_TYPa | 0x2000);
if(PM1B_CNT_BLK != 0)
outw(PM1B_CNT_BLK, SLP_TYPb | 0x2000);
fail:
;
} }