2018-01-02 01:00:07 +01:00
|
|
|
|
/* Copyright (C) Charles Forsyth
|
|
|
|
|
* See /doc/license/NOTICE.Plan9-9k.txt for details about the licensing.
|
|
|
|
|
*/
|
|
|
|
|
/* Portions of this file are Copyright (C) 9front's team.
|
|
|
|
|
* See /doc/license/9front-mit for details about the licensing.
|
|
|
|
|
* See http://code.9front.org/hg/plan9front/ for a list of authors.
|
|
|
|
|
*/
|
|
|
|
|
|
2016-11-25 17:18:40 +01:00
|
|
|
|
/*
|
|
|
|
|
* ACPI 5.0 support. overly ornate.
|
|
|
|
|
* - split table parsing out from file server
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "u.h"
|
|
|
|
|
#include "../port/lib.h"
|
|
|
|
|
#include "mem.h"
|
|
|
|
|
#include "dat.h"
|
|
|
|
|
#include "fns.h"
|
|
|
|
|
#include "io.h"
|
|
|
|
|
#include "../port/error.h"
|
|
|
|
|
#include "acpi.h"
|
|
|
|
|
#include <aml.h>
|
|
|
|
|
|
|
|
|
|
enum {
|
|
|
|
|
/* ACPI PM1 control */
|
|
|
|
|
Pscien = 1<<0, /* Generate SCI and not SMI */
|
|
|
|
|
Pbmrld = 1<<1, /* busmaster → C0 */
|
|
|
|
|
Pgblrls = 1<<2, /* global release */
|
|
|
|
|
|
|
|
|
|
/* pm1 events */
|
|
|
|
|
Etimer = 1<<0,
|
|
|
|
|
Ebme = 1<<4,
|
|
|
|
|
Eglobal = 1<<5,
|
|
|
|
|
Epowerbtn = 1<<8, /* power button pressed */
|
|
|
|
|
Esleepbtn = 1<<9,
|
|
|
|
|
Ertc = 1<<10,
|
|
|
|
|
Epciewake = 1<<14,
|
|
|
|
|
Ewake = 1<<15,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
typedef struct Aconf Aconf;
|
|
|
|
|
typedef struct Gpe Gpe;
|
|
|
|
|
|
|
|
|
|
struct Aconf {
|
|
|
|
|
Lock;
|
|
|
|
|
int init;
|
|
|
|
|
void (*powerbutton)(void);
|
|
|
|
|
|
|
|
|
|
uint32_t eventopen;
|
|
|
|
|
Queue *event;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct Gpe {
|
|
|
|
|
uintptr_t stsio; /* port used for status */
|
|
|
|
|
int stsbit; /* bit number */
|
|
|
|
|
uintptr_t enio; /* port used for enable */
|
|
|
|
|
int enbit; /* bit number */
|
|
|
|
|
int nb; /* event number */
|
|
|
|
|
char* obj; /* handler object */
|
|
|
|
|
int id; /* id as supplied by user */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum {
|
|
|
|
|
CMgpe, /* gpe name id */
|
|
|
|
|
CMpowerbut,
|
|
|
|
|
CMpower,
|
|
|
|
|
|
|
|
|
|
Qdir = 0,
|
|
|
|
|
Qctl,
|
|
|
|
|
Qevent,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static Cmdtab ctls[] = {
|
|
|
|
|
{CMgpe, "gpe", 3},
|
|
|
|
|
{CMpowerbut, "powerbutton", 2},
|
|
|
|
|
{CMpower, "power", 2},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static Dirtab acpidir[]={
|
|
|
|
|
".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
|
|
|
|
|
"acpictl", {Qctl}, 0, 0666,
|
|
|
|
|
"acpievent", {Qevent, 0, QTEXCL}, 0, DMEXCL|0440,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static Gpe* gpes; /* General purpose events */
|
|
|
|
|
static int ngpe;
|
|
|
|
|
static Aconf aconf;
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
acpigen(Chan *c, char* _1, Dirtab *tab, int ntab, int i, Dir *dp)
|
|
|
|
|
{
|
|
|
|
|
Qid qid;
|
|
|
|
|
|
|
|
|
|
if(i == DEVDOTDOT){
|
|
|
|
|
mkqid(&qid, Qdir, 0, QTDIR);
|
|
|
|
|
devdir(c, qid, ".", 0, eve, 0555, dp);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
i++; /* skip first element for . itself */
|
|
|
|
|
if(tab==0 || i>=ntab)
|
|
|
|
|
return -1;
|
|
|
|
|
tab += i;
|
|
|
|
|
qid = tab->qid;
|
|
|
|
|
qid.path &= ~Qdir;
|
|
|
|
|
qid.vers = 0;
|
|
|
|
|
devdir(c, qid, tab->name, tab->length, eve, tab->perm, dp);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ra/rb are int not uintmem because inb/outb are in the i/o address space. */
|
|
|
|
|
static uint32_t
|
|
|
|
|
getbanked(int ra, int rb, int sz)
|
|
|
|
|
{
|
|
|
|
|
uint32_t r;
|
|
|
|
|
|
|
|
|
|
r = 0;
|
|
|
|
|
switch(sz){
|
|
|
|
|
case 1:
|
|
|
|
|
if(ra != 0)
|
|
|
|
|
r |= inb(ra);
|
|
|
|
|
if(rb != 0)
|
|
|
|
|
r |= inb(rb);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
if(ra != 0)
|
|
|
|
|
r |= ins(ra);
|
|
|
|
|
if(rb != 0)
|
|
|
|
|
r |= ins(rb);
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
if(ra != 0)
|
|
|
|
|
r |= inl(ra);
|
|
|
|
|
if(rb != 0)
|
|
|
|
|
r |= inl(rb);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2017-04-19 23:33:14 +02:00
|
|
|
|
jehanne_print("getbanked: wrong size\n");
|
2016-11-25 17:18:40 +01:00
|
|
|
|
}
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint32_t
|
|
|
|
|
setbanked(int ra, int rb, int sz, int v)
|
|
|
|
|
{
|
|
|
|
|
uint32_t r;
|
|
|
|
|
|
|
|
|
|
r = -1;
|
|
|
|
|
switch(sz){
|
|
|
|
|
case 1:
|
|
|
|
|
if(ra != 0)
|
|
|
|
|
outb(ra, v);
|
|
|
|
|
if(rb != 0)
|
|
|
|
|
outb(rb, v);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
if(ra != 0)
|
|
|
|
|
outs(ra, v);
|
|
|
|
|
if(rb != 0)
|
|
|
|
|
outs(rb, v);
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
if(ra != 0)
|
|
|
|
|
outl(ra, v);
|
|
|
|
|
if(rb != 0)
|
|
|
|
|
outl(rb, v);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2017-04-19 23:33:14 +02:00
|
|
|
|
jehanne_print("setbanked: wrong size\n");
|
2016-11-25 17:18:40 +01:00
|
|
|
|
}
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* we must read the register group *as a whole*
|
|
|
|
|
*/
|
|
|
|
|
static uint32_t
|
|
|
|
|
getpm1ctl(void)
|
|
|
|
|
{
|
|
|
|
|
return getbanked(fadt.pm1acntblk, fadt.pm1bcntblk, fadt.pm1cntlen);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint32_t
|
|
|
|
|
getpm1sts(void)
|
|
|
|
|
{
|
|
|
|
|
return getbanked(fadt.pm1aevtblk, fadt.pm1bevtblk, fadt.pm1evtlen) & 0xffff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint32_t
|
|
|
|
|
getpm1en(void)
|
|
|
|
|
{
|
|
|
|
|
return getbanked(fadt.pm1aevtblk, fadt.pm1bevtblk, fadt.pm1evtlen)>>16;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
setpm1en(uint32_t v)
|
|
|
|
|
{
|
|
|
|
|
uint32_t r;
|
|
|
|
|
|
|
|
|
|
r = getbanked(fadt.pm1aevtblk, fadt.pm1bevtblk, fadt.pm1evtlen);
|
|
|
|
|
r &= 0xffff;
|
|
|
|
|
setbanked(fadt.pm1aevtblk, fadt.pm1bevtblk, fadt.pm1evtlen, r | v<<16);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
setpm1sts(uint32_t v)
|
|
|
|
|
{
|
|
|
|
|
uint32_t r;
|
|
|
|
|
|
|
|
|
|
DBG("acpi: setpm1sts %#ux\n", v);
|
|
|
|
|
|
|
|
|
|
r = getbanked(fadt.pm1aevtblk, fadt.pm1bevtblk, fadt.pm1evtlen);
|
|
|
|
|
r &= 0xffff0000;
|
|
|
|
|
setbanked(fadt.pm1aevtblk, fadt.pm1bevtblk, fadt.pm1evtlen, r | v);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
getgpeen(int n)
|
|
|
|
|
{
|
|
|
|
|
return inb(gpes[n].enio) & 1<<gpes[n].enbit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
setgpeen(int n, uint32_t v)
|
|
|
|
|
{
|
|
|
|
|
int old;
|
|
|
|
|
|
|
|
|
|
DBG("acpi: setgpe %d %d\n", n, v);
|
|
|
|
|
old = inb(gpes[n].enio);
|
|
|
|
|
if(v)
|
|
|
|
|
outb(gpes[n].enio, old | 1<<gpes[n].enbit);
|
|
|
|
|
else
|
|
|
|
|
outb(gpes[n].enio, old & ~(1<<gpes[n].enbit));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
clrgpests(int n)
|
|
|
|
|
{
|
|
|
|
|
outb(gpes[n].stsio, 1<<gpes[n].stsbit);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint32_t
|
|
|
|
|
getgpests(int n)
|
|
|
|
|
{
|
|
|
|
|
return inb(gpes[n].stsio) & 1<<gpes[n].stsbit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
setpm1ctl(uint32_t a, uint32_t b)
|
|
|
|
|
{
|
|
|
|
|
setbanked(fadt.pm1acntblk, 0, fadt.pm1cntlen, a);
|
|
|
|
|
setbanked(0, fadt.pm1bcntblk, fadt.pm1cntlen, b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
acpipoweroff(void)
|
|
|
|
|
{
|
|
|
|
|
uint32_t *t;
|
|
|
|
|
enum {
|
|
|
|
|
Go = 1<<13,
|
|
|
|
|
Sstate = 1<<10,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
iprint("acpi: power button: power cycle\n");
|
|
|
|
|
/*
|
|
|
|
|
* bug: we're assuming that this is a fixed function
|
|
|
|
|
*/
|
|
|
|
|
t = acpicfg.sval[5];
|
|
|
|
|
setpm1ctl(t[0]*Sstate | Go, t[1]*Sstate | Go);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
acpipowercycle(void)
|
|
|
|
|
{
|
|
|
|
|
exit(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
acpipowernop(void)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct {
|
|
|
|
|
char *name;
|
|
|
|
|
void (*f)(void);
|
|
|
|
|
} pwrbuttab[] = {
|
|
|
|
|
"reset", acpipowercycle, /* sic */
|
|
|
|
|
"off", acpipoweroff,
|
|
|
|
|
"nop", acpipowernop,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
acpiintr(Ureg* _1, void* _2)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
uint32_t sts, en;
|
|
|
|
|
Queue *q;
|
|
|
|
|
|
|
|
|
|
for(i = 0; i < ngpe; i++)
|
|
|
|
|
if(getgpests(i)){
|
|
|
|
|
iprint("gpe %d on\n", i);
|
|
|
|
|
en = getgpeen(i);
|
|
|
|
|
setgpeen(i, 0);
|
|
|
|
|
clrgpests(i);
|
|
|
|
|
if(en != 0)
|
2017-04-19 23:33:14 +02:00
|
|
|
|
jehanne_print("acpinitr: calling gpe %d\n", i);
|
2016-11-25 17:18:40 +01:00
|
|
|
|
/* queue gpe. reenable after done */
|
|
|
|
|
}
|
|
|
|
|
sts = getpm1sts(); /* § 4.8.3.3.1 */
|
|
|
|
|
en = getpm1en();
|
|
|
|
|
iprint("acpinitr: pm1sts %#ux pm1en %#ux\n", sts, en);
|
|
|
|
|
if(sts&en){
|
|
|
|
|
iprint("acpinitr: enabled: %#ux\n", sts&en);
|
|
|
|
|
}
|
|
|
|
|
setpm1sts(sts);
|
|
|
|
|
if(sts&Epowerbtn){
|
|
|
|
|
if((q = aconf.event) == nil ||
|
|
|
|
|
qiwrite(q, "powerbutton\n", 12) == -1)
|
|
|
|
|
aconf.powerbutton();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
initgpes(void)
|
|
|
|
|
{
|
|
|
|
|
int i, n0, n1;
|
|
|
|
|
|
|
|
|
|
n0 = fadt.gpe0blklen/2;
|
|
|
|
|
n1 = fadt.gpe1blklen/2;
|
|
|
|
|
ngpe = n0 + n1;
|
2017-04-19 23:33:14 +02:00
|
|
|
|
gpes = jehanne_mallocz(sizeof(Gpe) * ngpe, 1);
|
2016-11-25 17:18:40 +01:00
|
|
|
|
for(i = 0; i < n0; i++){
|
|
|
|
|
gpes[i].nb = i;
|
|
|
|
|
gpes[i].stsbit = i&7;
|
|
|
|
|
gpes[i].stsio = fadt.gpe0blk + (i>>3);
|
|
|
|
|
gpes[i].enbit = (n0 + i)&7;
|
|
|
|
|
gpes[i].enio = fadt.gpe0blk + ((n0 + i)>>3);
|
|
|
|
|
}
|
|
|
|
|
for(i = 0; i + n0 < ngpe; i++){
|
|
|
|
|
gpes[i + n0].nb = fadt.gp1base + i;
|
|
|
|
|
gpes[i + n0].stsbit = i&7;
|
|
|
|
|
gpes[i + n0].stsio = fadt.gpe1blk + (i>>3);
|
|
|
|
|
gpes[i + n0].enbit = (n1 + i)&7;
|
|
|
|
|
gpes[i + n0].enio = fadt.gpe1blk + ((n1 + i)>>3);
|
|
|
|
|
}
|
|
|
|
|
for(i = 0; i < ngpe; i++){
|
|
|
|
|
setgpeen(i, 0);
|
|
|
|
|
clrgpests(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
acpiioalloc(uint32_t addr, int len, char *name)
|
|
|
|
|
{
|
|
|
|
|
char buf[32];
|
|
|
|
|
|
|
|
|
|
if(addr != 0){
|
2017-04-19 23:33:14 +02:00
|
|
|
|
jehanne_snprint(buf, sizeof buf, "acpi %s", name);
|
2016-11-25 17:18:40 +01:00
|
|
|
|
ioalloc(addr, len, 0, buf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
init(void)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
aconf.powerbutton = acpipoweroff;
|
|
|
|
|
|
|
|
|
|
/* should we use fadt->xpm* and fadt->xgpe* registers for 64 bits? */
|
|
|
|
|
acpiioalloc(fadt.smicmd, 1, "scicmd");
|
|
|
|
|
acpiioalloc(fadt.pm1aevtblk, fadt.pm1evtlen, "pm1aevt");
|
|
|
|
|
acpiioalloc(fadt.pm1bevtblk, fadt.pm1evtlen, "pm1bevt");
|
|
|
|
|
acpiioalloc(fadt.pm1acntblk, fadt.pm1cntlen, "pm1acnt");
|
|
|
|
|
acpiioalloc(fadt.pm1bcntblk, fadt.pm1cntlen, "pm1bcnt");
|
|
|
|
|
acpiioalloc(fadt.pm2cntblk, fadt.pm2cntlen, "pm2cnt");
|
|
|
|
|
acpiioalloc(fadt.pmtmrblk, fadt.pmtmrlen, "pmtmr");
|
|
|
|
|
acpiioalloc(fadt.gpe0blk, fadt.gpe0blklen, "gpe0");
|
|
|
|
|
acpiioalloc(fadt.gpe1blk, fadt.gpe1blklen, "gpe1");
|
|
|
|
|
|
|
|
|
|
initgpes();
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This starts ACPI, which requires we handle
|
|
|
|
|
* power mgmt events ourselves.
|
|
|
|
|
*/
|
|
|
|
|
if(fadt.sciint == 0)
|
|
|
|
|
return;
|
|
|
|
|
if((getpm1ctl() & Pscien) == 0){
|
|
|
|
|
outb(fadt.smicmd, fadt.acpienable);
|
|
|
|
|
for(i = 0;; i++){
|
|
|
|
|
if(i == 10){
|
2017-04-19 23:33:14 +02:00
|
|
|
|
jehanne_print("acpi: failed to enable\n");
|
2016-11-25 17:18:40 +01:00
|
|
|
|
outb(fadt.smicmd, fadt.acpidisable);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(getpm1ctl() & Pscien)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(0){
|
2017-04-19 23:33:14 +02:00
|
|
|
|
jehanne_print("acpi: enable interrupt\n");
|
2016-11-25 17:18:40 +01:00
|
|
|
|
setpm1sts(getpm1sts());
|
|
|
|
|
setpm1en(Epowerbtn);
|
|
|
|
|
intrenable(fadt.sciint, acpiintr, 0, BUSUNKNOWN, "acpi");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static Chan*
|
|
|
|
|
acpiattach(Chan *c, Chan *ac, char *spec, int flags)
|
|
|
|
|
{
|
|
|
|
|
if(fadt.smicmd == 0)
|
|
|
|
|
error("no acpi");
|
|
|
|
|
return devattach(L'α', spec);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static Walkqid*
|
|
|
|
|
acpiwalk(Chan *c, Chan *nc, char **name, int nname)
|
|
|
|
|
{
|
|
|
|
|
return devwalk(c, nc, name, nname, acpidir, nelem(acpidir), acpigen);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static long
|
|
|
|
|
acpistat(Chan *c, uint8_t *dp, long n)
|
|
|
|
|
{
|
|
|
|
|
return devstat(c, dp, n, acpidir, nelem(acpidir), acpigen);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static Chan*
|
2016-12-01 00:09:42 +01:00
|
|
|
|
acpiopen(Chan *c, unsigned long omode)
|
2016-11-25 17:18:40 +01:00
|
|
|
|
{
|
|
|
|
|
c = devopen(c, omode, acpidir, nelem(acpidir), acpigen);
|
|
|
|
|
switch((uint32_t)c->qid.path){
|
|
|
|
|
case Qevent:
|
|
|
|
|
if(tas32(&aconf.eventopen) != 0){
|
|
|
|
|
c->flag &= ~COPEN;
|
|
|
|
|
error(Einuse);
|
|
|
|
|
}
|
|
|
|
|
if(aconf.event == nil){
|
|
|
|
|
aconf.event = qopen(8*1024, Qmsg, 0, 0);
|
|
|
|
|
if(aconf.event == nil){
|
|
|
|
|
c->flag &= ~COPEN;
|
|
|
|
|
error(Enomem);
|
|
|
|
|
}
|
|
|
|
|
qnoblock(aconf.event, 1);
|
|
|
|
|
}else
|
|
|
|
|
qreopen(aconf.event);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
acpiclose(Chan *c)
|
|
|
|
|
{
|
|
|
|
|
switch((uint32_t)c->qid.path){
|
|
|
|
|
case Qevent:
|
|
|
|
|
if(c->flag & COPEN){
|
|
|
|
|
aconf.eventopen = 0;
|
|
|
|
|
qhangup(aconf.event, nil);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static long
|
|
|
|
|
acpiread(Chan *c, void *a, long n, int64_t off)
|
|
|
|
|
{
|
|
|
|
|
char *s, *p, *e, buf[256];
|
|
|
|
|
int i;
|
|
|
|
|
long q;
|
|
|
|
|
|
|
|
|
|
q = c->qid.path;
|
|
|
|
|
switch(q){
|
|
|
|
|
case Qdir:
|
|
|
|
|
return devdirread(c, a, n, acpidir, nelem(acpidir), acpigen);
|
|
|
|
|
case Qctl:
|
|
|
|
|
p = buf;
|
|
|
|
|
e = buf + sizeof buf;
|
|
|
|
|
for(i = 0; i < nelem(pwrbuttab); i++)
|
|
|
|
|
if(pwrbuttab[i].f == aconf.powerbutton)
|
|
|
|
|
break;
|
|
|
|
|
if(i == nelem(pwrbuttab))
|
|
|
|
|
s = "??";
|
|
|
|
|
else
|
|
|
|
|
s = pwrbuttab[i].name;
|
2017-04-19 23:33:14 +02:00
|
|
|
|
p = jehanne_seprint(p, e, "powerbutton %s\n", s);
|
|
|
|
|
p = jehanne_seprint(p, e, "ngpe %d\n", ngpe);
|
2016-11-25 17:18:40 +01:00
|
|
|
|
USED(p);
|
|
|
|
|
return readstr(off, a, n, buf);
|
2016-12-01 00:09:42 +01:00
|
|
|
|
|
2016-11-25 17:18:40 +01:00
|
|
|
|
case Qevent:
|
|
|
|
|
return qread(aconf.event, a, n);
|
|
|
|
|
}
|
|
|
|
|
error(Eperm);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static long
|
|
|
|
|
acpiwrite(Chan *c, void *a, long n, int64_t _1)
|
|
|
|
|
{
|
|
|
|
|
uint32_t i;
|
|
|
|
|
Cmdtab *ct;
|
|
|
|
|
Cmdbuf *cb;
|
|
|
|
|
|
|
|
|
|
if(c->qid.path != Qctl)
|
|
|
|
|
error(Eperm);
|
|
|
|
|
|
|
|
|
|
cb = parsecmd(a, n);
|
|
|
|
|
if(waserror()){
|
2017-04-19 23:33:14 +02:00
|
|
|
|
jehanne_free(cb);
|
2016-11-25 17:18:40 +01:00
|
|
|
|
nexterror();
|
|
|
|
|
}
|
|
|
|
|
ct = lookupcmd(cb, ctls, nelem(ctls));
|
|
|
|
|
switch(ct->index){
|
|
|
|
|
case CMgpe:
|
2017-04-19 23:33:14 +02:00
|
|
|
|
i = jehanne_strtoul(cb->f[1], nil, 0);
|
2016-11-25 17:18:40 +01:00
|
|
|
|
if(i >= ngpe)
|
|
|
|
|
error("gpe out of range");
|
|
|
|
|
kstrdup(&gpes[i].obj, cb->f[2]);
|
|
|
|
|
DBG("gpe %d %s\n", i, gpes[i].obj);
|
|
|
|
|
setgpeen(i, 1);
|
|
|
|
|
break;
|
|
|
|
|
case CMpowerbut:
|
|
|
|
|
for(i = 0; i < nelem(pwrbuttab); i++)
|
2017-04-19 23:33:14 +02:00
|
|
|
|
if(jehanne_strcmp(cb->f[1], pwrbuttab[i].name) == 0){
|
2016-11-25 17:18:40 +01:00
|
|
|
|
ilock(&aconf);
|
|
|
|
|
aconf.powerbutton = pwrbuttab[i].f;
|
|
|
|
|
iunlock(&aconf);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if(i == nelem(pwrbuttab))
|
|
|
|
|
error("unknown power button action");
|
|
|
|
|
break;
|
|
|
|
|
case CMpower:
|
2017-04-19 23:33:14 +02:00
|
|
|
|
if(jehanne_strcmp(cb->f[1], "off") == 0)
|
2016-11-25 17:18:40 +01:00
|
|
|
|
aconf.powerbutton();
|
|
|
|
|
else
|
|
|
|
|
error("unknown power button command");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
poperror();
|
2017-04-19 23:33:14 +02:00
|
|
|
|
jehanne_free(cb);
|
2016-11-25 17:18:40 +01:00
|
|
|
|
return n;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Dev acpidevtab = {
|
|
|
|
|
L'α',
|
|
|
|
|
"acpi",
|
|
|
|
|
|
|
|
|
|
devreset,
|
|
|
|
|
init,
|
|
|
|
|
devshutdown,
|
|
|
|
|
acpiattach,
|
|
|
|
|
acpiwalk,
|
|
|
|
|
acpistat,
|
|
|
|
|
acpiopen,
|
|
|
|
|
devcreate,
|
|
|
|
|
acpiclose,
|
|
|
|
|
acpiread,
|
|
|
|
|
devbread,
|
|
|
|
|
acpiwrite,
|
|
|
|
|
devbwrite,
|
|
|
|
|
devremove,
|
|
|
|
|
devwstat,
|
|
|
|
|
};
|