pc, pc64: provide access to embedded controller with #P/ec file

This commit is contained in:
cinap_lenrek 2014-11-10 00:04:37 +01:00
parent b18a641397
commit bcb67353c1
9 changed files with 205 additions and 2 deletions

View file

@ -8,6 +8,7 @@ arch \- architecture-specific information and control
.B /dev/acpitbls
.B /dev/archctl
.B /dev/cputype
.B /dev/ec
.B /dev/ioalloc
.B /dev/iob
.B /dev/iol
@ -128,6 +129,10 @@ Reads and writes to
.I msr
go to the P4/P6/Core/Core2/AMD64 MSRs.
.PP
Reads and writes to
.I ec
transfer bytes from and to the embedded controller.
.PP
Reads from
.I acpitbls
return a concatenation of system ACPI tables. Each table

View file

@ -453,6 +453,30 @@ enumprt(void *dot, void *)
return 1;
}
static int
enumec(void *dot, void *)
{
int cmdport, dataport;
uchar *b;
void *x;
char *id;
b = nil;
id = eisaid(amlval(amlwalk(dot, "^_HID")));
if(id == nil || strcmp(id, "PNP0C09") != 0)
return 1;
if((x = amlwalk(dot, "^_CRS")) == nil)
return 1;
if(amleval(x, "", &b) < 0 || amltag(b) != 'b' || amllen(b) < 16)
return 1;
if(b[0] != 0x47 || b[8] != 0x47) /* two i/o port descriptors */
return 1;
dataport = b[0+2] | b[0+3]<<8;
cmdport = b[8+2] | b[8+3]<<8;
ecinit(cmdport, dataport);
return 1;
}
static void
acpiinit(void)
{
@ -589,6 +613,9 @@ Foundapic:
for(i=0; i<16; i++)
addirq(i, BusISA, 0, i, 0);
/* find embedded controller */
amlenum(amlroot, "_HID", enumec, nil);
/* free the AML interpreter */
amlexit();

View file

@ -34,6 +34,7 @@ enum {
Qiow,
Qiol,
Qmsr,
Qec,
Qbase,
Qmax = 16,
@ -62,7 +63,8 @@ static Dirtab archdir[Qmax] = {
"iob", { Qiob, 0 }, 0, 0660,
"iow", { Qiow, 0 }, 0, 0660,
"iol", { Qiol, 0 }, 0, 0660,
"msr", { Qmsr, 0}, 0, 0660,
"msr", { Qmsr, 0 }, 0, 0660,
"ec", { Qec, 0 }, 0, 0660,
};
Lock archwlock; /* the lock is only for changing archdir */
int narchdir = Qbase;
@ -361,7 +363,7 @@ static long
archread(Chan *c, void *a, long n, vlong offset)
{
char *buf, *p;
int port;
int port, v;
ushort *sp;
ulong *lp;
vlong *vp;
@ -407,6 +409,19 @@ archread(Chan *c, void *a, long n, vlong offset)
error(Ebadarg);
return n;
case Qec:
if(offset >= 256)
error(Ebadarg);
if(offset+n > 256)
n = 256 - offset;
p = a;
for(port = offset; port < offset+n; port++){
if((v = ecread(port)) < 0)
error(Eio);
*p++ = v;
}
return n;
case Qioalloc:
break;
@ -486,6 +501,15 @@ archwrite(Chan *c, void *a, long n, vlong offset)
error(Ebadarg);
return n;
case Qec:
if(offset+n > 256)
error(Ebadarg);
p = a;
for(port = offset; port < offset+n; port++)
if(ecwrite(port, *p++) < 0)
error(Eio);
return n;
default:
if(c->qid.path < narchdir && (fn = writefn[c->qid.path]))
return fn(c, a, n, offset);

138
sys/src/9/pc/ec.c Normal file
View file

@ -0,0 +1,138 @@
/*
* embedded controller (usually at ports 0x66/0x62)
*/
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"
enum {
/* registers */
EC_SC = 0,
EC_DATA,
/* Embedded Controller Status, EC_SC (R) */
OBF = 1<<0,
IBF = 1<<1,
CMD = 1<<3,
BURST = 1<<4,
SCI_EVT = 1<<5,
SMI_EVT = 1<<6,
/* Embedded Controller Command Set */
RD_EC = 0x80,
WR_EC = 0x81,
BE_EC = 0x82,
BD_EC = 0x83,
QR_EC = 0x84,
};
static struct {
Lock;
int init;
int port[2]; /* EC_SC and EC_DATA */
} ec;
static uchar
ecrr(int reg)
{
return inb(ec.port[reg]);
}
static void
ecwr(int reg, uchar val)
{
outb(ec.port[reg], val);
}
static int
ecwait(uchar mask, uchar val)
{
int i, s;
s = 0;
for(i=0; i<1000; i++){
s = ecrr(EC_SC);
if((s & mask) == val)
return 0;
delay(1);
}
print("ec: wait timeout status=%x pc=%#p\n", s, getcallerpc(&mask));
return -1;
}
int
ecinit(int cmdport, int dataport)
{
print("ec: cmd %X, data %X\n", cmdport, dataport);
if(ioalloc(cmdport, 1, 0, "ec.sc") < 0){
print("ec: cant allocate cmd port %X\n", cmdport);
return -1;
}
if(ioalloc(dataport, 1, 0, "ec.data") < 0){
print("ec: cant allocate data port %X\n", dataport);
iofree(cmdport);
return -1;
}
lock(&ec);
ec.port[EC_SC] = cmdport;
ec.port[EC_DATA] = dataport;
ec.init = 1;
unlock(&ec);
return 0;
}
int
ecread(uchar addr)
{
int r;
r = -1;
lock(&ec);
if(!ec.init)
goto out;
if(ecwait(BURST|CMD, 0))
goto out;
ecwr(EC_SC, RD_EC);
if(ecwait(IBF, 0))
goto out;
ecwr(EC_DATA, addr);
if(ecwait(OBF, OBF))
goto out;
r = ecrr(EC_DATA);
ecwait(OBF, 0);
out:
unlock(&ec);
return r;
}
int
ecwrite(uchar addr, uchar val)
{
int r;
r = -1;
lock(&ec);
if(!ec.init)
goto out;
if(ecwait(BURST|CMD, 0))
goto out;
ecwr(EC_SC, WR_EC);
if(ecwait(IBF, 0))
goto out;
ecwr(EC_DATA, addr);
if(ecwait(IBF, 0))
goto out;
ecwr(EC_DATA, val);
if(ecwait(IBF, 0))
goto out;
r = 0;
out:
unlock(&ec);
return r;
}

View file

@ -30,6 +30,9 @@ int dmainit(int, int);
#define DMALOOP 2
long dmasetup(int, void*, long, int);
void dumpmcregs(void);
int ecinit(int cmdport, int dataport);
int ecread(uchar addr);
int ecwrite(uchar addr, uchar val);
#define evenaddr(x) /* x86 doesn't care */
void fpclear(void);
void fpenv(FPsave*);

View file

@ -85,6 +85,7 @@ misc
archacpi mp apic squidboy
archmp mp apic squidboy
mtrr
ec
uarti8250
uartisa

View file

@ -87,6 +87,7 @@ misc
archacpi mp apic squidboy
archmp mp apic squidboy
mtrr
ec
sdaoe
sdide pci sdscsi

View file

@ -30,6 +30,9 @@ int dmainit(int, int);
#define DMALOOP 2
long dmasetup(int, void*, long, int);
void dumpmcregs(void);
int ecinit(int cmdport, int dataport);
int ecread(uchar addr);
int ecwrite(uchar addr, uchar val);
#define evenaddr(x) /* x86 doesn't care */
void (*fprestore)(FPsave*);
void (*fpsave)(FPsave*);

View file

@ -85,6 +85,7 @@ misc
archacpi mp apic squidboy
archmp mp apic squidboy
mtrr
ec
# sdaoe
sdide pci sdscsi