From 23672e4936061d634094d2153f3fd088e2f823ed Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 25 Sep 1991 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1991-09-25 --- pc/devfloppy.c | 146 ++++++++++++++++++++++++++++-------------------- pc/dma.c | 11 ++-- port/devlance.c | 20 +++---- port/devmnt.c | 21 ++++--- port/devnonet.c | 14 +---- 5 files changed, 113 insertions(+), 99 deletions(-) diff --git a/pc/devfloppy.c b/pc/devfloppy.c index 1ef6b3ddfb4d37d5c20e61fb4cfb97434b80437e..ec8a2f63fb7f602cd553cd22cf1a1a251a4a16a8 100644 --- a/pc/devfloppy.c +++ b/pc/devfloppy.c @@ -39,7 +39,8 @@ enum Fdumpreg= 0x0e, /* dump internal registers */ /* digital input register */ - Pdir= 0x3F7, /* disk changed port */ + Pdir= 0x3F7, /* disk changed port (read only) */ + Pdsr= 0x3F7, /* data rate select port (write only) */ Fchange= 0x80, /* disk has changed */ /* status 0 byte */ @@ -114,14 +115,13 @@ static int c2b[] = */ struct Drive { - QLock; /* exclusive access to the drive */ - Type *t; int dev; ulong lasttouched; /* time last touched */ int cyl; /* current cylinder */ int confused; /* needs to be recalibrated */ + int vers; int tcyl; /* target cylinder */ int thead; /* target head */ @@ -143,6 +143,7 @@ struct Controller QLock; /* exclusive access to the contoller */ Drive *d; /* the floppy drives */ + Drive *selected; uchar cmd[14]; /* command */ int ncmd; /* # command bytes */ uchar stat[14]; /* command status */ @@ -162,6 +163,7 @@ Controller fl; */ static int floppycmd(void); static void floppyeject(Drive*); +static void floppyintr(Ureg*); static void floppykproc(void*); static void floppyon(Drive*); static void floppyoff(Drive*); @@ -210,6 +212,7 @@ floppyreset(void) * allocate the drive storage */ fl.d = ialloc(conf.nfloppy*sizeof(Drive), 0); + fl.selected = fl.d; /* * stop the motors @@ -229,12 +232,14 @@ floppyreset(void) dp->cyl = -1; /* because we don't know */ dp->cache = (uchar*)ialloc(dp->t->tsize, 1); dp->ccyl = -1; + dp->vers = 1; } /* * first operation will recalibrate */ fl.confused = 1; + setvec(Floppyvec, floppyintr); } void @@ -278,7 +283,7 @@ floppystat(Chan *c, char *dp) Chan* floppyopen(Chan *c, int omode) { - return devopen(c, omode, floppydir, conf.nfloppy*NFDIR, devgen); + devopen(c, omode, floppydir, conf.nfloppy*NFDIR, devgen); } void @@ -304,6 +309,40 @@ floppywstat(Chan *c, char *dp) error(Eperm); } +static void +islegal(Chan *c, long n, Drive *dp) +{ + if(c->offset % dp->t->bytes) + errors("bad offset"); + if(n % dp->t->bytes) + errors("bad len"); +} + +/* + * check if the floppy has been replaced under foot + * + * a seek and a read clears the condition. this was determined experimentally, + * there has to be a better way. + */ +static void +changed(Chan *c, Drive *dp) +{ + ulong old; + + if(inb(Pdir)&Fchange) + dp->vers++; + old = c->qid.vers; + c->qid.vers = dp->vers; + if(old && old!=dp->vers){ + dp->ccyl = -1; + if(dp->cyl) + floppyxfer(dp, Fread, dp->cache, 0, dp->t->tsize); + else + floppyxfer(dp, Fread, dp->cache, dp->t->heads*dp->t->tsize, dp->t->tsize); + errors("disk changed"); + } +} + long floppyread(Chan *c, void *a, long n) { @@ -319,15 +358,19 @@ floppyread(Chan *c, void *a, long n) rv = 0; dp = &fl.d[c->qid.path & ~Qmask]; - switch ((int)(c->qid.path & Qmask)) { case Qdata: - if(c->offset % dp->t->bytes) - errors("bad offset"); - if(n % dp->t->bytes) - errors("bad len"); + islegal(c, n, dp); aa = a; nn = dp->t->tsize; + + qlock(&fl); + if(waserror()){ + qunlock(&fl); + nexterror(); + } + floppyon(dp); + changed(c, dp); for(rv = 0; rv < n; rv += len){ /* * truncate xfer at track boundary @@ -356,6 +399,9 @@ floppyread(Chan *c, void *a, long n) } memmove(aa+rv, dp->cache + (sec-1)*dp->t->bytes, len); } + qunlock(&fl); + poperror(); + break; case Qctl: break; @@ -377,13 +423,16 @@ floppywrite(Chan *c, void *a, long n) rv = 0; dp = &fl.d[c->qid.path & ~Qmask]; - switch ((int)(c->qid.path & Qmask)) { case Qdata: - if(c->offset % dp->t->bytes) - errors("bad offset"); - if(n % dp->t->bytes) - errors("bad len"); + islegal(c, n, dp); + qlock(&fl); + if(waserror()){ + qunlock(&fl); + nexterror(); + } + floppyon(dp); + changed(c, dp); for(rv = 0; rv < n; rv += i){ floppypos(dp, c->offset+rv); if(dp->tcyl == dp->ccyl) @@ -393,22 +442,18 @@ floppywrite(Chan *c, void *a, long n) if(i <= 0) break; } + qunlock(&fl); + poperror(); break; case Qctl: + qlock(&fl); if(SNCMP(aa, "eject") == 0){ floppyeject(dp); - } else if(SNCMP(aa, "seek") == 0){ - aa += 5; - floppyseek(dp, strtoul(aa, 0, 0)); - } else if(SNCMP(aa, "den") == 0){ - aa += 4; - i = strtoul(aa, 0, 0); - USED(i); -/* devp->dsr = i; - devp->ccr = i;/**/ } else if(SNCMP(aa, "reset") == 0){ + fl.confused = 1; floppyon(dp); } + qunlock(&fl); break; default: panic("floppywrite: bad qid"); @@ -421,26 +466,20 @@ static void floppykproc(void *a) { Drive *dp; -int i; -static int last; while(waserror()) ; for(;;){ -i = inb(Pdir) & 0x80; -if(i != last) - print("fromn %d to %d\n", last, i); -last = i; for(dp = fl.d; dp < &fl.d[conf.nfloppy]; dp++){ if((fl.motor&MOTORBIT(dp->dev)) && TK2SEC(m->ticks - dp->lasttouched) > 5 - && canqlock(dp)){ + && canqlock(&fl)){ if(TK2SEC(m->ticks - dp->lasttouched) > 5) floppyoff(dp); - qunlock(dp); + qunlock(&fl); } } - tsleep(&fl.kr, return0, 0, 5*100); + tsleep(&fl.kr, return0, 0, 1000); } } @@ -469,6 +508,7 @@ floppyon(Drive *dp) if(floppyrecal(dp) >= 0) break; dp->lasttouched = m->ticks; + fl.selected = dp; } /* @@ -479,6 +519,7 @@ floppyoff(Drive *dp) { fl.motor &= ~MOTORBIT(dp->dev); outb(Pdor, fl.motor | Fintena | Fena | dp->dev); + fl.selected = dp; } /* @@ -488,6 +529,7 @@ static void floppyeject(Drive *dp) { floppyon(dp); + dp->vers++; floppyoff(dp); } @@ -670,8 +712,7 @@ floppyrevive(void) fl.motor = 0; floppywait(); fl.confused = 0; -/* devp->dsr = 0; - devp->ccr = 0; /**/ + outb(Pdsr, 0); } } @@ -683,7 +724,6 @@ floppyrevive(void) static long floppyseek(Drive *dp, long off) { - floppyon(dp); floppypos(dp, off); if(dp->cyl == dp->tcyl) return dp->cyl; @@ -723,23 +763,13 @@ floppyxfer(Drive *dp, int cmd, void *a, long off, long n) if(off + n > dp->t->cap) n = dp->t->cap - off; - qlock(&fl); - qlock(dp); - if(waserror()){ - dmaend(DMAchan); - qunlock(&fl); - qunlock(dp); - fl.confused = 1; - nexterror(); - } - /* * calculate new position and seek to it (dp->len may be trimmed) */ dp->len = n; if(floppyseek(dp, off) < 0) errors("seeking floppy"); - + /*print("tcyl %d, thead %d, tsec %d, addr %lux, n %d\n", dp->tcyl, dp->thead, dp->tsec, a, dp->len);/**/ @@ -751,7 +781,7 @@ floppyxfer(Drive *dp, int cmd, void *a, long off, long n) /* * start operation */ -/* cmd = cmd | (dp->t->heads > 1 ? Fmulti : 0);/**/ + cmd = cmd | (dp->t->heads > 1 ? Fmulti : 0); fl.ncmd = 0; fl.cmd[fl.ncmd++] = cmd; fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev; @@ -783,14 +813,11 @@ floppyxfer(Drive *dp, int cmd, void *a, long off, long n) errors("floppy result failed"); } if((fl.stat[0] & Codemask)!=0 || fl.stat[1] || fl.stat[2]){ - if(fl.stat[1] != 0x80){ - print("xfer failed %lux %lux %lux\n", fl.stat[0], - fl.stat[1], fl.stat[2]); - print("offset %lud len %d\n", off, dp->len); - dp->confused = 1; - errors("floppy drive lost"); - } else - fl.stat[5]++; + print("xfer failed %lux %lux %lux\n", fl.stat[0], + fl.stat[1], fl.stat[2]); + print("offset %lud len %d\n", off, dp->len); + dp->confused = 1; + errors("floppy drive lost"); } /* @@ -801,20 +828,17 @@ floppyxfer(Drive *dp, int cmd, void *a, long off, long n) offset = offset * c2b[fl.stat[6]]; if(offset != off+dp->len){ print("new offset %d instead of %d\n", offset, off+dp->len); + print(" %d %d %d\n", fl.stat[3], fl.stat[4], fl.stat[5]); dp->confused = 1; errors("floppy drive lost"); } dp->lasttouched = m->ticks; - qunlock(&fl); - qunlock(dp); - poperror(); - return dp->len; } -void -floppyintr(void) +static void +floppyintr(Ureg *ur) { switch(fl.cmd[0]&~Fmulti){ case Fread: diff --git a/pc/dma.c b/pc/dma.c index 4c217df7511bf98c9daf13236f980ec2bbe56eb3..a2a211a9b50072fa623c2d826d1f7ec71c82ad75 100644 --- a/pc/dma.c +++ b/pc/dma.c @@ -106,7 +106,8 @@ dmasetup(int chan, void *va, long len, int isread) */ pa = ((ulong)va) & ~KZERO; if(!isphys(va) || (pa&0xFFFF0000)!=((pa+len)&0xFFFF0000)){ - xp->pg = newpage(1, 0, 0); + if(xp->pg == 0) + xp->pg = newpage(1, 0, 0); if(len > BY2PG) len = BY2PG; if(!isread) @@ -115,7 +116,8 @@ dmasetup(int chan, void *va, long len, int isread) xp->len = len; xp->isread = isread; pa = xp->pg->pa; - } + } else + xp->len = 0; /* * this setup must be atomic @@ -161,13 +163,12 @@ dmaend(int chan) unlock(dp); xp = &dp->x[chan]; - if(xp->pg == 0) + if(xp->len == 0) return; /* * copy out of temporary page */ memmove(xp->va, (void*)(KZERO|xp->pg->pa), xp->len); - putpage(xp->pg); - xp->pg = 0; + xp->len = 0; } diff --git a/port/devlance.c b/port/devlance.c index 3b1148b3e531a435e15ac4ed850b51d98701f788..de355c433285bd271f9993aba7ff2fa737c87ab8 100644 --- a/port/devlance.c +++ b/port/devlance.c @@ -258,6 +258,7 @@ lanceoput(Queue *q, Block *bp ) Etherpkt *p; Ethertype *e; Msg *m; + Block *nbp; if(bp->type == M_CTL){ e = q->ptr; @@ -275,17 +276,12 @@ lanceoput(Queue *q, Block *bp ) return; } - /* - * save up to a delim - */ - if(!putq(q, bp)) - return; - /* * only one transmitter at a time */ qlock(&l.tlock); if(waserror()){ + freeb(bp); qunlock(&l.tlock); nexterror(); } @@ -300,17 +296,14 @@ lanceoput(Queue *q, Block *bp ) * copy message into lance RAM */ len = 0; - while(bp = getq(q)){ - if(sizeof(Etherpkt) - len >= (n = BLEN(bp))){ - memmove(((uchar *)p)+len, bp->rptr, n); + for(nbp = bp; nbp; nbp = nbp->next){ + if(sizeof(Etherpkt) - len >= (n = BLEN(nbp))){ + memmove(((uchar *)p)+len, nbp->rptr, n); len += n; } else print("no room damn it\n"); - if(bp->flags & S_DELIM){ - freeb(bp); + if(bp->flags & S_DELIM) break; - } else - freeb(bp); } /* @@ -338,6 +331,7 @@ lanceoput(Queue *q, Block *bp ) l.tc = TSUCC(l.tc); *l.rdp = INEA|TDMD; /**/ wbflush(); + freeb(bp); qunlock(&l.tlock); poperror(); } diff --git a/port/devmnt.c b/port/devmnt.c index 2a108d494d2450da42d760e0b835c8d28ecdb69b..d02e963d50413204a2762c2784807e4fec69a6be 100644 --- a/port/devmnt.c +++ b/port/devmnt.c @@ -351,8 +351,11 @@ mntclunk(Chan *c, int t) m = mntchk(c); r = mntralloc(); if(waserror()){ + mntfree(r); if(decref(m) == 0) { for(q = m->queue; q; q = r) { +if(q->flushed == 0) +print("mail philw: %lux: not flushed\n", q); r = q->list; q->flushed = 0; mntfree(q); @@ -364,7 +367,6 @@ mntclunk(Chan *c, int t) mntalloc.mntfree = m; unlock(&mntalloc); } - mntfree(r); return; } @@ -493,15 +495,16 @@ mountio(Mnt *m, Mntrpc *r) n = convS2M(&r->request, r->rpc); if(waserror()) { qunlock(&m->c->wrl); - mntqrm(m, r); - nexterror(); + if(mntflush(m, r) == 0) + nexterror(); + } + else { + qlock(&m->c->wrl); + if((*devtab[m->c->type].write)(m->c, r->rpc, n, 0) != n) + error(Eshortmsg); + qunlock(&m->c->wrl); + poperror(); } - qlock(&m->c->wrl); - if((*devtab[m->c->type].write)(m->c, r->rpc, n, 0) != n) - error(Eshortmsg); - qunlock(&m->c->wrl); - poperror(); - if(m->mux) { mntqrm(m, r); mntrpcread(m, r); diff --git a/port/devnonet.c b/port/devnonet.c index 0f12ebbed26d61e86c1d0525420fd6c5d56f4b61..c420e01c2d9819b0c57cb9bf0f24062ee3fc6719 100644 --- a/port/devnonet.c +++ b/port/devnonet.c @@ -623,19 +623,11 @@ nooput(Queue *q, Block *bp) /* * send the message, the kproc will retry */ - if(waserror()){ - /* throw out the message */ - freeb(mp->first); - mp->first = 0; - mp->acked = 0; - if(MSUCC(cp->first) == cp->next) - cp->first = cp->next; - qunlock(cp); - nexterror(); + if(!waserror()){ + nosend(cp, mp); + poperror(); } - nosend(cp, mp); qunlock(cp); - poperror(); } /*