From a9d043d20ab911b2ed1331b57f5d96a4735d2396 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 19 Oct 1991 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1991-10-19 --- port/devip.c | 15 +++-- port/devwren.c | 43 ++++++-------- port/ipdat.h | 4 +- port/stil.c | 140 ++++++++++++++++++++++++++++++++++++++++------ port/tcpinput.c | 3 +- port/tcpoutput.c | 7 +-- power/devhotrod.c | 4 +- 7 files changed, 160 insertions(+), 56 deletions(-) diff --git a/port/devip.c b/port/devip.c index b7223ce9d0c65130594e6dabc10a3f8647bbf9bd..1ea2d848e4c65d7ed21253a4ef039981beb2c768 100644 --- a/port/devip.c +++ b/port/devip.c @@ -17,7 +17,7 @@ enum int udpsum = 1; -Queue *Tcpoutput; /* Tcp to lance output channel */ +Queue *Ipoutput; /* Control message stream for tcp/il */ Ipifc *ipifc; /* IP protocol interfaces for stip */ Ipconv *ipconv[Nrprotocol]; /* Connections for each protocol */ Dirtab *ipdir[Nrprotocol]; /* Connection directory structures */ @@ -609,14 +609,17 @@ void tcpstopen(Queue *q, Stream *s) { Ipconv *ipc; + static int tcpkprocs; - /* Start tcp service processes */ - if(!Tcpoutput) { - Tcpoutput = WR(q); - /* This never goes away - we use this queue to send acks/rejects */ + if(!Ipoutput) { + Ipoutput = WR(q); s->opens++; s->inuse++; - /* Flow control and tcp timer processes */ + } + + /* Flow control and tcp timer processes */ + if(tcpkprocs == 0) { + tcpkprocs = 1; kproc("tcpack", tcpackproc, 0); kproc("tcpflow", tcpflow, &ipconv[s->dev]); diff --git a/port/devwren.c b/port/devwren.c index 10ae369cdbf0a2baeee49ad36ed01865f37a53b5..2ee69351c61d2f7ab2147f2b48ea52df9aaf5b35 100644 --- a/port/devwren.c +++ b/port/devwren.c @@ -14,7 +14,8 @@ typedef struct Drive Drive; enum { Npart= 8+2, /* 8 sub partitions, disk, and partition */ - Ndisk= 64, /* maximum disks; must be power of 2 or change DRIVE */ + Ndisk= 64, /* maximum disks; if you change it, you must + map from dev to disk */ /* file types */ Qdir= 0, @@ -49,30 +50,20 @@ static long wrenio(Drive *, Partition *, int, char *, ulong, ulong); static int wrendev(char *p) { - int dev = 0; + int drive, unit; - if(p == 0 || p[0] == 0) - goto out; + if(p == 0 || p[0] == '\0') + return 0; if(p[0] < '0' || p[0] > '7') - goto cant; - dev = (p[0] - '0') << 3; - if(p[1] == 0) - goto out; - if(p[1] != '.') - goto cant; - if(p[2] == 0) - goto out; - if(p[2] < '0' || p[2] > '7') - goto cant; - dev |= p[2] - '0'; - if(p[3] != 0) - goto cant; -out: - if(dev >= Ndisk) - error(Ebadarg); - return dev; -cant: - error(Ebadarg); + errors("bad scsi drive specifier"); + drive = p[0] - '0'; + unit = 0; + if(p[1]){ + if(p[1] != '.' || p[2] < '0' || p[2] > '7' || p[3] != '\0') + errors("bad scsi unit specifier"); + unit = p[2] - '0'; + } + return (drive << 3) | unit; } static int @@ -191,7 +182,7 @@ wrenread(Chan *c, char *a, long n, ulong offset) d = &wren[DRIVE(c->qid.path)]; if(d->npart == 0) - errors("bad drive"); + errors("drive repartitioned"); p = &d->p[PART(c->qid.path)]; return wrenio(d, p, 0, a, n, offset); } @@ -204,7 +195,7 @@ wrenwrite(Chan *c, char *a, long n, ulong offset) d = &wren[DRIVE(c->qid.path)]; if(d->npart == 0) - errors("bad drive"); + errors("drive repartitioned"); p = &d->p[PART(c->qid.path)]; return wrenio(d, p, 1, a, n, offset); } @@ -216,7 +207,7 @@ wrenio(Drive *d, Partition *p, int write, char *a, ulong n, ulong offset) ulong block; if(n % d->bytes || offset % d->bytes) - error(Ebadarg); + errors("io not block aligned"); block = offset / d->bytes + p->start; if(block >= p->end) return 0; diff --git a/port/ipdat.h b/port/ipdat.h index 2122972591af69d1c4e23e81bdfb46382d97362b..a5afdd51411052df7b80b23388592390ee45aa98 100644 --- a/port/ipdat.h +++ b/port/ipdat.h @@ -82,7 +82,7 @@ struct Ilhdr uchar cksum[2]; /* Header checksum */ uchar src[4]; /* Ip source */ uchar dst[4]; /* Ip destination */ -#define IL_HDRSIZE 16 +#define IL_HDRSIZE 18 uchar ilsum[2]; /* Checksum including header */ uchar illen[2]; /* Packet length */ uchar iltype; /* Packet type */ @@ -95,6 +95,7 @@ struct Ilhdr struct Ilcb /* Control block */ { + Lock; int state; Block *unacked; Block *unackedtail; @@ -527,3 +528,4 @@ extern Qinfo tcpinfo; extern Qinfo ipinfo; extern Qinfo udpinfo; extern Qinfo ilinfo; +extern Queue *Ipoutput; diff --git a/port/stil.c b/port/stil.c index c06b40ee2b392424a33bac0461fdfe79043e831d..8c0f732fc353aeabc9c8edf5737682dc216e4352 100644 --- a/port/stil.c +++ b/port/stil.c @@ -13,7 +13,7 @@ #define DPRINT if(pip)print int ilcksum = 1; -Queue *Iloutput; /* Il to lance output channel */ + static int initseq = 25000; char *ilstate[] = { "Closed", "Syncer", "Syncee", "Established", "Listening", "Closing" }; @@ -25,13 +25,18 @@ void ilopen(Queue *q, Stream *s) { Ipconv *ipc; + static int ilkproc; /* Start il service processes */ - if(!Iloutput) { - Iloutput = WR(q); + if(!Ipoutput) { + Ipoutput = WR(q); /* This never goes away - we use this queue to send acks/rejects */ s->opens++; s->inuse++; + } + + if(ilkproc == 0) { + ilkproc = 1; kproc("ilack", ilackproc, 0); } @@ -62,11 +67,18 @@ iloput(Queue *q, Block *bp) int dlen; Block *np; - /* Prepend udp header to packet and pass on to ip layer */ ipc = (Ipconv *)(q->ptr); if(ipc->psrc == 0) error(Enoport); + switch(ipc->ilctl.state) { + case Ilclosed: + case Ilsyncee: + case Illistening: + case Ilclosing: + error(Ehungup); + } + if(bp->type != M_DATA) { freeb(bp); error(Ebadctl); @@ -90,7 +102,12 @@ iloput(Queue *q, Block *bp) ih = (Ilhdr *)(bp->rptr); ic = &ipc->ilctl; - hnputs(ih->illen, dlen+IL_EHSIZE+IL_HDRSIZE); + /* Ip fields */ + hnputl(ih->src, Myip); + hnputl(ih->dst, ipc->dst); + ih->proto = IP_ILPROTO; + /* Il fields */ + hnputs(ih->illen, dlen+IL_HDRSIZE); hnputs(ih->ilsrc, ipc->psrc); hnputs(ih->ildst, ipc->pdst); ih->iltype = Ildata; @@ -104,8 +121,20 @@ iloput(Queue *q, Block *bp) if(ilcksum) hnputs(ih->ilsum, ptcl_csum(bp, IL_EHSIZE, dlen+IL_HDRSIZE)); + ilackq(ic, bp); + + PUTNEXT(q, bp); +} + +void +ilackq(Ilctl *ic, Block *bp) +{ + Block *np; + /* Enqueue a copy on the unacked queue in case this one gets lost */ np = copyb(bp, blen(bp)); + + lock(ic); if(ic->unacked) { ic->unackedtail->next = np; ic->unackedtail = np; @@ -115,8 +144,33 @@ iloput(Queue *q, Block *bp) ic->unackedtail = np; } np->next = 0; + unlock(ic); +} - PUTNEXT(q, bp); +void +ilackto(Ilctl *ic, ulong ackto) +{ + Ilhdr *h; + Block *bp; + + for(;;) { + lock(ic); + if(ic->unacked) { + h = (Ilhdr *)ic->unacked->rptr; + if(ackto < hngetl(h->ilack)) { + unlock(ic); + break; + } + bp = ic->unacked; + ic->unacked = bp->next; + unlock(ic); + freeb(bp); + } + else { + unlock(ic); + break; + } + } } void @@ -143,29 +197,79 @@ ilrcvmsg(Ipconv *ipc, Block *bp) goto drop; } - s = ip_conn(ipc, nhgets(ih->ildst), nhgets(ih->ilsrc), nhgetl(ih->src), IP_ILPROTO); - if(s == 0) { - ilsendctl(0, ih, Ilreset); - goto drop; + etab = &ipc[conf.ip]; + for(s = ipc; s < etab; s++) { + if(s->sport == ih->ildst && s->dport == ih->ilsrc) { + ilprocess(s, ih, bp); + return; + } + } - - -drop: + for(s = ipc; s < etab; s++) { + if(s->state == Illistening && s->sport == 0) { + /* Do the listener stuff */ + ilprocess(s, ih, bp); + return; + } + } + ilsendctl(0, ih, Ilreset); freeb(bp); } void -ilsendctl(Ipconv *ipc, Ilhdr *inih, int type) +ilprocess(Ipconv *s, Ihdr *h, Block *bp) +{ + switch(s->ilctl.state) { + case Ilclosed: + case Ilclosing: + case Illistener: + error(Ehungup); + } + + switch(h->type) { + case Ilsync: + if(s->ilctl.state == Ilsync) + s->ilctl.state = Ilestablished; + freeb(bp); + break; + case Ilack: + ilackto(&s->ilctl, hngetl(g->ilack)); + freeb(bp); + break; + case Ilquerey: + ilsendctl(s, 0, Ilack, 1); + freeb(bp); + break; + case Ildataquery: + case Ildata: + ilackto(&s->ilctl, hngetl(h->ilack)); + bp->rptr += IL_EHSIZE+IL_HDRSIZE; + PUTNEXT(s->readq, bp); + break; + case Ilreset: + s->ilctl.state = Closed; + freeb(bp); + } +} + +void +ilsendctl(Ipconv *ipc, Ilhdr *inih, int type, int ack) { Ilhdr *ih; Ilcb *ic; Block *bp; bp = allocb(IL_EHSIZE+IL_HDRSIZE); + bp->wptr += IL_EHSIZE+IL_HDRSIZE; + ih = (Ilhdr *)(bp->rptr); ic = &ipc->ilctl; - hnputs(ih->illen, IL_EHSIZE+IL_HDRSIZE); + /* Ip fields */ + hnputl(ih->src, Myip); + hnputl(ih->dst, ipc->dst); + ih->proto = IP_ILPROTO; + hnputs(ih->illen, IL_HDRSIZE); if(inih) { hnputs(ih->ilsrc, nhgets(inih->ildst)); hnputs(ih->ildst, nhgets(inih->ilsrc)); @@ -186,7 +290,11 @@ ilsendctl(Ipconv *ipc, Ilhdr *inih, int type) if(ilcksum) hnputs(ih->ilsum, ptcl_csum(bp, IL_EHSIZE, IL_HDRSIZE)); - PUTNEXT(Iloutput, bp); + if(!ack) { + ic->sent++; /* Maybe needs locking */ + ilackq(&ipc->ilctl, bp); + } + PUTNEXT(Ipoutput, bp); } void diff --git a/port/tcpinput.c b/port/tcpinput.c index 1edef2bdf5eb8b12e930c3716afba99275268b9b..c8bdc2ca49319c4103c2f1610f8144af817cee31 100644 --- a/port/tcpinput.c +++ b/port/tcpinput.c @@ -11,7 +11,6 @@ int tcpdbg = 0; #define DPRINT if(tcpdbg) print #define LPRINT if(tcpdbg) print -extern Queue *Tcpoutput; QLock reseqlock; Reseq *reseqfree; @@ -497,7 +496,7 @@ reset(Ipaddr source, Ipaddr dest, char tos, ushort length, Tcp *seg) DPRINT("Reset: seq = %lux ack = %d flags = %lux\n", seg->seq, seg->ack, seg->flags); - PUTNEXT(Tcpoutput, hbp); + PUTNEXT(Ipoutput, hbp); } void diff --git a/port/tcpoutput.c b/port/tcpoutput.c index f433d69f435ed9c4419b9e1e424a7d8907c7cb87..ae1e58da3cafd461af95338a8412d39f73218879 100644 --- a/port/tcpoutput.c +++ b/port/tcpoutput.c @@ -9,7 +9,8 @@ extern int tcpdbg; extern ushort tcp_mss; -extern Queue *Tcpoutput; +int tcptimertype = 0; + #define DPRINT if(tcpdbg) print @@ -190,12 +191,10 @@ tcp_output(Ipconv *s) DPRINT("tcp_output: ip_send s%lux a%lux w%lux u%lux\n", seg.seq, seg.ack, seg.wnd, seg.up); - PUTNEXT(Tcpoutput, hbp); + PUTNEXT(Ipoutput, hbp); } } -int tcptimertype = 0; - void tcp_timeout(void *arg) { diff --git a/power/devhotrod.c b/power/devhotrod.c index f432c53a97eef10658758a4047afb61eeb47a596..d4151abdc6210357200e0a4abe2c1baec932e19a 100644 --- a/power/devhotrod.c +++ b/power/devhotrod.c @@ -473,7 +473,9 @@ hotrodintr(int vec) print("bad hotrod vec\n"); return; } - h->addr->lcsr3 &= ~INT_VME; + l = h->addr->lcsr3 & ~INT_VME; + h->addr->lcsr3 = l; + h->addr->lcsr3 = l; while(l = h->addr->replyq[h->ri]){ /* assign = */ hm = (Hotmsg*)(VME2MP(l)); h->addr->replyq[h->ri] = 0;