From 87045a95d062cbe60db5153bfc18bed71910b838 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 6 Sep 1992 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1992-09-06 --- pc/devether.c | 92 +++++++++++++++++---------- pc/devhard.c | 2 +- port/ipdat.h | 158 +++++++++++++++++++++++------------------------ port/net.c | 10 +-- port/tcpif.c | 9 ++- port/tcpinput.c | 41 ++++++------ port/tcpoutput.c | 29 +++++---- port/tcptimer.c | 33 +++++----- 8 files changed, 203 insertions(+), 171 deletions(-) diff --git a/pc/devether.c b/pc/devether.c index 25d87d7abe48383843b08af6ec8e14a72ddbfae0..69fff4424297e33cb43e260dc55f33b23dc2750a 100644 --- a/pc/devether.c +++ b/pc/devether.c @@ -15,6 +15,8 @@ typedef struct Ctlr Ctlr; struct Hw { int addr; /* interface address */ uchar *ram; /* interface shared memory address */ + int bt16; /* true if a 16 bit interface */ + int lvl; /* interrupt level */ int size; uchar tstart; uchar pstart; @@ -639,7 +641,14 @@ wd8013dumpregs(Hw *hw) print("id=#%2.2ux\n", IN(hw, id)); } +/* mapping from configuration bits to interrupt level */ +int intrmap[] = +{ + 9, 3, 5, 7, 10, 11, 15, 4, +}; + /* + * get configuration parameters, enable memory */ static void wd8013reset(Ctlr *cp) @@ -647,6 +656,9 @@ wd8013reset(Ctlr *cp) Hw *hw = cp->hw; int i; uchar msr; + uchar icr; + uchar laar; + uchar irr; ulong ram; cp->rb = xspanalloc(sizeof(Buffer)*Nrb, BY2PG, 0); @@ -655,19 +667,47 @@ wd8013reset(Ctlr *cp) cp->ntb = Ntb; msr = IN(hw, msr); - OUT(hw, msr, MENB|msr); + icr = IN(hw, icr); + irr = IN(hw, irr); + laar = IN(hw, laar); + /* ethernet address */ for(i = 0; i < sizeof(cp->ea); i++) cp->ea[i] = IN(hw, lan[i]); - /* get configuration info from card */ - ram = (IN(hw, msr) & 0x3f) << 13; - ram |= KZERO|0x80000; + /* 16 bit operation? */ + hw->bt16 = icr & 0x1; + + /* address of interface RAM */ + ram = KZERO | ((msr & 0x3f) << 13); + if(hw->bt16) + ram |= (laar & 0x3f)<<19; + else + ram |= 0x80000; hw->ram = (uchar*)ram; -print("ether ram is at %lux\n", ram); + + /* interrupt level */ + hw->lvl = intrmap[((irr>>5) & 0x3) | (icr & 0x4)]; + + /* ram size */ + if(icr&(1<<3)) + hw->size = 32*1024; + else + hw->size = 8*1024; + if(hw->bt16) + hw->size <<= 1; + hw->pstop = HOWMANY(hw->size, 256); + +print("ether width %d addr %lux size %d lvl %d\n", hw->bt16?16:8, + hw->ram, hw->size, hw->lvl); + + /* enable interface RAM, set interface width */ + OUT(hw, msr, MENB|msr); + if(hw->bt16) + OUT(hw, laar, laar|L16EN|M16EN); (*hw->init)(cp); - setvec(Ethervec, hw->intr); + setvec(Int0vec + hw->lvl, hw->intr); } static void @@ -693,7 +733,10 @@ wd8013init(Ctlr *cp) int i; OUT(hw, w.cr, 0x21); /* Page0|RD2|STP */ - OUT(hw, w.dcr, 0x48); /* FT1|LS */ + if(hw->bt16) + OUT(hw, w.dcr, 0x49); /* 16 bit interface, DMA burst size 8 */ + else + OUT(hw, w.dcr, 0x48); /* FT1|LS */ OUT(hw, w.rbcr0, 0); OUT(hw, w.rbcr1, 0); OUT(hw, w.rcr, 0x04); /* AB */ @@ -738,17 +781,6 @@ wd8013online(Ctlr *cp, int on) OUT(cp->hw, w.tcr, 0); } -static void -bmemmove(void *a, void *b, int n) -{ - uchar *to, *from; - - to = a; - from = b; - while(n-- > 0) - *to++ = *from++; -} - static void wd8013receive(Ctlr *cp) { @@ -769,16 +801,11 @@ wd8013receive(Ctlr *cp) if(next == curr) break; cp->inpackets++; -print("*"); -OUT(hw, laar, 0xC1); -print("!"); p = &((Ring*)hw->ram)[next]; -{ int ii; for(ii = 0; ii < 30; ii++) print("%2.2ux ", p->data[ii]); for(;;); } len = ((p->len1<<8)|p->len0)-4; if(p->next < hw->pstart || p->next >= hw->pstop || len < 60){ print("%d/%d : #%2.2ux #%2.2ux #%2.2ux #%2.2ux\n", next, len, p->status, p->next, p->len0, p->len1); -OUT(hw, laar, 0x01); dp8390rinit(cp); break; } @@ -788,25 +815,22 @@ OUT(hw, laar, 0x01); rb->len = len; if((p->data+len) >= (hw->ram+hw->size)){ len = (hw->ram+hw->size) - p->data; - bmemmove(rb->pkt+len, + memmove(rb->pkt+len, &((Ring*)hw->ram)[hw->pstart], (p->data+rb->len) - (hw->ram+hw->size)); } - bmemmove(rb->pkt, p->data, len); + memmove(rb->pkt, p->data, len); rb->owner = Host; cp->ri = NEXT(cp->ri, cp->nrb); } p->status = 0; next = p->next; -OUT(hw, laar, 0x01); -print("?"); bnry = next-1; if(bnry < hw->pstart) bnry = hw->pstop-1; OUT(hw, w.bnry, bnry); } -print(">"); } static void @@ -817,10 +841,10 @@ wd8013transmit(Ctlr *cp) int s; s = splhi(); + hw = cp->hw; tb = &cp->tb[cp->ti]; if(tb->busy == 0 && tb->owner == Interface){ - hw = cp->hw; - bmemmove(hw->ram, tb->pkt, tb->len); + memmove(hw->ram, tb->pkt, tb->len); OUT(hw, w.tbcr0, tb->len & 0xFF); OUT(hw, w.tbcr1, (tb->len>>8) & 0xFF); OUT(hw, w.cr, 0x26); /* Page0|RD2|TXP|STA */ @@ -876,11 +900,13 @@ wd8013intr(Ureg *ur) static Hw wd8013 = { 0x360, /* I/O base address */ - KZERO|0xF0000, /* shared memory address */ - 8*1024, + 0, + 0, + 0, + 0, 0, HOWMANY(sizeof(Etherpkt), 256), - HOWMANY(8*1024, 256), + 0, wd8013reset, wd8013init, wd8013mode, diff --git a/pc/devhard.c b/pc/devhard.c index a873afd495247bf14e4eccde751436c22bb3545f..f528b88111809c11b60beacdad8639b74787268e 100644 --- a/pc/devhard.c +++ b/pc/devhard.c @@ -831,7 +831,7 @@ hardpart(Drive *dp) * parse partition table. */ n = getfields(buf, line, Npart+1, '\n'); - if(strncmp(line[0], PARTMAGIC, sizeof(PARTMAGIC)-1) == 0){ + if(n && strncmp(line[0], PARTMAGIC, sizeof(PARTMAGIC)-1) == 0){ for(i = 1; i < n; i++){ pp++; if(getfields(line[i], field, 3, ' ') != 3) diff --git a/port/ipdat.h b/port/ipdat.h index f980ff07d7d823a1f6724aeae1e9cdc4445df832..372adafc8e48ddbb7e0f028852dc8c5c8fa1788d 100644 --- a/port/ipdat.h +++ b/port/ipdat.h @@ -38,7 +38,6 @@ struct Etherhdr /* Ethernet packet types */ #define ET_IP 0x0800 -/* A userlevel data gram */ struct Udphdr { #define UDP_EHSIZE 22 @@ -185,7 +184,12 @@ struct Tcphdr uchar tcpmss[2]; }; - +enum +{ + TimerOFF = 0, + TimerON = 1, + TimerDONE = 2, +}; struct Timer { @@ -200,50 +204,50 @@ struct Timer struct Tctl { - uchar state; /* Connection state */ - uchar type; /* Listening or active connection */ - uchar code; /* Icmp code */ + uchar state; /* Connection state */ + uchar type; /* Listening or active connection */ + uchar code; /* Icmp code */ struct { - int una; /* Unacked data pointer */ - int nxt; /* Next sequence expected */ - int ptr; /* Data pointer */ - ushort wnd; /* Tcp send window */ - int up; /* Urgent data pointer */ + int una; /* Unacked data pointer */ + int nxt; /* Next sequence expected */ + int ptr; /* Data pointer */ + ushort wnd; /* Tcp send window */ + int up; /* Urgent data pointer */ int wl1; int wl2; } snd; struct { - int nxt; - ushort wnd; - int up; + int nxt; /* Receive pointer to next byte slot */ + ushort wnd; /* Receive window incoming */ + int up; /* Urgent pointer */ } rcv; - int iss; - ushort cwind; - ushort ssthresh; - int resent; - int irs; - ushort mss; - int rerecv; - ushort window; - int max_snd; - int last_ack; /* Last acknowledege received */ - char backoff; - char flags; /* State flags */ - char tos; /* Type of service */ - - Blist rcvq; /* Received data */ - ulong rcvcnt; - - Block *sndq; /* List of data going out */ - ulong sndcnt; /* Amount of data in send queue */ - - Reseq *reseq; /* Resequencing queue */ - Timer timer; - Timer acktimer; /* Acknoledge timer */ - Timer rtt_timer; /* Round trip timer */ - int rttseq; /* Round trip sequence */ - int srtt; /* Shortened round trip */ - int mdev; /* Mean deviation of round trip */ + int iss; /* Initial sequence number */ + ushort cwind; /* Congestion window */ + ushort ssthresh; /* Slow start threshold */ + int resent; /* Bytes just resent */ + int irs; /* Initial received squence */ + ushort mss; /* Mean segment size */ + int rerecv; /* Overlap of data rerecevived */ + ushort window; /* Recevive window */ + int max_snd; /* Max send */ + int last_ack; /* Last acknowledege received */ + char backoff; /* Exponential backoff counter */ + char flags; /* State flags */ + char tos; /* Type of service */ + + Blist rcvq; /* Received data */ + ulong rcvcnt; /* Bytes queued for upstream */ + + Block *sndq; /* List of data going out */ + ulong sndcnt; /* Amount of data in send queue */ + + Reseq *reseq; /* Resequencing queue */ + Timer timer; /* Activity timer */ + Timer acktimer; /* Acknoledge timer */ + Timer rtt_timer; /* Round trip timer */ + int rttseq; /* Round trip sequence */ + int srtt; /* Shortened round trip */ + int mdev; /* Mean deviation of round trip */ }; struct Tcpctl @@ -277,53 +281,54 @@ struct Reseq /* An ip interface used for UDP/TCP/IL */ struct Ipconv { - QLock; /* Ref count lock */ - Netprot; /* stat info */ + QLock; /* Ref count lock */ + Netprot; /* stat info */ int ref; - Ipaddr dst; /* Destination from connect */ - Port psrc; /* Source port */ - Port pdst; /* Destination port */ - - Ipifc *ifc; /* Ip protocol interface */ - Queue *readq; /* Pointer to upstream read q */ - QLock listenq; /* List of people waiting incoming cons */ - Rendez listenr; /* Some where to sleep while waiting */ + Ipaddr dst; /* Destination from connect */ + Port psrc; /* Source port */ + Port pdst; /* Destination port */ + + Ipifc *ifc; /* Ip protocol interface */ + Queue *readq; /* Pointer to upstream read q */ + QLock listenq; /* List of people waiting incoming cons */ + Rendez listenr; /* Some where to sleep while waiting */ - char *err; /* Async protocol error */ - int backlog; /* Maximum number of waiting connections */ - int headers; /* include header in packet */ - int curlog; /* Number of waiting connections */ - Ipconv *newcon; /* This is the start of a connection */ + char *err; /* Async protocol error */ + int backlog; /* Maximum number of waiting connections */ + int headers; /* include header in packet */ + int curlog; /* Number of waiting connections */ + Ipconv *newcon; /* This is the start of a connection */ union { - Tcpctl tcpctl; /* Tcp control block */ - Ilcb ilctl; /* Il control block */ + Tcpctl tcpctl; /* Tcp control block */ + Ilcb ilctl; /* Il control block */ }; }; -enum { - MAX_TIME = (1<<20),/* Forever */ - TCP_ACK = 200, /* Timed ack sequence every 200ms */ +enum +{ + MAX_TIME = (1<<20), /* Forever */ + TCP_ACK = 200, /* Timed ack sequence every 200ms */ - URG = 0x20, /* Data marked urgent */ - ACK = 0x10, /* Aknowledge is valid */ - PSH = 0x08, /* Whole data pipe is pushed */ - RST = 0x04, /* Reset connection */ - SYN = 0x02, /* Pkt. is synchronise */ - FIN = 0x01, /* Start close down */ + URG = 0x20, /* Data marked urgent */ + ACK = 0x10, /* Aknowledge is valid */ + PSH = 0x08, /* Whole data pipe is pushed */ + RST = 0x04, /* Reset connection */ + SYN = 0x02, /* Pkt. is synchronise */ + FIN = 0x01, /* Start close down */ EOL_KIND = 0, NOOP_KIND = 1, MSS_KIND = 2, - MSS_LENGTH = 4, /* Mean segment size */ + MSS_LENGTH = 4, /* Mean segment size */ MSL2 = 10, - MSPTICK = 100, /* Milliseconds per timer tick */ - DEF_MSS = 1024, /* Default mean segment */ - DEF_RTT = 1000, /* Default round trip */ + MSPTICK = 100, /* Milliseconds per timer tick */ + DEF_MSS = 1024, /* Default mean segment */ + DEF_RTT = 1000, /* Default round trip */ - TCP_PASSIVE = 0, /* Listen connection */ - TCP_ACTIVE = 1, /* Outgoing connection */ + TCP_PASSIVE = 0, /* Listen connection */ + TCP_ACTIVE = 1, /* Outgoing connection */ IL_PASSIVE = 0, IL_ACTIVE = 1, @@ -335,16 +340,12 @@ enum { SYNACK = 16, AGAIN = 8, DGAIN = 4, - - TIMER_STOP = 0, - TIMER_RUN = 1, - TIMER_EXPIRE = 2, }; #define set_timer(t,x) (((t)->start) = (x)/MSPTICK) -#define run_timer(t) ((t)->state == TIMER_RUN) +#define run_timer(t) ((t)->state == TimerON) -enum /* Tcp connection states */ +enum /* Tcp connection states */ { Closed = 0, Listen, @@ -380,7 +381,6 @@ struct Ipifc int minmtu; /* Minumum tranfer unit */ int hsize; /* Media header size */ ulong chkerrs; /* checksum errors */ - Lock; Ipconv **conv; /* conversations */ }; diff --git a/port/net.c b/port/net.c index e5d28c42ec44067a9aa41c568e3983b43b4c3524..8c18d00de96accb071cac870b1b2bd8d53c23c04 100644 --- a/port/net.c +++ b/port/net.c @@ -7,11 +7,11 @@ enum { - Qlisten= 1, - Qclone= 2, - Q2nd= 3, - Q3rd= 4, - Qinf= 5, + Qlisten = 1, + Qclone = 2, + Q2nd = 3, + Q3rd = 4, + Qinf = 5, }; /* diff --git a/port/tcpif.c b/port/tcpif.c index 2fec1ed7a97803d24b95e3014d4b76980af4b647..2831acaf76cb63528d48755f3a5a7e541345c05f 100644 --- a/port/tcpif.c +++ b/port/tcpif.c @@ -15,11 +15,12 @@ tcpxstate(Ipconv *s, char oldstate, char newstate) { int len; Block *bp; - Tcpctl *tcb = &s->tcpctl; + Tcpctl *tcb; if(oldstate == newstate) return; + tcb = &s->tcpctl; switch(newstate) { case Closed: s->psrc = 0; /* This connection is toast */ @@ -68,14 +69,16 @@ notsyner(void *ic) void tcpstart(Ipconv *s, int mode, ushort window, char tos) { - Tcpctl *tcb = &s->tcpctl; + Tcpctl *tcb; + tcb = &s->tcpctl; if(tcb->state != Closed) return; init_tcpctl(s); - tcb->window = tcb->rcv.wnd = window; + tcb->window = window; + tcb->rcv.wnd = window; tcb->tos = tos; switch(mode){ diff --git a/port/tcpinput.c b/port/tcpinput.c index c5f54247f5e10d22206f3bf2b5f302e3db03767c..9abfe04ab0e5bd43e77f16c7957a67f8ba13550a 100644 --- a/port/tcpinput.c +++ b/port/tcpinput.c @@ -7,7 +7,10 @@ #include "arp.h" #include "ipdat.h" -int tcpdbg = 0; +int tcpdbg = 0; +ushort tcp_mss = DEF_MSS; /* Maximum segment size to be sent with SYN */ +int tcp_irtt = DEF_RTT; /* Initial guess at round trip time */ + #define DPRINT if(tcpdbg) print #define LPRINT if(tcpdbg) print @@ -118,9 +121,9 @@ tcpincoming(Ipifc *ifc, Ipconv *s, Tcp *segp, Ipaddr source) tcpmove(&new->tcpctl, &s->tcpctl); new->tcpctl.flags &= ~CLONE; new->tcpctl.timer.arg = new; - new->tcpctl.timer.state = TIMER_STOP; + new->tcpctl.timer.state = TimerOFF; new->tcpctl.acktimer.arg = new; - new->tcpctl.acktimer.state = TIMER_STOP; + new->tcpctl.acktimer.state = TimerOFF; new->newcon = s; wakeup(&s->listenr); @@ -130,15 +133,15 @@ tcpincoming(Ipifc *ifc, Ipconv *s, Tcp *segp, Ipaddr source) void tcpinput(Ipifc *ifc, Block *bp) { - Ipconv *s, **p, **etab; - Ipconv *spec, *gen; - Tcpctl *tcb; - Tcphdr *h; Tcp seg; - int hdrlen; - Ipaddr source, dest; char tos; + Tcphdr *h; + int hdrlen; + Tcpctl *tcb; ushort length; + Ipconv *spec, *gen; + Ipaddr source, dest; + Ipconv *s, **p, **etab; h = (Tcphdr *)(bp->rptr); dest = nhgetl(h->tcpdst); @@ -202,7 +205,8 @@ tcpinput(Ipifc *ifc, Block *bp) } /* The rest of the input state machine is run with the control block - * locked + * locked and implements the state machine directly out of the RFC + * Out-of-band data is ignored - it was always a bad idea. */ tcb = &s->tcpctl; qlock(tcb); @@ -681,10 +685,10 @@ trim(Tcpctl *tcb, Tcp *seg, Block **bp, ushort *length) } else { /* Some part of the segment should be in the window */ - if(in_window(tcb,seg->seq)) { + if(in_window(tcb,seg->seq)) accept++; - } - else if(len != 0) { + else + if(len != 0) { if(in_window(tcb, (int)(seg->seq+len-1)) || seq_within(tcb->rcv.nxt, seg->seq,(int)(seg->seq+len-1))) accept++; @@ -794,9 +798,6 @@ dupb(Block **hp, Block *bp, int offset, int count) return bytes; } -ushort tcp_mss = DEF_MSS; /* Maximum segment size to be sent with SYN */ -int tcp_irtt = DEF_RTT; /* Initial guess at round trip time */ - static void cleartcp(struct Tctl *a) { @@ -895,8 +896,10 @@ seq_ge(int x, int y) void tcpsetstate(Ipconv *s, char newstate) { + Tcpctl *tcb; char oldstate; - Tcpctl *tcb = &s->tcpctl; + + tcb = &s->tcpctl; oldstate = tcb->state; tcb->state = newstate; @@ -906,11 +909,11 @@ tcpsetstate(Ipconv *s, char newstate) Block * htontcp(Tcp *tcph, Block *data, Tcphdr *ph) { - ushort hdrlen; int dlen; - ushort csum; Tcphdr *h; Block *bp; + ushort csum; + ushort hdrlen; hdrlen = TCP_HDRSIZE; if(tcph->mss) diff --git a/port/tcpoutput.c b/port/tcpoutput.c index 496315045df4ae4943442f18a612709fdd37e03f..604de235639ca5e4d6c1c4ef4b8e52d31b825688 100644 --- a/port/tcpoutput.c +++ b/port/tcpoutput.c @@ -16,12 +16,12 @@ extern ushort tcp_mss; void tcpoutput(Ipconv *s) { - Block *hbp,*dbp, *sndq; - ushort ssize, dsize, usable, sent; + Tcp seg; int qlen; Tcphdr ph; - Tcp seg; Tcpctl *tcb; + Block *hbp,*dbp, *sndq; + ushort ssize, dsize, usable, sent; tcb = &s->tcpctl; @@ -157,11 +157,12 @@ tcprxmit(Ipconv *s) tcb->flags |= RETRAN|FORCE; tcb->snd.ptr = tcb->snd.una; - /* Reduce slowstart threshold to half current window */ + /* Pull window down to a single packet and halve the slow + * start threshold + */ tcb->ssthresh = tcb->cwind / 2; - tcb->ssthresh = MAX(tcb->ssthresh,tcb->mss); + tcb->ssthresh = MAX(tcb->ssthresh, tcb->mss); - /* Shrink congestion window to 1 packet */ tcb->cwind = tcb->mss; tcpoutput(s); qunlock(tcb); @@ -197,12 +198,11 @@ backoff(int n) { if(tcptimertype == 1) return n+1; - else { - if(n <= 4) - return 1 << n; - else - return n * n; - } + + if(n <= 4) + return 1 << n; + + return n*n; } void @@ -220,13 +220,12 @@ tcpacktimer(Ipconv *s) void tcprcvwin(Ipconv *s) /* Call with tcb locked */ { - Tcpctl *tcb = &s->tcpctl; int w; + Tcpctl *tcb; - /* Calculate new window */ + tcb = &s->tcpctl; qlock(s); if(s->readq) { - /* use w because rcv.wnd is unsigned */ w = Streamhi - s->readq->next->len; if(w < 0) tcb->rcv.wnd = 0; diff --git a/port/tcptimer.c b/port/tcptimer.c index 3ad35033e46f2c345a44ddf5cf9cb3ee886adb68..6ce0df195068c1a0827405f7452543c732578321 100644 --- a/port/tcptimer.c +++ b/port/tcptimer.c @@ -57,33 +57,34 @@ tcpflow(void *x) void tcpackproc(void *junk) { - Timer *t,*tp; - Timer *expired; + Timer *t, *tp, *timeo; USED(junk); for(;;) { - expired = 0; + timeo = 0; qlock(&tl); for(t = timers;t != 0; t = tp) { tp = t->next; - if(t->state == TIMER_RUN) - if(--(t->count) == 0){ - deltimer(t); - t->state = TIMER_EXPIRE; - t->next = expired; - expired = t; + if(t->state == TimerON) { + t->count--; + if(t->count == 0) { + deltimer(t); + t->state = TimerDONE; + t->next = timeo; + timeo = t; + } } } qunlock(&tl); for(;;) { - t = expired; + t = timeo; if(t == 0) break; - expired = t->next; - if(t->state == TIMER_EXPIRE) + timeo = t->next; + if(t->state == TimerDONE) if(t->func) (*t->func)(t->arg); } @@ -99,8 +100,8 @@ tcpgo(Timer *t) qlock(&tl); t->count = t->start; - if(t->state != TIMER_RUN) { - t->state = TIMER_RUN; + if(t->state != TimerON) { + t->state = TimerON; t->prev = 0; t->next = timers; if(t->next) @@ -117,8 +118,8 @@ tcphalt(Timer *t) return; qlock(&tl); - if(t->state == TIMER_RUN) + if(t->state == TimerON) deltimer(t); - t->state = TIMER_STOP; + t->state = TimerOFF; qunlock(&tl); }