Devtab created with linker tables
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 21 Jan 2014 00:30:44 +0000 (16:30 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 21 Jan 2014 00:36:12 +0000 (16:36 -0800)
One tricky thing is alignment.  Regardless of sizeof(struct dev), the
struct devs in the .devtab section are aligned to 32 bytes.

16 files changed:
kern/drivers/dev/alarm.c
kern/drivers/dev/cons.c
kern/drivers/dev/dev.c
kern/drivers/dev/mnt.c
kern/drivers/dev/pipe.c
kern/drivers/dev/root.c
kern/drivers/dev/tab.c
kern/drivers/dev/vm.c
kern/include/ns.h
kern/linker_tables.ld
kern/src/init.c
kern/src/net/devip.c
kern/src/net/ethermedium.c
kern/src/net/netdevmedium.c
kern/src/ns/chan.c
kern/src/ns/sysfile.c

index 3a29a37..9c7613e 100644 (file)
@@ -402,7 +402,7 @@ static long alarmwrite(struct chan *c, void *ubuf, long n, int64_t unused)
        return n;
 }
 
-struct dev alarmdevtab = {
+struct dev alarmdevtab __devtab = {
        'A',
        "alarm",
 
index 62a52e0..2950a27 100644 (file)
@@ -365,7 +365,7 @@ pprint(char *fmt, ...)
                poperror();
                return 0;
        }
-       devtab[c->type]->write(c, buf, n, c->offset);
+       devtab[c->type].write(c, buf, n, c->offset);
        poperror();
 
        spin_lock(&c->lock);
@@ -982,8 +982,8 @@ consread(struct chan *c, void *buf, long n, int64_t offset)
                if(p == NULL)
                        error(Enomem);
                l = 0;
-               for(i = 0; devtab[i] != NULL; i++)
-                       l += snprintf(p+l, READSTR-l, "#%c %s\n", devtab[i]->dc,  devtab[i]->name);
+               for(i = 0; &devtab[i] < __devtabend; i++)
+                       l += snprintf(p+l, READSTR-l, "#%c %s\n", devtab[i].dc,  devtab[i].name);
                if(waserror()){
                        kfree(p);
                        nexterror();
@@ -1192,7 +1192,7 @@ conswrite(struct chan *c, void *va, long n, int64_t offset)
        return n;
 }
 
-struct dev consdevtab = {
+struct dev consdevtab __devtab = {
        'c',
        "cons",
 
index 07766ea..a3c676f 100644 (file)
@@ -29,8 +29,8 @@ devno(int c, int user)
 {
        int i;
 
-       for(i = 0; devtab[i] != NULL; i++) {
-               if(devtab[i]->dc == c)
+       for(i = 0; &devtab[i] < __devtabend; i++) {
+               if(devtab[i].dc == c)
                        return i;
        }
        if (user == 0)
@@ -47,7 +47,7 @@ devdir(struct chan *c, struct qid qid, char *n,
        if(c->flag&CMSG)
                qid.type |= QTMOUNT;
        db->qid = qid;
-       db->type = devtab[c->type]->dc;
+       db->type = devtab[c->type].dc;
        db->dev = c->dev;
        db->mode = perm;
        db->mode |= qid.type << 24;
@@ -120,7 +120,7 @@ devclone(struct chan *c)
        struct chan *nc;
 
        if(c->flag & COPEN)
-               panic("clone of open file type %c\n", devtab[c->type]->dc);
+               panic("clone of open file type %c\n", devtab[c->type].dc);
 
        nc = newchan();
 
@@ -261,7 +261,7 @@ devstat(struct chan *c, uint8_t *db, int n,
                                        error(Ebadarg);
                                return n;
                        }
-                       printd("DEVSTAT fails:%c %llu\n", devtab[c->type]->dc, c->qid.path);
+                       printd("DEVSTAT fails:%c %llu\n", devtab[c->type].dc, c->qid.path);
                        error(Enonexist);
                case 0:
                        printd("DEVSTAT got 0\n");
@@ -385,7 +385,7 @@ devbread(struct chan *c, long n, uint32_t offset)
                freeb(bp);
                nexterror();
        }
-       bp->wp += devtab[c->type]->read(c, bp->wp, n, offset);
+       bp->wp += devtab[c->type].read(c, bp->wp, n, offset);
        poperror();
        return bp;
 }
@@ -400,7 +400,7 @@ devbwrite(struct chan *c, struct block *bp, uint32_t offset)
                freeb(bp);
                nexterror();
        }
-       n = devtab[c->type]->write(c, bp->rp, BLEN(bp), offset);
+       n = devtab[c->type].write(c, bp->rp, BLEN(bp), offset);
        poperror();
        freeb(bp);
 
@@ -450,9 +450,9 @@ devbyname(char *name)
 {
        int i;
 
-       for(i = 0; devtab[i] != NULL; i++)
-               if(strcmp(devtab[i]->name, name) == 0)
-                       return devtab[i];
+       for(i = 0; &devtab[i] < __devtabend; i++)
+               if(strcmp(devtab[i].name, name) == 0)
+                       return &devtab[i];
        return NULL;
 }
 
index 33d0f09..619d803 100644 (file)
@@ -176,7 +176,7 @@ mntversion(struct chan *c, char *version, int msize, int returnlen)
        c->offset += k;
        spin_unlock(&c->lock);
 
-       l = devtab[c->type]->write(c, msg, k, oo);
+       l = devtab[c->type].write(c, msg, k, oo);
 
        if(l < k){
                spin_lock(&c->lock);
@@ -186,7 +186,7 @@ mntversion(struct chan *c, char *version, int msize, int returnlen)
        }
 
        /* message sent; receive and decode reply */
-       k = devtab[c->type]->read(c, msg, 8192+IOHDRSZ, c->offset);
+       k = devtab[c->type].read(c, msg, 8192+IOHDRSZ, c->offset);
        if(k <= 0)
                error("EOF receiving fversion reply");
 
@@ -818,7 +818,7 @@ mountio(struct mnt *m, struct mntrpc *r)
        n = convS2M(&r->request, r->rpc, m->msize);
        if(n < 0)
                panic("bad message type in mountio");
-       if(devtab[m->c->type]->write(m->c, r->rpc, n, 0) != n)
+       if(devtab[m->c->type].write(m->c, r->rpc, n, 0) != n)
                error(Emountrpc);
 /*     r->stime = fastticks(NULL); */
        r->reqlen = n;
@@ -854,7 +854,7 @@ doread(struct mnt *m, int len)
        struct block *b;
 
        while(qlen(m->q) < len){
-               b = devtab[m->c->type]->bread(m->c, m->msize, 0);
+               b = devtab[m->c->type].bread(m->c, m->msize, 0);
                if(b == NULL)
                        return -1;
                if(blocklen(b) == 0){
@@ -1192,7 +1192,7 @@ mntdirfix(uint8_t *dirbuf, struct chan *c)
 {
        unsigned int r;
 
-       r = devtab[c->type]->dc;
+       r = devtab[c->type].dc;
        dirbuf += BIT16SZ;      /* skip count */
        PBIT16(dirbuf, r);
        dirbuf += BIT16SZ;
@@ -1208,7 +1208,7 @@ rpcattn(void *v)
        return r->done || r->m->rip == 0;
 }
 
-struct dev mntdevtab = {
+struct dev mntdevtab __devtab = {
        'M',
        "mnt",
 
index 960fbd0..5cb9ce3 100644 (file)
@@ -458,7 +458,7 @@ pipewstat(struct chan *c, uint8_t *dp, int n)
        return n;
 }
 
-struct dev pipedevtab = {
+struct dev pipedevtab __devtab = {
        '|',
        "pipe",
 
index fbc3f05..9c6693b 100644 (file)
@@ -167,7 +167,7 @@ rootwrite(struct chan *c, void *a, long n, int64_t off)
        return 0;
 }
 
-struct dev rootdevtab = {
+struct dev rootdevtab __devtab = {
        'r',
        "root",
        devreset,
index 535a0ff..7593e36 100644 (file)
 #include <event.h>
 #include <umem.h>
 
-/* at some point this will be done via ldscript Hackes. */
-//extern struct dev* devtab[];
-// the sooner the better!
-
-extern struct dev alarmdevtab;
-extern struct dev consdevtab;
-extern struct dev rootdevtab;
-extern struct dev ipdevtab;
-extern struct dev pipedevtab;
-/*extern struct dev regressdevtab;
-extern struct dev procdevtab;
-extern struct dev etherdevtab;
-extern struct dev mntdevtab;
-extern struct dev srvdevtab;
-extern struct dev vmdevtab;*/
-struct dev *devtab[] = {
-       &alarmdevtab,
-       &consdevtab,
-       &rootdevtab,
-       &ipdevtab,
-       &pipedevtab,
-/*
-       &regressdevtab,
-       &procdevtab,
-       &etherdevtab,
-       &mntdevtab,
-       &srvdevtab,
-       &vmdevtab,*/
-       NULL,
-};
-
 void devtabreset()
 {
        int i;
-       printk("devtabresets\n");
 
-       for (i = 0; devtab[i] != NULL; i++)
-               devtab[i]->reset();
+       for (i = 0; &devtab[i] < __devtabend; i++)
+               devtab[i].reset();
 }
 
 void devtabinit()
 {
        int i;
 
-       printk("devtabinit\n");
-       for (i = 0; devtab[i] != NULL; i++)
-               devtab[i]->init();
+       for (i = 0; &devtab[i] < __devtabend; i++) {
+               /* if we have errors, check the align of struct dev and objdump */
+               printd("i %d, dev %p, init %p\n", i, &devtab[i], devtab[i].init);
+               devtab[i].init();
+       }
 }
 
 void devtabshutdown()
@@ -72,18 +42,18 @@ void devtabshutdown()
        /*
         * Shutdown in reverse order.
         */
-       for (i = 0; devtab[i] != NULL; i++) ;
+       for (i = 0; &devtab[i] < __devtabend; i++) ;
        for (i--; i >= 0; i--)
-               devtab[i]->shutdown();
+               devtab[i].shutdown();
 }
 
 struct dev *devtabget(int dc, int user)
 {
        int i;
 
-       for (i = 0; devtab[i] != NULL; i++) {
-               if (devtab[i]->dc == dc)
-                       return devtab[i];
+       for (i = 0; &devtab[i] < __devtabend; i++) {
+               if (devtab[i].dc == dc)
+                       return &devtab[i];
        }
 
        printk("devtabget FAILED %c\n", dc);
@@ -105,8 +75,8 @@ devtabread(struct chan *c, void *buf, long n, int64_t off)
 
        p = alloc;
        e = p + READSTR;
-       for (i = 0; devtab[i] != NULL; i++) {
-               dev = devtab[i];
+       for (i = 0; &devtab[i] < __devtabend; i++) {
+               dev = &devtab[i];
                printd("p %p e %p e-p %d\n", p, e, e - p);
                printd("do %d %c %s\n", i, dev->dc, dev->name);
                p += snprintf(p, e - p, "#%c %s\n", dev->dc, dev->name);
index 384a9d8..86c1b25 100644 (file)
@@ -78,7 +78,7 @@ readn(struct chan *c, void *vp, long n)
 
        p = vp;
        while(n > 0) {
-               nn = devtab[c->type]->read(c, p, n, c->offset);
+               nn = devtab[c->type].read(c, p, n, c->offset);
                printk("readn: Got %d@%lld\n", nn, c->offset);
                if(nn == 0)
                        error("%s: wanted %d, got %d", Eshort, total, want);
@@ -506,7 +506,7 @@ static long vmwrite(struct chan *c, void *ubuf, long n, int64_t unused)
        return n;
 }
 
-struct dev vmdevtab = {
+struct dev vmdevtab __devtab = {
        'V',
        "vm",
 
index 8b83f34..4e35fda 100644 (file)
@@ -408,7 +408,8 @@ struct dev
        int     (*wstat)(struct chan*, uint8_t *unused_uint8_p_t, int);
        void    (*power)(int);  /* power mgt: power(1) → on, power (0) → off */
 //     int     (*config)( int unused_int, char *unused_char_p_t, DevConf*);
-};
+       /* we need to be aligned, i think to 32 bytes, for the linker tables. */
+} __attribute__ ((aligned(32)));;
 
 struct dirtab
 {
@@ -578,7 +579,9 @@ enum
        READSTR =       1000,           /* temporary buffer size for device reads */
 };
 
-extern struct dev*     devtab[];
+extern struct dev      devtab[];
+extern struct dev      __devtabend[];
+
 struct cmdbuf
 {
        char    *buf;
index 814ff9b..1c258a4 100644 (file)
@@ -7,6 +7,7 @@
        /* We shouldn't have to use PROVIDE, but if we don't, we get the wrong
         * value for '.'.  And items with empty tables get the KLA (basically 0) */
        PROVIDE(__devtabstart = .);
+       PROVIDE(devtab = .);
        .devtab : {
                *(.devtab)
        }
index 54153af..21ec4a4 100644 (file)
@@ -160,8 +160,8 @@ void _warn(const char *file, int line, const char *fmt,...)
  * Only really a problem for debugging. */
 void debug_linker_tables(void)
 {
-       extern char __devtabstart[];
-       extern char __devtabend[];
+       extern struct dev __devtabstart[];
+       extern struct dev __devtabend[];
        extern char __devlinkstart[];
        extern char __devlinkend[];
        extern char __etherlinkstart[];
index 3d904d2..083ec17 100644 (file)
@@ -1208,7 +1208,7 @@ ipbwrite(struct chan* ch, struct block* bp, uint32_t offset)
        }
 }
 
-struct dev ipdevtab = {
+struct dev ipdevtab __devtab = {
        'I',
        "ip",
 
index 88d3399..61250ff 100644 (file)
@@ -181,7 +181,7 @@ etherbind(struct Ipifc *ifc, int argc, char **argv)
        /*
         *  make it non-blocking
         */
-       devtab[cchan4->type]->write(cchan4, nbmsg, strlen(nbmsg), 0);
+       devtab[cchan4->type].write(cchan4, nbmsg, strlen(nbmsg), 0);
 
        /*
         *  get mac address and speed
@@ -239,7 +239,7 @@ etherbind(struct Ipifc *ifc, int argc, char **argv)
        /*
         *  make it non-blocking
         */
-       devtab[cchan6->type]->write(cchan6, nbmsg, strlen(nbmsg), 0);
+       devtab[cchan6->type].write(cchan6, nbmsg, strlen(nbmsg), 0);
 
        er = kzmalloc(sizeof(*er), 0);
        er->mchan4 = mchan4;
@@ -341,12 +341,12 @@ etherbwrite(struct Ipifc *ifc, struct block *bp, int version, uint8_t *ip)
        case V4:
                eh->t[0] = 0x08;
                eh->t[1] = 0x00;
-               devtab[er->mchan4->type]->bwrite(er->mchan4, bp, 0);
+               devtab[er->mchan4->type].bwrite(er->mchan4, bp, 0);
                break;
        case V6:
                eh->t[0] = 0x86;
                eh->t[1] = 0xDD;
-               devtab[er->mchan6->type]->bwrite(er->mchan6, bp, 0);
+               devtab[er->mchan6->type].bwrite(er->mchan6, bp, 0);
                break;
        default:
                panic("etherbwrite2: version %d", version);
@@ -376,7 +376,7 @@ etherread4(void *a)
                return;
        }
        for(;;){
-               bp = devtab[er->mchan4->type]->bread(er->mchan4, ifc->maxtu, 0);
+               bp = devtab[er->mchan4->type].bread(er->mchan4, ifc->maxtu, 0);
                if(!canrlock(&ifc->rwlock)){
                        freeb(bp);
                        continue;
@@ -419,7 +419,7 @@ etherread6(void *a)
                return;
        }
        for(;;){
-               bp = devtab[er->mchan6->type]->bread(er->mchan6, ifc->maxtu, 0);
+               bp = devtab[er->mchan6->type].bread(er->mchan6, ifc->maxtu, 0);
                if(!canrlock(&ifc->rwlock)){
                        freeb(bp);
                        continue;
@@ -452,10 +452,10 @@ etheraddmulti(struct Ipifc *ifc, uint8_t *a, uint8_t *unused)
        snprintf(buf, sizeof(buf), "addmulti %E", mac);
        switch(version){
        case V4:
-               devtab[er->cchan4->type]->write(er->cchan4, buf, strlen(buf), 0);
+               devtab[er->cchan4->type].write(er->cchan4, buf, strlen(buf), 0);
                break;
        case V6:
-               devtab[er->cchan6->type]->write(er->cchan6, buf, strlen(buf), 0);
+               devtab[er->cchan6->type].write(er->cchan6, buf, strlen(buf), 0);
                break;
        default:
                panic("etheraddmulti: version %d", version);
@@ -474,10 +474,10 @@ etherremmulti(struct Ipifc *ifc, uint8_t *a, uint8_t *unused)
        snprintf(buf, sizeof(buf), "remmulti %E", mac);
        switch(version){
        case V4:
-               devtab[er->cchan4->type]->write(er->cchan4, buf, strlen(buf), 0);
+               devtab[er->cchan4->type].write(er->cchan4, buf, strlen(buf), 0);
                break;
        case V6:
-               devtab[er->cchan6->type]->write(er->cchan6, buf, strlen(buf), 0);
+               devtab[er->cchan6->type].write(er->cchan6, buf, strlen(buf), 0);
                break;
        default:
                panic("etherremmulti: version %d", version);
@@ -534,7 +534,7 @@ sendarp(struct Ipifc *ifc, struct arpent *a)
        hnputs(e->op, ARPREQUEST);
        bp->wp += n;
 
-       n = devtab[er->achan->type]->bwrite(er->achan, bp, 0);
+       n = devtab[er->achan->type].bwrite(er->achan, bp, 0);
        if(n < 0)
                printd("arp: send: %r\n");
 }
@@ -611,7 +611,7 @@ sendgarp(struct Ipifc *ifc, uint8_t *ip)
        hnputs(e->op, ARPREQUEST);
        bp->wp += n;
 
-       n = devtab[er->achan->type]->bwrite(er->achan, bp, 0);
+       n = devtab[er->achan->type].bwrite(er->achan, bp, 0);
        if(n < 0)
                printd("garp: send: %r\n");
 }
@@ -626,7 +626,7 @@ recvarp(struct Ipifc *ifc)
        static uint8_t eprinted[4];
        Etherrock *er = ifc->arg;
 
-       ebp = devtab[er->achan->type]->bread(er->achan, ifc->maxtu, 0);
+       ebp = devtab[er->achan->type].bread(er->achan, ifc->maxtu, 0);
        if(ebp == NULL) {
                printd("arp: rcv: %r\n");
                return;
@@ -710,7 +710,7 @@ recvarp(struct Ipifc *ifc)
                memmove(r->s, ifc->mac, sizeof(r->s));
                rbp->wp += n;
 
-               n = devtab[er->achan->type]->bwrite(er->achan, rbp, 0);
+               n = devtab[er->achan->type].bwrite(er->achan, rbp, 0);
                if(n < 0)
                        printd("arp: write: %r\n");
        }
index a2dfa02..445c426 100644 (file)
@@ -99,7 +99,7 @@ netdevbwrite(struct Ipifc *ifc, struct block *bp, int unused_int, uint8_t *unuse
        if(BLEN(bp) < ifc->mintu)
                bp = adjustblock(bp, ifc->mintu);
 
-       devtab[er->mchan->type]->bwrite(er->mchan, bp, 0);
+       devtab[er->mchan->type].bwrite(er->mchan, bp, 0);
        ifc->out++;
 }
 
@@ -125,7 +125,7 @@ netdevread(void *a)
                return;
        }
        for(;;){
-               bp = devtab[er->mchan->type]->bread(er->mchan, ifc->maxtu, 0);
+               bp = devtab[er->mchan->type].bread(er->mchan, ifc->maxtu, 0);
                if(bp == NULL){
                        /*
                         * get here if mchan is a pipe and other side hangs up
index aa1e4c7..9892f10 100644 (file)
@@ -97,8 +97,8 @@ chandevreset(void)
 {
        int i;
 
-       for(i=0; devtab[i] != NULL; i++)
-               devtab[i]->reset();
+       for(i=0; &devtab[i] < __devtabend; i++)
+               devtab[i].reset();
 }
 
 void
@@ -106,8 +106,8 @@ chandevinit(void)
 {
        int i;
 
-       for(i=0; devtab[i] != NULL; i++)
-               devtab[i]->init();
+       for(i=0; &devtab[i] < __devtabend; i++)
+               devtab[i].init();
 }
 
 void
@@ -116,10 +116,10 @@ chandevshutdown(void)
        int i;
        
        /* shutdown in reverse order */
-       for(i=0; devtab[i] != NULL; i++)
+       for(i=0; &devtab[i] < __devtabend; i++)
                ;
        for(i--; i >= 0; i--)
-               devtab[i]->shutdown();
+               devtab[i].shutdown();
 }
 
 static void chan_release(struct kref *kref)
@@ -565,7 +565,7 @@ cclone(struct chan *c)
        struct chan *nc;
        struct walkqid *wq;
 
-       wq = devtab[c->type]->walk(c, NULL, NULL, 0);
+       wq = devtab[c->type].walk(c, NULL, NULL, 0);
        if(wq == NULL)
                error("clone failed");
        nc = wq->clone;
@@ -728,7 +728,7 @@ walk(struct chan **cp, char **names, int nnames, int nomount, int *nerror)
                type = c->type;
                dev = c->dev;
 
-               if((wq = devtab[type]->walk(c, NULL, names+nhave, ntry)) == NULL){
+               if((wq = devtab[type].walk(c, NULL, names+nhave, ntry)) == NULL){
                        /* try a union mount, if any */
                        if(mh && !nomount){
                                /*
@@ -736,7 +736,7 @@ walk(struct chan **cp, char **names, int nnames, int nomount, int *nerror)
                                 */
                                rlock(&mh->lock);
                                for(f = mh->mount->next; f; f = f->next)
-                                       if((wq = devtab[f->to->type]->walk(f->to, NULL, names+nhave, ntry)) != NULL)
+                                       if((wq = devtab[f->to->type].walk(f->to, NULL, names+nhave, ntry)) != NULL)
                                                break;
                                runlock(&mh->lock);
                                if(f != NULL){
@@ -962,7 +962,7 @@ memrchr(void *va, int c, long n)
  * Opening with amode Aopen, Acreate, or Aremove guarantees
  * that the result will be the only reference to that particular fid.
  * This is necessary since we might pass the result to
- * devtab[]->remove().
+ * devtab[].remove().
  *
  * Opening Atodir, Amount, or Aaccess does not guarantee this.
  *
@@ -1037,7 +1037,7 @@ namec(char *aname, int amode, int omode, uint32_t perm)
                t = devno(/*r*/get_cur_genbuf()[1], 1);
                if(t == -1)
                        error(Ebadsharp);
-               c = devtab[t]->attach(get_cur_genbuf()+n);
+               c = devtab[t].attach(get_cur_genbuf()+n);
                break;
 
        default:
@@ -1169,7 +1169,7 @@ if(c->umh != NULL){
                        if(omode == OEXEC)
                                c->flag &= ~CCACHE;
 
-                       c = devtab[c->type]->open(c, omode&~OCEXEC);
+                       c = devtab[c->type].open(c, omode&~OCEXEC);
 
                        if(omode & OCEXEC)
                                c->flag |= CCEXEC;
@@ -1272,7 +1272,7 @@ if(c->umh != NULL){
                        cnew->name = c->name;
                        kref_get(&cnew->name->ref, 1);
 
-                       devtab[cnew->type]->create(cnew, e.elems[e.ARRAY_SIZEs-1], omode&~(OEXCL|OCEXEC), perm);
+                       devtab[cnew->type].create(cnew, e.elems[e.ARRAY_SIZEs-1], omode&~(OEXCL|OCEXEC), perm);
                        poperror();
                        if(omode & OCEXEC)
                                cnew->flag |= CCEXEC;
index 2f1c8d5..3d188ea 100644 (file)
@@ -128,9 +128,9 @@ kchanio(void *vc, void *buf, int n, int mode)
        }
 
        if ((mode & OREAD) == OREAD)
-               r = devtab[c->type]->read(c, buf, n, c->offset);
+               r = devtab[c->type].read(c, buf, n, c->offset);
        else
-               r = devtab[c->type]->write(c, buf, n, c->offset);
+               r = devtab[c->type].write(c, buf, n, c->offset);
 
        spin_lock(&c->lock);
        c->offset += r;
@@ -333,7 +333,7 @@ sysfstat(int fd, uint8_t *buf, int n)
                cclose(c);
                nexterror();
        }
-       devtab[c->type]->stat(c, (void*)&dir9ns, sizeof(struct dir));
+       devtab[c->type].stat(c, (void*)&dir9ns, sizeof(struct dir));
 
        poperror();
        cclose(c);
@@ -450,7 +450,7 @@ syspipe(int fd[2])
 
        f = current->fgrp;
 
-       d = devtab[devno('|', 0)];
+       d = &devtab[devno('|', 0)];
        c[0] = namec("#|", Atodir, 0, 0);
        c[1] = 0;
        fd[0] = -1;
@@ -507,7 +507,7 @@ sysfwstat(int fd, uint8_t *buf, int n)
                cclose(c);
                nexterror();
        }
-       n = devtab[c->type]->wstat(c, buf, n);
+       n = devtab[c->type].wstat(c, buf, n);
        poperror();
        cclose(c);
 
@@ -589,7 +589,7 @@ sysmount(int fd, int afd, char *old, int flags, char *spec)
        mntparam.authchan = ac.c;
        mntparam.spec = spec;
        mntparam.flags = flags;
-       c0.c = devtab[devno('M', 0)]->attach(( char *)&mntparam);
+       c0.c = devtab[devno('M', 0)].attach(( char *)&mntparam);
 
        r = bindmount(c0.c, old, flags, spec);
        poperror();
@@ -685,10 +685,10 @@ unionread(struct chan *c, void *va, long n)
                        if (!waserror()) { /* discard style */
                                if(c->umc == NULL){
                                        c->umc = cclone(mount->to);
-                                       c->umc = devtab[c->umc->type]->open(c->umc, OREAD);
+                                       c->umc = devtab[c->umc->type].open(c->umc, OREAD);
                                }
        
-                               nr = devtab[c->umc->type]->read(c->umc, va, n, c->umc->offset);
+                               nr = devtab[c->umc->type].read(c->umc, va, n, c->umc->offset);
                                if(nr < 0)
                                        nr = 0; /* dev.c can return -1 */
                                c->umc->offset += nr;
@@ -791,7 +791,7 @@ rread(int fd, void *va, long n, int64_t *offp)
                        }
                        unionrewind(c);
                }
-               n = devtab[c->type]->read(c, va, n, off);
+               n = devtab[c->type].read(c, va, n, off);
                spin_lock(&c->lock);
                c->offset += n;
                spin_unlock(&c->lock);
@@ -839,7 +839,7 @@ sysremove(char *path)
                cclose(c);
                nexterror();
        }
-       devtab[c->type]->remove(c);
+       devtab[c->type].remove(c);
        /*
         * Remove clunks the fid, but we need to recover the Chan
         * so fake it up.  rootclose() is known to be a nop.
@@ -870,7 +870,7 @@ sysseek(int fd, int64_t off, int whence)
                nexterror();
        }
 
-       if(devtab[c->type]->dc == '|')
+       if(devtab[c->type].dc == '|')
                error(Eisstream);
 
        switch(whence) {
@@ -969,7 +969,7 @@ sysstat(char *path, uint8_t *buf, int n)
                cclose(c);
                nexterror();
        }
-       devtab[c->type]->stat(c, (void*)&dir9ns, sizeof(struct dir));
+       devtab[c->type].stat(c, (void*)&dir9ns, sizeof(struct dir));
        poperror();
        cclose(c);
 
@@ -1019,7 +1019,7 @@ rwrite(int fd, void *va, long n, int64_t *offp)
        }
        if(off < 0)
                error(Enegoff);
-       m = devtab[c->type]->write(c, va, n, off);
+       m = devtab[c->type].write(c, va, n, off);
        poperror();
 
        if(offp == NULL && m < n){
@@ -1064,7 +1064,7 @@ syswstat(char *path, uint8_t *buf, int n)
                cclose(c);
                nexterror();
        }
-       n = devtab[c->type]->wstat(c, buf, n);
+       n = devtab[c->type].wstat(c, buf, n);
        poperror();
        cclose(c);
 
@@ -1095,7 +1095,7 @@ chandirstat(struct chan *c)
                        poperror();
                        return NULL;
                }
-               n = devtab[c->type]->stat(c, buf, nd);
+               n = devtab[c->type].stat(c, buf, nd);
                poperror();
                if(n < BIT16SZ){
                        kfree(d);