2 #include </386/include/ureg.h>
8 ulong PM1a_CNT_BLK, PM1b_CNT_BLK, SLP_TYPa, SLP_TYPb;
9 ulong GPE0_BLK, GPE1_BLK, GPE0_BLK_LEN, GPE1_BLK_LEN;
15 typedef struct Tbl Tbl;
30 Tblsz = 4+4+1+1+6+8+4+4+4,
35 return p[3]<<24 | p[2]<<16 | p[1]<<8 | p[0];
42 if(write(fd, &u, sizeof u) < 0)
43 sysfatal("write: %r");
45 if(read(fd, &u, sizeof u) < 0)
48 sysfatal("apm: %lux", (u.ax>>8) & 0xFF);
61 t = malloc(sizeof(*t));
62 if((n = readn(fd, t, Tblsz)) <= 0)
70 t = realloc(t, sizeof(*t) + l);
71 if(readn(fd, t->data, l) != l)
73 if(memcmp("DSDT", t->sig, 4) == 0){
74 amlintmask = (~0ULL) >> (t->rev <= 1)*32;
77 else if(memcmp("SSDT", t->sig, 4) == 0)
79 else if(memcmp("FACP", t->sig, 4) == 0){
80 PM1a_CNT_BLK = get32(((uchar*)t) + 64);
81 PM1b_CNT_BLK = get32(((uchar*)t) + 68);
82 GPE0_BLK = get32(((uchar*)t) + 80);
83 GPE1_BLK = get32(((uchar*)t) + 84);
84 GPE0_BLK_LEN = *(((uchar*)t) + 92);
85 GPE1_BLK_LEN = *(((uchar*)t) + 93);
88 if(amleval(amlwalk(amlroot, "_S5"), "", &r) < 0)
90 if(amltag(r) != 'p' || amllen(r) < 2)
93 SLP_TYPa = amlint(rr[0]);
94 SLP_TYPb = amlint(rr[1]);
99 outw(long addr, ushort val)
107 pwrite(iofd, buf, 2, addr);
116 snprint(buf, sizeof(buf), "/proc/%d/ctl", getpid());
117 if((ctl = open(buf, OWRITE)) < 0){
118 snprint(buf, sizeof(buf), "#p/%d/ctl", getpid());
119 if((ctl = open(buf, OWRITE)) < 0)
122 write(ctl, "wired 0", 7);
133 if((fd = open("/dev/apm", ORDWR)) < 0)
134 if((fd = open("#P/apm", ORDWR)) < 0)
147 if((fd = open("/dev/acpitbls", OREAD)) < 0)
148 if((fd = open("#P/acpitbls", OREAD)) < 0)
150 if((iofd = open("/dev/iow", OWRITE)) < 0)
151 if((iofd = open("#P/iow", OWRITE)) < 0)
157 for(n = 0; GPE0_BLK > 0 && n < GPE0_BLK_LEN/2; n += 2){
158 outw(GPE0_BLK + GPE0_BLK_LEN/2 + n, 0); /* EN */
159 outw(GPE0_BLK + n, 0xffff); /* STS */
161 for(n = 0; GPE1_BLK > 0 && n < GPE1_BLK_LEN/2; n += 2){
162 outw(GPE1_BLK + GPE1_BLK_LEN/2 + n, 0); /* EN */
163 outw(GPE1_BLK + n, 0xffff); /* STS */
166 outw(PM1a_CNT_BLK, ((SLP_TYPa << 10) & SLP_TM) | SLP_EN);
167 outw(PM1b_CNT_BLK, ((SLP_TYPb << 10) & SLP_TM) | SLP_EN);
171 * The SetSystemSleeping() example from the ACPI spec
172 * writes the same value in both registers. But Linux/BSD
173 * write distinct values from the _Sx package (like the
174 * code above). The _S5 package on a HP DC5700 is
175 * Package(0x2){0x0, 0x7} and writing SLP_TYPa of 0 to
176 * PM1a_CNT_BLK seems to have no effect but 0x7 seems
177 * to work fine. So trying the following as a last effort.
179 SLP_TYPa |= SLP_TYPb;
180 outw(PM1a_CNT_BLK, ((SLP_TYPa << 10) & SLP_TM) | SLP_EN);
181 outw(PM1b_CNT_BLK, ((SLP_TYPa << 10) & SLP_TM) | SLP_EN);