In qemu, it still shows the device as having zero bytes. But it does find it.
Change-Id: I81262b460a9cd43a848c1d782c109ec216afb795 Signed-off-by: Ronald G. Minnich <[email protected]> Signed-off-by: Fergus Simpson <[email protected]> --- kern/drivers/dev/Kbuild | 3 + kern/drivers/dev/sd.c | 700 +++++++++++++++++++++------------------ kern/drivers/dev/sdiahci.c | 810 +++++++++++++++++++++++---------------------- kern/drivers/dev/sdscsi.c | 76 +++-- kern/include/ahci.h | 6 +- kern/include/sd.h | 150 ++++----- 6 files changed, 918 insertions(+), 827 deletions(-) diff --git a/kern/drivers/dev/Kbuild b/kern/drivers/dev/Kbuild index 9ea2b05..d2e68f6 100644 --- a/kern/drivers/dev/Kbuild +++ b/kern/drivers/dev/Kbuild @@ -13,6 +13,9 @@ obj-y += proc.o obj-y += random.o obj-$(CONFIG_REGRESS) += regress.o obj-y += root.o +obj-y += sd.o +obj-y += sdscsi.o +obj-y += sdiahci.o obj-y += srv.o obj-y += version.o obj-$(CONFIG_DEVVARS) += vars.o diff --git a/kern/drivers/dev/sd.c b/kern/drivers/dev/sd.c index 412bc78..cc1960d 100644 --- a/kern/drivers/dev/sd.c +++ b/kern/drivers/dev/sd.c @@ -10,28 +10,42 @@ /* * Storage Device. */ -#include "../port/error.h" -#include "../port/lib.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "mem.h" -#include "u.h" -#include "ureg.h" -#include "../port/sd.h" +#include <vfs.h> + +#include <assert.h> +#include <cpio.h> +#include <error.h> +#include <ip.h> +#include <kfs.h> +#include <kmalloc.h> +#include <kref.h> +#include <pmap.h> +#include <slab.h> +#include <smp.h> +#include <stdio.h> +#include <string.h> + +#include <sd.h> extern struct dev sddevtab; -extern struct sdifc *sdifc[]; +struct sdifc sdiahciifc; + +/* In Plan 9, this array is auto-generated. That's almost certainly not + * necessary; + * we can use linker sets at some point, as we do elsewhere in Akaros. */ +struct sdifc *sdifc[] = { + &sdiahciifc, NULL, +}; + +static const char Echange[] = "media or partition has changed"; -static char Echange[] = "media or partition has changed"; +static const char devletters[] = + "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; -static char devletters[] = "0123456789" - "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +static struct sdev *devs[sizeof(devletters) - 1]; -static struct sdev *devs[sizeof devletters - 1]; -static qlock_t devslock; +static qlock_t devslock = QLOCK_INITIALIZER(devslock); enum { Rawcmd, @@ -90,7 +104,7 @@ void sdaddpart(struct sdunit *unit, char *name, uint64_t start, uint64_t end) * Check name not already used * and look for a free slot. */ - if (unit->part != nil) { + if (unit->part != NULL) { partno = -1; for (i = 0; i < unit->npart; i++) { pp = &unit->part[i]; @@ -99,31 +113,34 @@ void sdaddpart(struct sdunit *unit, char *name, uint64_t start, uint64_t end) partno = i; break; } - if (strcmp(name, pp->SDperm.name) == 0) { + if (strcmp(name, pp->sdperm.name) == 0) { if (pp->start == start && pp->end == end) return; - error(Ebadctl); + error(EINVAL, "%s: '%s' is not valid", __func__, name); } } } else { - if ((unit->part = malloc(sizeof(struct sdpart) * SDnpart)) == nil) - error(Enomem); + unit->part = kzmalloc(sizeof(struct sdpart) * SDnpart, 0); + if (unit->part == NULL) + error(ENOMEM, "%s: can't allocate %d bytes", __func__, + sizeof(struct sdpart) * SDnpart); unit->npart = SDnpart; partno = 0; } /* * If no free slot found then increase the - * array size (can't get here with unit->part == nil). + * array size (can't get here with unit->part == NULL). */ if (partno == -1) { if (unit->npart >= NPart) - error(Enomem); - if ((pp = malloc(sizeof(struct sdpart) * (unit->npart + SDnpart))) == - nil) - error(Enomem); + error(ENOMEM, "%s: no memory", __func__); + pp = kzmalloc(sizeof(struct sdpart) * (unit->npart + SDnpart), 0); + if (pp == NULL) + error(ENOMEM, "%s: Can't allocate space for %d partitions", + unit->npart + SDnpart); memmove(pp, unit->part, sizeof(struct sdpart) * unit->npart); - free(unit->part); + kfree(unit->part); unit->part = pp; partno = unit->npart; unit->npart += SDnpart; @@ -132,20 +149,22 @@ void sdaddpart(struct sdunit *unit, char *name, uint64_t start, uint64_t end) /* * Check size and extent are valid. */ - if (start > end || end > unit->sectors) - error(Eio); + if (start > end) + error(EINVAL, "%s: start %d > end %d", __func__, start, end); + if (end > unit->sectors) + error(EINVAL, "%s: end %d > number of sectors %d", __func__, end, + unit->sectors); pp = &unit->part[partno]; pp->start = start; pp->end = end; - kstrdup(&pp->SDperm.name, name); - kstrdup(&pp->SDperm.user, eve); - pp->SDperm.perm = 0640; + kstrdup(&pp->sdperm.name, name); + kstrdup(&pp->sdperm.user, eve); + pp->sdperm.perm = 0640; pp->valid = 1; } static void sddelpart(struct sdunit *unit, char *name) { - struct proc *up = externup(); int i; struct sdpart *pp; /* @@ -154,14 +173,17 @@ static void sddelpart(struct sdunit *unit, char *name) */ pp = unit->part; for (i = 0; i < unit->npart; i++) { - if (strcmp(name, pp->SDperm.name) == 0) + if (strcmp(name, pp->sdperm.name) == 0) break; pp++; } if (i >= unit->npart) - error(Ebadctl); - if (strcmp(up->user, pp->SDperm.user) && !iseve()) - error(Eperm); + error(EINVAL, "%s: %d > npart %d", __func__, i, unit->npart); + + /* TODO: Implement permission checking and raise errors as appropriate. */ + // if (strcmp(up->user, pp->SDperm.user) && !iseve()) + // error(Eperm); + pp->valid = 0; pp->vers++; } @@ -222,12 +244,13 @@ static int sdinitpart(struct sdunit *unit) * The gen functions patch it up. */ #if 0 - snprint(buf, sizeof buf, "%spart", unit->SDperm.name); - for(p = getconf(buf); p != nil; p = q){ - if(q = strchr(p, '/')) + snprintf(buf, sizeof(buf), "%spart", unit->sdperm.name); + for (p = getconf(buf); p != NULL; p = q) { + q = strchr(p, '/'); + if (q) *q++ = '\0'; - nf = tokenize(p, f, nelem(f)); - if(nf < 3) + nf = tokenize(p, f, ARRAY_SIZE(f)); + if (nf < 3) continue; start = strtoull(f[1], 0, 0); @@ -248,7 +271,7 @@ static int sdindex(int idno) char *p; p = strchr(devletters, idno); - if (p == nil) + if (p == NULL) return -1; return p - devletters; } @@ -259,11 +282,12 @@ static struct sdev *sdgetdev(int idno) int i; if ((i = sdindex(idno)) < 0) - return nil; + return NULL; qlock(&devslock); - if (sdev = devs[i]) - incref(&sdev->r); + sdev = devs[i]; + if (sdev) + kref_get(&sdev->r, 1); qunlock(&devslock); return sdev; } @@ -282,31 +306,33 @@ static struct sdunit *sdgetunit(struct sdev *sdev, int subno) qlock(&sdev->unitlock); if (subno > sdev->nunit) { qunlock(&sdev->unitlock); - return nil; + return NULL; } unit = sdev->unit[subno]; - if (unit == nil) { + if (unit == NULL) { /* * Probe the unit only once. This decision * may be a little severe and reviewed later. */ if (sdev->unitflg[subno]) { qunlock(&sdev->unitlock); - return nil; + return NULL; } - if ((unit = malloc(sizeof(struct sdunit))) == nil) { + unit = kzmalloc(sizeof(struct sdunit), 0); + if (unit == NULL) { qunlock(&sdev->unitlock); - return nil; + return NULL; } sdev->unitflg[subno] = 1; - snprint(buf, sizeof(buf), "%s%d", sdev->name, subno); - kstrdup(&unit->SDperm.name, buf); - kstrdup(&unit->SDperm.user, eve); - unit->SDperm.perm = 0555; + snprintf(buf, sizeof(buf), "%s%d", sdev->name, subno); + kstrdup(&unit->sdperm.name, buf); + kstrdup(&unit->sdperm.user, eve); + unit->sdperm.perm = 0555; unit->subno = subno; unit->dev = sdev; + qlock_init(&unit->ctl); if (sdev->enabled == 0 && sdev->ifc->enable) sdev->ifc->enable(sdev); @@ -319,8 +345,8 @@ static struct sdunit *sdgetunit(struct sdev *sdev, int subno) */ if (unit->dev->ifc->verify(unit) == 0) { qunlock(&sdev->unitlock); - free(unit); - return nil; + kfree(unit); + return NULL; } sdev->unit[subno] = unit; } @@ -336,8 +362,11 @@ static void sdreset(void) /* * Probe all known controller types and register any devices found. */ - for (i = 0; sdifc[i] != nil; i++) { - if (sdifc[i]->pnp == nil || (sdev = sdifc[i]->pnp()) == nil) + for (i = 0; sdifc[i] != NULL; i++) { + if (sdifc[i]->pnp == NULL) + continue; + sdev = sdifc[i]->pnp(); + if (sdev == NULL) continue; sdadddevs(sdev); } @@ -351,56 +380,48 @@ void sdadddevs(struct sdev *sdev) for (; sdev; sdev = next) { next = sdev->next; - sdev->unit = - (struct sdunit **)malloc(sdev->nunit * sizeof(struct sdunit *)); - sdev->unitflg = (int *)malloc(sdev->nunit * sizeof(int)); - if (sdev->unit == nil || sdev->unitflg == nil) { - print("sdadddevs: out of memory\n"); + sdev->unit = (struct sdunit **)kzmalloc( + sdev->nunit * sizeof(struct sdunit *), 0); + sdev->unitflg = (int *)kzmalloc(sdev->nunit * sizeof(int), 0); + if (sdev->unit == NULL || sdev->unitflg == NULL) { + printd("sdadddevs: out of memory\n"); giveup: - free(sdev->unit); - free(sdev->unitflg); + kfree(sdev->unit); + kfree(sdev->unitflg); if (sdev->ifc->clear) sdev->ifc->clear(sdev); - free(sdev); + kfree(sdev); continue; } id = sdindex(sdev->idno); if (id == -1) { - print("sdadddevs: bad id number %d (%C)\n", id, id); + printd("sdadddevs: bad id number %d (%C)\n", id, id); goto giveup; } qlock(&devslock); - for (i = 0; i < nelem(devs); i++) { - if (devs[j = (id + i) % nelem(devs)] == nil) { + for (i = 0; i < ARRAY_SIZE(devs); i++) { + j = (id + i) % ARRAY_SIZE(devs); + if (devs[j] == NULL) { sdev->idno = devletters[j]; devs[j] = sdev; - snprint(sdev->name, sizeof sdev->name, "sd%c", devletters[j]); + snprintf(sdev->name, sizeof(sdev->name), "sd%c", devletters[j]); break; } } qunlock(&devslock); - if (i == nelem(devs)) { - print("sdadddevs: out of device letters\n"); + if (i == ARRAY_SIZE(devs)) { + printd("sdadddevs: out of device letters\n"); goto giveup; } } } -// void -// sdrmdevs(SDev *sdev) -// { -// char buf[2]; -// -// snprint(buf, sizeof buf, "%c", sdev->idno); -// unconfigure(buf); -// } - void sdaddallconfs(void (*addconf)(struct sdunit *)) { int i, u; struct sdev *sdev; - for (i = 0; i < nelem(devs); i++) /* each controller */ + for (i = 0; i < ARRAY_SIZE(devs); i++) /* each controller */ for (sdev = devs[i]; sdev; sdev = sdev->next) for (u = 0; u < sdev->nunit; u++) /* each drive */ (*addconf)(sdev->unit[u]); @@ -451,14 +472,14 @@ static int sd2gen(struct chan *c, int i, struct dir *dp) l = (pp->end - pp->start) * unit->secsize; mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qpart), unit->vers + pp->vers, QTFILE); - if (emptystr(pp->SDperm.user)) - kstrdup(&pp->SDperm.user, eve); - devdir(c, q, pp->SDperm.name, l, pp->SDperm.user, pp->SDperm.perm, dp); + if (emptystr(pp->sdperm.user)) + kstrdup(&pp->sdperm.user, eve); + devdir(c, q, pp->sdperm.name, l, pp->sdperm.user, pp->sdperm.perm, dp); rv = 1; break; } - decref(&sdev->r); + kref_put(&sdev->r); return rv; } @@ -478,7 +499,6 @@ static int sd1gen(struct chan *c, int i, struct dir *dp) static int sdgen(struct chan *c, char *d, struct dirtab *dir, int j, int s, struct dir *dp) { - struct proc *up = externup(); struct qid q = {}; int64_t l; int i, r; @@ -490,8 +510,8 @@ static int sdgen(struct chan *c, char *d, struct dirtab *dir, int j, int s, case Qtopdir: if (s == DEVDOTDOT) { mkqid(&q, QID(0, 0, 0, Qtopdir), 0, QTDIR); - sprint(up->genbuf, "#%C", sddevtab.dc); - devdir(c, q, up->genbuf, 0, eve, 0555, dp); + snprintf(get_cur_genbuf(), GENBUF_SZ, "#%s", sddevtab.name); + devdir(c, q, get_cur_genbuf(), 0, eve, 0555, dp); return 1; } @@ -500,7 +520,7 @@ static int sdgen(struct chan *c, char *d, struct dirtab *dir, int j, int s, s -= (Qunitdir - Qtopbase); qlock(&devslock); - for (i = 0; i < nelem(devs); i++) { + for (i = 0; i < ARRAY_SIZE(devs); i++) { if (devs[i]) { if (s < devs[i]->nunit) break; @@ -508,43 +528,47 @@ static int sdgen(struct chan *c, char *d, struct dirtab *dir, int j, int s, } } - if (i == nelem(devs)) { + if (i == ARRAY_SIZE(devs)) { /* Run off the end of the list */ qunlock(&devslock); return -1; } - if ((sdev = devs[i]) == nil) { + sdev = devs[i]; + if (sdev == NULL) { qunlock(&devslock); return 0; } - incref(&sdev->r); + kref_get(&sdev->r, 1); qunlock(&devslock); - if ((unit = sdev->unit[s]) == nil) - if ((unit = sdgetunit(sdev, s)) == nil) { - decref(&sdev->r); - return 0; - } + unit = sdev->unit[s]; + if (unit == NULL) + unit = sdgetunit(sdev, s); + if (unit == NULL) { + kref_put(&sdev->r); + return 0; + } mkqid(&q, QID(sdev->idno, s, 0, Qunitdir), 0, QTDIR); - if (emptystr(unit->SDperm.user)) - kstrdup(&unit->SDperm.user, eve); - devdir(c, q, unit->SDperm.name, 0, unit->SDperm.user, unit->SDperm.perm, + if (emptystr(unit->sdperm.user)) + kstrdup(&unit->sdperm.user, eve); + devdir(c, q, unit->sdperm.name, 0, unit->sdperm.user, unit->sdperm.perm, dp); - decref(&sdev->r); + kref_put(&sdev->r); return 1; case Qunitdir: if (s == DEVDOTDOT) { mkqid(&q, QID(0, 0, 0, Qtopdir), 0, QTDIR); - sprint(up->genbuf, "#%C", sddevtab.dc); - devdir(c, q, up->genbuf, 0, eve, 0555, dp); + snprintf(get_cur_genbuf(), GENBUF_SZ, "#%s", sddevtab.name); + devdir(c, q, get_cur_genbuf(), 0, eve, 0555, dp); return 1; } - if ((sdev = sdgetdev(DEV(c->qid))) == nil) { + sdev = sdgetdev(DEV(c->qid)); + if (sdev == NULL) { devdir(c, c->qid, "unavailable", 0, eve, 0, dp); return 1; } @@ -567,34 +591,35 @@ static int sdgen(struct chan *c, char *d, struct dirtab *dir, int j, int s, if (i < Qpart) { r = sd2gen(c, i, dp); qunlock(&unit->ctl); - decref(&sdev->r); + kref_put(&sdev->r); return r; } i -= Qpart; - if (unit->part == nil || i >= unit->npart) { + if (unit->part == NULL || i >= unit->npart) { qunlock(&unit->ctl); - decref(&sdev->r); + kref_put(&sdev->r); break; } pp = &unit->part[i]; if (!pp->valid) { qunlock(&unit->ctl); - decref(&sdev->r); + kref_put(&sdev->r); return 0; } l = (pp->end - pp->start) * (int64_t)unit->secsize; mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), i, Qpart), unit->vers + pp->vers, QTFILE); - if (emptystr(pp->SDperm.user)) - kstrdup(&pp->SDperm.user, eve); - devdir(c, q, pp->SDperm.name, l, pp->SDperm.user, pp->SDperm.perm, dp); + if (emptystr(pp->sdperm.user)) + kstrdup(&pp->sdperm.user, eve); + devdir(c, q, pp->sdperm.name, l, pp->sdperm.user, pp->sdperm.perm, dp); qunlock(&unit->ctl); - decref(&sdev->r); + kref_put(&sdev->r); return 1; case Qraw: case Qctl: case Qpart: - if ((sdev = sdgetdev(DEV(c->qid))) == nil) { + sdev = sdgetdev(DEV(c->qid)); + if (sdev == NULL) { devdir(c, q, "unavailable", 0, eve, 0, dp); return 1; } @@ -602,7 +627,7 @@ static int sdgen(struct chan *c, char *d, struct dirtab *dir, int j, int s, qlock(&unit->ctl); r = sd2gen(c, TYPE(c->qid), dp); qunlock(&unit->ctl); - decref(&sdev->r); + kref_put(&sdev->r); return r; case Qtopctl: return sd1gen(c, TYPE(c->qid), dp); @@ -621,46 +646,48 @@ static struct chan *sdattach(char *spec) int idno, subno; if (*spec == '\0') { - c = devattach(sddevtab.dc, spec); + c = devattach(sddevtab.name, spec); mkqid(&c->qid, QID(0, 0, 0, Qtopdir), 0, QTDIR); return c; } if (spec[0] != 's' || spec[1] != 'd') - error(Ebadspec); + error(EINVAL, "First two characters of spec must be 'sd', not %c%c", + spec[0], spec[1]); idno = spec[2]; subno = strtol(&spec[3], &p, 0); if (p == &spec[3]) - error(Ebadspec); - - if ((sdev = sdgetdev(idno)) == nil) - error(Enonexist); - if (sdgetunit(sdev, subno) == nil) { - decref(&sdev->r); - error(Enonexist); + error(EINVAL, "subno '%s' is not a number", &spec[3]); + + sdev = sdgetdev(idno); + if (sdev == NULL) + error(ENOENT, "No such unit %d", idno); + if (sdgetunit(sdev, subno) == NULL) { + kref_put(&sdev->r); + error(ENOENT, "No such subno %d", subno); } - c = devattach(sddevtab.dc, spec); + c = devattach(sddevtab.name, spec); mkqid(&c->qid, QID(sdev->idno, subno, 0, Qunitdir), 0, QTDIR); - c->devno = (sdev->idno << UnitLOG) + subno; - decref(&sdev->r); + c->dev = (sdev->idno << UnitLOG) + subno; + kref_put(&sdev->r); return c; } static struct walkqid *sdwalk(struct chan *c, struct chan *nc, char **name, int nname) { - return devwalk(c, nc, name, nname, nil, 0, sdgen); + return devwalk(c, nc, name, nname, NULL, 0, sdgen); } static int32_t sdstat(struct chan *c, uint8_t *db, int32_t n) { - return devstat(c, db, n, nil, 0, sdgen); + return devstat(c, db, n, NULL, 0, sdgen); } static struct chan *sdopen(struct chan *c, int omode) { - struct proc *up = externup(); + ERRSTACK(1); struct sdpart *pp; struct sdunit *unit; struct sdev *sdev; @@ -671,8 +698,8 @@ static struct chan *sdopen(struct chan *c, int omode) return c; sdev = sdgetdev(DEV(c->qid)); - if (sdev == nil) - error(Enonexist); + if (sdev == NULL) + error(ENOENT, "No such device"); unit = sdev->unit[UNIT(c->qid)]; @@ -682,10 +709,11 @@ static struct chan *sdopen(struct chan *c, int omode) break; case Qraw: c->qid.vers = unit->vers; - if (TAS(&unit->rawinuse) != 0) { + if (test_and_set_bit(0, (unsigned long *)&unit->rawinuse) != + 0) { c->flag &= ~COPEN; - decref(&sdev->r); - error(Einuse); + kref_put(&sdev->r); + error(EBUSY, "In use"); } unit->state = Rawcmd; break; @@ -694,7 +722,7 @@ static struct chan *sdopen(struct chan *c, int omode) if (waserror()) { qunlock(&unit->ctl); c->flag &= ~COPEN; - decref(&sdev->r); + kref_put(&sdev->r); nexterror(); } pp = &unit->part[PART(c->qid)]; @@ -703,7 +731,7 @@ static struct chan *sdopen(struct chan *c, int omode) poperror(); break; } - decref(&sdev->r); + kref_put(&sdev->r); return c; } @@ -725,7 +753,7 @@ static void sdclose(struct chan *c) if (sdev) { unit = sdev->unit[UNIT(c->qid)]; unit->rawinuse = 0; - decref(&sdev->r); + kref_put(&sdev->r); } break; } @@ -734,7 +762,7 @@ static void sdclose(struct chan *c) static int32_t sdbio(struct chan *c, int write, char *a, int32_t len, int64_t off) { - struct proc *up = externup(); + ERRSTACK(2); int nchange; uint8_t *b; struct sdpart *pp; @@ -744,32 +772,38 @@ static int32_t sdbio(struct chan *c, int write, char *a, int32_t len, int32_t l, max, nb, offset; sdev = sdgetdev(DEV(c->qid)); - if (sdev == nil) { - decref(&sdev->r); - error(Enonexist); + if (sdev == NULL) { + kref_put(&sdev->r); + error(ENOENT, "No such file or directory"); } unit = sdev->unit[UNIT(c->qid)]; - if (unit == nil) - error(Enonexist); + if (unit == NULL) + error(ENOENT, "No such file or directory"); nchange = 0; qlock(&unit->ctl); while (waserror()) { /* notification of media change; go around again */ - if (strcmp(up->errstr, Eio) == 0 && unit->sectors == 0 && - nchange++ == 0) { + /* Meta-comment: I'm leaving commented-out code in place, + * which originally contained a strcmp of the error string to + * a value, to remind us: plan 9 is a distributed system. It's + * possible in principle to have the storage device on this + * machine use an sdi{ata,ahci} on another machine, and it all + * works. Nobody is going to do that, now, so get_errno() it is. + * if (strcmp(up->errstr, Eio) == 0 ... */ + if ((get_errno() == EIO) && (unit->sectors == 0) && (nchange++ == 0)) { sdinitpart(unit); continue; } /* other errors; give up */ qunlock(&unit->ctl); - decref(&sdev->r); + kref_put(&sdev->r); nexterror(); } pp = &unit->part[PART(c->qid)]; if (unit->vers + pp->vers != c->qid.vers) - error(Echange); + error(EIO, "disk changed"); /* * Check the request is within bounds. @@ -791,9 +825,10 @@ static int32_t sdbio(struct chan *c, int write, char *a, int32_t len, nb = pp->end - bno; if (bno >= pp->end || nb == 0) { if (write) - error(Eio); + error(EIO, "bno(%d) >= pp->end(%d) or nb(%d) == 0", bno, pp->end, + nb); qunlock(&unit->ctl); - decref(&sdev->r); + kref_put(&sdev->r); poperror(); return 0; } @@ -802,13 +837,13 @@ static int32_t sdbio(struct chan *c, int write, char *a, int32_t len, poperror(); } - b = sdmalloc(nb * unit->secsize); - if (b == nil) - error(Enomem); + b = kzmalloc(nb * unit->secsize, MEM_WAIT); + if (b == NULL) + error(ENOMEM, "%s: could not allocate %d bytes", nb * unit->secsize); if (waserror()) { - sdfree(b); + kfree(b); if (!(unit->inquiry[1] & SDinq1removable)) - decref(&sdev->r); /* gadverdamme! */ + kref_put(&sdev->r); /* gadverdamme! */ nexterror(); } @@ -819,7 +854,7 @@ static int32_t sdbio(struct chan *c, int write, char *a, int32_t len, if (offset || (len % unit->secsize)) { l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno); if (l < 0) - error(Eio); + error(EIO, "IO Error"); if (l < (nb * unit->secsize)) { nb = l / unit->secsize; l = nb * unit->secsize - offset; @@ -830,7 +865,7 @@ static int32_t sdbio(struct chan *c, int write, char *a, int32_t len, memmove(b + offset, a, len); l = unit->dev->ifc->bio(unit, 0, 1, b, nb, bno); if (l < 0) - error(Eio); + error(EIO, "IO Error"); if (l < offset) len = 0; else if (len > l - offset) @@ -838,14 +873,14 @@ static int32_t sdbio(struct chan *c, int write, char *a, int32_t len, } else { l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno); if (l < 0) - error(Eio); + error(EIO, "IO Error"); if (l < offset) len = 0; else if (len > l - offset) len = l - offset; memmove(a, b + offset, len); } - sdfree(b); + kfree(b); poperror(); if (unit->inquiry[1] & SDinq1removable) { @@ -853,22 +888,23 @@ static int32_t sdbio(struct chan *c, int write, char *a, int32_t len, poperror(); } - decref(&sdev->r); + kref_put(&sdev->r); return len; } static int32_t sdrio(struct sdreq *r, void *a, int32_t n) { - struct proc *up = externup(); + ERRSTACK(2); void *data; if (n >= SDmaxio || n < 0) - error(Etoobig); + error(EINVAL, "%d is < 0 or > SDmaxio", n); - data = nil; + data = NULL; if (n) { - if ((data = sdmalloc(n)) == nil) - error(Enomem); + data = kzmalloc(n, MEM_WAIT); + if (data == NULL) + error(ENOMEM, "Alloc of %d bytes failed", n); if (r->write) memmove(data, a, n); } @@ -876,18 +912,18 @@ static int32_t sdrio(struct sdreq *r, void *a, int32_t n) r->dlen = n; if (waserror()) { - sdfree(data); - r->data = nil; + kfree(data); + r->data = NULL; nexterror(); } if (r->unit->dev->ifc->rio(r) != SDok) - error(Eio); + error(EIO, "IO Error"); if (!r->write && r->rlen > 0) memmove(a, data, r->rlen); - sdfree(data); - r->data = nil; + kfree(data); + r->data = NULL; poperror(); return r->rlen; @@ -910,8 +946,8 @@ int sdsetsense(struct sdreq *r, int status, int key, int asc, int ascq) if (status == SDcheck && !(r->flags & SDnosense)) { /* request sense case from sdfakescsi */ len = sizeof unit->sense; - if (len > sizeof r->sense - 1) - len = sizeof r->sense - 1; + if (len > sizeof(r->sense) - 1) + len = sizeof(r->sense) - 1; memmove(r->sense, unit->sense, len); unit->sense[2] = 0; unit->sense[12] = 0; @@ -938,7 +974,7 @@ int sdmodesense(struct sdreq *r, uint8_t *cmd, void *info, int ilen) return SDok; if (len < 8 + ilen) return sdsetsense(r, SDcheck, 0x05, 0x1A, 0); - if (r->data == nil || r->dlen < len) + if (r->data == NULL || r->dlen < len) return sdsetsense(r, SDcheck, 0x05, 0x20, 1); data = r->data; memset(data, 0, 8); @@ -1018,14 +1054,14 @@ int sdfakescsi(struct sdreq *r, void *info, int ilen) case 0x1B: /* start/stop unit */ /* - * nop for now, can use power management later. - */ + * nop for now, can use power management later. + */ return sdsetsense(r, SDok, 0, 0, 0); case 0x25: /* read capacity */ if ((cmd[1] & 0x01) || cmd[2] || cmd[3]) return sdsetsense(r, SDcheck, 0x05, 0x24, 0); - if (r->data == nil || r->dlen < 8) + if (r->data == NULL || r->dlen < 8) return sdsetsense(r, SDcheck, 0x05, 0x20, 1); /* @@ -1048,7 +1084,7 @@ int sdfakescsi(struct sdreq *r, void *info, int ilen) case 0x9E: /* long read capacity */ if ((cmd[1] & 0x01) || cmd[2] || cmd[3]) return sdsetsense(r, SDcheck, 0x05, 0x24, 0); - if (r->data == nil || r->dlen < 8) + if (r->data == NULL || r->dlen < 8) return sdsetsense(r, SDcheck, 0x05, 0x20, 1); /* * Read capcity returns the LBA of the last sector. @@ -1082,9 +1118,9 @@ int sdfakescsi(struct sdreq *r, void *info, int ilen) } } -static int32_t sdread(struct chan *c, void *a, int32_t n, int64_t off) +static long sdread(struct chan *c, void *a, long n, int64_t off) { - struct proc *up = externup(); + ERRSTACK(2); char *p, *e, *buf; struct sdpart *pp; struct sdunit *unit; @@ -1095,22 +1131,22 @@ static int32_t sdread(struct chan *c, void *a, int32_t n, int64_t off) offset = off; switch (TYPE(c->qid)) { default: - error(Eperm); + error(EPERM, "Permission denied"); case Qtopctl: mm = 64 * 1024; /* room for register dumps */ - p = buf = malloc(mm); - if (p == nil) - error(Enomem); + p = buf = kzmalloc(mm, 0); + if (p == NULL) + error(ENOMEM, "Alloc of %d bytes failed", mm); e = p + mm; qlock(&devslock); - for (i = 0; i < nelem(devs); i++) { + for (i = 0; i < ARRAY_SIZE(devs); i++) { sdev = devs[i]; if (sdev && sdev->ifc->rtopctl) p = sdev->ifc->rtopctl(sdev, p, e); } qunlock(&devslock); n = readstr(offset, a, n, buf); - free(buf); + kfree(buf); return n; case Qtopdir: @@ -1119,15 +1155,15 @@ static int32_t sdread(struct chan *c, void *a, int32_t n, int64_t off) case Qctl: sdev = sdgetdev(DEV(c->qid)); - if (sdev == nil) - error(Enonexist); + if (sdev == NULL) + error(ENOENT, "No such device"); unit = sdev->unit[UNIT(c->qid)]; mm = 16 * 1024; /* room for register dumps */ - p = malloc(mm); - if (p == nil) - error(Enomem); - l = snprint(p, mm, "inquiry %.48s\n", (char *)unit->inquiry + 8); + p = kzmalloc(mm, 0); + if (p == NULL) + error(ENOMEM, "Alloc of %d bytes failed", mm); + l = snprintf(p, mm, "inquiry %.48s\n", (char *)unit->inquiry + 8); qlock(&unit->ctl); /* * If there's a device specific routine it must @@ -1139,33 +1175,33 @@ static int32_t sdread(struct chan *c, void *a, int32_t n, int64_t off) if (unit->sectors == 0) sdinitpart(unit); if (unit->sectors) { - if (unit->dev->ifc->rctl == nil) - l += snprint(p + l, mm - l, "geometry %llu %lu\n", - unit->sectors, unit->secsize); + if (unit->dev->ifc->rctl == NULL) + l += snprintf(p + l, mm - l, "geometry %llu %lu\n", + unit->sectors, unit->secsize); pp = unit->part; for (i = 0; i < unit->npart; i++) { if (pp->valid) - l += snprint(p + l, mm - l, "part %s %llu %llu\n", - pp->SDperm.name, pp->start, pp->end); + l += snprintf(p + l, mm - l, "part %s %llu %llu\n", + pp->sdperm.name, pp->start, pp->end); pp++; } } qunlock(&unit->ctl); - decref(&sdev->r); + kref_put(&sdev->r); l = readstr(offset, a, n, p); - free(p); + kfree(p); return l; case Qraw: sdev = sdgetdev(DEV(c->qid)); - if (sdev == nil) - error(Enonexist); + if (sdev == NULL) + error(ENOENT, "No such file or directory"); unit = sdev->unit[UNIT(c->qid)]; qlock(&unit->raw); if (waserror()) { qunlock(&unit->raw); - decref(&sdev->r); + kref_put(&sdev->r); nexterror(); } if (unit->state == Rawdata) { @@ -1174,13 +1210,13 @@ static int32_t sdread(struct chan *c, void *a, int32_t n, int64_t off) } else if (unit->state == Rawstatus) { status = unit->req->status; unit->state = Rawcmd; - free(unit->req); - unit->req = nil; + kfree(unit->req); + unit->req = NULL; i = readnum(0, a, n, status, NUMSIZE); } else i = 0; qunlock(&unit->raw); - decref(&sdev->r); + kref_put(&sdev->r); poperror(); return i; @@ -1191,9 +1227,9 @@ static int32_t sdread(struct chan *c, void *a, int32_t n, int64_t off) static void legacytopctl(struct cmdbuf *); -static int32_t sdwrite(struct chan *c, void *a, int32_t n, int64_t off) +static long sdwrite(struct chan *c, void *a, long n, int64_t off) { - struct proc *up = externup(); + ERRSTACK(2); char *f0; int i; uint64_t end, start; @@ -1205,15 +1241,15 @@ static int32_t sdwrite(struct chan *c, void *a, int32_t n, int64_t off) switch (TYPE(c->qid)) { default: - error(Eperm); + error(EPERM, "Permission denied"); case Qtopctl: cb = parsecmd(a, n); if (waserror()) { - free(cb); + kfree(cb); nexterror(); } if (cb->nf == 0) - error("empty control message"); + error(EINVAL, "empty control message"); f0 = cb->f[0]; cb->f++; cb->nf--; @@ -1221,19 +1257,19 @@ static int32_t sdwrite(struct chan *c, void *a, int32_t n, int64_t off) /* wormhole into ugly legacy interface */ legacytopctl(cb); poperror(); - free(cb); + kfree(cb); break; } /* - * "ata arg..." invokes sdifc[i]->wtopctl(nil, cb), - * where sdifc[i]->SDperm.name=="ata" and cb contains the args. + * "ata arg..." invokes sdifc[i]->wtopctl(NULL, cb), + * where sdifc[i]->sdperm.name=="ata" and cb contains the args. */ - ifc = nil; - sdev = nil; + ifc = NULL; + sdev = NULL; for (i = 0; sdifc[i]; i++) { if (strcmp(sdifc[i]->name, f0) == 0) { ifc = sdifc[i]; - sdev = nil; + sdev = NULL; goto subtopctl; } } @@ -1243,88 +1279,94 @@ static int32_t sdwrite(struct chan *c, void *a, int32_t n, int64_t off) * and cb contains the args. */ if (f0[0] == 's' && f0[1] == 'd' && f0[2] && f0[3] == 0) { - if ((sdev = sdgetdev(f0[2])) != nil) { + sdev = sdgetdev(f0[2]); + if (sdev != NULL) { ifc = sdev->ifc; goto subtopctl; } } - error("unknown interface"); + error(EINVAL, "unknown interface"); subtopctl: if (waserror()) { if (sdev) - decref(&sdev->r); + kref_put(&sdev->r); nexterror(); } if (ifc->wtopctl) ifc->wtopctl(sdev, cb); else - error(Ebadctl); + error(EINVAL, "Bad control"); poperror(); poperror(); if (sdev) - decref(&sdev->r); - free(cb); + kref_put(&sdev->r); + kfree(cb); break; case Qctl: cb = parsecmd(a, n); sdev = sdgetdev(DEV(c->qid)); - if (sdev == nil) - error(Enonexist); + if (sdev == NULL) + error(ENOENT, "No such file or directory"); unit = sdev->unit[UNIT(c->qid)]; qlock(&unit->ctl); if (waserror()) { qunlock(&unit->ctl); - decref(&sdev->r); - free(cb); + kref_put(&sdev->r); + kfree(cb); nexterror(); } if (unit->vers != c->qid.vers) - error(Echange); + error(EIO, "Unit changed"); if (cb->nf < 1) - error(Ebadctl); + error(EINVAL, "%s requires at least one argument", cb->f[0]); if (strcmp(cb->f[0], "part") == 0) { if (cb->nf != 4) - error(Ebadctl); - if (unit->sectors == 0 && !sdinitpart(unit)) - error(Eio); - start = strtoull(cb->f[2], 0, 0); - end = strtoull(cb->f[3], 0, 0); + error(EINVAL, "Part got %d arguments, requires 4", cb->nf); + if (unit->sectors == 0) + error(EINVAL, "unit->sectors was 0"); + if (!sdinitpart(unit)) + error(EIO, "sdinitpart failed"); + start = strtoul(cb->f[2], 0, 0); + end = strtoul(cb->f[3], 0, 0); sdaddpart(unit, cb->f[1], start, end); } else if (strcmp(cb->f[0], "delpart") == 0) { - if (cb->nf != 2 || unit->part == nil) - error(Ebadctl); + if (cb->nf != 2) + error(EINVAL, "delpart got %d args, 2 required"); + if (unit->part == NULL) + error(EIO, "partition was NULL"); sddelpart(unit, cb->f[1]); } else if (unit->dev->ifc->wctl) unit->dev->ifc->wctl(unit, cb); else - error(Ebadctl); + error(EINVAL, "Bad control %s", cb->f[0]); qunlock(&unit->ctl); - decref(&sdev->r); + kref_put(&sdev->r); poperror(); - free(cb); + kfree(cb); break; case Qraw: sdev = sdgetdev(DEV(c->qid)); - if (sdev == nil) - error(Enonexist); + if (sdev == NULL) + error(ENOENT, "No such file or directory"); unit = sdev->unit[UNIT(c->qid)]; qlock(&unit->raw); if (waserror()) { qunlock(&unit->raw); - decref(&sdev->r); + kref_put(&sdev->r); nexterror(); } switch (unit->state) { case Rawcmd: if (n < 6 || n > sizeof(req->cmd)) - error(Ebadarg); - if ((req = malloc(sizeof(struct sdreq))) == nil) - error(Enomem); + error(EINVAL, "%d is < 6 or > %d", n, sizeof(req->cmd)); + req = kzmalloc(sizeof(struct sdreq), 0); + if (req == NULL) + error(ENOMEM, "Can't allocate an sdreq"); req->unit = unit; memmove(req->cmd, a, n); req->clen = n; @@ -1337,9 +1379,9 @@ static int32_t sdwrite(struct chan *c, void *a, int32_t n, int64_t off) case Rawstatus: unit->state = Rawcmd; - free(unit->req); - unit->req = nil; - error(Ebadusefd); + kfree(unit->req); + unit->req = NULL; + error(EINVAL, "Bad use of rawstatus"); case Rawdata: unit->state = Rawstatus; @@ -1347,7 +1389,7 @@ static int32_t sdwrite(struct chan *c, void *a, int32_t n, int64_t off) n = sdrio(unit->req, a, n); } qunlock(&unit->raw); - decref(&sdev->r); + kref_put(&sdev->r); poperror(); break; case Qpart: @@ -1359,7 +1401,7 @@ static int32_t sdwrite(struct chan *c, void *a, int32_t n, int64_t off) static int32_t sdwstat(struct chan *c, uint8_t *dp, int32_t n) { - struct proc *up = externup(); + ERRSTACK(2); struct dir *d; struct sdpart *pp; struct sdperm *perm; @@ -1367,24 +1409,24 @@ static int32_t sdwstat(struct chan *c, uint8_t *dp, int32_t n) struct sdev *sdev; if (c->qid.type & QTDIR) - error(Eperm); + error(EPERM, "Not a directory"); sdev = sdgetdev(DEV(c->qid)); - if (sdev == nil) - error(Enonexist); + if (sdev == NULL) + error(ENOENT, "No such file or device"); unit = sdev->unit[UNIT(c->qid)]; qlock(&unit->ctl); - d = nil; + d = NULL; if (waserror()) { - free(d); + kfree(d); qunlock(&unit->ctl); - decref(&sdev->r); + kref_put(&sdev->r); nexterror(); } switch (TYPE(c->qid)) { default: - error(Eperm); + error(EPERM, "Permission denied"); case Qctl: perm = &unit->ctlperm; break; @@ -1394,52 +1436,54 @@ static int32_t sdwstat(struct chan *c, uint8_t *dp, int32_t n) case Qpart: pp = &unit->part[PART(c->qid)]; if (unit->vers + pp->vers != c->qid.vers) - error(Enonexist); - perm = &pp->SDperm; + error(ENOENT, "No such file or directory"); + perm = &pp->sdperm; break; } - if (strcmp(up->user, perm->user) && !iseve()) - error(Eperm); + /* TODO: Implement permissions checking and raise errors as appropriate. */ + // if (strcmp(up->user, perm->user) && !iseve()) + // error(Eperm); - d = smalloc(sizeof(struct dir) + n); + d = kzmalloc(sizeof(struct dir) + n, 0); n = convM2D(dp, n, &d[0], (char *)&d[1]); if (n == 0) - error(Eshortstat); + error(EIO, "Short status"); if (!emptystr(d[0].uid)) kstrdup(&perm->user, d[0].uid); if (d[0].mode != (uint32_t)~0UL) perm->perm = (perm->perm & ~0777) | (d[0].mode & 0777); - free(d); + kfree(d); qunlock(&unit->ctl); - decref(&sdev->r); + kref_put(&sdev->r); poperror(); return n; } -static int configure(char *spec, DevConf *cf) +static int configure(char *spec, struct devconf *cf) { struct sdev *s, *sdev; char *p; int i; if (sdindex(*spec) < 0) - error("bad sd spec"); + error(EINVAL, "bad sd spec '%s'", spec); - if ((p = strchr(cf->type, '/')) != nil) + p = strchr(cf->type, '/'); + if (p != NULL) *p++ = '\0'; - for (i = 0; sdifc[i] != nil; i++) + for (i = 0; sdifc[i] != NULL; i++) if (strcmp(sdifc[i]->name, cf->type) == 0) break; - if (sdifc[i] == nil) - error("sd type not found"); + if (sdifc[i] == NULL) + error(ENOENT, "sd type not found"); if (p) *(p - 1) = '/'; - if (sdifc[i]->probe == nil) - error("sd type cannot probe"); + if (sdifc[i]->probe == NULL) + error(EIO, "sd type cannot probe"); sdev = sdifc[i]->probe(cf); for (s = sdev; s; s = s->next) @@ -1455,18 +1499,19 @@ static int unconfigure(char *spec) struct sdunit *unit; if ((i = sdindex(*spec)) < 0) - error(Enonexist); + error(ENOENT, "No such file or directory '%s'", spec); qlock(&devslock); - if ((sdev = devs[i]) == nil) { + sdev = devs[i]; + if (sdev == NULL) { qunlock(&devslock); - error(Enonexist); + error(ENOENT, "No such file or directory at index %d", i); } - if (sdev->r.ref) { + if (kref_refcnt(&sdev->r)) { qunlock(&devslock); - error(Einuse); + error(EBUSY, "%s is busy", spec); } - devs[i] = nil; + devs[i] = NULL; qunlock(&devslock); /* make sure no interrupts arrive anymore before removing resources */ @@ -1474,28 +1519,28 @@ static int unconfigure(char *spec) sdev->ifc->disable(sdev); for (i = 0; i != sdev->nunit; i++) { - if (unit = sdev->unit[i]) { - free(unit->SDperm.name); - free(unit->SDperm.user); - free(unit); + unit = sdev->unit[i]; + if (unit) { + kfree(unit->sdperm.name); + kfree(unit->sdperm.user); + kfree(unit); } } if (sdev->ifc->clear) sdev->ifc->clear(sdev); - free(sdev); + kfree(sdev); return 0; } -static int sdconfig(int on, char *spec, DevConf *cf) +static int sdconfig(int on, char *spec, struct devconf *cf) { if (on) return configure(spec, cf); return unconfigure(spec); } -struct dev sddevtab = { - .dc = 'S', +struct dev sddevtab __devtab = { .name = "sd", .reset = sdreset, @@ -1514,46 +1559,46 @@ struct dev sddevtab = { .remove = devremove, .wstat = sdwstat, .power = devpower, - .config = sdconfig, /* probe; only called for pcmcia-like devices */ }; /* * This is wrong for so many reasons. This code must go. */ -typedef struct Confdata Confdata; -struct Confdata { +struct confdata { int on; char *spec; - DevConf cf; + struct devconf cf; }; -static void parseswitch(Confdata *cd, char *option) +static void parseswitch(struct confdata *cd, char *option) { if (!strcmp("on", option)) cd->on = 1; else if (!strcmp("off", option)) cd->on = 0; else - error(Ebadarg); + error(EINVAL, "Got %s, must be on or off", option); } -static void parsespec(Confdata *cd, char *option) +static void parsespec(struct confdata *cd, char *option) { if (strlen(option) > 1) - error(Ebadarg); + error(EINVAL, "spec is %d bytes, must be 1", strlen(option)); cd->spec = option; } -static struct devport *getnewport(DevConf *dc) +static struct devport *getnewport(struct devconf *dc) { struct devport *p; - p = (struct devport *)malloc((dc->nports + 1) * sizeof(struct devport)); - if (p == nil) - error(Enomem); + p = (struct devport *)kzmalloc((dc->nports + 1) * sizeof(struct devport), + 0); + if (p == NULL) + error(ENOMEM, "Can't allocate %d bytes for %d ports", dc->nports, + (dc->nports + 1) * sizeof(struct devport)); if (dc->nports > 0) { memmove(p, dc->ports, dc->nports * sizeof(struct devport)); - free(dc->ports); + kfree(dc->ports); } dc->ports = p; p = &dc->ports[dc->nports++]; @@ -1562,22 +1607,22 @@ static struct devport *getnewport(DevConf *dc) return p; } -static void parseport(Confdata *cd, char *option) +static void parseport(struct confdata *cd, char *option) { char *e; struct devport *p; - if (cd->cf.nports == 0 || - cd->cf.ports[cd->cf.nports - 1].port != (uint32_t)-1) + if ((cd->cf.nports == 0) || + (cd->cf.ports[cd->cf.nports - 1].port != (uint32_t)-1)) p = getnewport(&cd->cf); else p = &cd->cf.ports[cd->cf.nports - 1]; p->port = strtol(option, &e, 0); - if (e == nil || *e != '\0') - error(Ebadarg); + if (e == NULL || *e != '\0') + error(EINVAL, "option %s is not a number", option); } -static void parsesize(Confdata *cd, char *option) +static void parsesize(struct confdata *cd, char *option) { char *e; struct devport *p; @@ -1587,53 +1632,60 @@ static void parsesize(Confdata *cd, char *option) else p = &cd->cf.ports[cd->cf.nports - 1]; p->size = (int)strtol(option, &e, 0); - if (e == nil || *e != '\0') - error(Ebadarg); + if (e == NULL || *e != '\0') + error(EINVAL, "%s is not a number", option); } -static void parseirq(Confdata *cd, char *option) +static void parseirq(struct confdata *cd, char *option) { char *e; cd->cf.intnum = strtoul(option, &e, 0); - if (e == nil || *e != '\0') - error(Ebadarg); + if (e == NULL || *e != '\0') + error(EINVAL, "%s is not a number", option); } -static void parsetype(Confdata *cd, char *option) { cd->cf.type = option; } +static void parsetype(struct confdata *cd, char *option) +{ + cd->cf.type = option; +} static struct { char *name; - void (*parse)(Confdata *, char *); + void (*parse)(struct confdata *, char *unused_char_p_t); } options[] = { - "switch", parseswitch, "spec", parsespec, "port", parseport, - "size", parsesize, "irq", parseirq, "type", parsetype, + {"switch", parseswitch}, + {"spec", parsespec}, + {"port", parseport}, + {"size", parsesize}, + {"irq", parseirq}, + {"type", parsetype}, }; static void legacytopctl(struct cmdbuf *cb) { char *opt; int i, j; - Confdata cd; + struct confdata cd; - memset(&cd, 0, sizeof cd); + memset(&cd, 0, sizeof(cd)); cd.on = -1; for (i = 0; i < cb->nf; i += 2) { if (i + 2 > cb->nf) - error(Ebadarg); + error(EINVAL, "FIX ME. I don't know what this means"); opt = cb->f[i]; - for (j = 0; j < nelem(options); j++) + for (j = 0; j < ARRAY_SIZE(options); j++) if (strcmp(opt, options[j].name) == 0) { options[j].parse(&cd, cb->f[i + 1]); break; } - if (j == nelem(options)) - error(Ebadarg); + if (j == ARRAY_SIZE(options)) + error(EINVAL, "FIX ME"); } - /* this has been rewritten to accomodate sdaoe */ + /* this has been rewritten to accommodate sdaoe */ if (cd.on < 0 || cd.spec == 0) - error(Ebadarg); - if (cd.on && cd.cf.type == nil) - error(Ebadarg); + error(EINVAL, "cd.on(%d) < 0 or cd.spec == 0", cd.on); + if (cd.on && cd.cf.type == NULL) + error(EINVAL, "cd.on non-zero and cd.cf.type == NULL"); sdconfig(cd.on, cd.spec, &cd.cf); } diff --git a/kern/drivers/dev/sdiahci.c b/kern/drivers/dev/sdiahci.c index 79506d9..accb4ca 100644 --- a/kern/drivers/dev/sdiahci.c +++ b/kern/drivers/dev/sdiahci.c @@ -1,3 +1,4 @@ +#define DEBUG /* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this @@ -12,15 +13,23 @@ * copyright © 2007-8 coraid, inc. */ -#include "../port/error.h" -#include "../port/lib.h" -#include "../port/sd.h" -#include "ahci.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "mem.h" -#include "u.h" +#include <vfs.h> + +#include <assert.h> +#include <cpio.h> +#include <error.h> +#include <ip.h> +#include <kfs.h> +#include <kmalloc.h> +#include <kref.h> +#include <pmap.h> +#include <sd.h> +#include <slab.h> +#include <smp.h> +#include <stdio.h> +#include <string.h> + +#include <ahci.h> enum { Vatiamd = 0x1002, @@ -28,24 +37,18 @@ enum { Vmarvell = 0x1b4b, }; -#define dprint(...) \ - if (debug) \ - iprint(__VA_ARGS__); \ - else \ - USED(debug) -#define idprint(...) \ - if (prid) \ - iprint(__VA_ARGS__); \ - else \ - USED(prid) -#define aprint(...) \ - if (datapi) \ - iprint(__VA_ARGS__); \ - else \ - USED(datapi) - +#define iprintd(...) \ + do { \ + if (prid) \ + printd(__VA_ARGS__); \ + } while (0) +#define aprintd(...) \ + do { \ + if (datapi) \ + printd(__VA_ARGS__); \ + } while (0) #define Tname(c) tname[(c)->type] -#define Intel(x) ((x)->pci->vid == Vintel) +#define Intel(x) ((x)->pci->ven_id == Vintel) enum { NCtlr = 16, @@ -123,11 +126,7 @@ static char *flagname[] = { "llba", "smart", "power", "nop", "atapi", "atapi16", }; -typedef struct Asleep Asleep; -typedef struct Ctlr Ctlr; -typedef struct Drive Drive; - -struct Drive { +struct drive { spinlock_t Lock; struct ctlr *ctlr; @@ -165,25 +164,24 @@ struct Drive { uint32_t intrs; }; -struct Ctlr { +struct ctlr { spinlock_t Lock; int type; int enabled; struct sdev *sdev; - Pcidev *pci; - void *vec; + struct pci_device *pci; + void *vector; /* virtual register addresses */ - unsigned char *mmio; - uint32_t *lmmio; + uintptr_t mmio; Ahba *hba; /* phyical register address */ - unsigned char *physio; + uintptr_t physio; - Drive *rawdrive; - Drive *drive[NCtlrdrv]; + struct drive *rawdrive; + struct drive *drive[NCtlrdrv]; int ndrive; int mport; /* highest drive # (0-origin) on ich9 at least */ @@ -202,7 +200,7 @@ static struct ctlr iactlr[NCtlr]; static struct sdev sdevs[NCtlr]; static int niactlr; -static Drive *iadrive[NDrive]; +static struct drive *iadrive[NDrive]; static int niadrive; /* these are fiddled in iawtopctl() */ @@ -211,16 +209,38 @@ static int prid = 1; static int datapi; // TODO: does this get initialized correctly? -static char stab[] = {[0] = 'i', 'm', [8] = 't', 'c', 'p', 'e', - [16] = 'N', 'I', 'W', 'B', 'D', 'C', - 'H', 'S', 'T', 'F', 'X'}; +static char stab[] = { + [0] = 'i', 'm', + [8] = 't', 'c', 'p', 'e', + [16] = 'N', 'I', 'W', 'B', 'D', 'C', 'H', 'S', 'T', 'F', 'X' +}; + +/* ALL time units in this file are in milliseconds. */ +static uint32_t ms(void) +{ + return (uint32_t)(epoch_nsec() / 1048576); +} + +/* TODO: if we like this, make it useable elsewhere. */ +static void sdierror(struct cmdbuf *cb, char *fmt, ...) +{ + char *c = kzmalloc(512, MEM_WAIT); + va_list ap; + + assert(fmt); + va_start(ap, fmt); + vsnprintf(c, 512, fmt, ap); + va_end(ap); + cmderror(cb, c); + kfree(c); +} static void serrstr(uint32_t r, char *s, char *e) { int i; e -= 3; - for (i = 0; i < nelem(stab) && s < e; i++) + for (i = 0; i < ARRAY_SIZE(stab) && s < e; i++) if (r & (1 << i) && stab[i]) { *s++ = stab[i]; if (SerrBad & (1 << i)) @@ -244,44 +264,44 @@ static void preg(unsigned char *reg, int n) } *e++ = '\n'; *e = 0; - dprint(buf); + printd(buf); } static void dreg(char *s, struct aport *p) { - dprint("ahci: %stask=%#lx; cmd=%#lx; ci=%#lx; is=%#lx\n", s, p->task, + printd("ahci: %stask=%#lx; cmd=%#lx; ci=%#lx; is=%#lx\n", s, p->task, p->cmd, p->ci, p->isr); } static void esleep(int ms) { - struct proc *up = externup(); + ERRSTACK(2); if (waserror()) return; - tsleep(&up->sleep, return0, 0, ms); + kthread_usleep(ms * 1000); poperror(); } static int ahciclear(void *v) { - Asleep *s; + struct Asleep *s; s = v; return (s->p->ci & s->i) == 0; } -static void aesleep(struct aportm *pm, Asleep *a, int ms) +static void aesleep(struct aportm *pm, struct Asleep *a, int ms) { - struct proc *up = externup(); + ERRSTACK(2); if (waserror()) return; - tsleep(&pm->Rendez, ahciclear, a, ms); + rendez_sleep_timeout(&pm->Rendez, ahciclear, a, ms * 1000); poperror(); } static int ahciwait(struct aportc *c, int ms) { - Asleep as; + struct Asleep as; struct aport *p; p = c->p; @@ -360,11 +380,7 @@ static int setudmamode(struct aportc *pc, unsigned char f) static void asleep(int ms) { - struct proc *up = externup(); - if (up == nil) - delay(ms); - else - esleep(ms); + udelay(ms * 1000); } static int ahciportreset(struct aportc *c) @@ -381,7 +397,8 @@ static int ahciportreset(struct aportc *c) asleep(25); } p->sctl = 1 | (p->sctl & ~7); - delay(1); + printk("Sleeping one second\n"); + udelay(1000 * 1000); p->sctl &= ~7; return 0; } @@ -399,9 +416,7 @@ static int smart(struct aportc *pc, int n) c[6] = 0xc2; listsetup(pc, Lwrite); if (ahciwait(pc, 1000) == -1 || pc->p->task & (1 | 32)) { - dprint("ahci: smart fail %#lx\n", pc->p->task); - /* This was commented out in the original. */ - /* preg(pc->m->fis.r, 20); */ + printd("ahci: smart fail %#lx\n", pc->p->task); return -1; } if (n) @@ -422,7 +437,7 @@ static int smartrs(struct aportc *pc) c = pc->pm->fis.r; if (ahciwait(pc, 1000) == -1 || pc->p->task & (1 | 32)) { - dprint("ahci: smart fail %#lx\n", pc->p->task); + printd("ahci: smart fail %#lx\n", pc->p->task); preg(c, 20); return -1; } @@ -439,7 +454,7 @@ static int ahciflushcache(struct aportc *pc) c[2] = pc->pm->feat & Dllba ? 0xea : 0xe7; listsetup(pc, Lwrite); if (ahciwait(pc, 60000) == -1 || pc->p->task & (1 | 32)) { - dprint("ahciflushcache: fail %#lx\n", pc->p->task); + printd("ahciflushcache: fail %#lx\n", pc->p->task); // preg(pc->m->fis.r, 20); return -1; } @@ -568,7 +583,7 @@ stop: return -1; stop1: /* extra check */ - dprint("ahci: clo clear %#lx\n", a->task); + printd("ahci: clo clear %#lx\n", a->task); if(a->task & ASbsy) return -1; *p |= Ast; @@ -582,10 +597,10 @@ ahcicomreset(Aportc *pc) { unsigned char *c; - dprint("ahcicomreset\n"); + printd("ahcicomreset\n"); dreg("ahci: comreset ", pc->p); if(ahciquiet(pc->p) == -1){ - dprint("ahciquiet failed\n"); + printd("ahciquiet failed\n"); return -1; } dreg("comreset ", pc->p); @@ -595,7 +610,7 @@ ahcicomreset(Aportc *pc) c[15] = 1<<2; /* srst */ listsetup(pc, Lclear | Lreset); if(ahciwait(pc, 500) == -1){ - dprint("ahcicomreset: first command failed\n"); + printd("ahcicomreset: first command failed\n"); return -1; } microdelay(250); @@ -604,8 +619,8 @@ ahcicomreset(Aportc *pc) c = cfissetup(pc); c[1] = 0; listsetup(pc, Lwrite); - if(ahciwait(pc, 150) == -1){ - dprint("ahcicomreset: second command failed\n"); + if (ahciwait(pc, 150) == -1) { + printd("ahcicomreset: second command failed\n"); return -1; } dreg("comreset ", pc->p); @@ -669,7 +684,7 @@ static int ahcirecover(struct aportc *pc) static void *malign(int size, int align) { - return mallocalign(size, align, 0, 0); + return kmalloc_align(size, MEM_WAIT, align); } static void setupfis(struct afis *f) @@ -694,12 +709,12 @@ static void ahciwakeup(struct aport *p) return; } p->sctl = 3 * Aipm | 0 * Aspd | Adet; - delay(1); + udelay(1000 * 1000); p->sctl &= ~7; // iprint("ahci: wake %#x -> %#x\n", s, p->sstatus); } -static int ahciconfigdrive(Drive *d) +static int ahciconfigdrive(struct drive *d) { char *name; Ahba *h; @@ -716,12 +731,12 @@ static int ahciconfigdrive(Drive *d) } if (d->unit) - name = d->unit->SDperm.name; + name = d->unit->sdperm.name; else - name = nil; + name = NULL; if (p->sstatus & (Devphycomm | Devpresent) && h->cap & Hsss) { /* device connected & staggered spin-up */ - dprint("ahci: configdrive: %s: spinning up ... [%#lx]\n", name, + printd("ahci: configdrive: %s: spinning up ... [%#lx]\n", name, p->sstatus); p->cmd |= Apod | Asud; asleep(1400); @@ -750,9 +765,15 @@ static int ahciconfigdrive(Drive *d) return 0; } -static void ahcienable(Ahba *h) { h->ghc |= Hie; } +static void ahcienable(Ahba *h) +{ + h->ghc |= Hie; +} -static void ahcidisable(Ahba *h) { h->ghc &= ~Hie; } +static void ahcidisable(Ahba *h) +{ + h->ghc &= ~Hie; +} static int countbits(uint32_t u) { @@ -776,7 +797,7 @@ static int ahciconf(struct ctlr *ctlr) if ((u & Hsam) == 0) h->ghc |= Hae; - dprint("#S/sd%c: type %s port %#p: sss %ld ncs %ld coal %ld " + printd("#S/sd%c: type %s port %#p: sss %ld ncs %ld coal %ld " "%ld ports, led %ld clo %ld ems %ld\n", ctlr->sdev->idno, tname[ctlr->type], h, (u >> 27) & 1, (u >> 8) & 0x1f, (u >> 7) & 1, (u & 0x1f) + 1, (u >> 25) & 1, @@ -819,18 +840,18 @@ static void idmove(char *p, uint16_t *a, int n) memmove(op, p, n - (e - p)); } -static int identify(Drive *d) +static int identify(struct drive *d) { uint16_t *id; int64_t osectors, s; unsigned char oserial[21]; struct sdunit *u; - if (d->info == nil) { + if (d->info == NULL) { d->infosz = 512 * sizeof(uint16_t); - d->info = malloc(d->infosz); + d->info = kzmalloc(d->infosz, 0); } - if (d->info == nil) { + if (d->info == NULL) { d->info = d->tinyinfo; d->infosz = sizeof d->tinyinfo; } @@ -875,7 +896,7 @@ static void clearci(struct aport *p) } } -static void updatedrive(Drive *d) +static void updatedrive(struct drive *d) { uint32_t cause, serr, s0, pr, ewake; char *name; @@ -889,22 +910,22 @@ static void updatedrive(Drive *d) serr = p->serror; p->isr = cause; name = "??"; - if (d->unit && d->unit->SDperm.name) - name = d->unit->SDperm.name; + if (d->unit && d->unit->sdperm.name) + name = d->unit->sdperm.name; if (p->ci == 0) { d->portm.flag |= Fdone; - wakeup(&d->portm.Rendez); + rendez_wakeup(&d->portm.Rendez); pr = 0; } else if (cause & Adps) pr = 0; if (cause & Ifatal) { ewake = 1; - dprint("ahci: updatedrive: %s: fatal\n", name); + printd("ahci: updatedrive: %s: fatal\n", name); } if (cause & Adhrs) { if (p->task & (1 << 5 | 1)) { - dprint("ahci: %s: Adhrs cause %#lx serr %#lx task %#lx\n", name, + printd("ahci: %s: Adhrs cause %#lx serr %#lx task %#lx\n", name, cause, serr, p->task); d->portm.flag |= Ferror; ewake = 1; @@ -912,10 +933,10 @@ static void updatedrive(Drive *d) pr = 0; } if (p->task & 1 && last != cause) - dprint("%s: err ca %#lx serr %#lx task %#lx sstat %#lx\n", name, cause, + printd("%s: err ca %#lx serr %#lx task %#lx sstat %#lx\n", name, cause, serr, p->task, p->sstatus); if (pr) - dprint("%s: upd %#lx ta %#lx\n", name, cause, p->task); + printd("%s: upd %#lx ta %#lx\n", name, cause, p->task); if (cause & (Aprcs | Aifs)) { s0 = d->state; @@ -939,11 +960,11 @@ static void updatedrive(Drive *d) d->state = Doffline; break; } - dprint("%s: %s → %s [Apcrs] %#lx\n", name, diskstates[s0], + printd("%s: %s → %s [Apcrs] %#lx\n", name, diskstates[s0], diskstates[d->state], p->sstatus); /* print pulled message here. */ if (s0 == Dready && d->state != Dready) - idprint("%s: pulled\n", name); /* wtf? */ + iprintd("%s: pulled\n", name); /* wtf? */ if (d->state != Dready) d->portm.flag |= Ferror; ewake = 1; @@ -951,12 +972,12 @@ static void updatedrive(Drive *d) p->serror = serr; if (ewake) { clearci(p); - wakeup(&d->portm.Rendez); + rendez_wakeup(&d->portm.Rendez); } last = cause; } -static void pstatus(Drive *d, uint32_t s) +static void pstatus(struct drive *d, uint32_t s) { /* * s is masked with Devdet. @@ -971,7 +992,7 @@ static void pstatus(Drive *d, uint32_t s) case Devpresent: /* device but no phy. comm. */ break; case Devphycomm: /* should this be missing? need testcase. */ - dprint("ahci: pstatus 2\n"); + printd("ahci: pstatus 2\n"); /* fallthrough */ case Devpresent | Devphycomm: d->wait = 0; @@ -986,48 +1007,48 @@ static void pstatus(Drive *d, uint32_t s) } } -static int configdrive(Drive *d) +static int configdrive(struct drive *d) { if (ahciconfigdrive(d) == -1) return -1; - ilock(&d->Lock); + spin_lock_irqsave(&d->Lock); pstatus(d, d->port->sstatus & Devdet); - iunlock(&d->Lock); + spin_unlock_irqsave(&d->Lock); return 0; } -static void setstate(Drive *d, int state) +static void setstate(struct drive *d, int state) { - ilock(&d->Lock); + spin_lock_irqsave(&d->Lock); d->state = state; - iunlock(&d->Lock); + spin_unlock_irqsave(&d->Lock); } -static void resetdisk(Drive *d) +static void resetdisk(struct drive *d) { - uint state, det, stat; + unsigned int state, det, stat; struct aport *p; p = d->port; det = p->sctl & 7; stat = p->sstatus & Devdet; state = (p->cmd >> 28) & 0xf; - dprint("ahci: resetdisk: icc %#x det %d sdet %d\n", state, det, stat); + printd("ahci: resetdisk: icc %#x det %d sdet %d\n", state, det, stat); - ilock(&d->Lock); + spin_lock_irqsave(&d->Lock); state = d->state; if (d->state != Dready || d->state != Dnew) d->portm.flag |= Ferror; clearci(p); /* satisfy sleep condition. */ - wakeup(&d->portm.Rendez); + rendez_wakeup(&d->portm.Rendez); if (stat != (Devpresent | Devphycomm)) { /* device absent or phy not communicating */ d->state = Dportreset; - iunlock(&d->Lock); + spin_unlock_irqsave(&d->Lock); return; } d->state = Derror; - iunlock(&d->Lock); + spin_unlock_irqsave(&d->Lock); qlock(&d->portm.ql); if (p->cmd & Ast && ahciswreset(&d->portc) == -1) @@ -1036,13 +1057,13 @@ static void resetdisk(Drive *d) setstate(d, Dmissing); configdrive(d); } - dprint("ahci: %s: resetdisk: %s → %s\n", - (d->unit ? d->unit->SDperm.name : nil), diskstates[state], + printd("ahci: %s: resetdisk: %s → %s\n", + (d->unit ? d->unit->sdperm.name : NULL), diskstates[state], diskstates[d->state]); qunlock(&d->portm.ql); } -static int newdrive(Drive *d) +static int newdrive(struct drive *d) { char *name; struct aportc *c; @@ -1051,7 +1072,7 @@ static int newdrive(Drive *d) c = &d->portc; pm = &d->portm; - name = d->unit->SDperm.name; + name = d->unit->sdperm.name; if (name == 0) name = "??"; @@ -1059,11 +1080,11 @@ static int newdrive(Drive *d) return -1; qlock(&c->pm->ql); if (setudmamode(c, 5) == -1) { - dprint("%s: can't set udma mode\n", name); + printd("%s: can't set udma mode\n", name); goto lose; } if (identify(d) == -1) { - dprint("%s: identify failure\n", name); + printd("%s: identify failure\n", name); goto lose; } if (pm->feat & Dpower && setfeatures(c, 0x85) == -1) { @@ -1074,48 +1095,48 @@ static int newdrive(Drive *d) setstate(d, Dready); qunlock(&c->pm->ql); - idprint("%s: %sLBA %,llu sectors: %s %s %s %s\n", d->unit->SDperm.name, + iprintd("%s: %sLBA %llu sectors: %s %s %s %s\n", d->unit->sdperm.name, (pm->feat & Dllba ? "L" : ""), d->sectors, d->model, d->firmware, d->serial, d->mediachange ? "[mediachange]" : ""); return 0; lose: - idprint("%s: can't be initialized\n", d->unit->SDperm.name); + iprintd("%s: can't be initialized\n", d->unit->sdperm.name); setstate(d, Dnull); qunlock(&c->pm->ql); return -1; } -static void westerndigitalhung(Drive *d) +static void westerndigitalhung(struct drive *d) { if ((d->portm.feat & Datapi) == 0 && d->active && - TK2MS(sys->ticks - d->intick) > 5000) { - dprint("%s: drive hung; resetting [%#lx] ci %#lx\n", - d->unit->SDperm.name, d->port->task, d->port->ci); + (ms() - d->intick) > 5000) { + printd("%s: drive hung; resetting [%#lx] ci %#lx\n", + d->unit->sdperm.name, d->port->task, d->port->ci); d->state = Dreset; } } static uint16_t olds[NCtlr * NCtlrdrv]; -static int doportreset(Drive *d) +static int doportreset(struct drive *d) { int i; i = -1; qlock(&d->portm.ql); if (ahciportreset(&d->portc) == -1) - dprint("ahci: doportreset: fails\n"); + printd("ahci: doportreset: fails\n"); else i = 0; qunlock(&d->portm.ql); - dprint("ahci: doportreset: portreset → %s [task %#lx]\n", + printd("ahci: doportreset: portreset → %s [task %#lx]\n", diskstates[d->state], d->port->task); return i; } /* drive must be locked */ -static void statechange(Drive *d) +static void statechange(struct drive *d) { switch (d->state) { case Dnull: @@ -1131,28 +1152,29 @@ static void statechange(Drive *d) } } -static void checkdrive(Drive *d, int i) +static void checkdrive(struct drive *d, int i) { uint16_t s; char *name; - if (d == nil) { - print("checkdrive: nil d\n"); + if (d == NULL) { + printd("checkdrive: NULL d\n"); return; } - ilock(&d->Lock); - if (d->unit == nil || d->port == nil) { + spin_lock_irqsave(&d->Lock); + if (d->unit == NULL || d->port == NULL) { if (0) - print("checkdrive: nil d->%s\n", d->unit == nil ? "unit" : "port"); - iunlock(&d->Lock); + printk("checkdrive: nil d->%s\n", + d->unit == NULL ? "unit" : "port"); + spin_unlock_irqsave(&d->Lock); return; } - name = d->unit->SDperm.name; + name = d->unit->sdperm.name; s = d->port->sstatus; if (s) - d->lastseen = sys->ticks; + d->lastseen = ms(); if (s != olds[i]) { - dprint("%s: status: %06#x -> %06#x: %s\n", name, olds[i], s, + printd("%s: status: %06#x -> %06#x: %s\n", name, olds[i], s, diskstates[d->state]); olds[i] = s; d->wait = 0; @@ -1172,7 +1194,7 @@ static void checkdrive(Drive *d, int i) case 0: /* no device */ break; default: - dprint("%s: unknown status %06#x\n", name, s); + printd("%s: unknown status %06#x\n", name, s); /* fall through */ case Intactive: /* active, no device */ if (++d->wait & Mphywait) @@ -1184,14 +1206,14 @@ static void checkdrive(Drive *d, int i) d->state = Dportreset; goto portreset; } - dprint("%s: reset; new mode %s\n", name, modename[d->mode]); - iunlock(&d->Lock); + printd("%s: reset; new mode %s\n", name, modename[d->mode]); + spin_unlock_irqsave(&d->Lock); resetdisk(d); - ilock(&d->Lock); + spin_lock_irqsave(&d->Lock); break; case Intactive | Devphycomm | Devpresent: if ((++d->wait & Midwait) == 0) { - dprint("%s: slow reset %06#x task=%#lx; %d\n", name, s, + printd("%s: slow reset %06#x task=%#lx; %d\n", name, s, d->port->task, d->wait); goto reset; } @@ -1199,9 +1221,9 @@ static void checkdrive(Drive *d, int i) if (s == 0x7f || ((d->port->sig >> 16) != 0xeb14 && (s & ~0x17) != (1 << 6))) break; - iunlock(&d->Lock); + spin_unlock_irqsave(&d->Lock); newdrive(d); - ilock(&d->Lock); + spin_lock_irqsave(&d->Lock); break; } break; @@ -1211,43 +1233,42 @@ static void checkdrive(Drive *d, int i) /* fallthrough */ case Derror: case Dreset: - dprint("%s: reset [%s]: mode %d; status %06#x\n", name, + printd("%s: reset [%s]: mode %d; status %06#x\n", name, diskstates[d->state], d->mode, s); - iunlock(&d->Lock); + spin_unlock_irqsave(&d->Lock); resetdisk(d); - ilock(&d->Lock); + spin_lock_irqsave(&d->Lock); break; case Dportreset: portreset: if (d->wait++ & 0xff && (s & Intactive) == 0) break; /* device is active */ - dprint("%s: portreset [%s]: mode %d; status %06#x\n", name, + printd("%s: portreset [%s]: mode %d; status %06#x\n", name, diskstates[d->state], d->mode, s); d->portm.flag |= Ferror; clearci(d->port); - wakeup(&d->portm.Rendez); + rendez_wakeup(&d->portm.Rendez); if ((s & Devdet) == 0) { /* no device */ d->state = Dmissing; break; } - iunlock(&d->Lock); + spin_unlock_irqsave(&d->Lock); doportreset(d); - ilock(&d->Lock); + spin_lock_irqsave(&d->Lock); break; } statechange(d); - iunlock(&d->Lock); + spin_unlock_irqsave(&d->Lock); } static void satakproc(void *v) { - struct proc *up = externup(); int i; for (;;) { - tsleep(&up->sleep, return0, 0, Nms); + kthread_usleep(Nms * 1000); for (i = 0; i < niadrive; i++) - if (iadrive[i] != nil) + if (iadrive[i] != NULL) checkdrive(iadrive[i], i); } } @@ -1256,7 +1277,7 @@ static void isctlrjabbering(struct ctlr *c, uint32_t cause) { uint32_t now; - now = TK2MS(sys->ticks); + now = ms(); if (now > c->lastintr0) { c->intrs = 0; c->lastintr0 = now; @@ -1269,36 +1290,35 @@ static void isctlrjabbering(struct ctlr *c, uint32_t cause) } } -static void isdrivejabbering(Drive *d) +static void isdrivejabbering(struct drive *d) { - uint32_t now; + uint32_t now = ms(); - now = TK2MS(sys->ticks); if (now > d->lastintr0) { d->intrs = 0; d->lastintr0 = now; } if (++d->intrs > Maxintrspertick) { iprint("sdiahci: %lu interrupts per tick for %s\n", d->intrs, - d->unit->SDperm.name); + d->unit->sdperm.name); d->intrs = 0; } } -static void iainterrupt(Ureg *u, void *a) +static void iainterrupt(struct hw_trapframe *unused_hw_trapframe, void *a) { int i; uint32_t cause, mask; struct ctlr *c; - Drive *d; + struct drive *d; c = a; - ilock(&c->Lock); + spin_lock_irqsave(&c->Lock); cause = c->hba->isr; if (cause == 0) { isctlrjabbering(c, cause); // iprint("sdiahci: interrupt for no drive\n"); - iunlock(&c->Lock); + spin_unlock_irqsave(&c->Lock); return; } for (i = 0; cause && i <= c->mport; i++) { @@ -1306,12 +1326,12 @@ static void iainterrupt(Ureg *u, void *a) if ((cause & mask) == 0) continue; d = c->rawdrive + i; - ilock(&d->Lock); + spin_lock_irqsave(&d->Lock); isdrivejabbering(d); if (d->port->isr && c->hba->pi & mask) updatedrive(d); c->hba->isr = mask; - iunlock(&d->Lock); + spin_unlock_irqsave(&d->Lock); cause &= ~mask; } @@ -1319,27 +1339,27 @@ static void iainterrupt(Ureg *u, void *a) isctlrjabbering(c, cause); iprint("sdiachi: intr cause unserviced: %#lx\n", cause); } - iunlock(&c->Lock); + spin_unlock_irqsave(&c->Lock); } /* checkdrive, called from satakproc, will prod the drive while we wait */ -static void awaitspinup(Drive *d) +static void awaitspinup(struct drive *d) { int ms; uint16_t s; char *name; - ilock(&d->Lock); - if (d->unit == nil || d->port == nil) { - panic("awaitspinup: nil d->unit or d->port"); - iunlock(&d->Lock); + spin_lock_irqsave(&d->Lock); + if (d->unit == NULL || d->port == NULL) { + panic("awaitspinup: NULL d->unit or d->port"); + spin_unlock_irqsave(&d->Lock); return; } - name = (d->unit ? d->unit->SDperm.name : nil); + name = (d->unit ? d->unit->sdperm.name : NULL); s = d->port->sstatus; if (!(s & Devpresent)) { /* never going to be ready */ - dprint("awaitspinup: %s absent, not waiting\n", name); - iunlock(&d->Lock); + printd("awaitspinup: %s absent, not waiting\n", name); + spin_unlock_irqsave(&d->Lock); return; } @@ -1347,15 +1367,15 @@ static void awaitspinup(Drive *d) switch (d->state) { case Dnull: /* absent; done */ - iunlock(&d->Lock); - dprint("awaitspinup: %s in null state\n", name); + spin_unlock_irqsave(&d->Lock); + printd("awaitspinup: %s in null state\n", name); return; case Dready: case Dnew: if (d->sectors || d->mediachange) { /* ready to use; done */ - iunlock(&d->Lock); - dprint("awaitspinup: %s ready!\n", name); + spin_unlock_irqsave(&d->Lock); + printd("awaitspinup: %s ready!\n", name); return; } /* fall through */ @@ -1365,27 +1385,27 @@ static void awaitspinup(Drive *d) case Doffline: /* transitional states */ case Derror: case Dportreset: - iunlock(&d->Lock); + spin_unlock_irqsave(&d->Lock); asleep(50); - ilock(&d->Lock); + spin_lock_irqsave(&d->Lock); break; } - print("awaitspinup: %s didn't spin up after 20 seconds\n", name); - iunlock(&d->Lock); + printd("awaitspinup: %s didn't spin up after 20 seconds\n", name); + spin_unlock_irqsave(&d->Lock); } static int iaverify(struct sdunit *u) { struct ctlr *c; - Drive *d; + struct drive *d; c = u->dev->ctlr; d = c->drive[u->subno]; - ilock(&c->Lock); - ilock(&d->Lock); + spin_lock_irqsave(&c->Lock); + spin_lock_irqsave(&d->Lock); d->unit = u; - iunlock(&d->Lock); - iunlock(&c->Lock); + spin_unlock_irqsave(&d->Lock); + spin_unlock_irqsave(&c->Lock); checkdrive(d, d->driveno); /* c->d0 + d->driveno */ /* @@ -1404,22 +1424,25 @@ static int iaenable(struct sdev *s) static int once; c = s->ctlr; - ilock(&c->Lock); + spin_lock_irqsave(&c->Lock); if (!c->enabled) { if (once == 0) { once = 1; - kproc("ahci", satakproc, 0); + ktask("ahci", satakproc, 0); } if (c->ndrive == 0) panic("iaenable: zero s->ctlr->ndrive"); - pcisetbme(c->pci); - snprint(name, sizeof name, "%s (%s)", s->name, s->ifc->name); - c->vec = intrenable(c->pci->intl, iainterrupt, c, c->pci->tbdf, name); + pci_set_bus_master(c->pci); + snprintf(name, sizeof(name), "%s (%s)", s->name, s->ifc->name); + /*c->vector = intrenable(c->pci->intl, iainterrupt, c, c->pci->tbdf, + *name);*/ + /* what do we do about the arg? */ + register_irq(c->pci->irqline, iainterrupt, c, pci_to_tbdf(c->pci)); /* supposed to squelch leftover interrupts here. */ ahcienable(c->hba); c->enabled = 1; } - iunlock(&c->Lock); + spin_unlock_irqsave(&c->Lock); return 1; } @@ -1429,12 +1452,13 @@ static int iadisable(struct sdev *s) struct ctlr *c; c = s->ctlr; - ilock(&c->Lock); + spin_lock_irqsave(&c->Lock); ahcidisable(c->hba); - snprint(name, sizeof name, "%s (%s)", s->name, s->ifc->name); - intrdisable(c->vec); + snprintf(name, sizeof(name), "%s (%s)", s->name, s->ifc->name); + // TODO: what to do here? + // intrdisable(c->vector); c->enabled = 0; - iunlock(&c->Lock); + spin_unlock_irqsave(&c->Lock); return 1; } @@ -1442,20 +1466,20 @@ static int iaonline(struct sdunit *unit) { int r; struct ctlr *c; - Drive *d; + struct drive *d; c = unit->dev->ctlr; d = c->drive[unit->subno]; r = 0; - if (d->portm.feat & Datapi && d->mediachange) { + if ((d->portm.feat & Datapi) && d->mediachange) { r = scsionline(unit); if (r > 0) d->mediachange = 0; return r; } - ilock(&d->Lock); + spin_lock_irqsave(&d->Lock); if (d->mediachange) { r = 2; d->mediachange = 0; @@ -1464,13 +1488,13 @@ static int iaonline(struct sdunit *unit) unit->secsize = 512; /* default size */ } else if (d->state == Dready) r = 1; - iunlock(&d->Lock); + spin_unlock_irqsave(&d->Lock); return r; } /* returns locked list! */ -static struct alist *ahcibuild(Drive *d, unsigned char *cmd, void *data, int n, - int64_t lba) +static struct alist *ahcibuild(struct drive *d, unsigned char *cmd, void *data, + int n, int64_t lba) { unsigned char *c, acmd, dir, llba; struct alist *l; @@ -1478,7 +1502,7 @@ static struct alist *ahcibuild(Drive *d, unsigned char *cmd, void *data, int n, struct aportm *pm; struct aprdt *p; static unsigned char tab[2][2] = { - 0xc8, 0x25, 0xca, 0x35, + {0xc8, 0x25}, {0xca, 0x35}, }; pm = &d->portm; @@ -1524,8 +1548,8 @@ static struct alist *ahcibuild(Drive *d, unsigned char *cmd, void *data, int n, p = &t->prdt; p->dba = PCIWADDR(data); p->dbahi = 0; - if (d->unit == nil) - panic("ahcibuild: nil d->unit"); + if (d->unit == NULL) + panic("ahcibuild: NULL d->unit"); p->count = 1 << 31 | (d->unit->secsize * n - 2) | 1; return l; @@ -1586,31 +1610,31 @@ static struct alist *ahcibuildpkt(struct aportm *pm, struct sdreq *r, return l; } -static int waitready(Drive *d) +static int waitready(struct drive *d) { uint32_t s, i, delta; for (i = 0; i < 15000; i += 250) { if (d->state == Dreset || d->state == Dportreset || d->state == Dnew) return 1; - delta = sys->ticks - d->lastseen; + delta = ms() - d->lastseen; if (d->state == Dnull || delta > 10 * 1000) return -1; - ilock(&d->Lock); + spin_lock_irqsave(&d->Lock); s = d->port->sstatus; - iunlock(&d->Lock); + spin_unlock_irqsave(&d->Lock); if ((s & Intpm) == 0 && delta > 1500) return -1; /* no detect */ if (d->state == Dready && (s & Devdet) == (Devphycomm | Devpresent)) return 0; /* ready, present & phy. comm. */ esleep(250); } - print("%s: not responding; offline\n", d->unit->SDperm.name); + printd("%s: not responding; offline\n", d->unit->sdperm.name); setstate(d, Doffline); return -1; } -static int lockready(Drive *d) +static int lockready(struct drive *d) { int i; @@ -1623,7 +1647,7 @@ static int lockready(Drive *d) return i; } -static int flushcache(Drive *d) +static int flushcache(struct drive *d) { int i; @@ -1634,30 +1658,28 @@ static int flushcache(Drive *d) return i; } -static int iariopkt(struct sdreq *r, Drive *d) +static int iariopkt(struct sdreq *r, struct drive *d) { - struct proc *up = externup(); - int n, count, try - , max, flag, task, wormwrite; + ERRSTACK(2); + int n, count, try, max, flag, task, wormwrite; char *name; unsigned char *cmd, *data; struct aport *p; - Asleep as; + struct Asleep as; cmd = r->cmd; - name = d->unit->SDperm.name; + name = d->unit->sdperm.name; p = d->port; - aprint("ahci: iariopkt: %04#x %04#x %c %d %p\n", cmd[0], cmd[2], - "rw"[r->write], r->dlen, r->data); + aprintd("ahci: iariopkt: %04#x %04#x %c %d %p\n", cmd[0], cmd[2], + "rw"[r->write], r->dlen, r->data); if (cmd[0] == 0x5a && (cmd[2] & 0x3f) == 0x3f) return sdmodesense(r, cmd, d->info, d->infosz); r->rlen = 0; count = r->dlen; max = 65536; - try - = 0; + try = 0; retry: data = r->data; n = count; @@ -1675,35 +1697,36 @@ retry: } /* d->portm qlock held here */ - ilock(&d->Lock); + spin_lock_irqsave(&d->Lock); d->portm.flag = 0; - iunlock(&d->Lock); + spin_unlock_irqsave(&d->Lock); p->ci = 1; as.p = p; as.i = 1; - d->intick = sys->ticks; + d->intick = ms(); d->active++; while (waserror()) ; /* don't sleep here forever */ - tsleep(&d->portm.Rendez, ahciclear, &as, 3 * 1000); + rendez_sleep_timeout(&d->portm.Rendez, ahciclear, &as, (3 * 1000) * 1000); poperror(); if (!ahciclear(&as)) { qunlock(&d->portm.ql); - print("%s: ahciclear not true after 3 seconds\n", name); + printd("%s: ahciclear not true after 3 seconds\n", name); r->status = SDcheck; return SDcheck; } d->active--; - ilock(&d->Lock); + spin_lock_irqsave(&d->Lock); flag = d->portm.flag; task = d->port->task; - iunlock(&d->Lock); + spin_unlock_irqsave(&d->Lock); - if (task & (Efatal << 8) || task & (ASbsy | ASdrq) && d->state == Dready) { + if ((task & (Efatal << 8)) || + ((task & (ASbsy | ASdrq)) && (d->state == Dready))) { d->port->ci = 0; ahcirecover(&d->portc); task = d->port->task; @@ -1712,7 +1735,7 @@ retry: qunlock(&d->portm.ql); if (flag == 0) { if (++try == 10) { - print("%s: bad disk\n", name); + printd("%s: bad disk\n", name); r->status = SDcheck; return SDcheck; } @@ -1735,13 +1758,13 @@ retry: break; } if (!wormwrite) { - print("%s: retry\n", name); + printd("%s: retry\n", name); goto retry; } } if (flag & Ferror) { if ((task & Eidnf) == 0) - print("%s: i/o error task=%#x\n", name, task); + printd("%s: i/o error task=%#x\n", name, task); r->status = SDcheck; return SDcheck; } @@ -1755,16 +1778,15 @@ retry: static int iario(struct sdreq *r) { - struct proc *up = externup(); - int i, n, count, try - , max, flag, task; + ERRSTACK(2); + int i, n, count, try, max, flag, task; int64_t lba; char *name; unsigned char *cmd, *data; struct aport *p; - Asleep as; + struct Asleep as; struct ctlr *c; - Drive *d; + struct drive *d; struct sdunit *unit; unit = r->unit; @@ -1773,7 +1795,7 @@ static int iario(struct sdreq *r) if (d->portm.feat & Datapi) return iariopkt(r, d); cmd = r->cmd; - name = d->unit->SDperm.name; + name = d->unit->sdperm.name; p = d->port; if (r->cmd[0] == 0x35 || r->cmd[0] == 0x91) { @@ -1788,21 +1810,20 @@ static int iario(struct sdreq *r) } if (*cmd != 0x28 && *cmd != 0x2a) { - print("%s: bad cmd %.2#x\n", name, cmd[0]); + printd("%s: bad cmd %.2#x\n", name, cmd[0]); r->status = SDcheck; return SDcheck; } lba = cmd[2] << 24 | cmd[3] << 16 | cmd[4] << 8 | cmd[5]; count = cmd[7] << 8 | cmd[8]; - if (r->data == nil) + if (r->data == NULL) return SDok; if (r->dlen < count * unit->secsize) count = r->dlen / unit->secsize; max = 128; - try - = 0; + try = 0; retry: data = r->data; while (count > 0) { @@ -1820,36 +1841,37 @@ retry: goto retry; } /* d->portm qlock held here */ - ilock(&d->Lock); + spin_lock_irqsave(&d->Lock); d->portm.flag = 0; - iunlock(&d->Lock); + spin_unlock_irqsave(&d->Lock); p->ci = 1; as.p = p; as.i = 1; - d->intick = sys->ticks; + d->intick = ms(); d->active++; while (waserror()) ; /* don't sleep here forever */ - tsleep(&d->portm.Rendez, ahciclear, &as, 3 * 1000); + rendez_sleep_timeout(&d->portm.Rendez, ahciclear, &as, + (3 * 1000) * 1000); poperror(); if (!ahciclear(&as)) { qunlock(&d->portm.ql); - print("%s: ahciclear not true after 3 seconds\n", name); + printd("%s: ahciclear not true after 3 seconds\n", name); r->status = SDcheck; return SDcheck; } d->active--; - ilock(&d->Lock); + spin_lock_irqsave(&d->Lock); flag = d->portm.flag; task = d->port->task; - iunlock(&d->Lock); + spin_unlock_irqsave(&d->Lock); - if (task & (Efatal << 8) || - task & (ASbsy | ASdrq) && d->state == Dready) { + if ((task & (Efatal << 8)) || + ((task & (ASbsy | ASdrq)) && d->state == Dready)) { d->port->ci = 0; ahcirecover(&d->portc); task = d->port->task; @@ -1857,15 +1879,15 @@ retry: qunlock(&d->portm.ql); if (flag == 0) { if (++try == 10) { - print("%s: bad disk\n", name); + printd("%s: bad disk\n", name); r->status = SDeio; return SDeio; } - print("%s: retry blk %lld\n", name, lba); + printd("%s: retry blk %lld\n", name, lba); goto retry; } if (flag & Ferror) { - print("%s: i/o error task=%#x @%,lld\n", name, task, lba); + printk("%s: i/o error task=%#x @%,lld\n", name, task, lba); r->status = SDeio; return SDeio; } @@ -1883,62 +1905,62 @@ retry: * configure drives 0-5 as ahci sata (c.f. errata). * what about 6 & 7, as claimed by marvell 0x9123? */ -static int iaahcimode(Pcidev *p) +static int iaahcimode(struct pci_device *p) { - dprint("iaahcimode: %#x %#x %#x\n", pcicfgr8(p, 0x91), pcicfgr8(p, 92), - pcicfgr8(p, 93)); - pcicfgw16(p, 0x92, pcicfgr16(p, 0x92) | 0x3f); /* ports 0-5 */ + printd("iaahcimode: %#x %#x %#x\n", pcidev_read8(p, 0x91), + pcidev_read8(p, 92), pcidev_read8(p, 93)); + pcidev_write16(p, 0x92, pcidev_read16(p, 0x92) | 0x3f); /* ports 0-5 */ return 0; } static void iasetupahci(struct ctlr *c) { + uint32_t *p = (void *)c->mmio; /* disable cmd block decoding. */ - pcicfgw16(c->pci, 0x40, pcicfgr16(c->pci, 0x40) & ~(1 << 15)); - pcicfgw16(c->pci, 0x42, pcicfgr16(c->pci, 0x42) & ~(1 << 15)); + pcidev_write16(c->pci, 0x40, pcidev_read16(c->pci, 0x40) & ~(1 << 15)); + pcidev_write16(c->pci, 0x42, pcidev_read16(c->pci, 0x42) & ~(1 << 15)); - c->lmmio[0x4 / 4] |= 1 << 31; /* enable ahci mode (ghc register) */ - c->lmmio[0xc / 4] = (1 << 6) - 1; /* 5 ports. (supposedly ro pi reg.) */ + p[0x4 / 4] |= 1 << 31; /* enable ahci mode (ghc register) */ + p[0xc / 4] = (1 << 6) - 1; /* 5 ports. (supposedly ro pi reg.) */ /* enable ahci mode and 6 ports; from ich9 datasheet */ - pcicfgw16(c->pci, 0x90, 1 << 6 | 1 << 5); + pcidev_write16(c->pci, 0x90, 1 << 6 | 1 << 5); } -static int didtype(Pcidev *p) +static int didtype(struct pci_device *p) { - switch (p->vid) { + switch (p->ven_id) { case Vintel: - if ((p->did & 0xfffc) == 0x2680) + if ((p->dev_id & 0xfffc) == 0x2680) return Tesb; /* * 0x27c4 is the intel 82801 in compatibility (not sata) mode. */ - if (p->did == 0x1e02 || /* c210 */ - p->did == 0x24d1 || /* 82801eb/er */ - (p->did & 0xfffb) == 0x27c1 || /* 82801g[bh]m ich7 */ - p->did == 0x2821 || /* 82801h[roh] */ - (p->did & 0xfffe) == 0x2824 || /* 82801h[b] */ - (p->did & 0xfeff) == 0x2829 || /* ich8/9m */ - (p->did & 0xfffe) == 0x2922 || /* ich9 */ - p->did == 0x3a02 || /* 82801jd/do */ - (p->did & 0xfefe) == 0x3a22 || /* ich10, pch */ - (p->did & 0xfff8) == 0x3b28) /* pchm */ + if (p->dev_id == 0x1e02 || /* c210 */ + p->dev_id == 0x24d1 || /* 82801eb/er */ + (p->dev_id & 0xfffb) == 0x27c1 || /* 82801g[bh]m ich7 */ + p->dev_id == 0x2821 || /* 82801h[roh] */ + (p->dev_id & 0xfffe) == 0x2824 || /* 82801h[b] */ + (p->dev_id & 0xfeff) == 0x2829 || /* ich8/9m */ + (p->dev_id & 0xfffe) == 0x2922 || /* ich9 */ + p->dev_id == 0x3a02 || /* 82801jd/do */ + (p->dev_id & 0xfefe) == 0x3a22 || /* ich10, pch */ + (p->dev_id & 0xfff8) == 0x3b28) /* pchm */ return Tich; break; case Vatiamd: - if (p->did == 0x4380 || p->did == 0x4390 || p->did == 0x4391) { - print("detected sb600 vid %#x did %#x\n", p->vid, p->did); + if (p->dev_id == 0x4380 || p->dev_id == 0x4390 || p->dev_id == 0x4391) { + printd("detected sb600 vid %#x did %#x\n", p->ven_id, p->dev_id); return Tsb600; } break; case Vmarvell: - if (p->did == 0x9123) - print("ahci: marvell sata 3 controller has delusions " - "of something on unit 7\n"); + if (p->dev_id == 0x9123) + printk("ahci: marvell sata 3 controller has delusions of something on unit 7\n"); break; } - if (p->ccrb == Pcibcstore && p->ccru == Pciscsata && p->ccrp == 1) { - print("ahci: Tunk: vid %#4.4x did %#4.4x\n", p->vid, p->did); + if (p->class == Pcibcstore && p->subclass == Pciscsata && p->progif == 1) { + printd("ahci: Tunk: vid %#4.4x did %#4.4x\n", p->ven_id, p->dev_id); return Tunk; } return -1; @@ -1947,23 +1969,24 @@ static int didtype(Pcidev *p) static int newctlr(struct ctlr *ctlr, struct sdev *sdev, int nunit) { int i, n; - Drive *drive; + struct drive *drive; ctlr->ndrive = sdev->nunit = nunit; ctlr->mport = ctlr->hba->cap & ((1 << 5) - 1); i = (ctlr->hba->cap >> 20) & ((1 << 4) - 1); /* iss */ - print("#S/sd%c: %s: %#p %s, %d ports, irq %d\n", sdev->idno, Tname(ctlr), - ctlr->physio, descmode[i], nunit, ctlr->pci->intl); + printk("#S/sd%c: %s: %#p %s, %d ports, irq %d\n", sdev->idno, Tname(ctlr), + ctlr->physio, descmode[i], nunit, ctlr->pci->irqline); /* map the drives -- they don't all need to be enabled. */ n = 0; - ctlr->rawdrive = malloc(NCtlrdrv * sizeof(Drive)); - if (ctlr->rawdrive == nil) { - print("ahci: out of memory\n"); + ctlr->rawdrive = kzmalloc(NCtlrdrv * sizeof(struct drive), 0); + if (ctlr->rawdrive == NULL) { + printd("ahci: out of memory\n"); return -1; } for (i = 0; i < NCtlrdrv; i++) { drive = ctlr->rawdrive + i; + spinlock_init(&drive->Lock); drive->portno = i; drive->driveno = -1; drive->sectors = 0; @@ -1974,13 +1997,15 @@ static int newctlr(struct ctlr *ctlr, struct sdev *sdev, int nunit) drive->port = (struct aport *)(ctlr->mmio + 0x80 * i + 0x100); drive->portc.p = drive->port; drive->portc.pm = &drive->portm; + qlock_init(&drive->portm.ql); + rendez_init(&drive->portm.Rendez); drive->driveno = n++; ctlr->drive[drive->driveno] = drive; iadrive[niadrive + drive->driveno] = drive; } for (i = 0; i < n; i++) if (ahciidle(ctlr->drive[i]->port) == -1) { - dprint("ahci: %s: port %d wedged; abort\n", Tname(ctlr), i); + printd("ahci: %s: port %d wedged; abort\n", Tname(ctlr), i); return -1; } for (i = 0; i < n; i++) { @@ -1990,42 +2015,50 @@ static int newctlr(struct ctlr *ctlr, struct sdev *sdev, int nunit) return n; } +static void releasedrive(struct kref *kref) +{ + printk("release drive called, but we don't do that yet\n"); +} + static struct sdev *iapnp(void) { int n, nunit, type; - uintptr_t io; struct ctlr *c; - Pcidev *p; + struct pci_device *p; struct sdev *head, *tail, *s; - static int done; - if (done++) - return nil; + // TODO: ensure we're only called once. memset(olds, 0xff, sizeof olds); - p = nil; - head = tail = nil; - while ((p = pcimatch(p, 0, 0)) != nil) { + p = NULL; + head = tail = NULL; + STAILQ_FOREACH(p, &pci_devices, all_dev) { type = didtype(p); - if (type == -1 || p->mem[Abar].bar == 0) + printd("didtype: %d\n", type); + if (type == -1) + continue; + if (p->bar[Abar].mmio_base32 == 0) continue; if (niactlr == NCtlr) { - print("ahci: iapnp: %s: too many controllers\n", tname[type]); + printk("ahci: iapnp: %s: too many controllers\n", tname[type]); break; } c = iactlr + niactlr; s = sdevs + niactlr; memset(c, 0, sizeof *c); memset(s, 0, sizeof *s); - io = p->mem[Abar].bar & ~0xf; - c->physio = (unsigned char *)io; - c->mmio = vmap(io, p->mem[Abar].size); + kref_init(&s->r, releasedrive, 1); + qlock_init(&s->ql); + qlock_init(&s->unitlock); + c->physio = p->bar[Abar].mmio_base32 & ~0xf; + c->mmio = vmap_pmem_nocache(c->physio, p->bar[Abar].mmio_sz); if (c->mmio == 0) { - print("ahci: %s: address %#lX in use did=%#x\n", Tname(c), io, - p->did); + printk("ahci: %s: address %#lX in use did=%#x\n", Tname(c), + c->physio, p->dev_id); continue; } - c->lmmio = (uint32_t *)c->mmio; + printk("sdiahci %s: Mapped %p/%d to %p\n", tname[type], c->physio, + p->bar[Abar].mmio_sz, c->mmio); c->pci = p; c->type = type; @@ -2034,14 +2067,14 @@ static struct sdev *iapnp(void) s->ctlr = c; c->sdev = s; - if (Intel(c) && p->did != 0x2681) + if (Intel(c) && p->dev_id != 0x2681) iasetupahci(c); nunit = ahciconf(c); // ahcihbareset((Ahba*)c->mmio); if (Intel(c) && iaahcimode(p) == -1) break; if (nunit < 1) { - vunmap(c->mmio, p->mem[Abar].size); + vunmap_vmem(c->mmio, p->bar[Abar].mmio_sz); continue; } n = newctlr(c, s, nunit); @@ -2066,8 +2099,8 @@ static char *pflag(char *s, char *e, unsigned char f) for (i = 0; i < 8; i++) if (f & (1 << i)) - s = seprint(s, e, "%s ", flagname[i]); - return seprint(s, e, "\n"); + s = seprintf(s, e, "%s ", flagname[i]); + return seprintf(s, e, "\n"); } static int iarctl(struct sdunit *u, char *p, int l) @@ -2076,11 +2109,11 @@ static int iarctl(struct sdunit *u, char *p, int l) char *e, *op; struct aport *o; struct ctlr *c; - Drive *d; + struct drive *d; c = u->dev->ctlr; - if (c == nil) { - print("iarctl: nil u->dev->ctlr\n"); + if (c == NULL) { + printk("iarctl: nil u->dev->ctlr\n"); return 0; } d = c->drive[u->subno]; @@ -2089,79 +2122,79 @@ static int iarctl(struct sdunit *u, char *p, int l) e = p + l; op = p; if (d->state == Dready) { - p = seprint(p, e, "model\t%s\n", d->model); - p = seprint(p, e, "serial\t%s\n", d->serial); - p = seprint(p, e, "firm\t%s\n", d->firmware); + p = seprintf(p, e, "model\t%s\n", d->model); + p = seprintf(p, e, "serial\t%s\n", d->serial); + p = seprintf(p, e, "firm\t%s\n", d->firmware); if (d->smartrs == 0xff) - p = seprint(p, e, "smart\tenable error\n"); + p = seprintf(p, e, "smart\tenable error\n"); else if (d->smartrs == 0) - p = seprint(p, e, "smart\tdisabled\n"); + p = seprintf(p, e, "smart\tdisabled\n"); else - p = seprint(p, e, "smart\t%s\n", smarttab[d->portm.smart]); - p = seprint(p, e, "flag\t"); + p = seprintf(p, e, "smart\t%s\n", smarttab[d->portm.smart]); + p = seprintf(p, e, "flag\t"); p = pflag(p, e, d->portm.feat); } else - p = seprint(p, e, "no disk present [%s]\n", diskstates[d->state]); + p = seprintf(p, e, "no disk present [%s]\n", diskstates[d->state]); serrstr(o->serror, buf, buf + sizeof buf - 1); - p = seprint(p, e, "reg\ttask %#lx cmd %#lx serr %#lx %s ci %#lx " - "is %#lx; sig %#lx sstatus %06#lx\n", - o->task, o->cmd, o->serror, buf, o->ci, o->isr, o->sig, - o->sstatus); - if (d->unit == nil) + p = seprintf(p, e, + "reg\ttask %#lx cmd %#lx serr %#lx %s ci %#lx is %#lx; sig %#lx sstatus %06#lx\n", + o->task, o->cmd, o->serror, buf, o->ci, o->isr, o->sig, + o->sstatus); + if (d->unit == NULL) panic("iarctl: nil d->unit"); - p = seprint(p, e, "geometry %llu %lu\n", d->sectors, d->unit->secsize); + p = seprintf(p, e, "geometry %llu %lu\n", d->sectors, d->unit->secsize); return p - op; } -static void runflushcache(Drive *d) +static void runflushcache(struct drive *d) { int32_t t0; - t0 = sys->ticks; + t0 = ms(); if (flushcache(d) != 0) - error(Eio); - dprint("ahci: flush in %ld ms\n", sys->ticks - t0); + error(EIO, "Flush cache failed"); + printd("ahci: flush in %ld ms\n", ms() - t0); } -static void forcemode(Drive *d, char *mode) +static void forcemode(struct drive *d, char *mode) { int i; - for (i = 0; i < nelem(modename); i++) + for (i = 0; i < ARRAY_SIZE(modename); i++) if (strcmp(mode, modename[i]) == 0) break; - if (i == nelem(modename)) + if (i == ARRAY_SIZE(modename)) i = 0; - ilock(&d->Lock); + spin_lock_irqsave(&d->Lock); d->mode = i; - iunlock(&d->Lock); + spin_unlock_irqsave(&d->Lock); } -static void runsmartable(Drive *d, int i) +static void runsmartable(struct drive *d, int i) { - struct proc *up = externup(); + ERRSTACK(2); if (waserror()) { qunlock(&d->portm.ql); d->smartrs = 0; nexterror(); } if (lockready(d) == -1) - error(Eio); + error(EIO, "runsmartable: lockready returned -1"); d->smartrs = smart(&d->portc, i); d->portm.smart = 0; qunlock(&d->portm.ql); poperror(); } -static void forcestate(Drive *d, char *state) +static void forcestate(struct drive *d, char *state) { int i; - for (i = 0; i < nelem(diskstates); i++) + for (i = 0; i < ARRAY_SIZE(diskstates); i++) if (strcmp(state, diskstates[i]) == 0) break; - if (i == nelem(diskstates)) - error(Ebadctl); + if (i == ARRAY_SIZE(diskstates)) + error(EINVAL, "Can't set state to invalid value '%s'", state); setstate(d, i); } @@ -2172,23 +2205,23 @@ static void forcestate(Drive *d, char *state) static void changemedia(struct sdunit *u) { struct ctlr *c; - Drive *d; + struct drive *d; c = u->dev->ctlr; d = c->drive[u->subno]; - ilock(&d->Lock); + spin_lock_irqsave(&d->Lock); d->mediachange = 1; u->sectors = 0; - iunlock(&d->Lock); + spin_unlock_irqsave(&d->Lock); } static int iawctl(struct sdunit *u, struct cmdbuf *cmd) { - struct proc *up = externup(); + ERRSTACK(2); char **f; struct ctlr *c; - Drive *d; - uint i; + struct drive *d; + unsigned int i; c = u->dev->ctlr; d = c->drive[u->subno]; @@ -2202,12 +2235,12 @@ static int iawctl(struct sdunit *u, struct cmdbuf *cmd) i = strtoul(f[1] ? f[1] : "0", 0, 0); if (i > 0xff) i = 0; - dprint("ahci: %04d %#x\n", i, d->info[i]); + printd("ahci: %04d %#x\n", i, d->info[i]); } else if (strcmp(f[0], "mode") == 0) forcemode(d, f[1] ? f[1] : "satai"); else if (strcmp(f[0], "nop") == 0) { if ((d->portm.feat & Dnop) == 0) { - cmderror(cmd, "no drive support"); + sdierror(cmd, "no drive support"); return -1; } if (waserror()) { @@ -2215,24 +2248,22 @@ static int iawctl(struct sdunit *u, struct cmdbuf *cmd) nexterror(); } if (lockready(d) == -1) - error(Eio); + error(EIO, "%s: lockready returned -1", __func__); nop(&d->portc); qunlock(&d->portm.ql); poperror(); } else if (strcmp(f[0], "reset") == 0) forcestate(d, "reset"); else if (strcmp(f[0], "smart") == 0) { - if (d->smartrs == 0) { - cmderror(cmd, "smart not enabled"); - return -1; - } + if (d->smartrs == 0) + sdierror(cmd, "smart not enabled"); if (waserror()) { qunlock(&d->portm.ql); d->smartrs = 0; nexterror(); } if (lockready(d) == -1) - error(Eio); + error(EIO, "%s: lockready returned -1", __func__); d->portm.smart = 2 + smartrs(&d->portc); qunlock(&d->portm.ql); poperror(); @@ -2243,13 +2274,13 @@ static int iawctl(struct sdunit *u, struct cmdbuf *cmd) else if (strcmp(f[0], "state") == 0) forcestate(d, f[1] ? f[1] : "null"); else { - cmderror(cmd, Ebadctl); + sdierror(cmd, "%s: unknown control '%s'", __func__, f[0]); return -1; } return 0; } -static char *portr(char *p, char *e, uint x) +static char *portr(char *p, char *e, unsigned int x) { int i, a; @@ -2258,18 +2289,18 @@ static char *portr(char *p, char *e, uint x) for (i = 0; i < 32; i++) { if ((x & (1 << i)) == 0) { if (a != -1 && i - 1 != a) - p = seprint(p, e, "-%d", i - 1); + p = seprintf(p, e, "-%d", i - 1); a = -1; continue; } if (a == -1) { if (i > 0) - p = seprint(p, e, ", "); - p = seprint(p, e, "%d", a = i); + p = seprintf(p, e, ", "); + p = seprintf(p, e, "%d", a = i); } } if (a != -1 && i - 1 != a) - p = seprint(p, e, "-%d", i - 1); + p = seprintf(p, e, "-%d", i - 1); return p; } @@ -2282,12 +2313,14 @@ static char *iartopctl(struct sdev *sdev, char *p, char *e) struct ctlr *ctlr; #define has(x, str) \ - if (cap & (x)) \ - p = seprint(p, e, "%s ", (str)) + do { \ + if (cap & (x)) \ + p = seprintf(p, e, "%s ", (str)); \ + } while (0) ctlr = sdev->ctlr; hba = ctlr->hba; - p = seprint(p, e, "sd%c ahci port %#p: ", sdev->idno, ctlr->physio); + p = seprintf(p, e, "sd%c ahci port %#p: ", sdev->idno, ctlr->physio); cap = hba->cap; has(Hs64a, "64a"); has(Hsalp, "alp"); @@ -2305,7 +2338,7 @@ static char *iartopctl(struct sdev *sdev, char *p, char *e) has(Hsss, "ss"); has(Hsxs, "sxs"); portr(pr, pr + sizeof pr, hba->pi); - return seprint( + return seprintf( p, e, "iss %ld ncs %ld np %ld; ghc %#lx isr %#lx pi %#lx %s ver %#lx\n", (cap >> 20) & 0xf, (cap >> 8) & 0x1f, 1 + (cap & 0x1f), hba->ghc, hba->isr, hba->pi, pr, hba->ver); @@ -2320,20 +2353,20 @@ static int iawtopctl(struct sdev *sdev, struct cmdbuf *cmd) f = cmd->f; v = 0; - if (f[0] == nil) + if (f[0] == NULL) return 0; if (strcmp(f[0], "debug") == 0) v = &debug; - else if (strcmp(f[0], "idprint") == 0) + else if (strcmp(f[0], "iprintd") == 0) v = &prid; else if (strcmp(f[0], "aprint") == 0) v = &datapi; else - cmderror(cmd, Ebadctl); + sdierror(cmd, "%s: bad control '%s'", __func__, f[0]); switch (cmd->nf) { default: - cmderror(cmd, Ebadarg); + sdierror(cmd, "%s: %d args, only 1 or 2 allowed", __func__, cmd->nf); case 1: *v ^= 1; break; @@ -2348,19 +2381,22 @@ static int iawtopctl(struct sdev *sdev, struct cmdbuf *cmd) } struct sdifc sdiahciifc = { - .name = "iahci", - - .pnp = iapnp, - .enable = iaenable, - .disable = iadisable, - - .verify = iaverify, - .online = iaonline, - .rio = iario, - .rctl = iarctl, - .wctl = iawctl, - - .bio = scsibio, - .rtopctl = iartopctl, - .wtopctl = iawtopctl, + "iahci", + + iapnp, + NULL, /* legacy */ + iaenable, + iadisable, + + iaverify, + iaonline, + iario, + iarctl, + iawctl, + + scsibio, + NULL, /* probe */ + NULL, /* clear */ + iartopctl, + iawtopctl, }; diff --git a/kern/drivers/dev/sdscsi.c b/kern/drivers/dev/sdscsi.c index 3b0f998..060e683 100644 --- a/kern/drivers/dev/sdscsi.c +++ b/kern/drivers/dev/sdscsi.c @@ -7,16 +7,21 @@ * in the LICENSE file. */ -#include "../port/error.h" -#include "../port/lib.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "mem.h" -#include "u.h" -#include "ureg.h" - -#include "../port/sd.h" +#include <vfs.h> + +#include <assert.h> +#include <cpio.h> +#include <error.h> +#include <ip.h> +#include <kfs.h> +#include <kmalloc.h> +#include <kref.h> +#include <pmap.h> +#include <sd.h> +#include <slab.h> +#include <smp.h> +#include <stdio.h> +#include <string.h> static int scsitest(struct sdreq *r) { @@ -24,7 +29,7 @@ static int scsitest(struct sdreq *r) memset(r->cmd, 0, sizeof(r->cmd)); r->cmd[1] = r->lun << 5; r->clen = 6; - r->data = nil; + r->data = NULL; r->dlen = 0; r->flags = 0; @@ -39,10 +44,12 @@ int scsiverify(struct sdunit *unit) int i, status; uint8_t *inquiry; - if ((r = malloc(sizeof(struct sdreq))) == nil) + r = kzmalloc(sizeof(struct sdreq), 0); + if (r == NULL) return 0; - if ((inquiry = sdmalloc(sizeof(unit->inquiry))) == nil) { - free(r); + inquiry = kzmalloc(sizeof(unit->inquiry), MEM_WAIT); + if (inquiry == NULL) { + kfree(r); return 0; } r->unit = unit; @@ -60,13 +67,12 @@ int scsiverify(struct sdunit *unit) r->status = ~0; if (unit->dev->ifc->rio(r) != SDok) { - free(r); + kfree(r); return 0; } memmove(unit->inquiry, inquiry, r->dlen); - free(inquiry); + kfree(inquiry); - SET(status); for (i = 0; i < 3; i++) { while ((status = scsitest(r)) == SDbusy) ; @@ -107,7 +113,7 @@ int scsiverify(struct sdunit *unit) r->cmd[1] = (r->lun << 5) | 0x01; r->cmd[4] = 1; r->clen = 6; - r->data = nil; + r->data = NULL; r->dlen = 0; r->flags = 0; @@ -115,7 +121,7 @@ int scsiverify(struct sdunit *unit) unit->dev->ifc->rio(r); } } - free(r); + kfree(r); if (status == SDok || status == SDcheck) return 1; @@ -124,7 +130,7 @@ int scsiverify(struct sdunit *unit) static int scsirio(struct sdreq *r) { - struct proc *up = externup(); + ERRSTACK(1); /* * Perform an I/O request, returning * -1 failure @@ -168,7 +174,7 @@ static int scsirio(struct sdreq *r) while (waserror()) ; - tsleep(&up->sleep, return0, 0, 500); + kthread_usleep(500 * 1000); poperror(); scsitest(r); return 2; @@ -188,10 +194,12 @@ int scsionline(struct sdunit *unit) uint8_t *p; int ok, retries; - if ((r = malloc(sizeof(struct sdreq))) == nil) + r = kzmalloc(sizeof(struct sdreq), 0); + if (r == NULL) return 0; - if ((p = sdmalloc(8)) == nil) { - free(r); + p = kzmalloc(8, 0); + if (p == NULL) { + kfree(r); return 0; } @@ -250,8 +258,8 @@ int scsionline(struct sdunit *unit) } break; } - free(p); - free(r); + kfree(p); + kfree(r); if (ok) return ok + retries; @@ -265,7 +273,8 @@ int scsiexec(struct sdunit *unit, int write, uint8_t *cmd, int clen, void *data, struct sdreq *r; int status; - if ((r = malloc(sizeof(struct sdreq))) == nil) + r = kzmalloc(sizeof(struct sdreq), 0); + if (r == NULL) return SDmalloc; r->unit = unit; r->lun = cmd[1] >> 5; /* ??? */ @@ -304,7 +313,7 @@ int scsiexec(struct sdunit *unit, int write, uint8_t *cmd, int clen, void *data, */ break; } - sdfree(r); + kfree(r); return status; } @@ -367,8 +376,9 @@ int32_t scsibio(struct sdunit *unit, int lun, int write, void *data, int32_t nb, struct sdreq *r; int32_t rlen; - if ((r = malloc(sizeof(struct sdreq))) == nil) - error(Enomem); + r = kzmalloc(sizeof(struct sdreq), 0); + if (r == NULL) + error(ENOMEM, "scsibio: can't allocate %d bytes", sizeof(*r)); r->unit = unit; r->lun = lun; again: @@ -397,8 +407,8 @@ again: default: break; case 0x01: /* recovered error */ - print("%s: recovered error at sector %llu\n", unit->SDperm.name, - bno); + printd("%s: recovered error at sector %llu\n", unit->SDperm.name, + bno); rlen = r->rlen; break; case 0x06: /* check condition */ @@ -423,7 +433,7 @@ again: } break; } - free(r); + kfree(r); return rlen; } diff --git a/kern/include/ahci.h b/kern/include/ahci.h index 2856470..1931fd2 100644 --- a/kern/include/ahci.h +++ b/kern/include/ahci.h @@ -86,7 +86,7 @@ enum { Hhr = 1 << 0, /* hba reset */ }; -typedef struct { +typedef struct abha { uint32_t cap; uint32_t ghc; uint32_t isr; @@ -286,8 +286,8 @@ enum { }; typedef struct aportm { - QLock ql; - Rendez Rendez; + qlock_t ql; + struct rendez Rendez; unsigned char flag; unsigned char feat; unsigned char smart; diff --git a/kern/include/sd.h b/kern/include/sd.h index 8fd386c..13f5e06 100644 --- a/kern/include/sd.h +++ b/kern/include/sd.h @@ -10,92 +10,93 @@ /* * Storage Device. */ -typedef struct SDev SDev; -typedef struct SDifc SDifc; -typedef struct SDio SDio; -typedef struct SDpart SDpart; -typedef struct SDperm SDperm; -typedef struct SDreq SDreq; -typedef struct SDunit SDunit; - -struct SDperm { +struct devconf; +struct sdev; +struct sdifc; +struct sdio; +struct sdpart; +struct sdperm; +struct sdreq; +struct sdunit; + +struct sdperm { char *name; char *user; uint32_t perm; }; -struct SDpart { +struct sdpart { uint64_t start; uint64_t end; - SDperm SDperm; + struct sdperm sdperm; int valid; uint32_t vers; }; -struct SDunit { - SDev *dev; +struct sdunit { + struct sdev *dev; int subno; unsigned char inquiry[255]; /* format follows SCSI spec */ unsigned char sense[18]; /* format follows SCSI spec */ - SDperm SDperm; + struct sdperm sdperm; - QLock ctl; + qlock_t ctl; uint64_t sectors; uint32_t secsize; - SDpart *part; /* nil or array of size npart */ + struct sdpart *part; /* nil or array of size npart */ int npart; uint32_t vers; - SDperm ctlperm; + struct sdperm ctlperm; - QLock raw; /* raw read or write in progress */ + qlock_t raw; /* raw read or write in progress */ uint32_t rawinuse; /* really just a test-and-set */ int state; - SDreq *req; - SDperm rawperm; + struct sdreq *req; + struct sdperm rawperm; }; /* - * Each controller is represented by a SDev. + * Each controller is represented by a struct sdev. */ -struct SDev { - Ref r; /* Number of callers using device */ - SDifc *ifc; /* pnp/legacy */ +struct sdev { + struct kref r; /* Number of callers using device */ + struct sdifc *ifc; /* pnp/legacy */ void *ctlr; int idno; char name[8]; - SDev *next; + struct sdev *next; - QLock ql; /* enable/disable */ + qlock_t ql; /* enable/disable */ int enabled; - int nunit; /* Number of units */ - QLock unitlock; /* `Loading' of units */ - int *unitflg; /* Unit flags */ - SDunit **unit; + int nunit; /* Number of units */ + qlock_t unitlock; /* `Loading' of units */ + int *unitflg; /* Unit flags */ + struct sdunit **unit; }; -struct SDifc { +struct sdifc { char *name; - SDev *(*pnp)(void); - SDev *(*legacy)(int, int); - int (*enable)(SDev *); - int (*disable)(SDev *); - - int (*verify)(SDunit *); - int (*online)(SDunit *); - int (*rio)(SDreq *); - int (*rctl)(SDunit *, char *, int); - int (*wctl)(SDunit *, Cmdbuf *); - - int32_t (*bio)(SDunit *, int, int, void *, int32_t, uint64_t); - SDev *(*probe)(DevConf *); - void (*clear)(SDev *); - char *(*rtopctl)(SDev *, char *, char *); - int (*wtopctl)(SDev *, Cmdbuf *); + struct sdev *(*pnp)(void); + struct sdev *(*legacy)(int, int); + int (*enable)(struct sdev *); + int (*disable)(struct sdev *); + + int (*verify)(struct sdunit *); + int (*online)(struct sdunit *); + int (*rio)(struct sdreq *); + int (*rctl)(struct sdunit *, char *, int); + int (*wctl)(struct sdunit *, struct cmdbuf *); + + int32_t (*bio)(struct sdunit *, int, int, void *, int32_t, uint64_t); + struct sdev *(*probe)(struct devconf *); + void (*clear)(struct sdev *); + char *(*rtopctl)(struct sdev *, char *, char *); + int (*wtopctl)(struct sdev *, struct cmdbuf *); }; -struct SDreq { - SDunit *unit; +struct sdreq { + struct sdunit *unit; int lun; int write; unsigned char cmd[16]; @@ -145,21 +146,10 @@ enum { }; /* - * Allow the default #defines for sdmalloc & sdfree to be overridden by - * system-specific versions. This can be used to avoid extra copying - * by making sure sd buffers are cache-aligned (some ARM systems) or - * page-aligned (xen) for DMA. - */ -#ifndef sdmalloc -#define sdmalloc(n) malloc(n) -#define sdfree(p) free(p) -#endif - -/* * mmc/sd/sdio host controller interface */ -struct SDio { +struct sdio { char *name; int (*init)(void); void (*enable)(void); @@ -169,34 +159,34 @@ struct SDio { void (*io)(int, unsigned char *, int); }; -extern SDio sdio; +extern struct sdio sdio; /* devsd.c */ -extern void sdadddevs(SDev *); -extern void sdaddconf(SDunit *); -extern void sdaddallconfs(void (*f)(SDunit *)); -extern void sdaddpart(SDunit *, char *, uint64_t, uint64_t); -extern int sdsetsense(SDreq *, int, int, int, int); -extern int sdmodesense(SDreq *, unsigned char *, void *, int); -extern int sdfakescsi(SDreq *, void *, int); +extern void sdadddevs(struct sdev *); +extern void sdaddconf(struct sdunit *); +extern void sdaddallconfs(void (*f)(struct sdunit *)); +extern void sdaddpart(struct sdunit *, char *, uint64_t, uint64_t); +extern int sdsetsense(struct sdreq *, int, int, int, int); +extern int sdmodesense(struct sdreq *, unsigned char *, void *, int); +extern int sdfakescsi(struct sdreq *, void *, int); /* sdscsi.c */ -extern int scsiverify(SDunit *); -extern int scsionline(SDunit *); -extern int32_t scsibio(SDunit *, int, int, void *, int32_t, uint64_t); -extern SDev *scsiid(SDev *, SDifc *); +extern int scsiverify(struct sdunit *); +extern int scsionline(struct sdunit *); +extern int32_t scsibio(struct sdunit *, int, int, void *, int32_t, uint64_t); +extern struct sdev *scsiid(struct sdev *, struct sdifc *); /* * hardware info about a device */ -typedef struct devport { +struct devport { uint32_t port; int size; -} Devport; +}; -struct DevConf { - uint32_t intnum; /* interrupt number */ - char *type; /* card type, malloced */ - int nports; /* Number of ports */ - Devport *ports; /* The ports themselves */ +struct devconf { + uint32_t intnum; /* interrupt number */ + char *type; /* card type, malloced */ + int nports; /* Number of ports */ + struct devport *ports; /* The ports themselves */ }; -- 2.8.0.rc3.226.g39d4020 -- You received this message because you are subscribed to the Google Groups "Akaros" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. For more options, visit https://groups.google.com/d/optout.
