M pc/devether.c => pc/devether.c +59 -33
@@ 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 */
@@ 739,17 782,6 @@ wd8013online(Ctlr *cp, int on)
}
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)
{
Hw *hw = cp->hw;
@@ 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,
M pc/devhard.c => pc/devhard.c +1 -1
@@ 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)
M port/ipdat.h => port/ipdat.h +79 -79
@@ 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 */
};
M port/net.c => port/net.c +5 -5
@@ 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,
};
/*
M port/tcpif.c => port/tcpif.c +6 -3
@@ 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){
M port/tcpinput.c => port/tcpinput.c +22 -19
@@ 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)
M port/tcpoutput.c => port/tcpoutput.c +14 -15
@@ 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;
M port/tcptimer.c => port/tcptimer.c +17 -16
@@ 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);
}