Start putting together ACPI for guests.
[akaros.git] / kern / drivers / dev / acpi.c
index 6a66287..d5aa3a3 100644 (file)
 #include <arch/pci.h>
 #endif
 
+struct dev acpidevtab;
+
+static char *devname(void)
+{
+       return acpidevtab.name;
+}
+
 /*
  * ACPI 4.0 Support.
  * Still WIP.
@@ -57,6 +64,7 @@ static struct dirtab acpidir[] = {
        {"acpipretty", {Qpretty}, 0, 0444},
        {"ioapic", {Qioapic}, 0, 0444},
        {"apic", {Qapic}, 0, 0444},
+       {"raw", {Qraw}, 0, 0444},
 };
 
 /*
@@ -86,7 +94,7 @@ static struct Xsdt *xsdt;             /* XSDT table */
 static struct Atable *tfirst;  /* loaded DSDT/SSDT/... tables */
 static struct Atable *tlast;   /* pointer to last table */
 struct Madt *apics;                            /* APIC info */
-static struct Srat *srat;              /* System resource affinity, used by physalloc */
+struct Srat *srat;                             /* System resource affinity, used by physalloc */
 static struct Slit *slit;              /* System locality information table used by the scheduler */
 static struct Msct *msct;              /* Maximum system characteristics table */
 static struct Reg *reg;                        /* region used for I/O */
@@ -340,7 +348,7 @@ static long regio(struct Reg *r, void *p, uint32_t len, uintptr_t off, int iswr)
                        if (r->p == NULL)
                                r->p = KADDR_NOCHECK(r->base);
                        if (r->p == NULL)
-                               error("regio: vmap/KADDR failed");
+                               error(EFAIL, "regio: vmap/KADDR failed");
                        rp = (uintptr_t) r->p + off;
                        rio = memio;
                        break;
@@ -360,7 +368,7 @@ static long regio(struct Reg *r, void *p, uint32_t len, uintptr_t off, int iswr)
                case Ripmi:
                case Rfixedhw:
                        printd("regio: reg %s not supported\n", acpiregstr(r->spc));
-                       error("region not supported");
+                       error(EFAIL, "region not supported");
        }
        if (iswr)
                regcpy(&rio, rp, &memio, (uintptr_t) p, len, r->accsz);
@@ -490,6 +498,7 @@ static char *dumpfadt(char *start, char *end, struct Fadt *fp)
                return NULL;
        }
 
+       start = seprintf(start, end, "acpi: FADT@%p\n", fp);
        start = seprintf(start, end, "acpi: fadt: facs: $%p\n", fp->facs);
        start = seprintf(start, end, "acpi: fadt: dsdt: $%p\n", fp->dsdt);
        start = seprintf(start, end, "acpi: fadt: pmprofile: $%p\n", fp->pmprofile);
@@ -676,7 +685,7 @@ static struct Atable *acpimsct(uint8_t * p, int len)
 
 static char *dumpsrat(char *start, char *end, struct Srat *st)
 {
-       start = seprintf(start, end, "acpi: srat:\n");
+       start = seprintf(start, end, "acpi: START@%p:\n", st);
        for (; st != NULL; st = st->next)
                switch (st->type) {
                        case SRlapic:
@@ -846,7 +855,7 @@ int pickcore(int mycolor, int index)
        if (slit == NULL) {
                return 0;
        }
-       ncorepercol = num_cpus / slit->rowlen;
+       ncorepercol = num_cores / slit->rowlen;
        color = slit->e[mycolor][index / ncorepercol].dom;
        return color * ncorepercol + index % ncorepercol;
 }
@@ -877,8 +886,8 @@ static char *dumpmadt(char *start, char *end, struct Madt *apics)
        struct Apicst *st;
 
        start =
-               seprintf(start, end, "acpi: madt lapic paddr %llux pcat %d:\n",
-                                apics->lapicpa, apics->pcat);
+               seprintf(start, end, "acpi: MADT@%p: lapic paddr %p pcat %d:\n",
+                               apics, apics->lapicpa, apics->pcat);
        for (st = apics->st; st != NULL; st = st->next)
 
                switch (st->type) {
@@ -891,7 +900,7 @@ static char *dumpmadt(char *start, char *end, struct Madt *apics)
                        case ASiosapic:
                                start =
                                        seprintf(start, end,
-                                                        "\tioapic id %d addr %#llux ibase %d\n",
+                                                        "\tioapic id %d addr %p ibase %d\n",
                                                         st->ioapic.id, st->ioapic.addr, st->ioapic.ibase);
                                break;
                        case ASintovr:
@@ -1171,10 +1180,16 @@ static void acpirsdptr(void)
        uintptr_t sdtpa;
 
        if ((rsd = rsdsearch("RSD PTR ")) == NULL) {
+               printk("NO RSDP\n");
                return;
        }
 
+
        assert(sizeof(struct Sdthdr) == 36);
+       printd("/* RSDP */ struct Rsdp = {%08c, %x, %06c, %x, %p, %d, %p, %x}\n",
+              rsd->signature, rsd->rchecksum, rsd->oemid, rsd->revision,
+              *(uint32_t *)rsd->raddr, *(uint32_t *)rsd->length,
+              *(uint32_t *)rsd->xaddr, rsd->xchecksum);
 
        printd("acpi: RSD PTR@ %#p, physaddr $%p length %ud %#llux rev %d\n",
                   rsd, l32get(rsd->raddr), l32get(rsd->length),
@@ -1233,7 +1248,7 @@ acpigen(struct chan *c, char *unused_char_p_t, struct dirtab *tab, int ntab,
 
        if (i == DEVDOTDOT) {
                mkqid(&qid, Qdir, 0, QTDIR);
-               devdir(c, qid, ".", 0, eve, 0555, dp);
+               devdir(c, qid, devname(), 0, eve, 0555, dp);
                return 1;
        }
        i++;    /* skip first element for . itself */
@@ -1487,9 +1502,8 @@ static struct chan *acpiattach(char *spec)
         * This was written for the stock kernel.
         * This code must use 64 registers to be acpi ready in nix.
         */
-       if (acpiinit() < 0) {
-               error("no acpi");
-       }
+       if (acpiinit() < 0)
+               error(ENOSYS, "no acpi");
 
        /*
         * should use fadt->xpm* and fadt->xgpe* registers for 64 bits.
@@ -1516,10 +1530,10 @@ static struct chan *acpiattach(char *spec)
                if (getpm1ctl() & Pm1SciEn)
                        break;
        if (i == 10)
-               error("acpi: failed to enable\n");
+               error(EFAIL, "acpi: failed to enable\n");
 //  if(fadt.sciint != 0)
 //      intrenable(fadt.sciint, acpiintr, 0, BUSUNKNOWN, "acpi");
-       return devattach('a', spec);
+       return devattach(devname(), spec);
 }
 
 static struct walkqid *acpiwalk(struct chan *c, struct chan *nc, char **name,
@@ -1555,17 +1569,19 @@ static long acpiread(struct chan *c, void *a, long n, int64_t off)
                tlen = 32768;
                ttext = kzmalloc(tlen, 0);
        }
-       if (ttext == NULL) {
-               error("acpiread: no memory");
-       }
+       if (ttext == NULL)
+               error(ENOMEM, "acpiread: no memory");
        q = c->qid.path;
        switch (q) {
                case Qdir:
                        return devdirread(c, a, n, acpidir, ARRAY_SIZE(acpidir), acpigen);
+               case Qraw:
+                       return readmem(off, a, n, ttext, tlen);
+                       break;
                case Qtbl:
                        s = ttext;
                        e = ttext + tlen;
-                       strncpy(s, "no tables\n", sizeof(s));
+                       strlcpy(s, "no tables\n", tlen);
                        for (t = tfirst; t != NULL; t = t->next) {
                                ns = seprinttable(s, e, t);
                                while (ns == e - 1) {
@@ -1598,10 +1614,10 @@ static long acpiread(struct chan *c, void *a, long n, int64_t off)
                        return readstr(off, a, n, ttext);
                case Qio:
                        if (reg == NULL)
-                               error("region not configured");
+                               error(EFAIL, "region not configured");
                        return regio(reg, a, n, off, 0);
        }
-       error(Eperm);
+       error(EPERM, NULL);
        return -1;
 }
 
@@ -1615,11 +1631,11 @@ static long acpiwrite(struct chan *c, void *a, long n, int64_t off)
 
        if (c->qid.path == Qio) {
                if (reg == NULL)
-                       error("region not configured");
+                       error(EFAIL, "region not configured");
                return regio(reg, a, n, off, 1);
        }
        if (c->qid.path != Qctl)
-               error(Eperm);
+               error(EPERM, NULL);
 
        cb = parsecmd(a, n);
        if (waserror()) {
@@ -1640,7 +1656,7 @@ static long acpiwrite(struct chan *c, void *a, long n, int64_t off)
                        if (r->spc < 0) {
                                kfree(r);
                                reg = NULL;
-                               error("bad region type");
+                               error(EFAIL, "bad region type");
                        }
                        if (r->spc == Rpcicfg || r->spc == Rpcibar) {
                                rno = r->base >> Rpciregshift & Rpciregmask;
@@ -1660,7 +1676,7 @@ static long acpiwrite(struct chan *c, void *a, long n, int64_t off)
                        if (r->accsz < 1 || r->accsz > 4) {
                                kfree(r);
                                reg = NULL;
-                               error("bad region access size");
+                               error(EFAIL, "bad region access size");
                        }
                        reg = r;
                        printd("region %s %s %p %p sz%d",
@@ -1669,7 +1685,7 @@ static long acpiwrite(struct chan *c, void *a, long n, int64_t off)
                case CMgpe:
                        i = strtoul(cb->f[1], NULL, 0);
                        if (i >= ngpes)
-                               error("gpe out of range");
+                               error(ERANGE, "gpe out of range");
                        kstrdup(&gpes[i].obj, cb->f[2]);
                        setgpeen(i, 1);
                        break;
@@ -1682,7 +1698,6 @@ static long acpiwrite(struct chan *c, void *a, long n, int64_t off)
 }
 
 struct dev acpidevtab __devtab = {
-       'a',
        "acpi",
 
        devreset,