M port/devip.c => port/devip.c +9 -6
@@ 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]);
M port/devwren.c => port/devwren.c +17 -26
@@ 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;
M port/ipdat.h => port/ipdat.h +3 -1
@@ 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;
M port/stil.c => port/stil.c +124 -16
@@ 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
M port/tcpinput.c => port/tcpinput.c +1 -2
@@ 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
M port/tcpoutput.c => port/tcpoutput.c +3 -4
@@ 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)
{
M power/devhotrod.c => power/devhotrod.c +3 -1
@@ 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;