19ef1f84bSDavid du Colombier #include "u.h"
29ef1f84bSDavid du Colombier #include "../port/lib.h"
39ef1f84bSDavid du Colombier #include "mem.h"
49ef1f84bSDavid du Colombier #include "dat.h"
59ef1f84bSDavid du Colombier #include "fns.h"
69ef1f84bSDavid du Colombier #include "io.h"
79ef1f84bSDavid du Colombier #include "../port/error.h"
89ef1f84bSDavid du Colombier #include "mp.h"
99ef1f84bSDavid du Colombier #include "acpi.h"
109ef1f84bSDavid du Colombier
119ef1f84bSDavid du Colombier /*
129ef1f84bSDavid du Colombier * ACPI 4.0 Support.
139ef1f84bSDavid du Colombier * Still WIP.
149ef1f84bSDavid du Colombier *
159ef1f84bSDavid du Colombier * This driver locates tables and parses only the FADT
169ef1f84bSDavid du Colombier * and the XSDT. All other tables are mapped and kept there
179ef1f84bSDavid du Colombier * for a user-level interpreter.
189ef1f84bSDavid du Colombier */
199ef1f84bSDavid du Colombier
209ef1f84bSDavid du Colombier #define l16get(p) (((p)[1]<<8)|(p)[0])
219ef1f84bSDavid du Colombier #define l32get(p) (((u32int)l16get(p+2)<<16)|l16get(p))
229ef1f84bSDavid du Colombier static Atable* acpifadt(uchar*, int);
239ef1f84bSDavid du Colombier static Atable* acpitable(uchar*, int);
249ef1f84bSDavid du Colombier static Atable* acpimadt(uchar*, int);
259ef1f84bSDavid du Colombier static Atable* acpimsct(uchar*, int);
269ef1f84bSDavid du Colombier static Atable* acpisrat(uchar*, int);
279ef1f84bSDavid du Colombier static Atable* acpislit(uchar*, int);
289ef1f84bSDavid du Colombier static Atable* acpihpet(uchar*, int);
299ef1f84bSDavid du Colombier
309ef1f84bSDavid du Colombier #pragma varargck type "G" Gas*
319ef1f84bSDavid du Colombier
329ef1f84bSDavid du Colombier static Cmdtab ctls[] =
339ef1f84bSDavid du Colombier {
349ef1f84bSDavid du Colombier {CMregion, "region", 6},
359ef1f84bSDavid du Colombier {CMgpe, "gpe", 3},
369ef1f84bSDavid du Colombier };
379ef1f84bSDavid du Colombier
389ef1f84bSDavid du Colombier static Dirtab acpidir[]={
399ef1f84bSDavid du Colombier ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
409ef1f84bSDavid du Colombier "acpictl", {Qctl}, 0, 0666,
419ef1f84bSDavid du Colombier "acpitbl", {Qtbl}, 0, 0444,
429ef1f84bSDavid du Colombier "acpiregio", {Qio}, 0, 0666,
439ef1f84bSDavid du Colombier };
449ef1f84bSDavid du Colombier
459ef1f84bSDavid du Colombier /*
469ef1f84bSDavid du Colombier * The DSDT is always given to the user interpreter.
479ef1f84bSDavid du Colombier * Tables listed here are also loaded from the XSDT:
489ef1f84bSDavid du Colombier * MSCT, MADT, and FADT are processed by us, because they are
499ef1f84bSDavid du Colombier * required to do early initialization before we have user processes.
509ef1f84bSDavid du Colombier * Other tables are given to the user level interpreter for
519ef1f84bSDavid du Colombier * execution.
529ef1f84bSDavid du Colombier */
539ef1f84bSDavid du Colombier static Parse ptables[] =
549ef1f84bSDavid du Colombier {
559ef1f84bSDavid du Colombier "FACP", acpifadt,
569ef1f84bSDavid du Colombier "APIC", acpimadt,
579ef1f84bSDavid du Colombier "SRAT", acpisrat,
589ef1f84bSDavid du Colombier "SLIT", acpislit,
599ef1f84bSDavid du Colombier "MSCT", acpimsct,
609ef1f84bSDavid du Colombier "HPET", acpihpet,
619ef1f84bSDavid du Colombier "SSDT", acpitable,
629ef1f84bSDavid du Colombier };
639ef1f84bSDavid du Colombier
649ef1f84bSDavid du Colombier static Facs* facs; /* Firmware ACPI control structure */
659ef1f84bSDavid du Colombier static Fadt fadt; /* Fixed ACPI description. To reach ACPI registers */
669ef1f84bSDavid du Colombier static Xsdt* xsdt; /* XSDT table */
679ef1f84bSDavid du Colombier static Atable* tfirst; /* loaded DSDT/SSDT/... tables */
689ef1f84bSDavid du Colombier static Atable* tlast; /* pointer to last table */
699ef1f84bSDavid du Colombier Madt* apics; /* APIC info */
709ef1f84bSDavid du Colombier static Srat* srat; /* System resource affinity, used by physalloc */
719ef1f84bSDavid du Colombier static Slit* slit; /* System locality information table used by the scheduler */
729ef1f84bSDavid du Colombier static Msct* msct; /* Maximum system characteristics table */
739ef1f84bSDavid du Colombier static Hpet* hpet;
749ef1f84bSDavid du Colombier static Reg* reg; /* region used for I/O */
759ef1f84bSDavid du Colombier static Gpe* gpes; /* General purpose events */
769ef1f84bSDavid du Colombier static int ngpes;
779ef1f84bSDavid du Colombier
789ef1f84bSDavid du Colombier static char* regnames[] = {
799ef1f84bSDavid du Colombier "mem", "io", "pcicfg", "embed",
809ef1f84bSDavid du Colombier "smb", "cmos", "pcibar",
819ef1f84bSDavid du Colombier };
829ef1f84bSDavid du Colombier
839ef1f84bSDavid du Colombier static char*
acpiregstr(int id)849ef1f84bSDavid du Colombier acpiregstr(int id)
859ef1f84bSDavid du Colombier {
869ef1f84bSDavid du Colombier static char buf[20]; /* BUG */
879ef1f84bSDavid du Colombier
889ef1f84bSDavid du Colombier if(id >= 0 && id < nelem(regnames))
899ef1f84bSDavid du Colombier return regnames[id];
909ef1f84bSDavid du Colombier seprint(buf, buf+sizeof(buf), "spc:%#x", id);
919ef1f84bSDavid du Colombier return buf;
929ef1f84bSDavid du Colombier }
939ef1f84bSDavid du Colombier
949ef1f84bSDavid du Colombier static int
acpiregid(char * s)959ef1f84bSDavid du Colombier acpiregid(char *s)
969ef1f84bSDavid du Colombier {
979ef1f84bSDavid du Colombier int i;
989ef1f84bSDavid du Colombier
999ef1f84bSDavid du Colombier for(i = 0; i < nelem(regnames); i++)
1009ef1f84bSDavid du Colombier if(strcmp(regnames[i], s) == 0)
1019ef1f84bSDavid du Colombier return i;
1029ef1f84bSDavid du Colombier return -1;
1039ef1f84bSDavid du Colombier }
1049ef1f84bSDavid du Colombier
1059ef1f84bSDavid du Colombier static u64int
l64get(u8int * p)1069ef1f84bSDavid du Colombier l64get(u8int* p)
1079ef1f84bSDavid du Colombier {
1089ef1f84bSDavid du Colombier /*
1099ef1f84bSDavid du Colombier * Doing this as a define
1109ef1f84bSDavid du Colombier * #define l64get(p) (((u64int)l32get(p+4)<<32)|l32get(p))
1119ef1f84bSDavid du Colombier * causes 8c to abort with "out of fixed registers" in
1129ef1f84bSDavid du Colombier * rsdlink() below.
1139ef1f84bSDavid du Colombier */
1149ef1f84bSDavid du Colombier return (((u64int)l32get(p+4)<<32)|l32get(p));
1159ef1f84bSDavid du Colombier }
1169ef1f84bSDavid du Colombier
1179ef1f84bSDavid du Colombier static u8int
mget8(uintptr p,void *)1189ef1f84bSDavid du Colombier mget8(uintptr p, void*)
1199ef1f84bSDavid du Colombier {
1209ef1f84bSDavid du Colombier u8int *cp = (u8int*)p;
1219ef1f84bSDavid du Colombier return *cp;
1229ef1f84bSDavid du Colombier }
1239ef1f84bSDavid du Colombier
1249ef1f84bSDavid du Colombier static void
mset8(uintptr p,u8int v,void *)1259ef1f84bSDavid du Colombier mset8(uintptr p, u8int v, void*)
1269ef1f84bSDavid du Colombier {
1279ef1f84bSDavid du Colombier u8int *cp = (u8int*)p;
1289ef1f84bSDavid du Colombier *cp = v;
1299ef1f84bSDavid du Colombier }
1309ef1f84bSDavid du Colombier
1319ef1f84bSDavid du Colombier static u16int
mget16(uintptr p,void *)1329ef1f84bSDavid du Colombier mget16(uintptr p, void*)
1339ef1f84bSDavid du Colombier {
1349ef1f84bSDavid du Colombier u16int *cp = (u16int*)p;
1359ef1f84bSDavid du Colombier return *cp;
1369ef1f84bSDavid du Colombier }
1379ef1f84bSDavid du Colombier
1389ef1f84bSDavid du Colombier static void
mset16(uintptr p,u16int v,void *)1399ef1f84bSDavid du Colombier mset16(uintptr p, u16int v, void*)
1409ef1f84bSDavid du Colombier {
1419ef1f84bSDavid du Colombier u16int *cp = (u16int*)p;
1429ef1f84bSDavid du Colombier *cp = v;
1439ef1f84bSDavid du Colombier }
1449ef1f84bSDavid du Colombier
1459ef1f84bSDavid du Colombier static u32int
mget32(uintptr p,void *)1469ef1f84bSDavid du Colombier mget32(uintptr p, void*)
1479ef1f84bSDavid du Colombier {
1489ef1f84bSDavid du Colombier u32int *cp = (u32int*)p;
1499ef1f84bSDavid du Colombier return *cp;
1509ef1f84bSDavid du Colombier }
1519ef1f84bSDavid du Colombier
1529ef1f84bSDavid du Colombier static void
mset32(uintptr p,u32int v,void *)1539ef1f84bSDavid du Colombier mset32(uintptr p, u32int v, void*)
1549ef1f84bSDavid du Colombier {
1559ef1f84bSDavid du Colombier u32int *cp = (u32int*)p;
1569ef1f84bSDavid du Colombier *cp = v;
1579ef1f84bSDavid du Colombier }
1589ef1f84bSDavid du Colombier
1599ef1f84bSDavid du Colombier static u64int
mget64(uintptr p,void *)1609ef1f84bSDavid du Colombier mget64(uintptr p, void*)
1619ef1f84bSDavid du Colombier {
1629ef1f84bSDavid du Colombier u64int *cp = (u64int*)p;
1639ef1f84bSDavid du Colombier return *cp;
1649ef1f84bSDavid du Colombier }
1659ef1f84bSDavid du Colombier
1669ef1f84bSDavid du Colombier static void
mset64(uintptr p,u64int v,void *)1679ef1f84bSDavid du Colombier mset64(uintptr p, u64int v, void*)
1689ef1f84bSDavid du Colombier {
1699ef1f84bSDavid du Colombier u64int *cp = (u64int*)p;
1709ef1f84bSDavid du Colombier *cp = v;
1719ef1f84bSDavid du Colombier }
1729ef1f84bSDavid du Colombier
1739ef1f84bSDavid du Colombier static u8int
ioget8(uintptr p,void *)1749ef1f84bSDavid du Colombier ioget8(uintptr p, void*)
1759ef1f84bSDavid du Colombier {
1769ef1f84bSDavid du Colombier return inb(p);
1779ef1f84bSDavid du Colombier }
1789ef1f84bSDavid du Colombier
1799ef1f84bSDavid du Colombier static void
ioset8(uintptr p,u8int v,void *)1809ef1f84bSDavid du Colombier ioset8(uintptr p, u8int v, void*)
1819ef1f84bSDavid du Colombier {
1829ef1f84bSDavid du Colombier outb(p, v);
1839ef1f84bSDavid du Colombier }
1849ef1f84bSDavid du Colombier
1859ef1f84bSDavid du Colombier static u16int
ioget16(uintptr p,void *)1869ef1f84bSDavid du Colombier ioget16(uintptr p, void*)
1879ef1f84bSDavid du Colombier {
1889ef1f84bSDavid du Colombier return ins(p);
1899ef1f84bSDavid du Colombier }
1909ef1f84bSDavid du Colombier
1919ef1f84bSDavid du Colombier static void
ioset16(uintptr p,u16int v,void *)1929ef1f84bSDavid du Colombier ioset16(uintptr p, u16int v, void*)
1939ef1f84bSDavid du Colombier {
1949ef1f84bSDavid du Colombier outs(p, v);
1959ef1f84bSDavid du Colombier }
1969ef1f84bSDavid du Colombier
1979ef1f84bSDavid du Colombier static u32int
ioget32(uintptr p,void *)1989ef1f84bSDavid du Colombier ioget32(uintptr p, void*)
1999ef1f84bSDavid du Colombier {
2009ef1f84bSDavid du Colombier return inl(p);
2019ef1f84bSDavid du Colombier }
2029ef1f84bSDavid du Colombier
2039ef1f84bSDavid du Colombier static void
ioset32(uintptr p,u32int v,void *)2049ef1f84bSDavid du Colombier ioset32(uintptr p, u32int v, void*)
2059ef1f84bSDavid du Colombier {
2069ef1f84bSDavid du Colombier outl(p, v);
2079ef1f84bSDavid du Colombier }
2089ef1f84bSDavid du Colombier
2099ef1f84bSDavid du Colombier static u8int
cfgget8(uintptr p,void * r)2109ef1f84bSDavid du Colombier cfgget8(uintptr p, void* r)
2119ef1f84bSDavid du Colombier {
2129ef1f84bSDavid du Colombier Reg *ro = r;
2139ef1f84bSDavid du Colombier Pcidev d;
2149ef1f84bSDavid du Colombier
2159ef1f84bSDavid du Colombier d.tbdf = ro->tbdf;
2169ef1f84bSDavid du Colombier return pcicfgr8(&d, p);
2179ef1f84bSDavid du Colombier }
2189ef1f84bSDavid du Colombier
2199ef1f84bSDavid du Colombier static void
cfgset8(uintptr p,u8int v,void * r)2209ef1f84bSDavid du Colombier cfgset8(uintptr p, u8int v, void* r)
2219ef1f84bSDavid du Colombier {
2229ef1f84bSDavid du Colombier Reg *ro = r;
2239ef1f84bSDavid du Colombier Pcidev d;
2249ef1f84bSDavid du Colombier
2259ef1f84bSDavid du Colombier d.tbdf = ro->tbdf;
2269ef1f84bSDavid du Colombier pcicfgw8(&d, p, v);
2279ef1f84bSDavid du Colombier }
2289ef1f84bSDavid du Colombier
2299ef1f84bSDavid du Colombier static u16int
cfgget16(uintptr p,void * r)2309ef1f84bSDavid du Colombier cfgget16(uintptr p, void* r)
2319ef1f84bSDavid du Colombier {
2329ef1f84bSDavid du Colombier Reg *ro = r;
2339ef1f84bSDavid du Colombier Pcidev d;
2349ef1f84bSDavid du Colombier
2359ef1f84bSDavid du Colombier d.tbdf = ro->tbdf;
2369ef1f84bSDavid du Colombier return pcicfgr16(&d, p);
2379ef1f84bSDavid du Colombier }
2389ef1f84bSDavid du Colombier
2399ef1f84bSDavid du Colombier static void
cfgset16(uintptr p,u16int v,void * r)2409ef1f84bSDavid du Colombier cfgset16(uintptr p, u16int v, void* r)
2419ef1f84bSDavid du Colombier {
2429ef1f84bSDavid du Colombier Reg *ro = r;
2439ef1f84bSDavid du Colombier Pcidev d;
2449ef1f84bSDavid du Colombier
2459ef1f84bSDavid du Colombier d.tbdf = ro->tbdf;
2469ef1f84bSDavid du Colombier pcicfgw16(&d, p, v);
2479ef1f84bSDavid du Colombier }
2489ef1f84bSDavid du Colombier
2499ef1f84bSDavid du Colombier static u32int
cfgget32(uintptr p,void * r)2509ef1f84bSDavid du Colombier cfgget32(uintptr p, void* r)
2519ef1f84bSDavid du Colombier {
2529ef1f84bSDavid du Colombier Reg *ro = r;
2539ef1f84bSDavid du Colombier Pcidev d;
2549ef1f84bSDavid du Colombier
2559ef1f84bSDavid du Colombier d.tbdf = ro->tbdf;
2569ef1f84bSDavid du Colombier return pcicfgr32(&d, p);
2579ef1f84bSDavid du Colombier }
2589ef1f84bSDavid du Colombier
2599ef1f84bSDavid du Colombier static void
cfgset32(uintptr p,u32int v,void * r)2609ef1f84bSDavid du Colombier cfgset32(uintptr p, u32int v, void* r)
2619ef1f84bSDavid du Colombier {
2629ef1f84bSDavid du Colombier Reg *ro = r;
2639ef1f84bSDavid du Colombier Pcidev d;
2649ef1f84bSDavid du Colombier
2659ef1f84bSDavid du Colombier d.tbdf = ro->tbdf;
2669ef1f84bSDavid du Colombier pcicfgw32(&d, p, v);
2679ef1f84bSDavid du Colombier }
2689ef1f84bSDavid du Colombier
2699ef1f84bSDavid du Colombier static Regio memio =
2709ef1f84bSDavid du Colombier {
2719ef1f84bSDavid du Colombier nil,
2729ef1f84bSDavid du Colombier mget8, mset8, mget16, mset16,
2739ef1f84bSDavid du Colombier mget32, mset32, mget64, mset64
2749ef1f84bSDavid du Colombier };
2759ef1f84bSDavid du Colombier
2769ef1f84bSDavid du Colombier static Regio ioio =
2779ef1f84bSDavid du Colombier {
2789ef1f84bSDavid du Colombier nil,
2799ef1f84bSDavid du Colombier ioget8, ioset8, ioget16, ioset16,
2809ef1f84bSDavid du Colombier ioget32, ioset32, nil, nil
2819ef1f84bSDavid du Colombier };
2829ef1f84bSDavid du Colombier
2839ef1f84bSDavid du Colombier static Regio cfgio =
2849ef1f84bSDavid du Colombier {
2859ef1f84bSDavid du Colombier nil,
2869ef1f84bSDavid du Colombier cfgget8, cfgset8, cfgget16, cfgset16,
2879ef1f84bSDavid du Colombier cfgget32, cfgset32, nil, nil
2889ef1f84bSDavid du Colombier };
2899ef1f84bSDavid du Colombier
2909ef1f84bSDavid du Colombier /*
2919ef1f84bSDavid du Colombier * Copy memory, 1/2/4/8-bytes at a time, to/from a region.
2929ef1f84bSDavid du Colombier */
2939ef1f84bSDavid du Colombier static long
regcpy(Regio * dio,uintptr da,Regio * sio,uintptr sa,long len,int align)2949ef1f84bSDavid du Colombier regcpy(Regio *dio, uintptr da, Regio *sio, uintptr sa, long len, int align)
2959ef1f84bSDavid du Colombier {
2969ef1f84bSDavid du Colombier int n, i;
2979ef1f84bSDavid du Colombier
2989ef1f84bSDavid du Colombier DBG("regcpy %#ullx %#ullx %#ulx %#ux\n", da, sa, len, align);
2999ef1f84bSDavid du Colombier if((len%align) != 0)
3009ef1f84bSDavid du Colombier print("regcpy: bug: copy not aligned. truncated\n");
3019ef1f84bSDavid du Colombier n = len/align;
3029ef1f84bSDavid du Colombier for(i = 0; i < n; i++){
3039ef1f84bSDavid du Colombier switch(align){
3049ef1f84bSDavid du Colombier case 1:
3059ef1f84bSDavid du Colombier DBG("cpy8 %#p %#p\n", da, sa);
3069ef1f84bSDavid du Colombier dio->set8(da, sio->get8(sa, sio->arg), dio->arg);
3079ef1f84bSDavid du Colombier break;
3089ef1f84bSDavid du Colombier case 2:
3099ef1f84bSDavid du Colombier DBG("cpy16 %#p %#p\n", da, sa);
3109ef1f84bSDavid du Colombier dio->set16(da, sio->get16(sa, sio->arg), dio->arg);
3119ef1f84bSDavid du Colombier break;
3129ef1f84bSDavid du Colombier case 4:
3139ef1f84bSDavid du Colombier DBG("cpy32 %#p %#p\n", da, sa);
3149ef1f84bSDavid du Colombier dio->set32(da, sio->get32(sa, sio->arg), dio->arg);
3159ef1f84bSDavid du Colombier break;
3169ef1f84bSDavid du Colombier case 8:
3179ef1f84bSDavid du Colombier DBG("cpy64 %#p %#p\n", da, sa);
3189ef1f84bSDavid du Colombier // dio->set64(da, sio->get64(sa, sio->arg), dio->arg);
3199ef1f84bSDavid du Colombier break;
3209ef1f84bSDavid du Colombier default:
3219ef1f84bSDavid du Colombier panic("regcpy: align bug");
3229ef1f84bSDavid du Colombier }
3239ef1f84bSDavid du Colombier da += align;
3249ef1f84bSDavid du Colombier sa += align;
3259ef1f84bSDavid du Colombier }
3269ef1f84bSDavid du Colombier return n*align;
3279ef1f84bSDavid du Colombier }
3289ef1f84bSDavid du Colombier
3299ef1f84bSDavid du Colombier /*
3309ef1f84bSDavid du Colombier * Perform I/O within region in access units of accsz bytes.
3319ef1f84bSDavid du Colombier * All units in bytes.
3329ef1f84bSDavid du Colombier */
3339ef1f84bSDavid du Colombier static long
regio(Reg * r,void * p,ulong len,uintptr off,int iswr)3349ef1f84bSDavid du Colombier regio(Reg *r, void *p, ulong len, uintptr off, int iswr)
3359ef1f84bSDavid du Colombier {
3369ef1f84bSDavid du Colombier Regio rio;
3379ef1f84bSDavid du Colombier uintptr rp;
3389ef1f84bSDavid du Colombier
3399ef1f84bSDavid du Colombier DBG("reg%s %s %#p %#ullx %#lx sz=%d\n",
3409ef1f84bSDavid du Colombier iswr ? "out" : "in", r->name, p, off, len, r->accsz);
3419ef1f84bSDavid du Colombier rp = 0;
3429ef1f84bSDavid du Colombier if(off + len > r->len){
3439ef1f84bSDavid du Colombier print("regio: access outside limits");
3449ef1f84bSDavid du Colombier len = r->len - off;
3459ef1f84bSDavid du Colombier }
3469ef1f84bSDavid du Colombier if(len <= 0){
3479ef1f84bSDavid du Colombier print("regio: zero len\n");
3489ef1f84bSDavid du Colombier return 0;
3499ef1f84bSDavid du Colombier }
3509ef1f84bSDavid du Colombier switch(r->spc){
3519ef1f84bSDavid du Colombier case Rsysmem:
3529ef1f84bSDavid du Colombier // XXX should map only what we are going to use
3539ef1f84bSDavid du Colombier // A region might be too large.
3549ef1f84bSDavid du Colombier if(r->p == nil)
3559ef1f84bSDavid du Colombier r->p = vmap(r->base, len);
3569ef1f84bSDavid du Colombier if(r->p == nil)
3579ef1f84bSDavid du Colombier error("regio: vmap failed");
3589ef1f84bSDavid du Colombier rp = (uintptr)r->p + off;
3599ef1f84bSDavid du Colombier rio = memio;
3609ef1f84bSDavid du Colombier break;
3619ef1f84bSDavid du Colombier case Rsysio:
3629ef1f84bSDavid du Colombier rp = r->base + off;
3639ef1f84bSDavid du Colombier rio = ioio;
3649ef1f84bSDavid du Colombier break;
3659ef1f84bSDavid du Colombier case Rpcicfg:
3669ef1f84bSDavid du Colombier rp = r->base + off;
3679ef1f84bSDavid du Colombier rio = cfgio;
3689ef1f84bSDavid du Colombier rio.arg = r;
3699ef1f84bSDavid du Colombier break;
3709ef1f84bSDavid du Colombier case Rpcibar:
3719ef1f84bSDavid du Colombier case Rembed:
3729ef1f84bSDavid du Colombier case Rsmbus:
3739ef1f84bSDavid du Colombier case Rcmos:
3749ef1f84bSDavid du Colombier case Ripmi:
3759ef1f84bSDavid du Colombier case Rfixedhw:
3769ef1f84bSDavid du Colombier print("regio: reg %s not supported\n", acpiregstr(r->spc));
3779ef1f84bSDavid du Colombier error("region not supported");
3789ef1f84bSDavid du Colombier }
3799ef1f84bSDavid du Colombier if(iswr)
3809ef1f84bSDavid du Colombier regcpy(&rio, rp, &memio, (uintptr)p, len, r->accsz);
3819ef1f84bSDavid du Colombier else
3829ef1f84bSDavid du Colombier regcpy(&memio, (uintptr)p, &rio, rp, len, r->accsz);
3839ef1f84bSDavid du Colombier return len;
3849ef1f84bSDavid du Colombier }
3859ef1f84bSDavid du Colombier
3869ef1f84bSDavid du Colombier static Atable*
newtable(uchar * p)3879ef1f84bSDavid du Colombier newtable(uchar *p)
3889ef1f84bSDavid du Colombier {
3899ef1f84bSDavid du Colombier Atable *t;
3909ef1f84bSDavid du Colombier Sdthdr *h;
3919ef1f84bSDavid du Colombier
3929ef1f84bSDavid du Colombier t = malloc(sizeof(Atable));
3939ef1f84bSDavid du Colombier if(t == nil)
3949ef1f84bSDavid du Colombier panic("no memory for more aml tables");
3959ef1f84bSDavid du Colombier t->tbl = p;
3969ef1f84bSDavid du Colombier h = (Sdthdr*)t->tbl;
3979ef1f84bSDavid du Colombier t->is64 = h->rev >= 2;
3989ef1f84bSDavid du Colombier t->dlen = l32get(h->length) - Sdthdrsz;
3999ef1f84bSDavid du Colombier memmove(t->sig, h->sig, sizeof(h->sig));
4009ef1f84bSDavid du Colombier t->sig[sizeof(t->sig)-1] = 0;
4019ef1f84bSDavid du Colombier memmove(t->oemid, h->oemid, sizeof(h->oemid));
4029ef1f84bSDavid du Colombier t->oemtblid[sizeof(t->oemtblid)-1] = 0;
4039ef1f84bSDavid du Colombier memmove(t->oemtblid, h->oemtblid, sizeof(h->oemtblid));
4049ef1f84bSDavid du Colombier t->oemtblid[sizeof(t->oemtblid)-1] = 0;
4059ef1f84bSDavid du Colombier t->next = nil;
4069ef1f84bSDavid du Colombier if(tfirst == nil)
4079ef1f84bSDavid du Colombier tfirst = tlast = t;
4089ef1f84bSDavid du Colombier else{
4099ef1f84bSDavid du Colombier tlast->next = t;
4109ef1f84bSDavid du Colombier tlast = t;
4119ef1f84bSDavid du Colombier }
4129ef1f84bSDavid du Colombier return t;
4139ef1f84bSDavid du Colombier }
4149ef1f84bSDavid du Colombier
4159ef1f84bSDavid du Colombier static void*
sdtchecksum(void * addr,int len)4169ef1f84bSDavid du Colombier sdtchecksum(void* addr, int len)
4179ef1f84bSDavid du Colombier {
4189ef1f84bSDavid du Colombier u8int *p, sum;
4199ef1f84bSDavid du Colombier
4209ef1f84bSDavid du Colombier sum = 0;
4219ef1f84bSDavid du Colombier for(p = addr; len-- > 0; p++)
4229ef1f84bSDavid du Colombier sum += *p;
4239ef1f84bSDavid du Colombier if(sum == 0)
4249ef1f84bSDavid du Colombier return addr;
4259ef1f84bSDavid du Colombier
4269ef1f84bSDavid du Colombier return nil;
4279ef1f84bSDavid du Colombier }
4289ef1f84bSDavid du Colombier
4299ef1f84bSDavid du Colombier static void *
sdtmap(uintmem pa,int * n,int cksum)4309ef1f84bSDavid du Colombier sdtmap(uintmem pa, int *n, int cksum)
4319ef1f84bSDavid du Colombier {
4329ef1f84bSDavid du Colombier Sdthdr* sdt;
4339ef1f84bSDavid du Colombier
4349ef1f84bSDavid du Colombier sdt = vmap(pa, sizeof(Sdthdr));
4359ef1f84bSDavid du Colombier if(sdt == nil){
4369ef1f84bSDavid du Colombier DBG("acpi: vmap1: nil\n");
4379ef1f84bSDavid du Colombier return nil;
4389ef1f84bSDavid du Colombier }
4399ef1f84bSDavid du Colombier *n = l32get(sdt->length);
4409ef1f84bSDavid du Colombier vunmap(sdt, sizeof(Sdthdr));
4419ef1f84bSDavid du Colombier if((sdt = vmap(pa, *n)) == nil){
4429ef1f84bSDavid du Colombier DBG("acpi: nil vmap\n");
4439ef1f84bSDavid du Colombier return nil;
4449ef1f84bSDavid du Colombier }
4459ef1f84bSDavid du Colombier DBG("acpi: sdtmap %#P -> %#p, length %d\n", pa, sdt, *n);
4469ef1f84bSDavid du Colombier if(cksum != 0 && sdtchecksum(sdt, *n) == nil){
4479ef1f84bSDavid du Colombier DBG("acpi: SDT: bad checksum\n");
4489ef1f84bSDavid du Colombier vunmap(sdt, sizeof(Sdthdr));
4499ef1f84bSDavid du Colombier return nil;
4509ef1f84bSDavid du Colombier }
4519ef1f84bSDavid du Colombier return sdt;
4529ef1f84bSDavid du Colombier }
4539ef1f84bSDavid du Colombier
4549ef1f84bSDavid du Colombier static int
loadfacs(uintmem pa)4559ef1f84bSDavid du Colombier loadfacs(uintmem pa)
4569ef1f84bSDavid du Colombier {
4579ef1f84bSDavid du Colombier int n;
4589ef1f84bSDavid du Colombier
4599ef1f84bSDavid du Colombier facs = sdtmap(pa, &n, 0);
4609ef1f84bSDavid du Colombier if(facs == nil)
4619ef1f84bSDavid du Colombier return -1;
4629ef1f84bSDavid du Colombier if(memcmp(facs, "FACS", 4) != 0){
4639ef1f84bSDavid du Colombier vunmap(facs, n);
4649ef1f84bSDavid du Colombier facs = nil;
4659ef1f84bSDavid du Colombier return -1;
4669ef1f84bSDavid du Colombier }
4679ef1f84bSDavid du Colombier /* no unmap */
4689ef1f84bSDavid du Colombier
4699ef1f84bSDavid du Colombier DBG("acpi: facs: hwsig: %#ux\n", facs->hwsig);
4709ef1f84bSDavid du Colombier DBG("acpi: facs: wakingv: %#ux\n", facs->wakingv);
4719ef1f84bSDavid du Colombier DBG("acpi: facs: flags: %#ux\n", facs->flags);
4729ef1f84bSDavid du Colombier DBG("acpi: facs: glock: %#ux\n", facs->glock);
4739ef1f84bSDavid du Colombier DBG("acpi: facs: xwakingv: %#llux\n", facs->xwakingv);
4749ef1f84bSDavid du Colombier DBG("acpi: facs: vers: %#ux\n", facs->vers);
4759ef1f84bSDavid du Colombier DBG("acpi: facs: ospmflags: %#ux\n", facs->ospmflags);
4769ef1f84bSDavid du Colombier return 0;
4779ef1f84bSDavid du Colombier }
4789ef1f84bSDavid du Colombier
4799ef1f84bSDavid du Colombier static void
loaddsdt(uintmem pa)4809ef1f84bSDavid du Colombier loaddsdt(uintmem pa)
4819ef1f84bSDavid du Colombier {
4829ef1f84bSDavid du Colombier int n;
4839ef1f84bSDavid du Colombier uchar *dsdtp;
4849ef1f84bSDavid du Colombier
4859ef1f84bSDavid du Colombier dsdtp = sdtmap(pa, &n, 1);
4869ef1f84bSDavid du Colombier if(dsdtp == nil)
4879ef1f84bSDavid du Colombier return;
4889ef1f84bSDavid du Colombier if(acpitable(dsdtp, n) == nil)
4899ef1f84bSDavid du Colombier vunmap(dsdtp, n);
4909ef1f84bSDavid du Colombier }
4919ef1f84bSDavid du Colombier
4929ef1f84bSDavid du Colombier static void
gasget(Gas * gas,uchar * p)4939ef1f84bSDavid du Colombier gasget(Gas *gas, uchar *p)
4949ef1f84bSDavid du Colombier {
4959ef1f84bSDavid du Colombier gas->spc = p[0];
4969ef1f84bSDavid du Colombier gas->len = p[1];
4979ef1f84bSDavid du Colombier gas->off = p[2];
4989ef1f84bSDavid du Colombier gas->accsz = p[3];
4999ef1f84bSDavid du Colombier gas->addr = l64get(p+4);
5009ef1f84bSDavid du Colombier }
5019ef1f84bSDavid du Colombier
5029ef1f84bSDavid du Colombier static void
dumpfadt(Fadt * fp,int revision)5039ef1f84bSDavid du Colombier dumpfadt(Fadt *fp, int revision)
5049ef1f84bSDavid du Colombier {
5059ef1f84bSDavid du Colombier USED(fp);
5069ef1f84bSDavid du Colombier DBG("acpi: fadt: facs: %#ux\n", fp->facs);
5079ef1f84bSDavid du Colombier DBG("acpi: fadt: dsdt: %#ux\n", fp->dsdt);
5089ef1f84bSDavid du Colombier DBG("acpi: fadt: pmprofile: %#ux\n", fp->pmprofile);
5099ef1f84bSDavid du Colombier DBG("acpi: fadt: sciint: %#ux\n", fp->sciint);
5109ef1f84bSDavid du Colombier DBG("acpi: fadt: smicmd: %#ux\n", fp->smicmd);
5119ef1f84bSDavid du Colombier DBG("acpi: fadt: acpienable: %#ux\n", fp->acpienable);
5129ef1f84bSDavid du Colombier DBG("acpi: fadt: acpidisable: %#ux\n", fp->acpidisable);
5139ef1f84bSDavid du Colombier DBG("acpi: fadt: s4biosreq: %#ux\n", fp->s4biosreq);
5149ef1f84bSDavid du Colombier DBG("acpi: fadt: pstatecnt: %#ux\n", fp->pstatecnt);
5159ef1f84bSDavid du Colombier DBG("acpi: fadt: pm1aevtblk: %#ux\n", fp->pm1aevtblk);
5169ef1f84bSDavid du Colombier DBG("acpi: fadt: pm1bevtblk: %#ux\n", fp->pm1bevtblk);
5179ef1f84bSDavid du Colombier DBG("acpi: fadt: pm1acntblk: %#ux\n", fp->pm1acntblk);
5189ef1f84bSDavid du Colombier DBG("acpi: fadt: pm1bcntblk: %#ux\n", fp->pm1bcntblk);
5199ef1f84bSDavid du Colombier DBG("acpi: fadt: pm2cntblk: %#ux\n", fp->pm2cntblk);
5209ef1f84bSDavid du Colombier DBG("acpi: fadt: pmtmrblk: %#ux\n", fp->pmtmrblk);
5219ef1f84bSDavid du Colombier DBG("acpi: fadt: gpe0blk: %#ux\n", fp->gpe0blk);
5229ef1f84bSDavid du Colombier DBG("acpi: fadt: gpe1blk: %#ux\n", fp->gpe1blk);
5239ef1f84bSDavid du Colombier DBG("acpi: fadt: pm1evtlen: %#ux\n", fp->pm1evtlen);
5249ef1f84bSDavid du Colombier DBG("acpi: fadt: pm1cntlen: %#ux\n", fp->pm1cntlen);
5259ef1f84bSDavid du Colombier DBG("acpi: fadt: pm2cntlen: %#ux\n", fp->pm2cntlen);
5269ef1f84bSDavid du Colombier DBG("acpi: fadt: pmtmrlen: %#ux\n", fp->pmtmrlen);
5279ef1f84bSDavid du Colombier DBG("acpi: fadt: gpe0blklen: %#ux\n", fp->gpe0blklen);
5289ef1f84bSDavid du Colombier DBG("acpi: fadt: gpe1blklen: %#ux\n", fp->gpe1blklen);
5299ef1f84bSDavid du Colombier DBG("acpi: fadt: gp1base: %#ux\n", fp->gp1base);
5309ef1f84bSDavid du Colombier DBG("acpi: fadt: cstcnt: %#ux\n", fp->cstcnt);
5319ef1f84bSDavid du Colombier DBG("acpi: fadt: plvl2lat: %#ux\n", fp->plvl2lat);
5329ef1f84bSDavid du Colombier DBG("acpi: fadt: plvl3lat: %#ux\n", fp->plvl3lat);
5339ef1f84bSDavid du Colombier DBG("acpi: fadt: flushsz: %#ux\n", fp->flushsz);
5349ef1f84bSDavid du Colombier DBG("acpi: fadt: flushstride: %#ux\n", fp->flushstride);
5359ef1f84bSDavid du Colombier DBG("acpi: fadt: dutyoff: %#ux\n", fp->dutyoff);
5369ef1f84bSDavid du Colombier DBG("acpi: fadt: dutywidth: %#ux\n", fp->dutywidth);
5379ef1f84bSDavid du Colombier DBG("acpi: fadt: dayalrm: %#ux\n", fp->dayalrm);
5389ef1f84bSDavid du Colombier DBG("acpi: fadt: monalrm: %#ux\n", fp->monalrm);
5399ef1f84bSDavid du Colombier DBG("acpi: fadt: century: %#ux\n", fp->century);
5409ef1f84bSDavid du Colombier DBG("acpi: fadt: iapcbootarch: %#ux\n", fp->iapcbootarch);
5419ef1f84bSDavid du Colombier DBG("acpi: fadt: flags: %#ux\n", fp->flags);
5429ef1f84bSDavid du Colombier
5439ef1f84bSDavid du Colombier if(revision < 3)
5449ef1f84bSDavid du Colombier return;
5459ef1f84bSDavid du Colombier
5469ef1f84bSDavid du Colombier DBG("acpi: fadt: resetreg: %G\n", &fp->resetreg);
5479ef1f84bSDavid du Colombier DBG("acpi: fadt: resetval: %#ux\n", fp->resetval);
5489ef1f84bSDavid du Colombier DBG("acpi: fadt: xfacs: %#llux\n", fp->xfacs);
5499ef1f84bSDavid du Colombier DBG("acpi: fadt: xdsdt: %#llux\n", fp->xdsdt);
5509ef1f84bSDavid du Colombier DBG("acpi: fadt: xpm1aevtblk: %G\n", &fp->xpm1aevtblk);
5519ef1f84bSDavid du Colombier DBG("acpi: fadt: xpm1bevtblk: %G\n", &fp->xpm1bevtblk);
5529ef1f84bSDavid du Colombier DBG("acpi: fadt: xpm1acntblk: %G\n", &fp->xpm1acntblk);
5539ef1f84bSDavid du Colombier DBG("acpi: fadt: xpm1bcntblk: %G\n", &fp->xpm1bcntblk);
5549ef1f84bSDavid du Colombier DBG("acpi: fadt: xpm2cntblk: %G\n", &fp->xpm2cntblk);
5559ef1f84bSDavid du Colombier DBG("acpi: fadt: xpmtmrblk: %G\n", &fp->xpmtmrblk);
5569ef1f84bSDavid du Colombier DBG("acpi: fadt: xgpe0blk: %G\n", &fp->xgpe0blk);
5579ef1f84bSDavid du Colombier DBG("acpi: fadt: xgpe1blk: %G\n", &fp->xgpe1blk);
5589ef1f84bSDavid du Colombier }
5599ef1f84bSDavid du Colombier
5609ef1f84bSDavid du Colombier static Atable*
acpifadt(uchar * p,int)5619ef1f84bSDavid du Colombier acpifadt(uchar *p, int)
5629ef1f84bSDavid du Colombier {
5639ef1f84bSDavid du Colombier Fadt *fp;
5649ef1f84bSDavid du Colombier int revision;
5659ef1f84bSDavid du Colombier
5669ef1f84bSDavid du Colombier fp = &fadt;
5679ef1f84bSDavid du Colombier revision = p[8];
5689ef1f84bSDavid du Colombier DBG("acpifadt %#p length %ud revision %ud\n", p, l32get(p+4), revision);
5699ef1f84bSDavid du Colombier fp->facs = l32get(p + 36);
5709ef1f84bSDavid du Colombier fp->dsdt = l32get(p + 40);
5719ef1f84bSDavid du Colombier fp->pmprofile = p[45];
5729ef1f84bSDavid du Colombier fp->sciint = l16get(p+46);
5739ef1f84bSDavid du Colombier fp->smicmd = l32get(p+48);
5749ef1f84bSDavid du Colombier fp->acpienable = p[52];
5759ef1f84bSDavid du Colombier fp->acpidisable = p[53];
5769ef1f84bSDavid du Colombier fp->s4biosreq = p[54];
5779ef1f84bSDavid du Colombier fp->pstatecnt = p[55];
5789ef1f84bSDavid du Colombier fp->pm1aevtblk = l32get(p+56);
5799ef1f84bSDavid du Colombier fp->pm1bevtblk = l32get(p+60);
5809ef1f84bSDavid du Colombier fp->pm1acntblk = l32get(p+64);
5819ef1f84bSDavid du Colombier fp->pm1bcntblk = l32get(p+68);
5829ef1f84bSDavid du Colombier fp->pm2cntblk = l32get(p+72);
5839ef1f84bSDavid du Colombier fp->pmtmrblk = l32get(p+76);
5849ef1f84bSDavid du Colombier fp->gpe0blk = l32get(p+80);
5859ef1f84bSDavid du Colombier fp->gpe1blk = l32get(p+84);
5869ef1f84bSDavid du Colombier fp->pm1evtlen = p[88];
5879ef1f84bSDavid du Colombier fp->pm1cntlen = p[89];
5889ef1f84bSDavid du Colombier fp->pm2cntlen = p[90];
5899ef1f84bSDavid du Colombier fp->pmtmrlen = p[91];
5909ef1f84bSDavid du Colombier fp->gpe0blklen = p[92];
5919ef1f84bSDavid du Colombier fp->gpe1blklen = p[93];
5929ef1f84bSDavid du Colombier fp->gp1base = p[94];
5939ef1f84bSDavid du Colombier fp->cstcnt = p[95];
5949ef1f84bSDavid du Colombier fp->plvl2lat = l16get(p+96);
5959ef1f84bSDavid du Colombier fp->plvl3lat = l16get(p+98);
5969ef1f84bSDavid du Colombier fp->flushsz = l16get(p+100);
5979ef1f84bSDavid du Colombier fp->flushstride = l16get(p+102);
5989ef1f84bSDavid du Colombier fp->dutyoff = p[104];
5999ef1f84bSDavid du Colombier fp->dutywidth = p[105];
6009ef1f84bSDavid du Colombier fp->dayalrm = p[106];
6019ef1f84bSDavid du Colombier fp->monalrm = p[107];
6029ef1f84bSDavid du Colombier fp->century = p[108];
6039ef1f84bSDavid du Colombier fp->iapcbootarch = l16get(p+109);
6049ef1f84bSDavid du Colombier fp->flags = l32get(p+112);
6059ef1f84bSDavid du Colombier
6069ef1f84bSDavid du Colombier /*
6079ef1f84bSDavid du Colombier * Revision 1 of this table stops here, and is described
6089ef1f84bSDavid du Colombier * in The ACPI Specification 1.0, 22-Dec-1996.
6099ef1f84bSDavid du Colombier * The ACPI Specification 2.0, 27-Jul-2000, bumped the revision
6109ef1f84bSDavid du Colombier * number up to 3 and added the extra fields on the end.
6119ef1f84bSDavid du Colombier * Thank you, QEMU.
6129ef1f84bSDavid du Colombier */
6139ef1f84bSDavid du Colombier if(revision >= 3){
6149ef1f84bSDavid du Colombier gasget(&fp->resetreg, p+116);
6159ef1f84bSDavid du Colombier
6169ef1f84bSDavid du Colombier fp->resetval = p[128];
6179ef1f84bSDavid du Colombier fp->xfacs = l64get(p+132);
6189ef1f84bSDavid du Colombier fp->xdsdt = l64get(p+140);
6199ef1f84bSDavid du Colombier gasget(&fp->xpm1aevtblk, p+148);
6209ef1f84bSDavid du Colombier gasget(&fp->xpm1bevtblk, p+160);
6219ef1f84bSDavid du Colombier gasget(&fp->xpm1acntblk, p+172);
6229ef1f84bSDavid du Colombier gasget(&fp->xpm1bcntblk, p+184);
6239ef1f84bSDavid du Colombier gasget(&fp->xpm2cntblk, p+196);
6249ef1f84bSDavid du Colombier gasget(&fp->xpmtmrblk, p+208);
6259ef1f84bSDavid du Colombier gasget(&fp->xgpe0blk, p+220);
6269ef1f84bSDavid du Colombier gasget(&fp->xgpe1blk, p+232);
6279ef1f84bSDavid du Colombier }
6289ef1f84bSDavid du Colombier
6299ef1f84bSDavid du Colombier dumpfadt(fp, revision);
6309ef1f84bSDavid du Colombier
6319ef1f84bSDavid du Colombier /* If xfacs or xdsdt are either nil
6329ef1f84bSDavid du Colombier * or different from their 32-bit
6339ef1f84bSDavid du Colombier * counter-parts, then go with
6349ef1f84bSDavid du Colombier * the 32-bit addresses (as the
6359ef1f84bSDavid du Colombier * ACPICA does), since those are
6369ef1f84bSDavid du Colombier * tested by BIOS manufacturers.
6379ef1f84bSDavid du Colombier */
6389ef1f84bSDavid du Colombier
6399ef1f84bSDavid du Colombier if(fp->xfacs != 0 && fp->xfacs == fp->facs)
6409ef1f84bSDavid du Colombier loadfacs(fp->xfacs);
6419ef1f84bSDavid du Colombier else
6429ef1f84bSDavid du Colombier loadfacs(fp->facs);
6439ef1f84bSDavid du Colombier
6449ef1f84bSDavid du Colombier if(fp->xdsdt != 0 && fp->xdsdt == fp->dsdt)
6459ef1f84bSDavid du Colombier loadfacs(fp->xdsdt);
6469ef1f84bSDavid du Colombier else
6479ef1f84bSDavid du Colombier loadfacs(fp->dsdt);
6489ef1f84bSDavid du Colombier
6499ef1f84bSDavid du Colombier return nil; /* can be unmapped once parsed */
6509ef1f84bSDavid du Colombier }
6519ef1f84bSDavid du Colombier
6529ef1f84bSDavid du Colombier static void
dumpmsct(Msct * msct)6539ef1f84bSDavid du Colombier dumpmsct(Msct *msct)
6549ef1f84bSDavid du Colombier {
6559ef1f84bSDavid du Colombier Mdom *st;
6569ef1f84bSDavid du Colombier
6579ef1f84bSDavid du Colombier DBG("acpi: msct: %d doms %d clkdoms %#ullx maxpa\n",
6589ef1f84bSDavid du Colombier msct->ndoms, msct->nclkdoms, msct->maxpa);
6599ef1f84bSDavid du Colombier for(st = msct->dom; st != nil; st = st->next)
6609ef1f84bSDavid du Colombier DBG("\t[%d:%d] %d maxproc %#ullx maxmmem\n",
6619ef1f84bSDavid du Colombier st->start, st->end, st->maxproc, st->maxmem);
6629ef1f84bSDavid du Colombier DBG("\n");
6639ef1f84bSDavid du Colombier }
6649ef1f84bSDavid du Colombier
6659ef1f84bSDavid du Colombier /*
6669ef1f84bSDavid du Colombier * XXX: should perhaps update our idea of available memory.
6679ef1f84bSDavid du Colombier * Else we should remove this code.
6689ef1f84bSDavid du Colombier */
6699ef1f84bSDavid du Colombier static Atable*
acpimsct(uchar * p,int len)6709ef1f84bSDavid du Colombier acpimsct(uchar *p, int len)
6719ef1f84bSDavid du Colombier {
6729ef1f84bSDavid du Colombier uchar *pe;
6739ef1f84bSDavid du Colombier Mdom **stl, *st;
6749ef1f84bSDavid du Colombier int off;
6759ef1f84bSDavid du Colombier
6769ef1f84bSDavid du Colombier msct = mallocz(sizeof(Msct), 1);
6779ef1f84bSDavid du Colombier msct->ndoms = l32get(p+40) + 1;
6789ef1f84bSDavid du Colombier msct->nclkdoms = l32get(p+44) + 1;
6799ef1f84bSDavid du Colombier msct->maxpa = l64get(p+48);
6809ef1f84bSDavid du Colombier msct->dom = nil;
6819ef1f84bSDavid du Colombier stl = &msct->dom;
6829ef1f84bSDavid du Colombier pe = p + len;
6839ef1f84bSDavid du Colombier off = l32get(p+36);
6849ef1f84bSDavid du Colombier for(p += off; p < pe; p += 22){
6859ef1f84bSDavid du Colombier st = mallocz(sizeof(Mdom), 1);
6869ef1f84bSDavid du Colombier st->next = nil;
6879ef1f84bSDavid du Colombier st->start = l32get(p+2);
6889ef1f84bSDavid du Colombier st->end = l32get(p+6);
6899ef1f84bSDavid du Colombier st->maxproc = l32get(p+10);
6909ef1f84bSDavid du Colombier st->maxmem = l64get(p+14);
6919ef1f84bSDavid du Colombier *stl = st;
6929ef1f84bSDavid du Colombier stl = &st->next;
6939ef1f84bSDavid du Colombier }
6949ef1f84bSDavid du Colombier
6959ef1f84bSDavid du Colombier dumpmsct(msct);
6969ef1f84bSDavid du Colombier return nil; /* can be unmapped once parsed */
6979ef1f84bSDavid du Colombier }
6989ef1f84bSDavid du Colombier
6999ef1f84bSDavid du Colombier static Atable*
acpihpet(uchar * p,int)7009ef1f84bSDavid du Colombier acpihpet(uchar *p, int)
7019ef1f84bSDavid du Colombier {
7029ef1f84bSDavid du Colombier hpet = mallocz(sizeof(Hpet), 1);
7039ef1f84bSDavid du Colombier p += 36;
7049ef1f84bSDavid du Colombier
7059ef1f84bSDavid du Colombier hpet->id = l32get(p);
7069ef1f84bSDavid du Colombier p += 4;
7079ef1f84bSDavid du Colombier
7089ef1f84bSDavid du Colombier p += 4; /* it's a Gas */
7099ef1f84bSDavid du Colombier hpet->addr = l64get(p);
7109ef1f84bSDavid du Colombier p += 8;
7119ef1f84bSDavid du Colombier
7129ef1f84bSDavid du Colombier hpet->seqno = *p;
7139ef1f84bSDavid du Colombier p++;
7149ef1f84bSDavid du Colombier
7159ef1f84bSDavid du Colombier hpet->minticks = l16get(p);
7169ef1f84bSDavid du Colombier p += 2;
7179ef1f84bSDavid du Colombier hpet->attr = *p;
7189ef1f84bSDavid du Colombier
7199ef1f84bSDavid du Colombier DBG("hpet: id %#ux addr %#p seqno %d ticks %d attr %#ux\n",
7209ef1f84bSDavid du Colombier hpet->id, hpet->addr, hpet->seqno, hpet->minticks, hpet->attr);
7219ef1f84bSDavid du Colombier // hpetinit(hpet->seqno, hpet->addr, hpet->minticks)
7229ef1f84bSDavid du Colombier return nil; /* can be unmapped once parsed */
7239ef1f84bSDavid du Colombier }
7249ef1f84bSDavid du Colombier
7259ef1f84bSDavid du Colombier
7269ef1f84bSDavid du Colombier static void
dumpsrat(Srat * st)7279ef1f84bSDavid du Colombier dumpsrat(Srat *st)
7289ef1f84bSDavid du Colombier {
7299ef1f84bSDavid du Colombier DBG("acpi: srat:\n");
7309ef1f84bSDavid du Colombier for(; st != nil; st = st->next)
7319ef1f84bSDavid du Colombier switch(st->type){
7329ef1f84bSDavid du Colombier case SRlapic:
7339ef1f84bSDavid du Colombier DBG("\tlapic: dom %d apic %d sapic %d clk %d\n",
7349ef1f84bSDavid du Colombier st->lapic.dom, st->lapic.apic,
7359ef1f84bSDavid du Colombier st->lapic.sapic, st->lapic.clkdom);
7369ef1f84bSDavid du Colombier break;
7379ef1f84bSDavid du Colombier case SRmem:
7389ef1f84bSDavid du Colombier DBG("\tmem: dom %d %#ullx %#ullx %c%c\n",
7399ef1f84bSDavid du Colombier st->mem.dom, st->mem.addr, st->mem.len,
7409ef1f84bSDavid du Colombier st->mem.hplug?'h':'-',
7419ef1f84bSDavid du Colombier st->mem.nvram?'n':'-');
7429ef1f84bSDavid du Colombier break;
7439ef1f84bSDavid du Colombier case SRlx2apic:
7449ef1f84bSDavid du Colombier DBG("\tlx2apic: dom %d apic %d clk %d\n",
7459ef1f84bSDavid du Colombier st->lx2apic.dom, st->lx2apic.apic,
7469ef1f84bSDavid du Colombier st->lx2apic.clkdom);
7479ef1f84bSDavid du Colombier break;
7489ef1f84bSDavid du Colombier default:
7499ef1f84bSDavid du Colombier DBG("\t<unknown srat entry>\n");
7509ef1f84bSDavid du Colombier }
7519ef1f84bSDavid du Colombier DBG("\n");
7529ef1f84bSDavid du Colombier }
7539ef1f84bSDavid du Colombier
7549ef1f84bSDavid du Colombier static Atable*
acpisrat(uchar * p,int len)7559ef1f84bSDavid du Colombier acpisrat(uchar *p, int len)
7569ef1f84bSDavid du Colombier {
7579ef1f84bSDavid du Colombier Srat **stl, *st;
7589ef1f84bSDavid du Colombier uchar *pe;
7599ef1f84bSDavid du Colombier int stlen, flags;
7609ef1f84bSDavid du Colombier
7619ef1f84bSDavid du Colombier if(srat != nil){
7629ef1f84bSDavid du Colombier print("acpi: two SRATs?\n");
7639ef1f84bSDavid du Colombier return nil;
7649ef1f84bSDavid du Colombier }
7659ef1f84bSDavid du Colombier
7669ef1f84bSDavid du Colombier stl = &srat;
7679ef1f84bSDavid du Colombier pe = p + len;
7689ef1f84bSDavid du Colombier for(p += 48; p < pe; p += stlen){
7699ef1f84bSDavid du Colombier st = mallocz(sizeof(Srat), 1);
7709ef1f84bSDavid du Colombier st->type = p[0];
7719ef1f84bSDavid du Colombier st->next = nil;
7729ef1f84bSDavid du Colombier stlen = p[1];
7739ef1f84bSDavid du Colombier switch(st->type){
7749ef1f84bSDavid du Colombier case SRlapic:
7759ef1f84bSDavid du Colombier st->lapic.dom = p[2] | p[9]<<24| p[10]<<16 | p[11]<<8;
7769ef1f84bSDavid du Colombier st->lapic.apic = p[3];
7779ef1f84bSDavid du Colombier st->lapic.sapic = p[8];
7789ef1f84bSDavid du Colombier st->lapic.clkdom = l32get(p+12);
7799ef1f84bSDavid du Colombier if(l32get(p+4) == 0){
7809ef1f84bSDavid du Colombier free(st);
7819ef1f84bSDavid du Colombier st = nil;
7829ef1f84bSDavid du Colombier }
7839ef1f84bSDavid du Colombier break;
7849ef1f84bSDavid du Colombier case SRmem:
7859ef1f84bSDavid du Colombier st->mem.dom = l32get(p+2);
7869ef1f84bSDavid du Colombier st->mem.addr = l64get(p+8);
7879ef1f84bSDavid du Colombier st->mem.len = l64get(p+16);
7889ef1f84bSDavid du Colombier flags = l32get(p+28);
7899ef1f84bSDavid du Colombier if((flags&1) == 0){ /* not enabled */
7909ef1f84bSDavid du Colombier free(st);
7919ef1f84bSDavid du Colombier st = nil;
7929ef1f84bSDavid du Colombier }else{
7939ef1f84bSDavid du Colombier st->mem.hplug = flags & 2;
7949ef1f84bSDavid du Colombier st->mem.nvram = flags & 4;
7959ef1f84bSDavid du Colombier }
7969ef1f84bSDavid du Colombier break;
7979ef1f84bSDavid du Colombier case SRlx2apic:
7989ef1f84bSDavid du Colombier st->lx2apic.dom = l32get(p+4);
7999ef1f84bSDavid du Colombier st->lx2apic.apic = l32get(p+8);
8009ef1f84bSDavid du Colombier st->lx2apic.clkdom = l32get(p+16);
8019ef1f84bSDavid du Colombier if(l32get(p+12) == 0){
8029ef1f84bSDavid du Colombier free(st);
8039ef1f84bSDavid du Colombier st = nil;
8049ef1f84bSDavid du Colombier }
8059ef1f84bSDavid du Colombier break;
8069ef1f84bSDavid du Colombier default:
8079ef1f84bSDavid du Colombier print("unknown SRAT structure\n");
8089ef1f84bSDavid du Colombier free(st);
8099ef1f84bSDavid du Colombier st = nil;
8109ef1f84bSDavid du Colombier }
8119ef1f84bSDavid du Colombier if(st != nil){
8129ef1f84bSDavid du Colombier *stl = st;
8139ef1f84bSDavid du Colombier stl = &st->next;
8149ef1f84bSDavid du Colombier }
8159ef1f84bSDavid du Colombier }
8169ef1f84bSDavid du Colombier
8179ef1f84bSDavid du Colombier dumpsrat(srat);
8189ef1f84bSDavid du Colombier return nil; /* can be unmapped once parsed */
8199ef1f84bSDavid du Colombier }
8209ef1f84bSDavid du Colombier
8219ef1f84bSDavid du Colombier static void
dumpslit(Slit * sl)8229ef1f84bSDavid du Colombier dumpslit(Slit *sl)
8239ef1f84bSDavid du Colombier {
8249ef1f84bSDavid du Colombier int i;
8259ef1f84bSDavid du Colombier
8269ef1f84bSDavid du Colombier DBG("acpi slit:\n");
8279ef1f84bSDavid du Colombier for(i = 0; i < sl->rowlen*sl->rowlen; i++){
8289ef1f84bSDavid du Colombier DBG(" %ux", sl->e[i/sl->rowlen][i%sl->rowlen].dist);
8299ef1f84bSDavid du Colombier }
8309ef1f84bSDavid du Colombier DBG("\n");
8319ef1f84bSDavid du Colombier }
8329ef1f84bSDavid du Colombier
8339ef1f84bSDavid du Colombier static int
cmpslitent(void * v1,void * v2)8349ef1f84bSDavid du Colombier cmpslitent(void* v1, void* v2)
8359ef1f84bSDavid du Colombier {
8369ef1f84bSDavid du Colombier SlEntry *se1, *se2;
8379ef1f84bSDavid du Colombier
8389ef1f84bSDavid du Colombier se1 = v1;
8399ef1f84bSDavid du Colombier se2 = v2;
8409ef1f84bSDavid du Colombier return se1->dist - se2->dist;
8419ef1f84bSDavid du Colombier }
8429ef1f84bSDavid du Colombier
8439ef1f84bSDavid du Colombier static Atable*
acpislit(uchar * p,int len)8449ef1f84bSDavid du Colombier acpislit(uchar *p, int len)
8459ef1f84bSDavid du Colombier {
8469ef1f84bSDavid du Colombier uchar *pe;
8479ef1f84bSDavid du Colombier int i, j, k;
8489ef1f84bSDavid du Colombier SlEntry *se;
8499ef1f84bSDavid du Colombier
8509ef1f84bSDavid du Colombier pe = p + len;
8519ef1f84bSDavid du Colombier slit = malloc(sizeof(*slit));
8529ef1f84bSDavid du Colombier slit->rowlen = l64get(p+36);
8539ef1f84bSDavid du Colombier slit->e = malloc(slit->rowlen*sizeof(SlEntry*));
8549ef1f84bSDavid du Colombier for(i = 0; i < slit->rowlen; i++)
8559ef1f84bSDavid du Colombier slit->e[i] = malloc(sizeof(SlEntry)*slit->rowlen);
8569ef1f84bSDavid du Colombier
8579ef1f84bSDavid du Colombier i = 0;
8589ef1f84bSDavid du Colombier for(p += 44; p < pe; p++, i++){
8599ef1f84bSDavid du Colombier j = i/slit->rowlen;
8609ef1f84bSDavid du Colombier k = i%slit->rowlen;
8619ef1f84bSDavid du Colombier se = &slit->e[j][k];
8629ef1f84bSDavid du Colombier se->dom = k;
8639ef1f84bSDavid du Colombier se->dist = *p;
8649ef1f84bSDavid du Colombier }
8659ef1f84bSDavid du Colombier dumpslit(slit);
8669ef1f84bSDavid du Colombier for(i = 0; i < slit->rowlen; i++)
8679ef1f84bSDavid du Colombier qsort(slit->e[i], slit->rowlen, sizeof(slit->e[0][0]), cmpslitent);
8689ef1f84bSDavid du Colombier
8699ef1f84bSDavid du Colombier dumpslit(slit);
8709ef1f84bSDavid du Colombier return nil; /* can be unmapped once parsed */
8719ef1f84bSDavid du Colombier }
8729ef1f84bSDavid du Colombier
873*094d6818SDavid du Colombier uintmem
acpimblocksize(uintmem addr,int * dom)874*094d6818SDavid du Colombier acpimblocksize(uintmem addr, int *dom)
875*094d6818SDavid du Colombier {
876*094d6818SDavid du Colombier Srat *sl;
877*094d6818SDavid du Colombier
878*094d6818SDavid du Colombier for(sl = srat; sl != nil; sl = sl->next)
879*094d6818SDavid du Colombier if(sl->type == SRmem)
880*094d6818SDavid du Colombier if(sl->mem.addr <= addr && sl->mem.addr + sl->mem.len > addr){
881*094d6818SDavid du Colombier *dom = sl->mem.dom;
882*094d6818SDavid du Colombier return sl->mem.len - (addr - sl->mem.addr);
883*094d6818SDavid du Colombier }
884*094d6818SDavid du Colombier return 0;
885*094d6818SDavid du Colombier }
886*094d6818SDavid du Colombier
8879ef1f84bSDavid du Colombier /*
8889ef1f84bSDavid du Colombier * Return a number identifying a color for the memory at
8899ef1f84bSDavid du Colombier * the given address (color identifies locality) and fill *sizep
8909ef1f84bSDavid du Colombier * with the size for memory of the same color starting at addr.
8919ef1f84bSDavid du Colombier */
8929ef1f84bSDavid du Colombier int
memcolor(uintmem addr,uintmem * sizep)8939ef1f84bSDavid du Colombier memcolor(uintmem addr, uintmem *sizep)
8949ef1f84bSDavid du Colombier {
8959ef1f84bSDavid du Colombier Srat *sl;
8969ef1f84bSDavid du Colombier
8979ef1f84bSDavid du Colombier for(sl = srat; sl != nil; sl = sl->next)
8989ef1f84bSDavid du Colombier if(sl->type == SRmem)
8999ef1f84bSDavid du Colombier if(sl->mem.addr <= addr && addr-sl->mem.addr < sl->mem.len){
9009ef1f84bSDavid du Colombier if(sizep != nil)
9019ef1f84bSDavid du Colombier *sizep = sl->mem.len - (addr - sl->mem.addr);
9029ef1f84bSDavid du Colombier if(sl->mem.dom >= NCOLOR)
9039ef1f84bSDavid du Colombier print("memcolor: NCOLOR too small");
9049ef1f84bSDavid du Colombier return sl->mem.dom%NCOLOR;
9059ef1f84bSDavid du Colombier }
9069ef1f84bSDavid du Colombier return -1;
9079ef1f84bSDavid du Colombier }
9089ef1f84bSDavid du Colombier
9099ef1f84bSDavid du Colombier /*
9109ef1f84bSDavid du Colombier * Being machno an index in sys->machptr, return the color
9119ef1f84bSDavid du Colombier * for that mach (color identifies locality).
9129ef1f84bSDavid du Colombier */
9139ef1f84bSDavid du Colombier int
corecolor(int machno)9149ef1f84bSDavid du Colombier corecolor(int machno)
9159ef1f84bSDavid du Colombier {
9169ef1f84bSDavid du Colombier Srat *sl;
9179ef1f84bSDavid du Colombier Mach *m;
9189ef1f84bSDavid du Colombier static int colors[32];
9199ef1f84bSDavid du Colombier
9209ef1f84bSDavid du Colombier if(machno < 0 || machno >= MACHMAX)
9219ef1f84bSDavid du Colombier return -1;
9229ef1f84bSDavid du Colombier m = sys->machptr[machno];
9239ef1f84bSDavid du Colombier if(m == nil)
9249ef1f84bSDavid du Colombier return -1;
9259ef1f84bSDavid du Colombier
9269ef1f84bSDavid du Colombier if(machno >= 0 && machno < nelem(colors) && colors[machno] != 0)
9279ef1f84bSDavid du Colombier return colors[machno] - 1;
9289ef1f84bSDavid du Colombier
9299ef1f84bSDavid du Colombier for(sl = srat; sl != nil; sl = sl->next)
9309ef1f84bSDavid du Colombier if(sl->type == SRlapic && sl->lapic.apic == m->apicno){
9319ef1f84bSDavid du Colombier if(machno >= 0 && machno < nelem(colors))
9329ef1f84bSDavid du Colombier colors[machno] = 1 + sl->lapic.dom;
9339ef1f84bSDavid du Colombier if(sl->lapic.dom >= NCOLOR)
9349ef1f84bSDavid du Colombier print("memcolor: NCOLOR too small");
9359ef1f84bSDavid du Colombier return sl->lapic.dom%NCOLOR;
9369ef1f84bSDavid du Colombier }
9379ef1f84bSDavid du Colombier return -1;
9389ef1f84bSDavid du Colombier }
9399ef1f84bSDavid du Colombier
9409ef1f84bSDavid du Colombier
9419ef1f84bSDavid du Colombier int
pickcore(int mycolor,int index)9429ef1f84bSDavid du Colombier pickcore(int mycolor, int index)
9439ef1f84bSDavid du Colombier {
9449ef1f84bSDavid du Colombier int color;
9459ef1f84bSDavid du Colombier int ncorepercol;
9469ef1f84bSDavid du Colombier
9479ef1f84bSDavid du Colombier if(slit == nil)
9489ef1f84bSDavid du Colombier return index;
9499ef1f84bSDavid du Colombier ncorepercol = MACHMAX/slit->rowlen;
9509ef1f84bSDavid du Colombier color = slit->e[mycolor][index/ncorepercol].dom;
9519ef1f84bSDavid du Colombier return color * ncorepercol + index % ncorepercol;
9529ef1f84bSDavid du Colombier }
9539ef1f84bSDavid du Colombier
9549ef1f84bSDavid du Colombier
9559ef1f84bSDavid du Colombier static void
dumpmadt(Madt * apics)9569ef1f84bSDavid du Colombier dumpmadt(Madt *apics)
9579ef1f84bSDavid du Colombier {
9589ef1f84bSDavid du Colombier Apicst *st;
9599ef1f84bSDavid du Colombier
9609ef1f84bSDavid du Colombier DBG("acpi: madt lapic paddr %llux pcat %d:\n", apics->lapicpa, apics->pcat);
9619ef1f84bSDavid du Colombier for(st = apics->st; st != nil; st = st->next)
9629ef1f84bSDavid du Colombier switch(st->type){
9639ef1f84bSDavid du Colombier case ASlapic:
9649ef1f84bSDavid du Colombier DBG("\tlapic pid %d id %d\n", st->lapic.pid, st->lapic.id);
9659ef1f84bSDavid du Colombier break;
9669ef1f84bSDavid du Colombier case ASioapic:
9679ef1f84bSDavid du Colombier case ASiosapic:
9689ef1f84bSDavid du Colombier DBG("\tioapic id %d addr %#llux ibase %d\n",
9699ef1f84bSDavid du Colombier st->ioapic.id, st->ioapic.addr, st->ioapic.ibase);
9709ef1f84bSDavid du Colombier break;
9719ef1f84bSDavid du Colombier case ASintovr:
9729ef1f84bSDavid du Colombier DBG("\tintovr irq %d intr %d flags %#ux\n",
9739ef1f84bSDavid du Colombier st->intovr.irq, st->intovr.intr,st->intovr.flags);
9749ef1f84bSDavid du Colombier break;
9759ef1f84bSDavid du Colombier case ASnmi:
9769ef1f84bSDavid du Colombier DBG("\tnmi intr %d flags %#ux\n",
9779ef1f84bSDavid du Colombier st->nmi.intr, st->nmi.flags);
9789ef1f84bSDavid du Colombier break;
9799ef1f84bSDavid du Colombier case ASlnmi:
9809ef1f84bSDavid du Colombier DBG("\tlnmi pid %d lint %d flags %#ux\n",
9819ef1f84bSDavid du Colombier st->lnmi.pid, st->lnmi.lint, st->lnmi.flags);
9829ef1f84bSDavid du Colombier break;
9839ef1f84bSDavid du Colombier case ASlsapic:
9849ef1f84bSDavid du Colombier DBG("\tlsapic pid %d id %d eid %d puid %d puids %s\n",
9859ef1f84bSDavid du Colombier st->lsapic.pid, st->lsapic.id,
9869ef1f84bSDavid du Colombier st->lsapic.eid, st->lsapic.puid,
9879ef1f84bSDavid du Colombier st->lsapic.puids);
9889ef1f84bSDavid du Colombier break;
9899ef1f84bSDavid du Colombier case ASintsrc:
9909ef1f84bSDavid du Colombier DBG("\tintr type %d pid %d peid %d iosv %d intr %d %#x\n",
9919ef1f84bSDavid du Colombier st->type, st->intsrc.pid,
9929ef1f84bSDavid du Colombier st->intsrc.peid, st->intsrc.iosv,
9939ef1f84bSDavid du Colombier st->intsrc.intr, st->intsrc.flags);
9949ef1f84bSDavid du Colombier break;
9959ef1f84bSDavid du Colombier case ASlx2apic:
9969ef1f84bSDavid du Colombier DBG("\tlx2apic puid %d id %d\n", st->lx2apic.puid, st->lx2apic.id);
9979ef1f84bSDavid du Colombier break;
9989ef1f84bSDavid du Colombier case ASlx2nmi:
9999ef1f84bSDavid du Colombier DBG("\tlx2nmi puid %d intr %d flags %#ux\n",
10009ef1f84bSDavid du Colombier st->lx2nmi.puid, st->lx2nmi.intr, st->lx2nmi.flags);
10019ef1f84bSDavid du Colombier break;
10029ef1f84bSDavid du Colombier default:
10039ef1f84bSDavid du Colombier DBG("\t<unknown madt entry>\n");
10049ef1f84bSDavid du Colombier }
10059ef1f84bSDavid du Colombier DBG("\n");
10069ef1f84bSDavid du Colombier }
10079ef1f84bSDavid du Colombier
10089ef1f84bSDavid du Colombier static Atable*
acpimadt(uchar * p,int len)10099ef1f84bSDavid du Colombier acpimadt(uchar *p, int len)
10109ef1f84bSDavid du Colombier {
10119ef1f84bSDavid du Colombier uchar *pe;
10129ef1f84bSDavid du Colombier Apicst *st, *l, **stl;
10139ef1f84bSDavid du Colombier int stlen, id;
10149ef1f84bSDavid du Colombier
10159ef1f84bSDavid du Colombier apics = mallocz(sizeof(Madt), 1);
10169ef1f84bSDavid du Colombier apics->lapicpa = l32get(p+36);
10179ef1f84bSDavid du Colombier apics->pcat = l32get(p+40);
10189ef1f84bSDavid du Colombier apics->st = nil;
10199ef1f84bSDavid du Colombier stl = &apics->st;
10209ef1f84bSDavid du Colombier pe = p + len;
10219ef1f84bSDavid du Colombier for(p += 44; p < pe; p += stlen){
10229ef1f84bSDavid du Colombier st = mallocz(sizeof(Apicst), 1);
10239ef1f84bSDavid du Colombier st->type = p[0];
10249ef1f84bSDavid du Colombier st->next = nil;
10259ef1f84bSDavid du Colombier stlen = p[1];
10269ef1f84bSDavid du Colombier switch(st->type){
10279ef1f84bSDavid du Colombier case ASlapic:
10289ef1f84bSDavid du Colombier st->lapic.pid = p[2];
10299ef1f84bSDavid du Colombier st->lapic.id = p[3];
10309ef1f84bSDavid du Colombier if(l32get(p+4) == 0){
10319ef1f84bSDavid du Colombier free(st);
10329ef1f84bSDavid du Colombier st = nil;
10339ef1f84bSDavid du Colombier }
10349ef1f84bSDavid du Colombier break;
10359ef1f84bSDavid du Colombier case ASioapic:
10369ef1f84bSDavid du Colombier st->ioapic.id = id = p[2];
10379ef1f84bSDavid du Colombier st->ioapic.addr = l32get(p+4);
10389ef1f84bSDavid du Colombier st->ioapic.ibase = l32get(p+8);
10399ef1f84bSDavid du Colombier /* iosapic overrides any ioapic entry for the same id */
10409ef1f84bSDavid du Colombier for(l = apics->st; l != nil; l = l->next)
10419ef1f84bSDavid du Colombier if(l->type == ASiosapic && l->iosapic.id == id){
10429ef1f84bSDavid du Colombier st->ioapic = l->iosapic;
10439ef1f84bSDavid du Colombier /* we leave it linked; could be removed */
10449ef1f84bSDavid du Colombier break;
10459ef1f84bSDavid du Colombier }
10469ef1f84bSDavid du Colombier break;
10479ef1f84bSDavid du Colombier case ASintovr:
10489ef1f84bSDavid du Colombier st->intovr.irq = p[3];
10499ef1f84bSDavid du Colombier st->intovr.intr = l32get(p+4);
10509ef1f84bSDavid du Colombier st->intovr.flags = l16get(p+8);
10519ef1f84bSDavid du Colombier break;
10529ef1f84bSDavid du Colombier case ASnmi:
10539ef1f84bSDavid du Colombier st->nmi.flags = l16get(p+2);
10549ef1f84bSDavid du Colombier st->nmi.intr = l32get(p+4);
10559ef1f84bSDavid du Colombier break;
10569ef1f84bSDavid du Colombier case ASlnmi:
10579ef1f84bSDavid du Colombier st->lnmi.pid = p[2];
10589ef1f84bSDavid du Colombier st->lnmi.flags = l16get(p+3);
10599ef1f84bSDavid du Colombier st->lnmi.lint = p[5];
10609ef1f84bSDavid du Colombier break;
10619ef1f84bSDavid du Colombier case ASladdr:
10629ef1f84bSDavid du Colombier if(sizeof(apics->lapicpa) >= 8)
10639ef1f84bSDavid du Colombier apics->lapicpa = l64get(p+8);
10649ef1f84bSDavid du Colombier break;
10659ef1f84bSDavid du Colombier case ASiosapic:
10669ef1f84bSDavid du Colombier id = st->iosapic.id = p[2];
10679ef1f84bSDavid du Colombier st->iosapic.ibase = l32get(p+4);
10689ef1f84bSDavid du Colombier st->iosapic.addr = l64get(p+8);
10699ef1f84bSDavid du Colombier /* iosapic overrides any ioapic entry for the same id */
10709ef1f84bSDavid du Colombier for(l = apics->st; l != nil; l = l->next)
10719ef1f84bSDavid du Colombier if(l->type == ASioapic && l->ioapic.id == id){
10729ef1f84bSDavid du Colombier l->ioapic = st->iosapic;
10739ef1f84bSDavid du Colombier free(st);
10749ef1f84bSDavid du Colombier st = nil;
10759ef1f84bSDavid du Colombier break;
10769ef1f84bSDavid du Colombier }
10779ef1f84bSDavid du Colombier break;
10789ef1f84bSDavid du Colombier case ASlsapic:
10799ef1f84bSDavid du Colombier st->lsapic.pid = p[2];
10809ef1f84bSDavid du Colombier st->lsapic.id = p[3];
10819ef1f84bSDavid du Colombier st->lsapic.eid = p[4];
10829ef1f84bSDavid du Colombier st->lsapic.puid = l32get(p+12);
10839ef1f84bSDavid du Colombier if(l32get(p+8) == 0){
10849ef1f84bSDavid du Colombier free(st);
10859ef1f84bSDavid du Colombier st = nil;
10869ef1f84bSDavid du Colombier }else
10879ef1f84bSDavid du Colombier kstrdup(&st->lsapic.puids, (char*)p+16);
10889ef1f84bSDavid du Colombier break;
10899ef1f84bSDavid du Colombier case ASintsrc:
10909ef1f84bSDavid du Colombier st->intsrc.flags = l16get(p+2);
10919ef1f84bSDavid du Colombier st->type = p[4];
10929ef1f84bSDavid du Colombier st->intsrc.pid = p[5];
10939ef1f84bSDavid du Colombier st->intsrc.peid = p[6];
10949ef1f84bSDavid du Colombier st->intsrc.iosv = p[7];
10959ef1f84bSDavid du Colombier st->intsrc.intr = l32get(p+8);
10969ef1f84bSDavid du Colombier st->intsrc.any = l32get(p+12);
10979ef1f84bSDavid du Colombier break;
10989ef1f84bSDavid du Colombier case ASlx2apic:
10999ef1f84bSDavid du Colombier st->lx2apic.id = l32get(p+4);
11009ef1f84bSDavid du Colombier st->lx2apic.puid = l32get(p+12);
11019ef1f84bSDavid du Colombier if(l32get(p+8) == 0){
11029ef1f84bSDavid du Colombier free(st);
11039ef1f84bSDavid du Colombier st = nil;
11049ef1f84bSDavid du Colombier }
11059ef1f84bSDavid du Colombier break;
11069ef1f84bSDavid du Colombier case ASlx2nmi:
11079ef1f84bSDavid du Colombier st->lx2nmi.flags = l16get(p+2);
11089ef1f84bSDavid du Colombier st->lx2nmi.puid = l32get(p+4);
11099ef1f84bSDavid du Colombier st->lx2nmi.intr = p[8];
11109ef1f84bSDavid du Colombier break;
11119ef1f84bSDavid du Colombier default:
11129ef1f84bSDavid du Colombier print("unknown APIC structure\n");
11139ef1f84bSDavid du Colombier free(st);
11149ef1f84bSDavid du Colombier st = nil;
11159ef1f84bSDavid du Colombier }
11169ef1f84bSDavid du Colombier if(st != nil){
11179ef1f84bSDavid du Colombier *stl = st;
11189ef1f84bSDavid du Colombier stl = &st->next;
11199ef1f84bSDavid du Colombier }
11209ef1f84bSDavid du Colombier }
11219ef1f84bSDavid du Colombier
11229ef1f84bSDavid du Colombier dumpmadt(apics);
11239ef1f84bSDavid du Colombier return nil; /* can be unmapped once parsed */
11249ef1f84bSDavid du Colombier }
11259ef1f84bSDavid du Colombier
11269ef1f84bSDavid du Colombier /*
11279ef1f84bSDavid du Colombier * Map the table and keep it there.
11289ef1f84bSDavid du Colombier */
11299ef1f84bSDavid du Colombier static Atable*
acpitable(uchar * p,int len)11309ef1f84bSDavid du Colombier acpitable(uchar *p, int len)
11319ef1f84bSDavid du Colombier {
11329ef1f84bSDavid du Colombier if(len < Sdthdrsz)
11339ef1f84bSDavid du Colombier return nil;
11349ef1f84bSDavid du Colombier return newtable(p);
11359ef1f84bSDavid du Colombier }
11369ef1f84bSDavid du Colombier
11379ef1f84bSDavid du Colombier static void
dumptable(char * sig,uchar * p,int l)11389ef1f84bSDavid du Colombier dumptable(char *sig, uchar *p, int l)
11399ef1f84bSDavid du Colombier {
11409ef1f84bSDavid du Colombier int n, i;
11419ef1f84bSDavid du Colombier
11429ef1f84bSDavid du Colombier USED(sig);
11439ef1f84bSDavid du Colombier if(DBGFLG > 1){
11449ef1f84bSDavid du Colombier DBG("%s @ %#p\n", sig, p);
11459ef1f84bSDavid du Colombier if(DBGFLG > 2)
11469ef1f84bSDavid du Colombier n = l;
11479ef1f84bSDavid du Colombier else
11489ef1f84bSDavid du Colombier n = 256;
11499ef1f84bSDavid du Colombier for(i = 0; i < n; i++){
11509ef1f84bSDavid du Colombier if((i % 16) == 0)
11519ef1f84bSDavid du Colombier DBG("%x: ", i);
11529ef1f84bSDavid du Colombier DBG(" %2.2ux", p[i]);
11539ef1f84bSDavid du Colombier if((i % 16) == 15)
11549ef1f84bSDavid du Colombier DBG("\n");
11559ef1f84bSDavid du Colombier }
11569ef1f84bSDavid du Colombier DBG("\n");
11579ef1f84bSDavid du Colombier DBG("\n");
11589ef1f84bSDavid du Colombier }
11599ef1f84bSDavid du Colombier }
11609ef1f84bSDavid du Colombier
11619ef1f84bSDavid du Colombier static char*
seprinttable(char * s,char * e,Atable * t)11629ef1f84bSDavid du Colombier seprinttable(char *s, char *e, Atable *t)
11639ef1f84bSDavid du Colombier {
11649ef1f84bSDavid du Colombier uchar *p;
11659ef1f84bSDavid du Colombier int i, n;
11669ef1f84bSDavid du Colombier
11679ef1f84bSDavid du Colombier p = (uchar*)t->tbl; /* include header */
11689ef1f84bSDavid du Colombier n = Sdthdrsz + t->dlen;
11699ef1f84bSDavid du Colombier s = seprint(s, e, "%s @ %#p\n", t->sig, p);
11709ef1f84bSDavid du Colombier for(i = 0; i < n; i++){
11719ef1f84bSDavid du Colombier if((i % 16) == 0)
11729ef1f84bSDavid du Colombier s = seprint(s, e, "%x: ", i);
11739ef1f84bSDavid du Colombier s = seprint(s, e, " %2.2ux", p[i]);
11749ef1f84bSDavid du Colombier if((i % 16) == 15)
11759ef1f84bSDavid du Colombier s = seprint(s, e, "\n");
11769ef1f84bSDavid du Colombier }
11779ef1f84bSDavid du Colombier return seprint(s, e, "\n\n");
11789ef1f84bSDavid du Colombier }
11799ef1f84bSDavid du Colombier
11809ef1f84bSDavid du Colombier /*
11819ef1f84bSDavid du Colombier * process xsdt table and load tables with sig, or all if nil.
11829ef1f84bSDavid du Colombier * (XXX: should be able to search for sig, oemid, oemtblid)
11839ef1f84bSDavid du Colombier */
11849ef1f84bSDavid du Colombier static int
acpixsdtload(char * sig)11859ef1f84bSDavid du Colombier acpixsdtload(char *sig)
11869ef1f84bSDavid du Colombier {
11879ef1f84bSDavid du Colombier int i, l, t, unmap, found;
11889ef1f84bSDavid du Colombier uintmem dhpa;
11899ef1f84bSDavid du Colombier uchar *sdt;
11909ef1f84bSDavid du Colombier char tsig[5];
11919ef1f84bSDavid du Colombier
11929ef1f84bSDavid du Colombier found = 0;
11939ef1f84bSDavid du Colombier for(i = 0; i < xsdt->len; i += xsdt->asize){
11949ef1f84bSDavid du Colombier if(xsdt->asize == 8)
11959ef1f84bSDavid du Colombier dhpa = l64get(xsdt->p+i);
11969ef1f84bSDavid du Colombier else
11979ef1f84bSDavid du Colombier dhpa = l32get(xsdt->p+i);
11989ef1f84bSDavid du Colombier if((sdt = sdtmap(dhpa, &l, 1)) == nil)
11999ef1f84bSDavid du Colombier continue;
12009ef1f84bSDavid du Colombier unmap = 1;
12019ef1f84bSDavid du Colombier memmove(tsig, sdt, 4);
12029ef1f84bSDavid du Colombier tsig[4] = 0;
12039ef1f84bSDavid du Colombier if(sig == nil || strcmp(sig, tsig) == 0){
12049ef1f84bSDavid du Colombier DBG("acpi: %s addr %#p\n", tsig, sdt);
12059ef1f84bSDavid du Colombier for(t = 0; t < nelem(ptables); t++)
12069ef1f84bSDavid du Colombier if(strcmp(tsig, ptables[t].sig) == 0){
12079ef1f84bSDavid du Colombier dumptable(tsig, sdt, l);
12089ef1f84bSDavid du Colombier unmap = ptables[t].f(sdt, l) == nil;
12099ef1f84bSDavid du Colombier found = 1;
12109ef1f84bSDavid du Colombier break;
12119ef1f84bSDavid du Colombier }
12129ef1f84bSDavid du Colombier }
12139ef1f84bSDavid du Colombier if(unmap)
12149ef1f84bSDavid du Colombier vunmap(sdt, l);
12159ef1f84bSDavid du Colombier }
12169ef1f84bSDavid du Colombier return found;
12179ef1f84bSDavid du Colombier }
12189ef1f84bSDavid du Colombier
12199ef1f84bSDavid du Colombier static void*
rsdscan(u8int * addr,int len,char * signature)12209ef1f84bSDavid du Colombier rsdscan(u8int* addr, int len, char* signature)
12219ef1f84bSDavid du Colombier {
12229ef1f84bSDavid du Colombier int sl;
12239ef1f84bSDavid du Colombier u8int *e, *p;
12249ef1f84bSDavid du Colombier
12259ef1f84bSDavid du Colombier e = addr+len;
12269ef1f84bSDavid du Colombier sl = strlen(signature);
12279ef1f84bSDavid du Colombier for(p = addr; p+sl < e; p += 16){
12289ef1f84bSDavid du Colombier if(memcmp(p, signature, sl))
12299ef1f84bSDavid du Colombier continue;
12309ef1f84bSDavid du Colombier return p;
12319ef1f84bSDavid du Colombier }
12329ef1f84bSDavid du Colombier
12339ef1f84bSDavid du Colombier return nil;
12349ef1f84bSDavid du Colombier }
12359ef1f84bSDavid du Colombier
12369ef1f84bSDavid du Colombier static void*
rsdsearch(char * signature)12379ef1f84bSDavid du Colombier rsdsearch(char* signature)
12389ef1f84bSDavid du Colombier {
12399ef1f84bSDavid du Colombier uintmem p;
12409ef1f84bSDavid du Colombier u8int *bda;
12419ef1f84bSDavid du Colombier void *rsd;
12429ef1f84bSDavid du Colombier
12439ef1f84bSDavid du Colombier /*
12449ef1f84bSDavid du Colombier * Search for the data structure signature:
12459ef1f84bSDavid du Colombier * 1) in the first KB of the EBDA;
12469ef1f84bSDavid du Colombier * 2) in the BIOS ROM between 0xE0000 and 0xFFFFF.
12479ef1f84bSDavid du Colombier */
12489ef1f84bSDavid du Colombier if(strncmp((char*)KADDR(0xFFFD9), "EISA", 4) == 0){
12499ef1f84bSDavid du Colombier bda = BIOSSEG(0x40);
12509ef1f84bSDavid du Colombier if((p = (bda[0x0F]<<8)|bda[0x0E])){
12519ef1f84bSDavid du Colombier if(rsd = rsdscan(KADDR(p), 1024, signature))
12529ef1f84bSDavid du Colombier return rsd;
12539ef1f84bSDavid du Colombier }
12549ef1f84bSDavid du Colombier }
12559ef1f84bSDavid du Colombier return rsdscan(BIOSSEG(0xE000), 0x20000, signature);
12569ef1f84bSDavid du Colombier }
12579ef1f84bSDavid du Colombier
12589ef1f84bSDavid du Colombier static void
acpirsdptr(void)12599ef1f84bSDavid du Colombier acpirsdptr(void)
12609ef1f84bSDavid du Colombier {
12619ef1f84bSDavid du Colombier Rsdp *rsd;
12629ef1f84bSDavid du Colombier int asize;
12639ef1f84bSDavid du Colombier uintmem sdtpa;
12649ef1f84bSDavid du Colombier
12659ef1f84bSDavid du Colombier if((rsd = rsdsearch("RSD PTR ")) == nil)
12669ef1f84bSDavid du Colombier return;
12679ef1f84bSDavid du Colombier
12689ef1f84bSDavid du Colombier assert(sizeof(Sdthdr) == 36);
12699ef1f84bSDavid du Colombier
12709ef1f84bSDavid du Colombier DBG("acpi: RSD PTR@ %#p, physaddr %#ux length %ud %#llux rev %d\n",
12719ef1f84bSDavid du Colombier rsd, l32get(rsd->raddr), l32get(rsd->length),
12729ef1f84bSDavid du Colombier l64get(rsd->xaddr), rsd->revision);
12739ef1f84bSDavid du Colombier
12749ef1f84bSDavid du Colombier if(rsd->revision >= 2){
12759ef1f84bSDavid du Colombier if(sdtchecksum(rsd, 36) == nil){
12769ef1f84bSDavid du Colombier DBG("acpi: RSD: bad checksum\n");
12779ef1f84bSDavid du Colombier return;
12789ef1f84bSDavid du Colombier }
12799ef1f84bSDavid du Colombier sdtpa = l64get(rsd->xaddr);
12809ef1f84bSDavid du Colombier asize = 8;
12819ef1f84bSDavid du Colombier }
12829ef1f84bSDavid du Colombier else{
12839ef1f84bSDavid du Colombier if(sdtchecksum(rsd, 20) == nil){
12849ef1f84bSDavid du Colombier DBG("acpi: RSD: bad checksum\n");
12859ef1f84bSDavid du Colombier return;
12869ef1f84bSDavid du Colombier }
12879ef1f84bSDavid du Colombier sdtpa = l32get(rsd->raddr);
12889ef1f84bSDavid du Colombier asize = 4;
12899ef1f84bSDavid du Colombier }
12909ef1f84bSDavid du Colombier
12919ef1f84bSDavid du Colombier /*
12929ef1f84bSDavid du Colombier * process the RSDT or XSDT table.
12939ef1f84bSDavid du Colombier */
12949ef1f84bSDavid du Colombier xsdt = malloc(sizeof(Xsdt));
12959ef1f84bSDavid du Colombier if(xsdt == nil){
12969ef1f84bSDavid du Colombier DBG("acpi: malloc failed\n");
12979ef1f84bSDavid du Colombier return;
12989ef1f84bSDavid du Colombier }
12999ef1f84bSDavid du Colombier if((xsdt->p = sdtmap(sdtpa, &xsdt->len, 1)) == nil){
13009ef1f84bSDavid du Colombier DBG("acpi: sdtmap failed\n");
13019ef1f84bSDavid du Colombier return;
13029ef1f84bSDavid du Colombier }
13039ef1f84bSDavid du Colombier if((xsdt->p[0] != 'R' && xsdt->p[0] != 'X') || memcmp(xsdt->p+1, "SDT", 3) != 0){
13049ef1f84bSDavid du Colombier DBG("acpi: xsdt sig: %c%c%c%c\n",
13059ef1f84bSDavid du Colombier xsdt->p[0], xsdt->p[1], xsdt->p[2], xsdt->p[3]);
13069ef1f84bSDavid du Colombier free(xsdt);
13079ef1f84bSDavid du Colombier xsdt = nil;
13089ef1f84bSDavid du Colombier vunmap(xsdt, xsdt->len);
13099ef1f84bSDavid du Colombier return;
13109ef1f84bSDavid du Colombier }
13119ef1f84bSDavid du Colombier xsdt->p += sizeof(Sdthdr);
13129ef1f84bSDavid du Colombier xsdt->len -= sizeof(Sdthdr);
13139ef1f84bSDavid du Colombier xsdt->asize = asize;
13149ef1f84bSDavid du Colombier DBG("acpi: XSDT %#p\n", xsdt);
13159ef1f84bSDavid du Colombier acpixsdtload(nil);
13169ef1f84bSDavid du Colombier /* xsdt is kept and not unmapped */
13179ef1f84bSDavid du Colombier
13189ef1f84bSDavid du Colombier }
13199ef1f84bSDavid du Colombier
13209ef1f84bSDavid du Colombier static int
acpigen(Chan * c,char *,Dirtab * tab,int ntab,int i,Dir * dp)13219ef1f84bSDavid du Colombier acpigen(Chan *c, char*, Dirtab *tab, int ntab, int i, Dir *dp)
13229ef1f84bSDavid du Colombier {
13239ef1f84bSDavid du Colombier Qid qid;
13249ef1f84bSDavid du Colombier
13259ef1f84bSDavid du Colombier if(i == DEVDOTDOT){
13269ef1f84bSDavid du Colombier mkqid(&qid, Qdir, 0, QTDIR);
13279ef1f84bSDavid du Colombier devdir(c, qid, ".", 0, eve, 0555, dp);
13289ef1f84bSDavid du Colombier return 1;
13299ef1f84bSDavid du Colombier }
13309ef1f84bSDavid du Colombier i++; /* skip first element for . itself */
13319ef1f84bSDavid du Colombier if(tab==0 || i>=ntab)
13329ef1f84bSDavid du Colombier return -1;
13339ef1f84bSDavid du Colombier tab += i;
13349ef1f84bSDavid du Colombier qid = tab->qid;
13359ef1f84bSDavid du Colombier qid.path &= ~Qdir;
13369ef1f84bSDavid du Colombier qid.vers = 0;
13379ef1f84bSDavid du Colombier devdir(c, qid, tab->name, tab->length, eve, tab->perm, dp);
13389ef1f84bSDavid du Colombier return 1;
13399ef1f84bSDavid du Colombier }
13409ef1f84bSDavid du Colombier
13419ef1f84bSDavid du Colombier static int
Gfmt(Fmt * f)13429ef1f84bSDavid du Colombier Gfmt(Fmt* f)
13439ef1f84bSDavid du Colombier {
13449ef1f84bSDavid du Colombier Gas *g;
13459ef1f84bSDavid du Colombier
13469ef1f84bSDavid du Colombier g = va_arg(f->args, Gas*);
13479ef1f84bSDavid du Colombier switch(g->spc){
13489ef1f84bSDavid du Colombier case Rsysmem:
13499ef1f84bSDavid du Colombier case Rsysio:
13509ef1f84bSDavid du Colombier case Rembed:
13519ef1f84bSDavid du Colombier case Rsmbus:
13529ef1f84bSDavid du Colombier case Rcmos:
13539ef1f84bSDavid du Colombier case Rpcibar:
13549ef1f84bSDavid du Colombier case Ripmi:
13559ef1f84bSDavid du Colombier fmtprint(f, "[%s ", acpiregstr(g->spc));
13569ef1f84bSDavid du Colombier break;
13579ef1f84bSDavid du Colombier case Rpcicfg:
13589ef1f84bSDavid du Colombier fmtprint(f, "[pci ");
13599ef1f84bSDavid du Colombier fmtprint(f, "dev %#ulx ", (ulong)(g->addr >> 32) & 0xFFFF);
13609ef1f84bSDavid du Colombier fmtprint(f, "fn %#ulx ", (ulong)(g->addr & 0xFFFF0000) >> 16);
13619ef1f84bSDavid du Colombier fmtprint(f, "adr %#ulx ", (ulong)(g->addr &0xFFFF));
13629ef1f84bSDavid du Colombier break;
13639ef1f84bSDavid du Colombier case Rfixedhw:
13649ef1f84bSDavid du Colombier fmtprint(f, "[hw ");
13659ef1f84bSDavid du Colombier break;
13669ef1f84bSDavid du Colombier default:
13679ef1f84bSDavid du Colombier fmtprint(f, "[spc=%#ux ", g->spc);
13689ef1f84bSDavid du Colombier }
13699ef1f84bSDavid du Colombier return fmtprint(f, "off %d len %d addr %#ullx sz%d]",
13709ef1f84bSDavid du Colombier g->off, g->len, g->addr, g->accsz);
13719ef1f84bSDavid du Colombier }
13729ef1f84bSDavid du Colombier
13739ef1f84bSDavid du Colombier static uint
getbanked(int ra,int rb,int sz)13749ef1f84bSDavid du Colombier getbanked(int ra, int rb, int sz)
13759ef1f84bSDavid du Colombier {
13769ef1f84bSDavid du Colombier uint r;
13779ef1f84bSDavid du Colombier
13789ef1f84bSDavid du Colombier r = 0;
13799ef1f84bSDavid du Colombier switch(sz){
13809ef1f84bSDavid du Colombier case 1:
13819ef1f84bSDavid du Colombier if(ra != 0)
13829ef1f84bSDavid du Colombier r |= inb(ra);
13839ef1f84bSDavid du Colombier if(rb != 0)
13849ef1f84bSDavid du Colombier r |= inb(rb);
13859ef1f84bSDavid du Colombier break;
13869ef1f84bSDavid du Colombier case 2:
13879ef1f84bSDavid du Colombier if(ra != 0)
13889ef1f84bSDavid du Colombier r |= ins(ra);
13899ef1f84bSDavid du Colombier if(rb != 0)
13909ef1f84bSDavid du Colombier r |= ins(rb);
13919ef1f84bSDavid du Colombier break;
13929ef1f84bSDavid du Colombier case 4:
13939ef1f84bSDavid du Colombier if(ra != 0)
13949ef1f84bSDavid du Colombier r |= inl(ra);
13959ef1f84bSDavid du Colombier if(rb != 0)
13969ef1f84bSDavid du Colombier r |= inl(rb);
13979ef1f84bSDavid du Colombier break;
13989ef1f84bSDavid du Colombier default:
13999ef1f84bSDavid du Colombier print("getbanked: wrong size\n");
14009ef1f84bSDavid du Colombier }
14019ef1f84bSDavid du Colombier return r;
14029ef1f84bSDavid du Colombier }
14039ef1f84bSDavid du Colombier
14049ef1f84bSDavid du Colombier static uint
setbanked(int ra,int rb,int sz,int v)14059ef1f84bSDavid du Colombier setbanked(int ra, int rb, int sz, int v)
14069ef1f84bSDavid du Colombier {
14079ef1f84bSDavid du Colombier uint r;
14089ef1f84bSDavid du Colombier
14099ef1f84bSDavid du Colombier r = -1;
14109ef1f84bSDavid du Colombier switch(sz){
14119ef1f84bSDavid du Colombier case 1:
14129ef1f84bSDavid du Colombier if(ra != 0)
14139ef1f84bSDavid du Colombier outb(ra, v);
14149ef1f84bSDavid du Colombier if(rb != 0)
14159ef1f84bSDavid du Colombier outb(rb, v);
14169ef1f84bSDavid du Colombier break;
14179ef1f84bSDavid du Colombier case 2:
14189ef1f84bSDavid du Colombier if(ra != 0)
14199ef1f84bSDavid du Colombier outs(ra, v);
14209ef1f84bSDavid du Colombier if(rb != 0)
14219ef1f84bSDavid du Colombier outs(rb, v);
14229ef1f84bSDavid du Colombier break;
14239ef1f84bSDavid du Colombier case 4:
14249ef1f84bSDavid du Colombier if(ra != 0)
14259ef1f84bSDavid du Colombier outl(ra, v);
14269ef1f84bSDavid du Colombier if(rb != 0)
14279ef1f84bSDavid du Colombier outl(rb, v);
14289ef1f84bSDavid du Colombier break;
14299ef1f84bSDavid du Colombier default:
14309ef1f84bSDavid du Colombier print("setbanked: wrong size\n");
14319ef1f84bSDavid du Colombier }
14329ef1f84bSDavid du Colombier return r;
14339ef1f84bSDavid du Colombier }
14349ef1f84bSDavid du Colombier
14359ef1f84bSDavid du Colombier static uint
getpm1ctl(void)14369ef1f84bSDavid du Colombier getpm1ctl(void)
14379ef1f84bSDavid du Colombier {
14389ef1f84bSDavid du Colombier return getbanked(fadt.pm1acntblk, fadt.pm1bcntblk, fadt.pm1cntlen);
14399ef1f84bSDavid du Colombier }
14409ef1f84bSDavid du Colombier
14419ef1f84bSDavid du Colombier static void
setpm1sts(uint v)14429ef1f84bSDavid du Colombier setpm1sts(uint v)
14439ef1f84bSDavid du Colombier {
14449ef1f84bSDavid du Colombier DBG("acpi: setpm1sts %#ux\n", v);
14459ef1f84bSDavid du Colombier setbanked(fadt.pm1aevtblk, fadt.pm1bevtblk, fadt.pm1evtlen/2, v);
14469ef1f84bSDavid du Colombier }
14479ef1f84bSDavid du Colombier
14489ef1f84bSDavid du Colombier static uint
getpm1sts(void)14499ef1f84bSDavid du Colombier getpm1sts(void)
14509ef1f84bSDavid du Colombier {
14519ef1f84bSDavid du Colombier return getbanked(fadt.pm1aevtblk, fadt.pm1bevtblk, fadt.pm1evtlen/2);
14529ef1f84bSDavid du Colombier }
14539ef1f84bSDavid du Colombier
14549ef1f84bSDavid du Colombier static uint
getpm1en(void)14559ef1f84bSDavid du Colombier getpm1en(void)
14569ef1f84bSDavid du Colombier {
14579ef1f84bSDavid du Colombier int sz;
14589ef1f84bSDavid du Colombier
14599ef1f84bSDavid du Colombier sz = fadt.pm1evtlen/2;
14609ef1f84bSDavid du Colombier return getbanked(fadt.pm1aevtblk+sz, fadt.pm1bevtblk+sz, sz);
14619ef1f84bSDavid du Colombier }
14629ef1f84bSDavid du Colombier
14639ef1f84bSDavid du Colombier static int
getgpeen(int n)14649ef1f84bSDavid du Colombier getgpeen(int n)
14659ef1f84bSDavid du Colombier {
14669ef1f84bSDavid du Colombier return inb(gpes[n].enio) & 1<<gpes[n].enbit;
14679ef1f84bSDavid du Colombier }
14689ef1f84bSDavid du Colombier
14699ef1f84bSDavid du Colombier static void
setgpeen(int n,uint v)14709ef1f84bSDavid du Colombier setgpeen(int n, uint v)
14719ef1f84bSDavid du Colombier {
14729ef1f84bSDavid du Colombier int old;
14739ef1f84bSDavid du Colombier
14749ef1f84bSDavid du Colombier DBG("acpi: setgpe %d %d\n", n, v);
14759ef1f84bSDavid du Colombier old = inb(gpes[n].enio);
14769ef1f84bSDavid du Colombier if(v)
14779ef1f84bSDavid du Colombier outb(gpes[n].enio, old | 1<<gpes[n].enbit);
14789ef1f84bSDavid du Colombier else
14799ef1f84bSDavid du Colombier outb(gpes[n].enio, old & ~(1<<gpes[n].enbit));
14809ef1f84bSDavid du Colombier }
14819ef1f84bSDavid du Colombier
14829ef1f84bSDavid du Colombier static void
clrgpests(int n)14839ef1f84bSDavid du Colombier clrgpests(int n)
14849ef1f84bSDavid du Colombier {
14859ef1f84bSDavid du Colombier outb(gpes[n].stsio, 1<<gpes[n].stsbit);
14869ef1f84bSDavid du Colombier }
14879ef1f84bSDavid du Colombier
14889ef1f84bSDavid du Colombier static uint
getgpests(int n)14899ef1f84bSDavid du Colombier getgpests(int n)
14909ef1f84bSDavid du Colombier {
14919ef1f84bSDavid du Colombier return inb(gpes[n].stsio) & 1<<gpes[n].stsbit;
14929ef1f84bSDavid du Colombier }
14939ef1f84bSDavid du Colombier
14949ef1f84bSDavid du Colombier static void
acpiintr(Ureg *,void *)14959ef1f84bSDavid du Colombier acpiintr(Ureg*, void*)
14969ef1f84bSDavid du Colombier {
14979ef1f84bSDavid du Colombier int i;
14989ef1f84bSDavid du Colombier uint sts, en;
14999ef1f84bSDavid du Colombier
15009ef1f84bSDavid du Colombier print("acpi: intr\n");
15019ef1f84bSDavid du Colombier
15029ef1f84bSDavid du Colombier for(i = 0; i < ngpes; i++)
15039ef1f84bSDavid du Colombier if(getgpests(i)){
15049ef1f84bSDavid du Colombier print("gpe %d on\n", i);
15059ef1f84bSDavid du Colombier en = getgpeen(i);
15069ef1f84bSDavid du Colombier setgpeen(i, 0);
15079ef1f84bSDavid du Colombier clrgpests(i);
15089ef1f84bSDavid du Colombier if(en != 0)
15099ef1f84bSDavid du Colombier print("acpiitr: calling gpe %d\n", i);
15109ef1f84bSDavid du Colombier // queue gpe for calling gpe->ho in the
15119ef1f84bSDavid du Colombier // aml process.
15129ef1f84bSDavid du Colombier // enable it again when it returns.
15139ef1f84bSDavid du Colombier }
15149ef1f84bSDavid du Colombier sts = getpm1sts();
15159ef1f84bSDavid du Colombier en = getpm1en();
15169ef1f84bSDavid du Colombier print("acpiitr: pm1sts %#ux pm1en %#ux\n", sts, en);
15179ef1f84bSDavid du Colombier if(sts&en)
15189ef1f84bSDavid du Colombier print("have enabled events\n");
15199ef1f84bSDavid du Colombier if(sts&1)
15209ef1f84bSDavid du Colombier print("power button\n");
15219ef1f84bSDavid du Colombier // XXX serve other interrupts here.
15229ef1f84bSDavid du Colombier setpm1sts(sts);
15239ef1f84bSDavid du Colombier }
15249ef1f84bSDavid du Colombier
15259ef1f84bSDavid du Colombier static void
initgpes(void)15269ef1f84bSDavid du Colombier initgpes(void)
15279ef1f84bSDavid du Colombier {
15289ef1f84bSDavid du Colombier int i, n0, n1;
15299ef1f84bSDavid du Colombier
15309ef1f84bSDavid du Colombier n0 = fadt.gpe0blklen/2;
15319ef1f84bSDavid du Colombier n1 = fadt.gpe1blklen/2;
15329ef1f84bSDavid du Colombier ngpes = n0 + n1;
15339ef1f84bSDavid du Colombier gpes = mallocz(sizeof(Gpe) * ngpes, 1);
15349ef1f84bSDavid du Colombier for(i = 0; i < n0; i++){
15359ef1f84bSDavid du Colombier gpes[i].nb = i;
15369ef1f84bSDavid du Colombier gpes[i].stsbit = i&7;
15379ef1f84bSDavid du Colombier gpes[i].stsio = fadt.gpe0blk + (i>>3);
15389ef1f84bSDavid du Colombier gpes[i].enbit = (n0 + i)&7;
15399ef1f84bSDavid du Colombier gpes[i].enio = fadt.gpe0blk + ((n0 + i)>>3);
15409ef1f84bSDavid du Colombier }
15419ef1f84bSDavid du Colombier for(i = 0; i + n0 < ngpes; i++){
15429ef1f84bSDavid du Colombier gpes[i + n0].nb = fadt.gp1base + i;
15439ef1f84bSDavid du Colombier gpes[i + n0].stsbit = i&7;
15449ef1f84bSDavid du Colombier gpes[i + n0].stsio = fadt.gpe1blk + (i>>3);
15459ef1f84bSDavid du Colombier gpes[i + n0].enbit = (n1 + i)&7;
15469ef1f84bSDavid du Colombier gpes[i + n0].enio = fadt.gpe1blk + ((n1 + i)>>3);
15479ef1f84bSDavid du Colombier }
15489ef1f84bSDavid du Colombier for(i = 0; i < ngpes; i++){
15499ef1f84bSDavid du Colombier setgpeen(i, 0);
15509ef1f84bSDavid du Colombier clrgpests(i);
15519ef1f84bSDavid du Colombier }
15529ef1f84bSDavid du Colombier }
15539ef1f84bSDavid du Colombier
15549ef1f84bSDavid du Colombier static void
acpiioalloc(uint addr,int len)15559ef1f84bSDavid du Colombier acpiioalloc(uint addr, int len)
15569ef1f84bSDavid du Colombier {
15579ef1f84bSDavid du Colombier if(addr != 0)
15589ef1f84bSDavid du Colombier ioalloc(addr, len, 0, "acpi");
15599ef1f84bSDavid du Colombier }
15609ef1f84bSDavid du Colombier
15619ef1f84bSDavid du Colombier int
acpiinit(void)15629ef1f84bSDavid du Colombier acpiinit(void)
15639ef1f84bSDavid du Colombier {
15649ef1f84bSDavid du Colombier if(fadt.smicmd == 0){
15659ef1f84bSDavid du Colombier fmtinstall('G', Gfmt);
15669ef1f84bSDavid du Colombier acpirsdptr();
15679ef1f84bSDavid du Colombier if(fadt.smicmd == 0)
15689ef1f84bSDavid du Colombier return -1;
15699ef1f84bSDavid du Colombier }
15709ef1f84bSDavid du Colombier return 0;
15719ef1f84bSDavid du Colombier }
15729ef1f84bSDavid du Colombier
15739ef1f84bSDavid du Colombier static Chan*
acpiattach(char * spec)15749ef1f84bSDavid du Colombier acpiattach(char *spec)
15759ef1f84bSDavid du Colombier {
15769ef1f84bSDavid du Colombier int i;
15779ef1f84bSDavid du Colombier
15789ef1f84bSDavid du Colombier /*
15799ef1f84bSDavid du Colombier * This was written for the stock kernel.
15809ef1f84bSDavid du Colombier * This code must use 64bit registers to be acpi ready in nix.
15819ef1f84bSDavid du Colombier * Besides, we mostly want the locality and affinity tables.
15829ef1f84bSDavid du Colombier */
15839ef1f84bSDavid du Colombier if(1 || acpiinit() < 0)
15849ef1f84bSDavid du Colombier error("acpi not enabled");
15859ef1f84bSDavid du Colombier
15869ef1f84bSDavid du Colombier /*
15879ef1f84bSDavid du Colombier * should use fadt->xpm* and fadt->xgpe* registers for 64 bits.
15889ef1f84bSDavid du Colombier * We are not ready in this kernel for that.
15899ef1f84bSDavid du Colombier */
15909ef1f84bSDavid du Colombier DBG("acpi io alloc\n");
15919ef1f84bSDavid du Colombier acpiioalloc(fadt.smicmd, 1);
15929ef1f84bSDavid du Colombier acpiioalloc(fadt.pm1aevtblk, fadt.pm1evtlen);
15939ef1f84bSDavid du Colombier acpiioalloc(fadt.pm1bevtblk, fadt.pm1evtlen );
15949ef1f84bSDavid du Colombier acpiioalloc(fadt.pm1acntblk, fadt.pm1cntlen);
15959ef1f84bSDavid du Colombier acpiioalloc(fadt.pm1bcntblk, fadt.pm1cntlen);
15969ef1f84bSDavid du Colombier acpiioalloc(fadt.pm2cntblk, fadt.pm2cntlen);
15979ef1f84bSDavid du Colombier acpiioalloc(fadt.pmtmrblk, fadt.pmtmrlen);
15989ef1f84bSDavid du Colombier acpiioalloc(fadt.gpe0blk, fadt.gpe0blklen);
15999ef1f84bSDavid du Colombier acpiioalloc(fadt.gpe1blk, fadt.gpe1blklen);
16009ef1f84bSDavid du Colombier
16019ef1f84bSDavid du Colombier DBG("acpi init gpes\n");
16029ef1f84bSDavid du Colombier initgpes();
16039ef1f84bSDavid du Colombier
16049ef1f84bSDavid du Colombier /*
16059ef1f84bSDavid du Colombier * This starts ACPI, which may require we handle
16069ef1f84bSDavid du Colombier * power mgmt events ourselves. Use with care.
16079ef1f84bSDavid du Colombier */
16089ef1f84bSDavid du Colombier DBG("acpi starting\n");
16099ef1f84bSDavid du Colombier outb(fadt.smicmd, fadt.acpienable);
16109ef1f84bSDavid du Colombier for(i = 0; i < 10; i++)
16119ef1f84bSDavid du Colombier if(getpm1ctl() & Pm1SciEn)
16129ef1f84bSDavid du Colombier break;
16139ef1f84bSDavid du Colombier if(i == 10)
16149ef1f84bSDavid du Colombier error("acpi: failed to enable\n");
16159ef1f84bSDavid du Colombier if(fadt.sciint != 0)
16169ef1f84bSDavid du Colombier intrenable(fadt.sciint, acpiintr, 0, BUSUNKNOWN, "acpi");
16179ef1f84bSDavid du Colombier return devattach(L'α', spec);
16189ef1f84bSDavid du Colombier }
16199ef1f84bSDavid du Colombier
16209ef1f84bSDavid du Colombier static Walkqid*
acpiwalk(Chan * c,Chan * nc,char ** name,int nname)16219ef1f84bSDavid du Colombier acpiwalk(Chan *c, Chan *nc, char **name, int nname)
16229ef1f84bSDavid du Colombier {
16239ef1f84bSDavid du Colombier return devwalk(c, nc, name, nname, acpidir, nelem(acpidir), acpigen);
16249ef1f84bSDavid du Colombier }
16259ef1f84bSDavid du Colombier
16269ef1f84bSDavid du Colombier static long
acpistat(Chan * c,uchar * dp,long n)16279ef1f84bSDavid du Colombier acpistat(Chan *c, uchar *dp, long n)
16289ef1f84bSDavid du Colombier {
16299ef1f84bSDavid du Colombier return devstat(c, dp, n, acpidir, nelem(acpidir), acpigen);
16309ef1f84bSDavid du Colombier }
16319ef1f84bSDavid du Colombier
16329ef1f84bSDavid du Colombier static Chan*
acpiopen(Chan * c,int omode)16339ef1f84bSDavid du Colombier acpiopen(Chan *c, int omode)
16349ef1f84bSDavid du Colombier {
16359ef1f84bSDavid du Colombier return devopen(c, omode, acpidir, nelem(acpidir), acpigen);
16369ef1f84bSDavid du Colombier }
16379ef1f84bSDavid du Colombier
16389ef1f84bSDavid du Colombier static void
acpiclose(Chan *)16399ef1f84bSDavid du Colombier acpiclose(Chan *)
16409ef1f84bSDavid du Colombier {
16419ef1f84bSDavid du Colombier }
16429ef1f84bSDavid du Colombier
16439ef1f84bSDavid du Colombier static char*ttext;
16449ef1f84bSDavid du Colombier static int tlen;
16459ef1f84bSDavid du Colombier
16469ef1f84bSDavid du Colombier static long
acpiread(Chan * c,void * a,long n,vlong off)16479ef1f84bSDavid du Colombier acpiread(Chan *c, void *a, long n, vlong off)
16489ef1f84bSDavid du Colombier {
16499ef1f84bSDavid du Colombier long q;
16509ef1f84bSDavid du Colombier Atable *t;
16519ef1f84bSDavid du Colombier char *ns, *s, *e, *ntext;
16529ef1f84bSDavid du Colombier
16539ef1f84bSDavid du Colombier q = c->qid.path;
16549ef1f84bSDavid du Colombier switch(q){
16559ef1f84bSDavid du Colombier case Qdir:
16569ef1f84bSDavid du Colombier return devdirread(c, a, n, acpidir, nelem(acpidir), acpigen);
16579ef1f84bSDavid du Colombier case Qtbl:
16589ef1f84bSDavid du Colombier if(ttext == nil){
16599ef1f84bSDavid du Colombier tlen = 1024;
16609ef1f84bSDavid du Colombier ttext = malloc(tlen);
16619ef1f84bSDavid du Colombier if(ttext == nil){
16629ef1f84bSDavid du Colombier print("acpi: no memory\n");
16639ef1f84bSDavid du Colombier return 0;
16649ef1f84bSDavid du Colombier }
16659ef1f84bSDavid du Colombier s = ttext;
16669ef1f84bSDavid du Colombier e = ttext + tlen;
16679ef1f84bSDavid du Colombier strcpy(s, "no tables\n");
16689ef1f84bSDavid du Colombier for(t = tfirst; t != nil; t = t->next){
16699ef1f84bSDavid du Colombier ns = seprinttable(s, e, t);
16709ef1f84bSDavid du Colombier while(ns == e - 1){
16719ef1f84bSDavid du Colombier DBG("acpiread: allocated %d\n", tlen*2);
16729ef1f84bSDavid du Colombier ntext = realloc(ttext, tlen*2);
16739ef1f84bSDavid du Colombier if(ntext == nil)
16749ef1f84bSDavid du Colombier panic("acpi: no memory\n");
16759ef1f84bSDavid du Colombier s = ntext + (ttext - s);
16769ef1f84bSDavid du Colombier ttext = ntext;
16779ef1f84bSDavid du Colombier tlen *= 2;
16789ef1f84bSDavid du Colombier e = ttext + tlen;
16799ef1f84bSDavid du Colombier ns = seprinttable(s, e, t);
16809ef1f84bSDavid du Colombier }
16819ef1f84bSDavid du Colombier s = ns;
16829ef1f84bSDavid du Colombier }
16839ef1f84bSDavid du Colombier
16849ef1f84bSDavid du Colombier }
16859ef1f84bSDavid du Colombier return readstr(off, a, n, ttext);
16869ef1f84bSDavid du Colombier case Qio:
16879ef1f84bSDavid du Colombier if(reg == nil)
16889ef1f84bSDavid du Colombier error("region not configured");
16899ef1f84bSDavid du Colombier return regio(reg, a, n, off, 0);
16909ef1f84bSDavid du Colombier }
16919ef1f84bSDavid du Colombier error(Eperm);
16929ef1f84bSDavid du Colombier return -1;
16939ef1f84bSDavid du Colombier }
16949ef1f84bSDavid du Colombier
16959ef1f84bSDavid du Colombier static long
acpiwrite(Chan * c,void * a,long n,vlong off)16969ef1f84bSDavid du Colombier acpiwrite(Chan *c, void *a, long n, vlong off)
16979ef1f84bSDavid du Colombier {
16989ef1f84bSDavid du Colombier Cmdtab *ct;
16999ef1f84bSDavid du Colombier Cmdbuf *cb;
17009ef1f84bSDavid du Colombier Reg *r;
17019ef1f84bSDavid du Colombier uint rno, fun, dev, bus, i;
17029ef1f84bSDavid du Colombier
17039ef1f84bSDavid du Colombier if(c->qid.path == Qio){
17049ef1f84bSDavid du Colombier if(reg == nil)
17059ef1f84bSDavid du Colombier error("region not configured");
17069ef1f84bSDavid du Colombier return regio(reg, a, n, off, 1);
17079ef1f84bSDavid du Colombier }
17089ef1f84bSDavid du Colombier if(c->qid.path != Qctl)
17099ef1f84bSDavid du Colombier error(Eperm);
17109ef1f84bSDavid du Colombier
17119ef1f84bSDavid du Colombier cb = parsecmd(a, n);
17129ef1f84bSDavid du Colombier if(waserror()){
17139ef1f84bSDavid du Colombier free(cb);
17149ef1f84bSDavid du Colombier nexterror();
17159ef1f84bSDavid du Colombier }
17169ef1f84bSDavid du Colombier ct = lookupcmd(cb, ctls, nelem(ctls));
17179ef1f84bSDavid du Colombier DBG("acpi ctl %s\n", cb->f[0]);
17189ef1f84bSDavid du Colombier switch(ct->index){
17199ef1f84bSDavid du Colombier case CMregion:
17209ef1f84bSDavid du Colombier r = reg;
17219ef1f84bSDavid du Colombier if(r == nil){
17229ef1f84bSDavid du Colombier r = smalloc(sizeof(Reg));
17239ef1f84bSDavid du Colombier r->name = nil;
17249ef1f84bSDavid du Colombier }
17259ef1f84bSDavid du Colombier kstrdup(&r->name, cb->f[1]);
17269ef1f84bSDavid du Colombier r->spc = acpiregid(cb->f[2]);
17279ef1f84bSDavid du Colombier if(r->spc < 0){
17289ef1f84bSDavid du Colombier free(r);
17299ef1f84bSDavid du Colombier reg = nil;
17309ef1f84bSDavid du Colombier error("bad region type");
17319ef1f84bSDavid du Colombier }
17329ef1f84bSDavid du Colombier if(r->spc == Rpcicfg || r->spc == Rpcibar){
17339ef1f84bSDavid du Colombier rno = r->base>>Rpciregshift & Rpciregmask;
17349ef1f84bSDavid du Colombier fun = r->base>>Rpcifunshift & Rpcifunmask;
17359ef1f84bSDavid du Colombier dev = r->base>>Rpcidevshift & Rpcidevmask;
17369ef1f84bSDavid du Colombier bus = r->base>>Rpcibusshift & Rpcibusmask;
17379ef1f84bSDavid du Colombier r->tbdf = MKBUS(BusPCI, bus, dev, fun);
17389ef1f84bSDavid du Colombier r->base = rno; /* register ~ our base addr */
17399ef1f84bSDavid du Colombier }
17409ef1f84bSDavid du Colombier r->base = strtoull(cb->f[3], nil, 0);
17419ef1f84bSDavid du Colombier r->len = strtoull(cb->f[4], nil, 0);
17429ef1f84bSDavid du Colombier r->accsz = strtoul(cb->f[5], nil, 0);
17439ef1f84bSDavid du Colombier if(r->accsz < 1 || r->accsz > 4){
17449ef1f84bSDavid du Colombier free(r);
17459ef1f84bSDavid du Colombier reg = nil;
17469ef1f84bSDavid du Colombier error("bad region access size");
17479ef1f84bSDavid du Colombier }
17489ef1f84bSDavid du Colombier reg = r;
17499ef1f84bSDavid du Colombier DBG("region %s %s %llux %llux sz%d",
17509ef1f84bSDavid du Colombier r->name, acpiregstr(r->spc), r->base, r->len, r->accsz);
17519ef1f84bSDavid du Colombier break;
17529ef1f84bSDavid du Colombier case CMgpe:
17539ef1f84bSDavid du Colombier i = strtoul(cb->f[1], nil, 0);
17549ef1f84bSDavid du Colombier if(i >= ngpes)
17559ef1f84bSDavid du Colombier error("gpe out of range");
17569ef1f84bSDavid du Colombier kstrdup(&gpes[i].obj, cb->f[2]);
17579ef1f84bSDavid du Colombier DBG("gpe %d %s\n", i, gpes[i].obj);
17589ef1f84bSDavid du Colombier setgpeen(i, 1);
17599ef1f84bSDavid du Colombier break;
17609ef1f84bSDavid du Colombier default:
17619ef1f84bSDavid du Colombier panic("acpi: unknown ctl");
17629ef1f84bSDavid du Colombier }
17639ef1f84bSDavid du Colombier poperror();
17649ef1f84bSDavid du Colombier free(cb);
17659ef1f84bSDavid du Colombier return n;
17669ef1f84bSDavid du Colombier }
17679ef1f84bSDavid du Colombier
17689ef1f84bSDavid du Colombier
17699ef1f84bSDavid du Colombier Dev acpidevtab = {
17709ef1f84bSDavid du Colombier L'α',
17719ef1f84bSDavid du Colombier "acpi",
17729ef1f84bSDavid du Colombier
17739ef1f84bSDavid du Colombier devreset,
17749ef1f84bSDavid du Colombier devinit,
17759ef1f84bSDavid du Colombier devshutdown,
17769ef1f84bSDavid du Colombier acpiattach,
17779ef1f84bSDavid du Colombier acpiwalk,
17789ef1f84bSDavid du Colombier acpistat,
17799ef1f84bSDavid du Colombier acpiopen,
17809ef1f84bSDavid du Colombier devcreate,
17819ef1f84bSDavid du Colombier acpiclose,
17829ef1f84bSDavid du Colombier acpiread,
17839ef1f84bSDavid du Colombier devbread,
17849ef1f84bSDavid du Colombier acpiwrite,
17859ef1f84bSDavid du Colombier devbwrite,
17869ef1f84bSDavid du Colombier devremove,
17879ef1f84bSDavid du Colombier devwstat,
17889ef1f84bSDavid du Colombier };
1789