M pc/dat.h => pc/dat.h +22 -6
@@ 182,14 182,30 @@ extern User *u;
extern int flipD[]; /* for flipping bitblt destination polarity */
+/*
+ * bootline passed by boot program
+ */
+#define BOOTLINE ((char *)0x80000100)
+
+/*
+ * configuration info
+ */
enum
{
- PMUnsx20= 0,
- PMUother= 1,
-
- Mouseserial= 0,
- MousePS2= 1,
- Mouseother= 2,
+ /* what kind of power management */
+ PMUother= 0,
+ PMUnsx20= 1,
+
+ /* what kind of mouse */
+ Mouseother= 0,
+ Mouseserial= 1,
+ MousePS2= 2,
+
+ /* how to reset the processor */
+ Resetother= 0,
+ Reset8042= 1,
+ Resetheadland= 2,
};
extern int mousetype;
extern int pmutype;
+extern int resettype;
M pc/devhard.c => pc/devhard.c +149 -126
@@ 6,7 6,7 @@
#include "io.h"
#include "../port/error.h"
-#define DPRINT if(0)print
+#define DPRINT if(1)print
typedef struct Drive Drive;
typedef struct Ident Ident;
@@ 53,44 53,6 @@ enum
#define DRIVE(x) (((x)>>4)&0x7)
#define MKQID(d,p) (((d)<<4) | (p))
-/*
- * ident sector from drive
- */
-struct Ident
-{
- ushort magic; /* drive type magic */
- ushort lcyls; /* logical number of cylinders */
- ushort rcyl; /* number of removable cylinders */
- ushort lheads; /* logical number of heads */
- ushort b2t; /* unformatted bytes/track */
- ushort b2s; /* unformated bytes/sector */
- ushort ls2t; /* logical sectors/track */
- ushort gap; /* bytes in inter-sector gaps */
- ushort sync; /* bytes in sync fields */
- ushort magic2; /* must be 0x0000 */
- ushort serial[10]; /* serial number */
- ushort type; /* controller type (0x0003) */
- ushort bsize; /* buffer size/512 */
- ushort ecc; /* ecc bytes returned by read long */
- ushort firm[4]; /* firmware revision */
- ushort model[20]; /* model number */
- ushort s2i; /* number of sectors/interrupt */
- ushort dwtf; /* double word transfer flag */
- ushort alernate;
- ushort piomode;
- ushort dmamode;
- ushort reserved[76];
- ushort ncyls; /* native number of cylinders */
- ushort nheads; /* native number of heads, sectors */
- ushort dlcyls; /* default logical number of cyinders */
- ushort dlheads; /* default logical number of heads, sectors */
- ushort interface;
- ushort power; /* 0xFFFF if power commands supported */
- ushort flags;
- ushort ageprog; /* MSB = age, LSB = program */
- ushort reserved2[120];
-};
-
struct Partition
{
ulong start;
@@ 126,8 88,6 @@ struct Drive
int sectors; /* sectors/track */
int heads; /* heads/cyl */
long cyl; /* cylinders/drive */
-
- Ident id; /* disk properties */
};
/*
@@ 161,8 121,9 @@ static void hardintr(Ureg*);
static long hardxfer(Drive*, Partition*, int, long, long, char*);
static void hardident(Drive*);
static void hardsetbuf(Drive*, int);
-static void hardinitparam(Drive*);
+static void hardparams(Drive*);
static void hardpart(Drive*);
+static int hardprobe(Drive*, int, int, int);
static int
hardgen(Chan *c, Dirtab *tab, long ntab, long s, Dir *dirp)
@@ 237,66 198,24 @@ Chan*
hardattach(char *spec)
{
Drive *dp;
- static int drivecomment=1;
for(dp = hard; dp < &hard[conf.nhard]; dp++){
- if(!waserror()){
- /*
- * the following is magic to determine the parameters
- * (number of cylinders/sectors/heads) on an IDE drive.
- * I haven't found a method that is guaranteed to work.
- * For some drives, it may be necessary to compile the
- * numbers into this driver and circumvent this code.
- * The BIOS disk type & tables doesn't help since the
- * types are inconsistent from one BIOS to the next.
- */
- dp->bytes = 512; /* until we know better */
- hardsetbuf(dp, 0); /* turned off during ident */
- hardident(dp);
- hardsetbuf(dp, 1);
- /*
- * for now use the configuration word to identify the
- * wayward 6386 disk. BUG!!! This word isn't
- * meant to identify disks, but we have nothing
- * better.
- */
- switch(dp->id.magic){
- case 0x324A: /* hard drive on the AT&T 6386, it lies */
- dp->cyl = dp->id.lcyls - 4;
- dp->heads = dp->id.lheads;
- dp->sectors = dp->id.ls2t - 1;
- break;
- default: /* others: we hope this works */
- dp->cyl = dp->id.lcyls;
- dp->heads = dp->id.lheads;
- dp->sectors = dp->id.ls2t;
- break;
- }
- dp->bytes = 512;
- dp->cap = dp->bytes * dp->cyl * dp->heads * dp->sectors;
- dp->online = 1;
- /*
- * Try reading the partition table (last disk sector).
- * If an error occurs set the drive parameters and try
- * again. This works if the parameters reported
- * by the disk are the physical parameters rather than
- * the current logical ones (as they are on the NCR 3170).
- *
- * We don't routinely set the parameters since it confuses
- * some disks (on the Gateway and AT&T Safari for example).
- */
- if(waserror()){
- hardinitparam(dp); /* set drive parameters */
- hardpart();
- } else {
- hardpart();
- poperror();
- }
- poperror();
- } else
+ if(waserror()){
dp->online = 0;
+ continue;
+ }
+ if(!dp->online){
+ hardparams(dp);
+ dp->online = 1;
+ hardsetbuf(dp, 1);
+ }
+
+ /*
+ * read Plan 9 partition table
+ */
+ hardpart(dp);
+ poperror();
}
- drivecomment=0; /* only the first time */
return devattach('w', spec);
}
@@ 629,35 548,42 @@ hardsetbuf(Drive *dp, int on)
}
/*
- * set the drive parameters
+ * ident sector from drive
*/
-static void
-hardinitparam(Drive *dp)
+struct Ident
{
- Controller *cp = dp->cp;
-
- qlock(cp);
- if(waserror()){
- qunlock(cp);
- nexterror();
- }
-
- cmdreadywait(cp);
-
- cp->cmd = Cinitparam;
- outb(cp->pbase+Psector, dp->sectors);
- outb(cp->pbase+Pdh, 0x20 | (dp->heads-1) | (dp->drive<<4));
- outb(cp->pbase+Pcmd, Cinitparam);
-
- sleep(&cp->r, cmddone, cp);
-
- if(cp->status & Serr)
- DPRINT("hd%d initparam err: status %lux, err %lux\n",
- dp-hard, cp->status, cp->error);
-
- poperror();
- qunlock(cp);
-}
+ ushort magic; /* drive type magic */
+ ushort lcyls; /* logical number of cylinders */
+ ushort rcyl; /* number of removable cylinders */
+ ushort lheads; /* logical number of heads */
+ ushort b2t; /* unformatted bytes/track */
+ ushort b2s; /* unformated bytes/sector */
+ ushort ls2t; /* logical sectors/track */
+ ushort gap; /* bytes in inter-sector gaps */
+ ushort sync; /* bytes in sync fields */
+ ushort magic2; /* must be 0x0000 */
+ ushort serial[10]; /* serial number */
+ ushort type; /* controller type (0x0003) */
+ ushort bsize; /* buffer size/512 */
+ ushort ecc; /* ecc bytes returned by read long */
+ ushort firm[4]; /* firmware revision */
+ ushort model[20]; /* model number */
+ ushort s2i; /* number of sectors/interrupt */
+ ushort dwtf; /* double word transfer flag */
+ ushort alernate;
+ ushort piomode;
+ ushort dmamode;
+ ushort reserved[76];
+ ushort ncyls; /* native number of cylinders */
+ ushort nheads; /* native number of heads, sectors */
+ ushort dlcyls; /* default logical number of cyinders */
+ ushort dlheads; /* default logical number of heads, sectors */
+ ushort interface;
+ ushort power; /* 0xFFFF if power commands supported */
+ ushort flags;
+ ushort ageprog; /* MSB = age, LSB = program */
+ ushort reserved2[120];
+};
/*
* get parameters from the drive
@@ 667,6 593,7 @@ hardident(Drive *dp)
{
Controller *cp;
char *buf;
+ Ident *ip;
cp = dp->cp;
buf = smalloc(Maxxfer);
@@ 690,7 617,8 @@ hardident(Drive *dp)
DPRINT("bad disk ident status\n");
error(Eio);
}
- memmove(&dp->id, buf, dp->bytes);
+ ip = (Ident*)buf;
+
/*
* this function appears to respond with an extra interrupt after
* the ident information is read, except on the safari. The following
@@ 700,6 628,11 @@ hardident(Drive *dp)
*/
if (cp->cmd == Cident2)
tsleep(&cp->r, return0, 0, 10);
+
+ dp->cyl = ip->lcyls;
+ dp->heads = ip->lheads;
+ dp->sectors = ip->ls2t;
+ dp->cap = dp->bytes * dp->cyl * dp->heads * dp->sectors;
cp->cmd = 0;
cp->buf = 0;
free(buf);
@@ 707,6 640,96 @@ hardident(Drive *dp)
qunlock(cp);
}
+/*
+ * probe the given sector to see if it exists
+ */
+static int
+hardprobe(Drive *dp, int cyl, int sec, int head)
+{
+ Controller *cp;
+ char *buf;
+ int rv;
+
+ cp = dp->cp;
+ buf = smalloc(Maxxfer);
+ qlock(cp);
+ if(waserror()){
+ qunlock(cp);
+ nexterror();
+ }
+
+ cmdreadywait(cp);
+
+ cp->cmd = Cread;
+ cp->dp = dp;
+ cp->status = 0;
+ cp->nsecs = 1;
+
+ outb(cp->pbase+Pcount, 1);
+ outb(cp->pbase+Psector, sec+1);
+ outb(cp->pbase+Pdh, 0x20 | head);
+ outb(cp->pbase+Pcyllsb, cyl);
+ outb(cp->pbase+Pcylmsb, cyl>>8);
+ outb(cp->pbase+Pcmd, Cread);
+
+ sleep(&cp->r, cmddone, cp);
+
+ if(cp->status & Serr)
+ rv = -1;
+ else
+ rv = 0;
+
+ cp->buf = 0;
+ free(buf);
+ poperror();
+ qunlock(cp);
+ return rv;
+}
+
+/*
+ * figure out the drive parameters
+ */
+static void
+hardparams(Drive *dp)
+{
+ int i, hi, lo;
+
+ /*
+ * first try the easy way, ask the drive and make sure it
+ * isn't lying.
+ */
+ dp->bytes = 512;
+ hardident(dp);
+ if(hardprobe(dp, dp->cyl-1, dp->sectors-1, dp->heads-1) == 0)
+ return;
+
+ /*
+ * the drive lied, determine parameters by seeing which ones
+ * work to read sectors.
+ */
+ for(i = 0; i < 32; i++)
+ if(hardprobe(dp, 0, 0, i) < 0)
+ break;
+ dp->heads = i;
+ for(i = 0; i < 128; i++)
+ if(hardprobe(dp, 0, i, 0) < 0)
+ break;
+ dp->sectors = i;
+ for(i = 512; ; i += 512)
+ if(hardprobe(dp, i, dp->sectors-1, dp->heads-1) < 0)
+ break;
+ lo = i - 512;
+ hi = i;
+ for(; hi-lo > 1;){
+ i = lo + (hi - lo)/2;
+ if(hardprobe(dp, i, dp->sectors-1, dp->heads-1) < 0)
+ hi = i;
+ else
+ lo = i;
+ }
+ dp->cyl = lo + 1;
+ dp->cap = dp->bytes * dp->cyl * dp->heads * dp->sectors;
+}
/*
* Read block replacement table.
M pc/main.c => pc/main.c +29 -9
@@ 7,9 7,12 @@
#include "ureg.h"
#include "init.h"
+/* configuration parameters */
int mousetype;
int pmutype;
-uchar *sp; /* stack pointer for /boot */
+int resettype;
+
+uchar *sp; /* stack pointer for /boot */
void
main(void)
@@ 41,24 44,24 @@ main(void)
}
/*
- * this should be changed to describe architecture dependencies outside the
- * PC model
+ * This tries to capture architecture dependencies since things
+ * like power management/reseting/mouse are outside the hardware
+ * model.
*/
void
ident(void)
{
char *id = (char*)(ROMBIOS + 0xFF40);
- /* check for a safari (tres special) */
if(strncmp(id, "AT&TNSX", 7) == 0){
mousetype = MousePS2;
pmutype = PMUnsx20;
+ resettype = Resetheadland;
}else if(strncmp(id, "NCRD.0", 6) == 0){
mousetype = MousePS2;
- pmutype = PMUother;
+ resettype = Reset8042;
}else{
mousetype = Mouseserial;
- pmutype = PMUother;
}
}
@@ 184,12 187,22 @@ bootargs(ulong base)
int i, ac;
uchar *av[32];
uchar **lsp;
+ char *cp = BOOTLINE;
+ char buf[64];
sp = (uchar*)base + BY2PG - MAXSYSARG*BY2WD;
ac = 0;
av[ac++] = pusharg("/386/9safari");
av[ac++] = pusharg("-p");
+ cp[64] = 0;
+ if(strncmp(cp, "fd!", 3) == 0){
+ sprint(buf, "local!#f/fd%ddisk", atoi(cp+3));
+ av[ac++] = pusharg(buf);
+ } else if(strncmp(cp, "hd!", 3) == 0){
+ sprint(buf, "local!#w/hd%ddisk", atoi(cp+3));
+ av[ac++] = pusharg(buf);
+ }
/* 4 byte word align stack */
sp = (uchar*)((ulong)sp & ~3);
@@ 413,9 426,16 @@ exit(int ispanic)
print("exiting\n");
if(ispanic)
for(;;);
- i8042reset(); /* via keyboard controller */
- print("can't reset via software, do something drastic!\n");
- for(;;);
+
+ switch(resettype){
+ case Resetheadland:
+ headreset();
+ case Reset8042:
+ i8042reset(); /* via keyboard controller */
+ default:
+ print("Reset the machine!\n");
+ for(;;);
+ }
}
/*
M port/devbit.c => port/devbit.c +19 -5
@@ 1661,11 1661,18 @@ bitstring(GBitmap *bp, Point pt, GFont *f, uchar *p, long l, Fcode fc)
Rectangle rect;
ushort r;
GCacheinfo *c;
+ int x;
+ Fcode clr;
- full = (fc==S || fc==notS); /* for reverse-video */
+ clr = 0;
+ full = (fc&~S)^(D&~S); /* result involves source */
if(full){
rect.min.y = 0;
rect.max.y = f->height;
+ /* set clr to result under fc if source pixel is zero */
+ /* hard to do without knowing layout of bits, so we cheat */
+ clr = (fc&3); /* fc&3 is result if source is zero */
+ clr |= clr<<2; /* fc&(3<<2) is result if source is one */
}
while(l > 0){
@@ 1678,10 1685,17 @@ bitstring(GBitmap *bp, Point pt, GFont *f, uchar *p, long l, Fcode fc)
if(!full){
rect.min.y = c->top;
rect.max.y = c->bottom;
- }else if(c->left > 0)
- gbitblt(bp, pt, f->b,
- Rect(pt.x, pt.y, pt.x+c->left, pt.y+f->height),
- fc==S? 0 : F);
+ }else{
+ if(c->left > 0)
+ gbitblt(bp, pt, bp,
+ Rect(pt.x, pt.y, pt.x+c->left, pt.y+f->height),
+ clr);
+ x = c->left+(c->xright-c->x);
+ if(x < c->width)
+ gbitblt(bp, Pt(pt.x+x, pt.y), bp,
+ Rect(pt.x+x, pt.y, pt.x+c->width, pt.y+f->height),
+ clr);
+ }
rect.min.x = c->x;
rect.max.x = c->xright;
gbitblt(bp, Pt(pt.x+c->left, pt.y+rect.min.y), f->b, rect, fc);
M port/devip.c => port/devip.c +21 -16
@@ 23,9 23,10 @@ Ipifc *ipifc[Nrprotocol+1];
QLock ipalloc; /* Protocol port allocation lock */
Ipconv **tcpbase;
-Streamput udpstiput, udpstoput, tcpstiput, tcpstoput, iliput, iloput, bsdiput, bsdoput;
-Streamopen udpstopen, tcpstopen, ilopen, bsdopen;
-Streamclose udpstclose, tcpstclose, ilclose, bsdclose;
+Streamput udpstiput, udpstoput, tcpstiput, tcpstoput;
+Streamput iliput, iloput, bsdiput, bsdoput;
+Streamopen udpstopen, tcpstopen, ilopen, bsdopen;
+Streamclose udpstclose, tcpstclose, ilclose, bsdclose;
Qinfo tcpinfo = { tcpstiput, tcpstoput, tcpstopen, tcpstclose, "tcp", 0, 1 };
Qinfo udpinfo = { udpstiput, udpstoput, udpstopen, udpstclose, "udp" };
@@ 76,8 77,8 @@ ipinit(void)
Chan *
ipattach(char *spec)
{
- Chan *c;
int i;
+ Chan *c;
/* fail if ip is not yet configured */
if(Ipoutput == 0)
@@ 169,8 170,8 @@ ipcreateconv(Ipifc *ifc, int id)
Ipconv*
ipincoming(Ipifc *ifc, Ipconv *from)
{
- Ipconv **p, **etab;
Ipconv *new;
+ Ipconv **p, **etab;
/* look for an unused existing conversation */
etab = &ifc->conv[Nipconv];
@@ 554,10 555,11 @@ udpstoput(Queue *q, Block *bp)
hnputs(uh->udpplen, ptcllen);
hnputl(uh->udpsrc, Myip[Myself]);
hnputs(uh->udpsport, cp->psrc);
- if(cp->headers){
+ if(cp->headers) {
hnputl(uh->udpdst, addr);
hnputs(uh->udpdport, port);
- } else {
+ }
+ else {
hnputl(uh->udpdst, cp->dst);
hnputs(uh->udpdport, cp->pdst);
}
@@ 627,14 629,17 @@ tcpstoput(Queue *q, Block *bp)
switch(tcb->state) {
case Listen:
tcb->flags |= ACTIVE;
- send_syn(tcb);
- setstate(s, Syn_sent);
+ tcpsndsyn(tcb);
+ tcpsetstate(s, Syn_sent);
/* No break */
case Syn_sent:
case Syn_received:
case Established:
case Close_wait:
+ /*
+ * Push data
+ */
qlock(tcb);
if(waserror()) {
qunlock(tcb);
@@ 649,7 654,7 @@ tcpstoput(Queue *q, Block *bp)
f->next = bp;
}
tcprcvwin(s);
- tcp_output(s);
+ tcpoutput(s);
poperror();
qunlock(tcb);
break;
@@ 686,7 691,7 @@ tcpstopen(Queue *q, Stream *s)
if(tcpbase == 0)
tcpbase = ipifc[s->dev]->conv;
ifc = ipifc[s->dev];
- initipifc(ifc, IP_TCPPROTO, tcp_input, 1500, 512, ETHER_HDR);
+ initipifc(ifc, IP_TCPPROTO, tcpinput, 1500, 512, ETHER_HDR);
ipc = ipcreateconv(ifc, s->id);
ipc->readq = RD(q);
@@ 730,8 735,8 @@ iplocalfill(Chan *c, char *buf, int len)
void
ipstatusfill(Chan *c, char *buf, int len)
{
- int connection;
Ipconv *cp;
+ int connection;
if(len < 64)
error(Ebadarg);
@@ 759,9 764,9 @@ iphavecon(Ipconv *s)
int
iplisten(Chan *c)
{
- Ipconv **p, **etab, *new;
Ipconv *s;
int connection;
+ Ipconv **p, **etab, *new;
connection = STREAMID(c->qid.path);
s = ipcreateconv(ipifc[c->dev], connection);
@@ 850,20 855,20 @@ tcpstclose(Queue *q)
case Established:
tcb->sndcnt++;
tcb->snd.nxt++;
- setstate(s, Finwait1);
+ tcpsetstate(s, Finwait1);
goto output;
case Close_wait:
tcb->sndcnt++;
tcb->snd.nxt++;
- setstate(s, Last_ack);
+ tcpsetstate(s, Last_ack);
output:
qlock(tcb);
if(waserror()) {
qunlock(tcb);
nexterror();
}
- tcp_output(s);
+ tcpoutput(s);
poperror();
qunlock(tcb);
break;
M port/ipdat.h => port/ipdat.h +9 -9
@@ 472,7 472,7 @@ void proc_syn(Ipconv*, char, Tcp*);
ushort ptcl_csum(Block*bp, int, int);
int pullb(Block **, int);
void reset(Ipaddr, Ipaddr, char, ushort, Tcp*);
-void send_syn(Tcpctl*);
+void tcpsndsyn(Tcpctl*);
int seq_ge(int, int);
int seq_gt(int, int);
int seq_gt(int, int);
@@ 480,14 480,14 @@ int seq_le(int, int);
int seq_lt(int, int);
int seq_within(int, int, int);
int seq_within(int, int, int);
-void setstate(Ipconv *, char);
-void start_timer(Timer *);
-void state_upcall(Ipconv*, char oldstate, char newstate);
-void stop_timer(Timer *);
-void tcp_acktimer(void *);
-void tcp_input(Ipifc*, Block *);
-void tcp_output(Ipconv*);
-void tcp_timeout(void *);
+void tcpsetstate(Ipconv *, char);
+void tcpgo(Timer *);
+void tcphalt(Timer *);
+void tcpxstate(Ipconv*, char oldstate, char newstate);
+void tcpacktimer(void *);
+void tcpinput(Ipifc*, Block *);
+void tcpoutput(Ipconv*);
+void tcptimeout(void *);
void tcpackproc(void*);
void tcpflow(void*);
void tcpflushincoming(Ipconv*);
M port/tcpif.c => port/tcpif.c +9 -12
@@ 11,24 11,21 @@ extern int tcpdbg;
#define DPRINT if(tcpdbg) print
void
-state_upcall(Ipconv *s, char oldstate, char newstate)
+tcpxstate(Ipconv *s, char oldstate, char newstate)
{
- Block *bp;
int len;
+ Block *bp;
Tcpctl *tcb = &s->tcpctl;
- DPRINT("state_upcall: %s -> %s err %s\n",
- tcpstate[oldstate], tcpstate[newstate], s->err);
-
if(oldstate == newstate)
return;
switch(newstate) {
case Closed:
- s->psrc = 0;
+ s->psrc = 0; /* This connection is toast */
s->pdst = 0;
s->dst = 0;
- /* NO break */
+
case Close_wait: /* Remote closes */
if(s->err) {
len = strlen(s->err);
@@ 46,7 43,7 @@ state_upcall(Ipconv *s, char oldstate, char newstate)
qunlock(s);
nexterror();
}
- if(s->readq == 0){
+ if(s->readq == 0) {
if(newstate == Close_wait)
putb(&tcb->rcvq, bp);
else
@@ 84,7 81,7 @@ tcpstart(Ipconv *s, int mode, ushort window, char tos)
switch(mode){
case TCP_PASSIVE:
tcb->flags |= CLONE;
- setstate(s, Listen);
+ tcpsetstate(s, Listen);
break;
case TCP_ACTIVE:
@@ 95,9 92,9 @@ tcpstart(Ipconv *s, int mode, ushort window, char tos)
qunlock(tcb);
nexterror();
}
- send_syn(tcb);
- setstate(s, Syn_sent);
- tcp_output(s);
+ tcpsndsyn(tcb);
+ tcpsetstate(s, Syn_sent);
+ tcpoutput(s);
poperror();
qunlock(tcb);
sleep(&tcb->syner, notsyner, tcb);
M port/tcpinput.c => port/tcpinput.c +61 -66
@@ 19,15 19,13 @@ char *tcpstate[] =
};
void
-sndrst(Ipaddr source, Ipaddr dest, char tos, ushort length, Tcp *seg)
+sndrst(Ipaddr source, Ipaddr dest, ushort length, Tcp *seg)
{
Block *hbp;
Port tmp;
char rflags;
Tcphdr ph;
- USED(tos); /* is this right??? */
-
if(seg->flags & RST)
return;
@@ 85,7 83,7 @@ tcpflushincoming(Ipconv *s)
seg.seq = tcb->snd.ptr;
seg.ack = tcb->last_ack = tcb->rcv.nxt;
- sndrst(s->dst, Myip[Myself], 0, 0, &seg);
+ sndrst(s->dst, Myip[Myself], 0, &seg);
localclose(s, 0);
}
@@ 130,7 128,7 @@ tcpincoming(Ipifc *ifc, Ipconv *s, Tcp *segp, Ipaddr source)
}
void
-tcp_input(Ipifc *ifc, Block *bp)
+tcpinput(Ipifc *ifc, Block *bp)
{
Ipconv *s, **p, **etab;
Ipconv *spec, *gen;
@@ 198,7 196,7 @@ tcp_input(Ipifc *ifc, Block *bp)
}
if(s == 0){
freeb(bp);
- sndrst(source, dest, tos, length, &seg);
+ sndrst(source, dest, length, &seg);
return;
}
}
@@ 212,7 210,7 @@ tcp_input(Ipifc *ifc, Block *bp)
switch(tcb->state) {
case Closed:
freeb(bp);
- sndrst(source, dest, tos, length, &seg);
+ sndrst(source, dest, length, &seg);
goto done;
case Listen:
if(seg.flags & RST) {
@@ 221,13 219,13 @@ tcp_input(Ipifc *ifc, Block *bp)
}
if(seg.flags & ACK) {
freeb(bp);
- sndrst(source, dest, tos, length, &seg);
+ sndrst(source, dest, length, &seg);
goto done;
}
if(seg.flags & SYN) {
proc_syn(s, tos, &seg);
- send_syn(tcb);
- setstate(s, Syn_received);
+ tcpsndsyn(tcb);
+ tcpsetstate(s, Syn_received);
if(length != 0 || (seg.flags & FIN))
break;
freeb(bp);
@@ 239,7 237,7 @@ tcp_input(Ipifc *ifc, Block *bp)
if(seg.flags & ACK) {
if(!seq_within(seg.ack, tcb->iss+1, tcb->snd.nxt)) {
freeb(bp);
- sndrst(source, dest, tos, length, &seg);
+ sndrst(source, dest, length, &seg);
goto done;
}
}
@@ 253,7 251,7 @@ tcp_input(Ipifc *ifc, Block *bp)
if(seg.flags & ACK)
if(PREC(tos) != PREC(tcb->tos)){
freeb(bp);
- sndrst(source, dest, tos, length, &seg);
+ sndrst(source, dest, length, &seg);
goto done;
}
@@ 261,10 259,10 @@ tcp_input(Ipifc *ifc, Block *bp)
proc_syn(s, tos, &seg);
if(seg.flags & ACK){
update(s, &seg);
- setstate(s, Established);
+ tcpsetstate(s, Established);
}
else
- setstate(s, Syn_received);
+ tcpsetstate(s, Syn_received);
if(length != 0 || (seg.flags & FIN))
break;
@@ 291,7 289,7 @@ tcp_input(Ipifc *ifc, Block *bp)
if(s->readq == 0)
if(tcb->state == Closed) {
freeb(bp);
- sndrst(source, dest, tos, length, &seg);
+ sndrst(source, dest, length, &seg);
goto done;
}
@@ 309,7 307,7 @@ tcp_input(Ipifc *ifc, Block *bp)
if(seg.flags & RST) {
if(tcb->state == Syn_received
&& !(tcb->flags & (CLONE|ACTIVE)))
- setstate(s, Listen);
+ tcpsetstate(s, Listen);
else
localclose(s, Econrefused);
@@ 317,9 315,10 @@ tcp_input(Ipifc *ifc, Block *bp)
goto done;
}
+ /* This tos stuff should be removed */
if(PREC(tos) != PREC(tcb->tos) || (seg.flags & SYN)){
freeb(bp);
- sndrst(source, dest, tos, length, &seg);
+ sndrst(source, dest, length, &seg);
goto done;
}
@@ 330,16 329,13 @@ tcp_input(Ipifc *ifc, Block *bp)
switch(tcb->state) {
case Syn_received:
- if(seq_within(seg.ack, tcb->snd.una+1, tcb->snd.nxt)){
- update(s, &seg);
- setstate(s, Established);
- }
- else {
+ if(!seq_within(seg.ack, tcb->snd.una+1, tcb->snd.nxt)){
freeb(bp);
- sndrst(source, dest, tos, length, &seg);
+ sndrst(source, dest, length, &seg);
goto done;
}
- break;
+ update(s, &seg);
+ tcpsetstate(s, Established);
case Established:
case Close_wait:
update(s, &seg);
@@ 347,7 343,7 @@ tcp_input(Ipifc *ifc, Block *bp)
case Finwait1:
update(s, &seg);
if(tcb->sndcnt == 0)
- setstate(s, Finwait2);
+ tcpsetstate(s, Finwait2);
break;
case Finwait2:
update(s, &seg);
@@ 355,9 351,9 @@ tcp_input(Ipifc *ifc, Block *bp)
case Closing:
update(s, &seg);
if(tcb->sndcnt == 0) {
- setstate(s, Time_wait);
+ tcpsetstate(s, Time_wait);
tcb->timer.start = MSL2 * (1000 / MSPTICK);
- start_timer(&tcb->timer);
+ tcpgo(&tcb->timer);
}
break;
case Last_ack:
@@ 369,7 365,7 @@ tcp_input(Ipifc *ifc, Block *bp)
}
case Time_wait:
tcb->flags |= FORCE;
- start_timer(&tcb->timer);
+ tcpgo(&tcb->timer);
}
if((seg.flags&URG) && seg.up) {
@@ 409,7 405,7 @@ tcp_input(Ipifc *ifc, Block *bp)
tcprcvwin(s);
- start_timer(&tcb->acktimer);
+ tcpgo(&tcb->acktimer);
if(tcb->max_snd <= tcb->rcv.nxt-tcb->last_ack)
tcb->flags |= FORCE;
@@ 418,7 414,7 @@ tcp_input(Ipifc *ifc, Block *bp)
/* no process to read the data, send a reset */
if(bp)
freeb(bp);
- sndrst(source, dest, tos, length, &seg);
+ sndrst(source, dest, length, &seg);
goto done;
}
}
@@ 430,35 426,35 @@ tcp_input(Ipifc *ifc, Block *bp)
case Syn_received:
case Established:
tcb->rcv.nxt++;
- setstate(s, Close_wait);
+ tcpsetstate(s, Close_wait);
break;
case Finwait1:
tcb->rcv.nxt++;
if(tcb->sndcnt == 0) {
- setstate(s, Time_wait);
+ tcpsetstate(s, Time_wait);
tcb->timer.start = MSL2 * (1000/MSPTICK);
- start_timer(&tcb->timer);
+ tcpgo(&tcb->timer);
}
else
- setstate(s, Closing);
+ tcpsetstate(s, Closing);
break;
case Finwait2:
tcb->rcv.nxt++;
- setstate(s, Time_wait);
+ tcpsetstate(s, Time_wait);
tcb->timer.start = MSL2 * (1000/MSPTICK);
- start_timer(&tcb->timer);
+ tcpgo(&tcb->timer);
break;
case Close_wait:
case Closing:
case Last_ack:
break;
case Time_wait:
- start_timer(&tcb->timer);
+ tcpgo(&tcb->timer);
break;
}
}
- while(tcb->reseq != 0) {
+ while(tcb->reseq) {
if(seq_ge(tcb->rcv.nxt, tcb->reseq->seg.seq) == 0)
break;
@@ 470,7 466,7 @@ tcp_input(Ipifc *ifc, Block *bp)
break;
}
output:
- tcp_output(s);
+ tcpoutput(s);
done:
qunlock(tcb);
}
@@ 521,7 517,7 @@ update(Ipconv *s, Tcp *seg)
/* Adjust the timers acorrding to the round trip time */
if(run_timer(&tcb->rtt_timer))
if(seq_ge(seg->ack, tcb->rttseq)) {
- stop_timer(&tcb->rtt_timer);
+ tcphalt(&tcb->rtt_timer);
if((tcb->flags&RETRAN) == 0) {
tcb->backoff = 0;
rtt = tcb->rtt_timer.start - tcb->rtt_timer.count;
@@ 550,9 546,9 @@ update(Ipconv *s, Tcp *seg)
if(seq_gt(seg->ack, tcb->snd.up))
tcb->snd.up = seg->ack;
- stop_timer(&tcb->timer);
+ tcphalt(&tcb->timer);
if(tcb->snd.una != tcb->snd.nxt)
- start_timer(&tcb->timer);
+ tcpgo(&tcb->timer);
if(seq_lt(tcb->snd.ptr, tcb->snd.una))
tcb->snd.ptr = tcb->snd.una;
@@ 595,7 591,7 @@ proc_syn(Ipconv *s, char tos, Tcp *seg)
/* Generate an initial sequence number and put a SYN on the send queue */
void
-send_syn(Tcpctl *tcb)
+tcpsndsyn(Tcpctl *tcb)
{
static int start;
@@ 630,16 626,16 @@ add_reseq(Tcpctl *tcb, char tos, Tcp *seg, Block *bp, ushort length)
if(rp1 == 0 || seq_lt(seg->seq, rp1->seg.seq)) {
rp->next = rp1;
tcb->reseq = rp;
- }
- else {
- for(;;){
- if(rp1->next == 0 || seq_lt(seg->seq, rp1->next->seg.seq)) {
- rp->next = rp1->next;
- rp1->next = rp;
- break;
- }
- rp1 = rp1->next;
+ return;
+ }
+
+ for(;;) {
+ if(rp1->next == 0 || seq_lt(seg->seq, rp1->next->seg.seq)) {
+ rp->next = rp1->next;
+ rp1->next = rp;
+ break;
}
+ rp1 = rp1->next;
}
}
@@ 648,7 644,8 @@ get_reseq(Tcpctl *tcb, char *tos, Tcp *seg, Block **bp, ushort *length)
{
Reseq *rp;
- if((rp = tcb->reseq) == 0)
+ rp = tcb->reseq;
+ if(rp == 0)
return;
tcb->reseq = rp->next;
@@ 818,16 815,13 @@ init_tcpctl(Ipconv *s)
tcb->ssthresh = 65535;
tcb->srtt = tcp_irtt;
- /* Initialize timer intervals */
tcb->timer.start = tcb->srtt / MSPTICK;
- tcb->timer.func = (void(*)(void*))tcp_timeout;
- tcb->timer.arg = (void *)s;
+ tcb->timer.func = tcptimeout;
+ tcb->timer.arg = s;
tcb->rtt_timer.start = MAX_TIME;
-
- /* Initialise ack timer */
tcb->acktimer.start = TCP_ACK / MSPTICK;
- tcb->acktimer.func = (void(*)(void*))tcp_acktimer;
- tcb->acktimer.arg = (void *)s;
+ tcb->acktimer.func = tcpacktimer;
+ tcb->acktimer.arg = s;
}
/*
@@ 840,8 834,8 @@ localclose(Ipconv *s, char reason[])
Tcpctl *tcb = &s->tcpctl;
Block *bp;
- stop_timer(&tcb->timer);
- stop_timer(&tcb->rtt_timer);
+ tcphalt(&tcb->timer);
+ tcphalt(&tcb->rtt_timer);
s->err = reason;
/* flush receive queue */
@@ 857,7 851,7 @@ localclose(Ipconv *s, char reason[])
tcb->reseq = 0;
s->err = reason;
- setstate(s, Closed);
+ tcpsetstate(s, Closed);
}
int
@@ 899,14 893,14 @@ seq_ge(int x, int y)
}
void
-setstate(Ipconv *s, char newstate)
+tcpsetstate(Ipconv *s, char newstate)
{
char oldstate;
Tcpctl *tcb = &s->tcpctl;
oldstate = tcb->state;
tcb->state = newstate;
- state_upcall(s, oldstate, newstate);
+ tcpxstate(s, oldstate, newstate);
}
Block *
@@ 1004,7 998,8 @@ ntohtcp(Tcp *tcph, Block **bpp)
if(!*bpp)
return -1;
- for(optr = h->tcpopt, i = TCP_HDRSIZE; i < hdrlen;) {
+ optr = h->tcpopt;
+ for(i = TCP_HDRSIZE; i < hdrlen;) {
switch(*optr++){
case EOL_KIND:
return hdrlen;
M port/tcpoutput.c => port/tcpoutput.c +23 -24
@@ 7,13 7,14 @@
#include "arp.h"
#include "ipdat.h"
-extern int tcpdbg;
#define DPRINT if(tcpdbg) print
-extern ushort tcp_mss;
-int tcptimertype = 0;
+
+extern int tcpdbg;
+extern ushort tcp_mss;
+ int tcptimertype;
void
-tcp_output(Ipconv *s)
+tcpoutput(Ipconv *s)
{
Block *hbp,*dbp, *sndq;
ushort ssize, dsize, usable, sent;
@@ 30,7 31,7 @@ tcp_output(Ipconv *s)
return;
}
- for(;;){
+ for(;;) {
qlen = tcb->sndcnt;
sent = tcb->snd.ptr - tcb->snd.una;
sndq = tcb->sndq;
@@ 40,16 41,15 @@ tcp_output(Ipconv *s)
if((tcb->flags & SYNACK) == 0)
break;
+ /* Compute usable segment based on offered window and limit
+ * window probes to one
+ */
if(tcb->snd.wnd == 0){
- /* Allow only one closed-window probe at a time */
if(sent != 0)
break;
- /* Force a closed-window probe */
usable = 1;
- } else {
- /* usable window = offered window - unacked bytes in transit
- * limited by the congestion window
- */
+ }
+ else {
usable = MIN(tcb->snd.wnd,tcb->cwind) - sent;
if(sent != 0)
if(qlen - sent < tcb->mss)
@@ 61,20 61,18 @@ tcp_output(Ipconv *s)
dsize = ssize;
seg.up = 0;
- DPRINT("tcp_out: ssize = %lux\n", ssize);
if(ssize == 0)
if((tcb->flags&FORCE) == 0)
break;
- /* Stop ack timer if one will be piggy backed on data */
- stop_timer(&tcb->acktimer);
+ tcphalt(&tcb->acktimer);
tcb->flags &= ~FORCE;
tcprcvwin(s);
+ /* By default we will generate an ack */
seg.source = s->psrc;
seg.dest = s->pdst;
- /* Every state except SYN_SENT */
seg.flags = ACK;
seg.mss = 0;
@@ 137,11 135,11 @@ tcp_output(Ipconv *s)
tcb->timer.start = backoff(tcb->backoff) *
(2 * tcb->mdev + tcb->srtt + MSPTICK) / MSPTICK;
if(!run_timer(&tcb->timer))
- start_timer(&tcb->timer);
+ tcpgo(&tcb->timer);
/* If round trip timer isn't running, start it */
if(!run_timer(&tcb->rtt_timer)){
- start_timer(&tcb->rtt_timer);
+ tcpgo(&tcb->rtt_timer);
tcb->rttseq = tcb->snd.ptr;
}
}
@@ 165,12 163,12 @@ tcprxmit(Ipconv *s)
/* Shrink congestion window to 1 packet */
tcb->cwind = tcb->mss;
- tcp_output(s);
+ tcpoutput(s);
qunlock(tcb);
}
void
-tcp_timeout(void *arg)
+tcptimeout(void *arg)
{
Tcpctl *tcb;
Ipconv *s;
@@ 181,10 179,11 @@ tcp_timeout(void *arg)
switch(tcb->state){
default:
tcb->backoff++;
- if (tcb->backoff >= MAXBACKOFF)
+ if (tcb->backoff >= MAXBACKOFF) {
localclose(s, Etimedout);
- else
- tcprxmit(s);
+ break;
+ }
+ tcprxmit(s);
break;
case Time_wait:
@@ 207,14 206,14 @@ backoff(int n)
}
void
-tcp_acktimer(Ipconv *s)
+tcpacktimer(Ipconv *s)
{
Tcpctl *tcb = &s->tcpctl;
qlock(tcb);
tcb->flags |= FORCE;
tcprcvwin(s);
- tcp_output(s);
+ tcpoutput(s);
qunlock(tcb);
}
M port/tcptimer.c => port/tcptimer.c +58 -67
@@ 7,12 7,53 @@
#include "arp.h"
#include "ipdat.h"
-/* Head of running timer chain */
-Timer *timers;
-QLock timerlock;
-Rendez Tcpack;
+static Timer *timers; /* List of active timers */
+static QLock tl; /* Protect timer list */
+static Rendez Tcpack;
Rendez tcpflowr;
+static void
+deltimer(Timer *t)
+{
+ if(timers == t)
+ timers = t->next;
+
+ if(t->next)
+ t->next->prev = t->prev;
+
+ if(t->prev)
+ t->prev->next = t->next;
+}
+
+/*
+ * Poke each tcp connection to recompute window size and
+ * acknowledgement timer
+ */
+
+void
+tcpflow(void *x)
+{
+ Ipifc *ifc;
+ Ipconv *cp, **p, **etab;
+
+ ifc = x;
+ etab = &ifc->conv[Nipconv];
+
+ for(;;) {
+ sleep(&tcpflowr, return0, 0);
+
+ for(p = ifc->conv; p < etab; p++) {
+ cp = *p;
+ if(cp == 0)
+ break;
+ if(cp->readq && cp->ref != 0 && !QFULL(cp->readq->next)) {
+ tcprcvwin(cp);
+ tcpacktimer(cp);
+ }
+ }
+ }
+}
+
void
tcpackproc(void *junk)
{
@@ 23,30 64,18 @@ tcpackproc(void *junk)
for(;;) {
expired = 0;
- qlock(&timerlock);
+ qlock(&tl);
for(t = timers;t != 0; t = tp) {
tp = t->next;
- if(tp == t)
- panic("Timer loop at %lux\n",(long)tp);
-
if(t->state == TIMER_RUN)
if(--(t->count) == 0){
-
- /* Delete from active timer list */
- if(timers == t)
- timers = t->next;
- if(t->next != 0)
- t->next->prev = t->prev;
- if(t->prev != 0)
- t->prev->next = t->next;
-
+ deltimer(t);
t->state = TIMER_EXPIRE;
- /* Put on head of expired timer list */
t->next = expired;
expired = t;
}
}
- qunlock(&timerlock);
+ qunlock(&tl);
for(;;) {
t = expired;
@@ 58,76 87,38 @@ tcpackproc(void *junk)
if(t->func)
(*t->func)(t->arg);
}
-
tsleep(&Tcpack, return0, 0, MSPTICK);
}
}
void
-start_timer(Timer *t)
+tcpgo(Timer *t)
{
-
if(t == 0 || t->start == 0)
return;
- qlock(&timerlock);
-
+ qlock(&tl);
t->count = t->start;
- if(t->state != TIMER_RUN){
+ if(t->state != TIMER_RUN) {
t->state = TIMER_RUN;
- /* Put on head of active timer list */
t->prev = 0;
t->next = timers;
- if(t->next != 0)
+ if(t->next)
t->next->prev = t;
timers = t;
}
- qunlock(&timerlock);
+ qunlock(&tl);
}
void
-stop_timer(Timer *t)
+tcphalt(Timer *t)
{
if(t == 0)
return;
- qlock(&timerlock);
-
- if(t->state == TIMER_RUN){
- /* Delete from active timer list */
- if(timers == t)
- timers = t->next;
- if(t->next != 0)
- t->next->prev = t->prev;
- if(t->prev != 0)
- t->prev->next = t->next;
- }
+ qlock(&tl);
+ if(t->state == TIMER_RUN)
+ deltimer(t);
t->state = TIMER_STOP;
-
- qunlock(&timerlock);
-}
-
-void
-tcpflow(void *x)
-{
- Ipifc *ifc;
- Ipconv *cp, **p, **etab;
-
- ifc = x;
- etab = &ifc->conv[Nipconv];
-
- for(;;) {
- sleep(&tcpflowr, return0, 0);
-
- for(p = ifc->conv; p < etab; p++) {
- cp = *p;
- if(cp == 0)
- break;
- if(cp->readq && cp->ref != 0 && !QFULL(cp->readq->next)) {
- tcprcvwin(cp);
- tcp_acktimer(cp);
- }
- }
- }
+ qunlock(&tl);
}
-