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 <rminn...@gmail.com>
Signed-off-by: Fergus Simpson <afe...@google.com>
---
 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 akaros+unsubscr...@googlegroups.com.
To post to this group, send email to akaros@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to