Browse Source

Plan 9 from Bell Labs 2003-02-13

David du Colombier 21 years ago
parent
commit
19ec7cd778

+ 21 - 19
dist/replica/plan9.db

@@ -356,7 +356,7 @@
 386/bin/srvold9p - 775 sys sys 1039758592 130502
 386/bin/ssh - 775 sys sys 1042440491 209672
 386/bin/sshnet - 775 sys sys 1039758593 281010
-386/bin/stats - 775 sys sys 1039758593 184849
+386/bin/stats - 775 sys sys 1045059500 186222
 386/bin/strings - 775 sys sys 1039758593 60879
 386/bin/strip - 775 sys sys 1039758593 60826
 386/bin/sum - 775 sys sys 1039758593 40355
@@ -4870,7 +4870,7 @@ sys/man/8/securenet - 664 sys sys 954305552 3160
 sys/man/8/send - 664 sys sys 1032237031 2154
 sys/man/8/smtp - 664 sys sys 1037397434 3845
 sys/man/8/snoopy - 664 sys sys 1034009982 3714
-sys/man/8/stats - 664 sys sys 1016731553 3939
+sys/man/8/stats - 664 sys sys 1045059512 4042
 sys/man/8/stub - 664 sys sys 1044830500 943
 sys/man/8/swap - 664 sys sys 944959679 880
 sys/man/8/timesync - 664 sys sys 1022590210 1629
@@ -4910,7 +4910,7 @@ sys/src/9/alphapc/devvga.c - 664 sys sys 1015012784 7513
 sys/src/9/alphapc/dma.c - 664 sys sys 1015012784 6112
 sys/src/9/alphapc/errstr.h - 664 sys sys 1015012784 2100
 sys/src/9/alphapc/ether2114x.c - 664 sys sys 1015012784 30
-sys/src/9/alphapc/etherif.h - 664 sys sys 1039753421 1049
+sys/src/9/alphapc/etherif.h - 664 sys sys 1045063621 1025
 sys/src/9/alphapc/faultalpha.c - 664 sys sys 1015012784 1257
 sys/src/9/alphapc/fdc37c93x.c - 664 sys sys 1015012785 1110
 sys/src/9/alphapc/floppy.h - 664 sys sys 1015012785 3783
@@ -5007,6 +5007,7 @@ sys/src/9/boot/bootmkfile - 664 sys sys 1032053196 390
 sys/src/9/boot/doauthenticate.c - 664 sys sys 1015012529 2300
 sys/src/9/boot/embed.c - 664 sys sys 1039763720 1191
 sys/src/9/boot/getpasswd.c - 664 sys sys 957373373 654
+sys/src/9/boot/libboot.a8 - 664 sys sys 1045063737 54718
 sys/src/9/boot/local.c - 664 sys sys 1039763718 2041
 sys/src/9/boot/mkboot - 775 sys sys 1015012530 1928
 sys/src/9/boot/nopsession.c - 664 sys sys 957373374 843
@@ -5020,30 +5021,30 @@ sys/src/9/ip/chandial.c - 664 sys sys 1022588098 2276
 sys/src/9/ip/devip.c - 664 sys sys 1044630546 24033
 sys/src/9/ip/eipconvtest.c - 664 sys sys 1022588098 3135
 sys/src/9/ip/esp.c - 664 sys sys 1026847565 17081
-sys/src/9/ip/ethermedium.c - 664 sys sys 1044630549 15013
+sys/src/9/ip/ethermedium.c - 664 sys sys 1045063514 15116
 sys/src/9/ip/gre.c - 664 sys sys 1026847565 4702
 sys/src/9/ip/icmp.c - 664 sys sys 1039098191 9443
-sys/src/9/ip/icmp6.c - 644 sys sys 1032053255 18087
+sys/src/9/ip/icmp6.c - 644 sys sys 1045063518 18086
 sys/src/9/ip/igmp.c - 664 sys sys 1026847566 5185
 sys/src/9/ip/il.c - 664 sys sys 1028566049 26975
 sys/src/9/ip/inferno.c - 664 sys sys 1022588098 517
-sys/src/9/ip/ip.c - 664 sys sys 1039098191 15147
-sys/src/9/ip/ip.h - 664 sys sys 1039098190 15812
+sys/src/9/ip/ip.c - 664 sys sys 1045063517 15146
+sys/src/9/ip/ip.h - 664 sys sys 1045063514 15846
 sys/src/9/ip/ipaux.c - 664 sys sys 1022588098 12656
-sys/src/9/ip/ipifc.c - 664 sys sys 1044630553 37714
+sys/src/9/ip/ipifc.c - 664 sys sys 1045063513 37702
 sys/src/9/ip/ipmux.c - 664 sys sys 1044630555 15352
 sys/src/9/ip/iproute.c - 664 sys sys 1022588099 14260
-sys/src/9/ip/ipv6.c - 664 sys sys 1044630557 14365
+sys/src/9/ip/ipv6.c - 664 sys sys 1045063516 14364
 sys/src/9/ip/ipv6.h - 644 sys sys 1022588099 4304
-sys/src/9/ip/loopbackmedium.c - 664 sys sys 1026847568 1651
-sys/src/9/ip/netdevmedium.c - 664 sys sys 1022588099 2680
+sys/src/9/ip/loopbackmedium.c - 664 sys sys 1045063513 1651
+sys/src/9/ip/netdevmedium.c - 664 sys sys 1045063517 2675
 sys/src/9/ip/netlog.c - 664 sys sys 1026847568 4003
 sys/src/9/ip/nullmedium.c - 664 sys sys 1022588099 491
-sys/src/9/ip/pktmedium.c - 664 sys sys 1044630559 1357
+sys/src/9/ip/pktmedium.c - 664 sys sys 1045063516 1355
 sys/src/9/ip/ptclbsum.c - 664 sys sys 1022588099 1243
 sys/src/9/ip/rudp.c - 664 sys sys 1026847569 21413
-sys/src/9/ip/tcp.c - 664 sys sys 1044906740 61753
-sys/src/9/ip/tripmedium.c - 664 sys sys 1022588099 7141
+sys/src/9/ip/tcp.c - 664 sys sys 1045063512 64964
+sys/src/9/ip/tripmedium.c - 664 sys sys 1045063515 7136
 sys/src/9/ip/udp.c - 664 sys sys 1026847570 13046
 sys/src/9/mkfile - 664 sys sys 1017795039 191
 sys/src/9/mtx - 20000000775 sys sys 1018721288 0
@@ -5116,7 +5117,7 @@ sys/src/9/pc/etherec2t.c - 664 sys sys 1020284820 4038
 sys/src/9/pc/etherelnk3.c - 664 sys sys 1026847641 48003
 sys/src/9/pc/etherga620.c - 664 sys sys 1032052917 28786
 sys/src/9/pc/etherga620fw.h - 644 sys sys 1026847642 222295
-sys/src/9/pc/etherif.h - 664 sys sys 1026847642 985
+sys/src/9/pc/etherif.h - 664 sys sys 1045063564 961
 sys/src/9/pc/ethermii.c - 664 sys sys 1039803177 4555
 sys/src/9/pc/ethermii.h - 664 sys sys 1039895684 3259
 sys/src/9/pc/ethersink.c - 664 sys sys 1017854323 1075
@@ -5159,6 +5160,7 @@ sys/src/9/pc/rebootcode.s - 664 sys sys 1015014522 988
 sys/src/9/pc/screen.c - 664 sys sys 1039753497 7266
 sys/src/9/pc/screen.h - 664 sys sys 1039753497 3742
 sys/src/9/pc/sd53c8xx.c - 664 sys sys 1033134905 51568
+sys/src/9/pc/sd53c8xx.i - 664 sys sys 1045063730 27355
 sys/src/9/pc/sd53c8xx.n - 664 sys sys 1032059019 12455
 sys/src/9/pc/sdata.c - 664 sys sys 1044630537 45002
 sys/src/9/pc/sdmylex.c - 664 sys sys 1015014523 27750
@@ -5227,7 +5229,7 @@ sys/src/9/port/devsd.c - 664 sys sys 1026847547 28679
 sys/src/9/port/devsdp.c - 664 sys sys 1026847548 44841
 sys/src/9/port/devsegment.c - 664 sys sys 1017679394 9600
 sys/src/9/port/devsrv.c - 664 sys sys 1014931174 5146
-sys/src/9/port/devssl.c - 664 sys sys 1026847548 26502
+sys/src/9/port/devssl.c - 664 sys sys 1045063590 26100
 sys/src/9/port/devtinyfs.c - 664 sys sys 1015278339 15347
 sys/src/9/port/devtls.c - 664 sys sys 1018721201 43664
 sys/src/9/port/devuart.c - 664 sys sys 1044630513 11590
@@ -5249,8 +5251,8 @@ sys/src/9/port/mkerrstr - 775 sys sys 1015278340 75
 sys/src/9/port/mkextract - 775 sys sys 1039753334 435
 sys/src/9/port/mkroot - 775 sys sys 1039753334 235
 sys/src/9/port/mksystab - 664 sys sys 1014931176 783
-sys/src/9/port/netif.c - 664 sys sys 1042855805 13131
-sys/src/9/port/netif.h - 664 sys sys 1042855799 2908
+sys/src/9/port/netif.c - 664 sys sys 1045063591 13188
+sys/src/9/port/netif.h - 664 sys sys 1045063591 2944
 sys/src/9/port/nulledf.c - 664 sys sys 1037669300 821
 sys/src/9/port/page.c - 664 sys sys 1014931177 8086
 sys/src/9/port/parse.c - 664 sys sys 1014931177 2026
@@ -9842,7 +9844,7 @@ sys/src/cmd/ssh/ssh_genkey.c - 664 sys sys 1016466380 1563
 sys/src/cmd/ssh/sshnet.c - 664 sys sys 1038293468 17653
 sys/src/cmd/ssh/sshserve.c - 664 sys sys 1019678647 5940
 sys/src/cmd/ssh/util.c - 664 sys sys 1038293465 5506
-sys/src/cmd/stats.c - 664 sys sys 1017854328 26826
+sys/src/cmd/stats.c - 664 sys sys 1045059499 26965
 sys/src/cmd/strings.c - 664 sys sys 944961364 1216
 sys/src/cmd/strip.c - 664 sys sys 1014926661 3306
 sys/src/cmd/sum.c - 664 sys sys 1014926615 5548

+ 21 - 0
dist/replica/plan9.log

@@ -17271,3 +17271,24 @@
 1045015278 0 c sys/src/cmd/hget.c - 664 sys sys 1045015305 21966
 1045017079 0 c 386/bin/hget - 775 sys sys 1045015306 216245
 1045017079 1 c sys/man/1/hget - 664 sys sys 1045015493 1286
+1045060367 0 c 386/bin/stats - 775 sys sys 1045059500 186222
+1045060367 1 c sys/man/8/stats - 664 sys sys 1045059512 4042
+1045060367 2 c sys/src/cmd/stats.c - 664 sys sys 1045059499 26965
+1045063968 0 c sys/src/9/alphapc/etherif.h - 664 sys sys 1045063621 1025
+1045063968 1 a sys/src/9/boot/libboot.a8 - 664 sys sys 1045063737 54718
+1045063968 2 c sys/src/9/ip/ethermedium.c - 664 sys sys 1045063514 15116
+1045063968 3 c sys/src/9/ip/icmp6.c - 644 sys sys 1045063518 18086
+1045063968 4 c sys/src/9/ip/ip.c - 664 sys sys 1045063517 15146
+1045063968 5 c sys/src/9/ip/ip.h - 664 sys sys 1045063514 15846
+1045063968 6 c sys/src/9/ip/ipifc.c - 664 sys sys 1045063513 37702
+1045063968 7 c sys/src/9/ip/ipv6.c - 664 sys sys 1045063516 14364
+1045063968 8 c sys/src/9/ip/loopbackmedium.c - 664 sys sys 1045063513 1651
+1045063968 9 c sys/src/9/ip/netdevmedium.c - 664 sys sys 1045063517 2675
+1045063968 10 c sys/src/9/ip/pktmedium.c - 664 sys sys 1045063516 1355
+1045063968 11 c sys/src/9/ip/tcp.c - 664 sys sys 1045063512 64964
+1045063968 12 c sys/src/9/ip/tripmedium.c - 664 sys sys 1045063515 7136
+1045063968 13 c sys/src/9/pc/etherif.h - 664 sys sys 1045063564 961
+1045063968 14 a sys/src/9/pc/sd53c8xx.i - 664 sys sys 1045063730 27355
+1045063968 15 c sys/src/9/port/devssl.c - 664 sys sys 1045063590 26100
+1045063968 16 c sys/src/9/port/netif.c - 664 sys sys 1045063591 13188
+1045063968 17 c sys/src/9/port/netif.h - 664 sys sys 1045063591 2944

+ 5 - 0
sys/man/8/stats

@@ -102,6 +102,11 @@ Upper-case options control details of the display.
 All graphs are affected; there is no mechanism to
 affect only one graph.
 .TP
+.BI -T " sleepsecs
+Set the number of seconds between samples to
+.I sleepsecs
+(default one second).
+.TP
 .BI -S " scale
 Sets a scale factor for the displays.  A value of 2, for example,
 means that the highest value plotted will be twice as large as the default.

+ 0 - 1
sys/src/9/alphapc/etherif.h

@@ -9,7 +9,6 @@ struct Ether {
 
 	int	ctlrno;
 	int	tbdf;			/* type+busno+devno+funcno */
-	int	mbps;			/* Mbps */
 	int	minmtu;
 	int 	maxmtu;
 	uchar	ea[Eaddrlen];

+ 23 - 17
sys/src/9/ip/ethermedium.c

@@ -35,8 +35,8 @@ Medium ethermedium =
 {
 .name=		"ether",
 .hsize=		14,
-.minmtu=	60,
-.maxmtu=	1514,
+.mintu=		60,
+.maxtu=		1514,
 .maclen=	6,
 .bind=		etherbind,
 .unbind=	etherunbind,
@@ -52,8 +52,8 @@ Medium gbemedium =
 {
 .name=		"gbe",
 .hsize=		14,
-.minmtu=	60,
-.maxmtu=	9014,
+.mintu=		60,
+.maxtu=		9014,
 .maclen=	6,
 .bind=		etherbind,
 .unbind=	etherunbind,
@@ -161,7 +161,7 @@ etherbind(Ipifc *ifc, int argc, char **argv)
 	devtab[cchan4->type]->write(cchan4, nbmsg, strlen(nbmsg), 0);
 
 	/*
-	 *  get mac address
+	 *  get mac address and speed
 	 */
 	snprint(addr, sizeof(addr), "%s/stats", dir);
 	buf = smalloc(512);
@@ -179,9 +179,15 @@ etherbind(Ipifc *ifc, int argc, char **argv)
 	if(!ptr)
 		error(Eio);
 	ptr += 6;
-
 	parsemac(ifc->mac, ptr, 6);
 
+	ptr = strstr(buf, "mbps: ");
+	if(ptr){
+		ptr += 6;
+		ifc->mbps = atoi(ptr);
+	} else
+		ifc->mbps = 100;
+
 	/*
  	 *  open arp conversation
 	 */
@@ -287,8 +293,8 @@ etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip)
 	bp = padblock(bp, ifc->m->hsize);
 	if(bp->next)
 		bp = concatblock(bp);
-	if(BLEN(bp) < ifc->minmtu)
-		bp = adjustblock(bp, ifc->minmtu);
+	if(BLEN(bp) < ifc->mintu)
+		bp = adjustblock(bp, ifc->mintu);
 	eh = (Etherhdr*)bp->rp;
 
 	/* copy in mac addresses and ether type */
@@ -331,7 +337,7 @@ etherread4(void *a)
 		pexit("hangup", 1);
 	}
 	for(;;){
-		bp = devtab[er->mchan4->type]->bread(er->mchan4, ifc->maxmtu, 0);
+		bp = devtab[er->mchan4->type]->bread(er->mchan4, ifc->maxtu, 0);
 		if(!canrlock(ifc)){
 			freeb(bp);
 			continue;
@@ -370,7 +376,7 @@ etherread6(void *a)
 		pexit("hangup", 1);
 	}
 	for(;;){
-		bp = devtab[er->mchan6->type]->bread(er->mchan6, ifc->maxmtu, 0);
+		bp = devtab[er->mchan6->type]->bread(er->mchan6, ifc->maxtu, 0);
 		if(!canrlock(ifc)){
 			freeb(bp);
 			continue;
@@ -465,8 +471,8 @@ sendarp(Ipifc *ifc, Arpent *a)
 	arprelease(er->f->arp, a);
 
 	n = sizeof(Etherarp);
-	if(n < a->type->minmtu)
-		n = a->type->minmtu;
+	if(n < a->type->mintu)
+		n = a->type->mintu;
 	bp = allocb(n);
 	memset(bp->rp, 0, n);
 	e = (Etherarp*)bp->rp;
@@ -542,8 +548,8 @@ sendgarp(Ipifc *ifc, uchar *ip)
 		return;
 
 	n = sizeof(Etherarp);
-	if(n < ifc->m->minmtu)
-		n = ifc->m->minmtu;
+	if(n < ifc->m->mintu)
+		n = ifc->m->mintu;
 	bp = allocb(n);
 	memset(bp->rp, 0, n);
 	e = (Etherarp*)bp->rp;
@@ -576,7 +582,7 @@ recvarp(Ipifc *ifc)
 	static uchar eprinted[4];
 	Etherrock *er = ifc->arg;
 
-	ebp = devtab[er->achan->type]->bread(er->achan, ifc->maxmtu, 0);
+	ebp = devtab[er->achan->type]->bread(er->achan, ifc->maxtu, 0);
 	if(ebp == nil) {
 		print("arp: rcv: %r\n");
 		return;
@@ -633,8 +639,8 @@ recvarp(Ipifc *ifc)
 			break;
 
 		n = sizeof(Etherarp);
-		if(n < ifc->minmtu)
-			n = ifc->minmtu;
+		if(n < ifc->mintu)
+			n = ifc->mintu;
 		rbp = allocb(n);
 		r = (Etherarp*)rbp->rp;
 		memset(r, 0, sizeof(Etherarp));

+ 1 - 1
sys/src/9/ip/icmp6.c

@@ -543,7 +543,7 @@ icmppkttoobig6(Fs *f, Ipifc *ifc, Block *bp)
 	memmove(np->dst, p->src, IPaddrlen);
 	np->type = PacketTooBigV6;
 	np->code = 0;
-	hnputl(np->icmpid, ifc->maxmtu - ifc->m->hsize);
+	hnputl(np->icmpid, ifc->maxtu - ifc->m->hsize);
 	memmove(nbp->rp + sizeof(IPICMP), bp->rp, sz - sizeof(IPICMP));
 	set_cksum(nbp);
 	np->ttl = HOP_LIMIT;

+ 1 - 1
sys/src/9/ip/ip.c

@@ -294,7 +294,7 @@ ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos)
 		goto raise;
 
 	/* If we dont need to fragment just send it */
-	medialen = ifc->maxmtu - ifc->m->hsize;
+	medialen = ifc->maxtu - ifc->m->hsize;
 	if(len <= medialen) {
 		if(!gating)
 			hnputs(eh->id, incref(&ip->id4));

+ 5 - 4
sys/src/9/ip/ip.h

@@ -124,8 +124,8 @@ struct Medium
 {
 	char	*name;
 	int	hsize;		/* medium header size */
-	int	minmtu;		/* default min mtu */
-	int	maxmtu;		/* default max mtu */
+	int	mintu;		/* default min mtu */
+	int	maxtu;		/* default max mtu */
 	int	maclen;		/* mac address length  */
 	void	(*bind)(Ipifc*, int, char**);
 	void	(*unbind)(Ipifc*);
@@ -212,8 +212,9 @@ struct Ipifc
 	Conv	*conv;		/* link to its conversation structure */
 	char	dev[64];	/* device we're attached to */
 	Medium	*m;		/* Media pointer */
-	int	maxmtu;		/* Maximum transfer unit */
-	int	minmtu;		/* Minumum tranfer unit */
+	int	maxtu;		/* Maximum transfer unit */
+	int	mintu;		/* Minumum tranfer unit */
+	int	mbps;		/* megabits per second */
 	void	*arg;		/* medium specific */
 	int	reassemble;	/* reassemble IP packets before forwarding */
 

+ 8 - 8
sys/src/9/ip/ipifc.c

@@ -140,8 +140,8 @@ ipifcbind(Conv *c, char **argv, int argc)
 
 	/* set up parameters */
 	ifc->m = m;
-	ifc->minmtu = ifc->m->minmtu;
-	ifc->maxmtu = ifc->m->maxmtu;
+	ifc->mintu = ifc->m->mintu;
+	ifc->maxtu = ifc->m->maxtu;
 	if(ifc->m->unbindonclose == 0)
 		ifc->conv->inuse++;
 	ifc->rp.mflag	= 0;		// default not managed
@@ -226,7 +226,7 @@ ipifcunbind(Ipifc *ifc)
 
 
 
-char sfixedformat[] = "device %s maxmtu %d sendra %d recvra %d mflag %d oflag %d maxraint %d minraint %d linkmtu %d reachtime %d rxmitra %d ttl %d routerlt %d pktin %lud pktout %lud errin %lud errout %lud\n";
+char sfixedformat[] = "device %s maxtu %d sendra %d recvra %d mflag %d oflag %d maxraint %d minraint %d linkmtu %d reachtime %d rxmitra %d ttl %d routerlt %d pktin %lud pktout %lud errin %lud errout %lud\n";
 
 char slineformat[] = "	%-40.40I %-10.10M %-40.40I %-12lud %-12lud\n";
 
@@ -241,7 +241,7 @@ ipifcstate(Conv *c, char *state, int n)
 	ifc = (Ipifc*)c->ptcl;
 
 	m = snprint(state, n, sfixedformat, 
-		ifc->dev, ifc->maxmtu, ifc->sendra6, ifc->recvra6,
+		ifc->dev, ifc->maxtu, ifc->sendra6, ifc->recvra6,
 		ifc->rp.mflag, ifc->rp.oflag, ifc->rp.maxraint,
 		ifc->rp.minraint, ifc->rp.linkmtu, ifc->rp.reachtime,
 		ifc->rp.rxmitra, ifc->rp.ttl, ifc->rp.routerlt,
@@ -358,9 +358,9 @@ ipifcsetmtu(Ipifc *ifc, char **argv, int argc)
 	if(ifc->m == nil)
 		return Ebadarg;
 	mtu = strtoul(argv[1], 0, 0);
-	if(mtu < ifc->m->minmtu || mtu > ifc->m->maxmtu)
+	if(mtu < ifc->m->mintu || mtu > ifc->m->maxtu)
 		return Ebadarg;
-	ifc->maxmtu = mtu;
+	ifc->maxtu = mtu;
 	return nil;
 }
 
@@ -393,8 +393,8 @@ ipifcadd(Ipifc *ifc, char **argv, int argc, int tentative, Iplifc *lifcp)
 		/* fall through */
 	case 5:
 		mtu = strtoul(argv[4], 0, 0);
-		if(mtu >= ifc->m->minmtu && mtu <= ifc->m->maxmtu)
-			ifc->maxmtu = mtu;
+		if(mtu >= ifc->m->mintu && mtu <= ifc->m->maxtu)
+			ifc->maxtu = mtu;
 		/* fall through */
 	case 4:
 		parseip(ip, argv[1]);

+ 1 - 1
sys/src/9/ip/ipv6.c

@@ -222,7 +222,7 @@ ipoput6(Fs *f, Block *bp, int gating, int ttl, int tos)
 	}
 
 	/* If we dont need to fragment just send it */
-	medialen = ifc->maxmtu - ifc->m->hsize;
+	medialen = ifc->maxtu - ifc->m->hsize;
 	if(len <= medialen) {
 		hnputs(eh->ploadlen, len-IPV6HDR_LEN);
 		ifc->m->bwrite(ifc, bp, V6, gate);

+ 2 - 2
sys/src/9/ip/loopbackmedium.c

@@ -103,8 +103,8 @@ loopbackread(void *a)
 Medium loopbackmedium =
 {
 .hsize=		0,
-.minmtu=	0,
-.maxmtu=	Maxtu,
+.mintu=		0,
+.maxtu=		Maxtu,
 .maclen=	0,
 .name=		"loopback",
 .bind=		loopbackbind,

+ 5 - 5
sys/src/9/ip/netdevmedium.c

@@ -24,8 +24,8 @@ Medium netdevmedium =
 {
 .name=		"netdev",
 .hsize=		0,
-.minmtu=	0,
-.maxmtu=	64000,
+.mintu=	0,
+.maxtu=	64000,
 .maclen=	0,
 .bind=		netdevbind,
 .unbind=	netdevunbind,
@@ -88,8 +88,8 @@ netdevbwrite(Ipifc *ifc, Block *bp, int, uchar*)
 
 	if(bp->next)
 		bp = concatblock(bp);
-	if(BLEN(bp) < ifc->minmtu)
-		bp = adjustblock(bp, ifc->minmtu);
+	if(BLEN(bp) < ifc->mintu)
+		bp = adjustblock(bp, ifc->mintu);
 
 	devtab[er->mchan->type]->bwrite(er->mchan, bp, 0);
 	ifc->out++;
@@ -114,7 +114,7 @@ netdevread(void *a)
 		pexit("hangup", 1);
 	}
 	for(;;){
-		bp = devtab[er->mchan->type]->bread(er->mchan, ifc->maxmtu, 0);
+		bp = devtab[er->mchan->type]->bread(er->mchan, ifc->maxtu, 0);
 		if(bp == nil){
 			/*
 			 * get here if mchan is a pipe and other side hangs up

+ 2 - 2
sys/src/9/ip/pktmedium.c

@@ -17,8 +17,8 @@ Medium pktmedium =
 {
 .name=		"pkt",
 .hsize=		14,
-.minmtu=	40,
-.maxmtu=	4*1024,
+.mintu=	40,
+.maxtu=	4*1024,
 .maclen=	6,
 .bind=		pktbind,
 .unbind=	pktunbind,

+ 208 - 71
sys/src/9/ip/tcp.c

@@ -29,6 +29,7 @@ enum
 	TcptimerDONE	= 2,
 	MAX_TIME 	= (1<<20),	/* Forever */
 	TCP_ACK		= 50,		/* Timed ack sequence in ms */
+	MAXBACKMS	= 30000,	/* longest backoff time (ms) before hangup */
 
 	URG		= 0x20,		/* Data marked urgent */
 	ACK		= 0x10,		/* Acknowledge is valid */
@@ -39,9 +40,10 @@ enum
 
 	EOLOPT		= 0,
 	NOOPOPT		= 1,
-	MAXBACKMS	= 30000,	/* longest backoff time (ms) before hangup */
 	MSSOPT		= 2,
 	MSS_LENGTH	= 4,		/* Mean segment size */
+	WSOPT		= 3,
+	WS_LENGTH	= 3,		/* Bits to scale window size by */
 	MSL2		= 10,
 	MSPTICK		= 50,		/* Milliseconds per timer tick */
 	DEF_MSS		= 1460,		/* Default mean segment */
@@ -77,7 +79,9 @@ enum
 
 	Maxlimbo	= 1000,		/* maximum procs waiting for response to SYN ACK */
 	NLHT		= 256,		/* hash table size, must be a power of 2 */
-	LHTMASK		= NLHT-1
+	LHTMASK		= NLHT-1,
+
+	HaveWS		= 1<<8,
 };
 
 /* Must correspond to the enumeration above */
@@ -127,8 +131,7 @@ struct Tcp4hdr
 	uchar	tcpcksum[2];
 	uchar	tcpurg[2];
 	/* Options segment */
-	uchar	tcpopt[2];
-	uchar	tcpmss[2];
+	uchar	tcpopt[1];
 };
 
 typedef struct Tcp6hdr Tcp6hdr;
@@ -149,8 +152,7 @@ struct Tcp6hdr
 	uchar	tcpcksum[2];
 	uchar	tcpurg[2];
 	/* Options segment */
-	uchar	tcpopt[2];
-	uchar	tcpmss[2];
+	uchar	tcpopt[1];
 };
 
 /*
@@ -167,9 +169,10 @@ struct	Tcp
 	ulong	seq;
 	ulong	ack;
 	uchar	flags;
-	ushort	wnd;
+	ushort	ws;	/* window scale option (if not zero) */
+	ulong	wnd;
 	ushort	urg;
-	ushort	mss;
+	ushort	mss;	/* max segment size option (if not zero) */
 	ushort	len;	/* size of data */
 };
 
@@ -199,9 +202,10 @@ struct Tcpctl
 		ulong	una;		/* Unacked data pointer */
 		ulong	nxt;		/* Next sequence expected */
 		ulong	ptr;		/* Data pointer */
-		ushort	wnd;		/* Tcp send window */
+		ulong	wnd;		/* Tcp send window */
 		ulong	urg;		/* Urgent data pointer */
 		ulong	wl2;
+		int	scale;		/* how much to right shift window in xmitted packets */
 		/* to implement tahoe and reno TCP */
 		ulong	dupacks;	/* number of duplicate acks rcvd */
 		int	recovery;	/* loss recovery flag */
@@ -209,20 +213,22 @@ struct Tcpctl
 	} snd;
 	struct {
 		ulong	nxt;		/* Receive pointer to next uchar slot */
-		ushort	wnd;		/* Receive window incoming */
+		ulong	wnd;		/* Receive window incoming */
 		ulong	urg;		/* Urgent pointer */
-		ulong	lastacked;	/* Last ack sent */
 		int	blocked;
 		int	una;		/* unacked data segs */
+		int	scale;		/* how much to left shift window in rcved packets */
 	} rcv;
 	ulong	iss;			/* Initial sequence number */
-	ushort	cwind;			/* Congestion window */
+	int	sawwsopt;		/* true if we saw a wsopt on the incoming SYN */
+	ulong	cwind;			/* Congestion window */
+	int	scale;			/* desired snd.scale */
 	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 */
+	ulong	window;			/* Recevive window */
 	uchar	backoff;		/* Exponential backoff counter */
 	int	backedoff;		/* ms we've backed off for rexmits */
 	uchar	flags;			/* State flags */
@@ -271,6 +277,8 @@ struct Limbo
 	ulong	irs;		/* initial received sequence */
 	ulong	iss;		/* initial sent sequence */
 	ushort	mss;		/* mss from the other end */
+	ushort	rcvscale;	/* how much to scale rcvd windows */
+	ushort	sndscale;	/* how much to scale sent windows */
 	ulong	lastsend;	/* last time we sent a synack */
 	uchar	version;	/* v4 or v6 */
 	uchar	rexmits;	/* number of retransmissions */
@@ -362,9 +370,9 @@ void	procsyn(Conv*, Tcp*);
 void	tcpiput(Proto*, Ipifc*, Block*);
 void	tcpoutput(Conv*);
 int	tcptrim(Tcpctl*, Tcp*, Block**, ushort*);
-void	tcpstart(Conv*, int, ushort);
+void	tcpstart(Conv*, int);
 void	tcptimeout(void*);
-void	tcpsndsyn(Tcpctl*);
+void	tcpsndsyn(Conv*, Tcpctl*);
 void	tcprcvwin(Conv*);
 void	tcpacktimer(void*);
 void	tcpkeepalive(void*);
@@ -372,6 +380,7 @@ void	tcpsetkacounter(Tcpctl*);
 void    tcprxmit(Conv*);
 void	tcpsettimer(Tcpctl*);
 void	tcpsynackrtt(Conv*);
+void	tcpsetscale(Conv*, Tcpctl*, ushort, ushort);
 
 static void limborexmit(Proto*);
 static void limbo(Conv*, uchar*, uchar*, Tcp*, int);
@@ -427,7 +436,7 @@ tcpconnect(Conv *c, char **argv, int argc)
 	e = Fsstdconnect(c, argv, argc);
 	if(e != nil)
 		return e;
-	tcpstart(c, TCP_CONNECT, QMAX);
+	tcpstart(c, TCP_CONNECT);
 
 	return nil;
 }
@@ -440,9 +449,9 @@ tcpstate(Conv *c, char *state, int n)
 	s = (Tcpctl*)(c->ptcl);
 
 	return snprint(state, n,
-		"%s srtt %d mdev %d cwin %d swin %d rwin %d timer.start %d timer.count %d rerecv %d\n",
+		"%s srtt %d mdev %d cwin %lud swin %lud>>%d rwin %lud>>%d timer.start %d timer.count %d rerecv %d\n",
 		tcpstates[s->state], s->srtt, s->mdev,
-		s->cwind, s->snd.wnd, s->rcv.wnd,
+		s->cwind, s->snd.wnd, s->rcv.scale, s->rcv.wnd, s->snd.scale,
 		s->timer.start, s->timer.count, s->rerecv);
 }
 
@@ -463,7 +472,7 @@ tcpannounce(Conv *c, char **argv, int argc)
 	e = Fsstdannounce(c, argv, argc);
 	if(e != nil)
 		return e;
-	tcpstart(c, TCP_LISTEN, QMAX);
+	tcpstart(c, TCP_LISTEN);
 	Fsconnected(c, nil);
 
 	return nil;
@@ -554,7 +563,7 @@ tcprcvwin(Conv *s)				/* Call with tcb locked */
 	Tcpctl *tcb;
 
 	tcb = (Tcpctl*)s->ptcl;
-	w = QMAX - qlen(s->rq);
+	w = tcb->window - qlen(s->rq);
 	if(w < 0)
 		w = 0;
 	tcb->rcv.wnd = w;
@@ -740,7 +749,7 @@ localclose(Conv *s, char *reason)	 /*  called with tcb locked */
 
 /* mtu (- TCP + IP hdr len) of 1st hop */
 int
-tcpmtu(Proto *tcp, uchar *addr, int version)
+tcpmtu(Proto *tcp, uchar *addr, int version, int *scale)
 {
 	Ipifc *ifc;
 	int mtu;
@@ -751,14 +760,23 @@ tcpmtu(Proto *tcp, uchar *addr, int version)
 	case V4:
 		mtu = DEF_MSS;
 		if(ifc != nil)
-			mtu = ifc->maxmtu - ifc->m->hsize - (TCP4_PKT + TCP4_HDRSIZE);
+			mtu = ifc->maxtu - ifc->m->hsize - (TCP4_PKT + TCP4_HDRSIZE);
 		break;
 	case V6:
 		mtu = DEF_MSS6;
 		if(ifc != nil)
-			mtu = ifc->maxmtu - ifc->m->hsize - (TCP6_PKT + TCP6_HDRSIZE);
+			mtu = ifc->maxtu - ifc->m->hsize - (TCP6_PKT + TCP6_HDRSIZE);
 		break;
 	}
+	if(ifc != nil){
+		if(ifc->mbps > 100)
+			*scale = HaveWS | 3;
+		else if(ifc->mbps > 10)
+			*scale = HaveWS | 1;
+		else
+			*scale = HaveWS | 0;
+	} else
+		*scale = HaveWS | 0;
 
 	return mtu;
 }
@@ -769,6 +787,7 @@ inittcpctl(Conv *s, int mode)
 	Tcpctl *tcb;
 	Tcp4hdr* h4;
 	Tcp6hdr* h6;
+	int mss;
 
 	tcb = (Tcpctl*)s->ptcl;
 
@@ -790,6 +809,8 @@ inittcpctl(Conv *s, int mode)
 	tcb->katimer.func = tcpkeepalive;
 	tcb->katimer.arg = s;
 
+	mss = DEF_MSS;
+
 	/* create a prototype(pseudo) header */
 	if(mode != TCP_LISTEN){
 		if(ipcmp(s->laddr, IPnoaddr) == 0)
@@ -813,20 +834,28 @@ inittcpctl(Conv *s, int mode)
 			hnputs(h6->tcpdport, s->rport);
 			ipmove(h6->tcpsrc, s->laddr);
 			ipmove(h6->tcpdst, s->raddr);
+			mss = DEF_MSS6;
 			break;
 		default:
 			panic("inittcpctl: version %d", s->ipversion);
 		}
 	}
 
-	tcb->mss = tcb->cwind = tcpmtu(s->p, s->laddr, s->ipversion);
+	tcb->mss = tcb->cwind = mss;
+
+	/* default is no window scaling */
+	tcb->window = QMAX;
+	tcb->rcv.wnd = QMAX;
+	tcb->rcv.scale = 0;
+	tcb->snd.scale = 0;
+	qsetlimit(s->rq, QMAX);
 }
 
 /*
  *  called with s qlocked
  */
 void
-tcpstart(Conv *s, int mode, ushort window)
+tcpstart(Conv *s, int mode)
 {
 	Tcpctl *tcb;
 	Tcppriv *tpriv;
@@ -846,10 +875,7 @@ tcpstart(Conv *s, int mode, ushort window)
 
 	tcb = (Tcpctl*)s->ptcl;
 
-	/* Send SYN, go into SYN_SENT state */
 	inittcpctl(s, mode);
-	tcb->window = window;
-	tcb->rcv.wnd = window;
 
 	iphtadd(&tpriv->ht, s);
 	switch(mode) {
@@ -862,7 +888,7 @@ tcpstart(Conv *s, int mode, ushort window)
 	case TCP_CONNECT:
 		tpriv->stats[ActiveOpens]++;
 		tcb->flags |= ACTIVE;
-		tcpsndsyn(tcb);
+		tcpsndsyn(s, tcb);
 		tcpsetstate(s, Syn_sent);
 		tcpoutput(s);
 		break;
@@ -897,11 +923,20 @@ htontcp6(Tcp *tcph, Block *data, Tcp6hdr *ph, Tcpctl *tcb)
 	int dlen;
 	Tcp6hdr *h;
 	ushort csum;
-	ushort hdrlen;
+	ushort hdrlen, optpad = 0;
+	uchar *opt;
 
 	hdrlen = TCP6_HDRSIZE;
-	if(tcph->mss)
-		hdrlen += MSS_LENGTH;
+	if(tcph->flags & SYN){
+		if(tcph->mss)
+			hdrlen += MSS_LENGTH;
+		if(tcph->ws)
+			hdrlen += WS_LENGTH;
+		optpad = hdrlen & 3;
+		if(optpad)
+			optpad = 4 - optpad;
+		hdrlen += optpad;
+	}
 
 	if(data) {
 		dlen = blocklen(data);
@@ -930,14 +965,26 @@ htontcp6(Tcp *tcph, Block *data, Tcp6hdr *ph, Tcpctl *tcb)
 	hnputl(h->tcpseq, tcph->seq);
 	hnputl(h->tcpack, tcph->ack);
 	hnputs(h->tcpflag, (hdrlen<<10) | tcph->flags);
-	hnputs(h->tcpwin, tcph->wnd);
+	hnputs(h->tcpwin, tcph->wnd>>(tcb != nil ? tcb->snd.scale : 0));
 	hnputs(h->tcpurg, tcph->urg);
 
-	if(tcph->mss != 0){
-		h->tcpopt[0] = MSSOPT;
-		h->tcpopt[1] = MSS_LENGTH;
-		hnputs(h->tcpmss, tcph->mss);
+	if(tcph->flags & SYN){
+		opt = h->tcpopt;
+		if(tcph->mss != 0){
+			*opt++ = MSSOPT;
+			*opt++ = MSS_LENGTH;
+			hnputs(opt, tcph->mss);
+			opt += 2;
+		}
+		if(tcph->ws != 0){
+			*opt++ = WSOPT;
+			*opt++ = WS_LENGTH;
+			*opt++ = tcph->ws;
+		}
+		while(optpad-- > 0)
+			*opt++ = NOOPOPT;
 	}
+
 	if(tcb != nil && tcb->nochecksum){
 		h->tcpcksum[0] = h->tcpcksum[1] = 0;
 	} else {
@@ -960,11 +1007,20 @@ htontcp4(Tcp *tcph, Block *data, Tcp4hdr *ph, Tcpctl *tcb)
 	int dlen;
 	Tcp4hdr *h;
 	ushort csum;
-	ushort hdrlen;
+	ushort hdrlen, optpad = 0;
+	uchar *opt;
 
 	hdrlen = TCP4_HDRSIZE;
-	if(tcph->mss)
-		hdrlen += MSS_LENGTH;
+	if(tcph->flags & SYN){
+		if(tcph->mss)
+			hdrlen += MSS_LENGTH;
+		if(tcph->ws)
+			hdrlen += WS_LENGTH;
+		optpad = hdrlen & 3;
+		if(optpad)
+			optpad = 4 - optpad;
+		hdrlen += optpad;
+	}
 
 	if(data) {
 		dlen = blocklen(data);
@@ -989,14 +1045,26 @@ htontcp4(Tcp *tcph, Block *data, Tcp4hdr *ph, Tcpctl *tcb)
 	hnputl(h->tcpseq, tcph->seq);
 	hnputl(h->tcpack, tcph->ack);
 	hnputs(h->tcpflag, (hdrlen<<10) | tcph->flags);
-	hnputs(h->tcpwin, tcph->wnd);
+	hnputs(h->tcpwin, tcph->wnd>>(tcb != nil ? tcb->snd.scale : 0));
 	hnputs(h->tcpurg, tcph->urg);
 
-	if(tcph->mss != 0){
-		h->tcpopt[0] = MSSOPT;
-		h->tcpopt[1] = MSS_LENGTH;
-		hnputs(h->tcpmss, tcph->mss);
+	if(tcph->flags & SYN){
+		opt = h->tcpopt;
+		if(tcph->mss != 0){
+			*opt++ = MSSOPT;
+			*opt++ = MSS_LENGTH;
+			hnputs(opt, tcph->mss);
+			opt += 2;
+		}
+		if(tcph->ws != 0){
+			*opt++ = WSOPT;
+			*opt++ = WS_LENGTH;
+			*opt++ = tcph->ws;
+		}
+		while(optpad-- > 0)
+			*opt++ = NOOPOPT;
 	}
+
 	if(tcb != nil && tcb->nochecksum){
 		h->tcpcksum[0] = h->tcpcksum[1] = 0;
 	} else {
@@ -1025,7 +1093,7 @@ ntohtcp6(Tcp *tcph, Block **bpp)
 	tcph->dest = nhgets(h->tcpdport);
 	tcph->seq = nhgetl(h->tcpseq);
 	tcph->ack = nhgetl(h->tcpack);
-	hdrlen = (h->tcpflag[0] & 0xf0)>>2;
+	hdrlen = (h->tcpflag[0]>>2) & ~3;
 	if(hdrlen < TCP6_HDRSIZE) {
 		freeblist(*bpp);
 		return -1;
@@ -1035,6 +1103,7 @@ ntohtcp6(Tcp *tcph, Block **bpp)
 	tcph->wnd = nhgets(h->tcpwin);
 	tcph->urg = nhgets(h->tcpurg);
 	tcph->mss = 0;
+	tcph->ws = 0;
 	tcph->len = nhgets(h->ploadlen) - hdrlen;
 
 	*bpp = pullupblock(*bpp, hdrlen+TCP6_PKT);
@@ -1057,6 +1126,10 @@ ntohtcp6(Tcp *tcph, Block **bpp)
 			if(optlen == MSS_LENGTH)
 				tcph->mss = nhgets(optr+2);
 			break;
+		case WSOPT:
+			if(optlen == WS_LENGTH && *(optr+2) <= 14)
+				tcph->ws = HaveWS | *(optr+2);
+			break;
 		}
 		n -= optlen;
 		optr += optlen;
@@ -1083,7 +1156,7 @@ ntohtcp4(Tcp *tcph, Block **bpp)
 	tcph->seq = nhgetl(h->tcpseq);
 	tcph->ack = nhgetl(h->tcpack);
 
-	hdrlen = (h->tcpflag[0] & 0xf0)>>2;
+	hdrlen = (h->tcpflag[0]>>2) & ~3;
 	if(hdrlen < TCP4_HDRSIZE) {
 		freeblist(*bpp);
 		return -1;
@@ -1093,6 +1166,7 @@ ntohtcp4(Tcp *tcph, Block **bpp)
 	tcph->wnd = nhgets(h->tcpwin);
 	tcph->urg = nhgets(h->tcpurg);
 	tcph->mss = 0;
+	tcph->ws = 0;
 	tcph->len = nhgets(h->length) - (hdrlen + TCP4_PKT);
 
 	*bpp = pullupblock(*bpp, hdrlen+TCP4_PKT);
@@ -1115,6 +1189,10 @@ ntohtcp4(Tcp *tcph, Block **bpp)
 			if(optlen == MSS_LENGTH)
 				tcph->mss = nhgets(optr+2);
 			break;
+		case WSOPT:
+			if(optlen == WS_LENGTH && *(optr+2) <= 14)
+				tcph->ws = HaveWS | *(optr+2);
+			break;
 		}
 		n -= optlen;
 		optr += optlen;
@@ -1127,7 +1205,7 @@ ntohtcp4(Tcp *tcph, Block **bpp)
  *  number and put a SYN on the send queue
  */
 void
-tcpsndsyn(Tcpctl *tcb)
+tcpsndsyn(Conv *s, Tcpctl *tcb)
 {
 	tcb->iss = (nrand(1<<16)<<16)|nrand(1<<16);
 	tcb->rttseq = tcb->iss;
@@ -1138,6 +1216,9 @@ tcpsndsyn(Tcpctl *tcb)
 	tcb->flgcnt++;
 	tcb->flags |= FORCE;
 	tcb->sndsyntime = NOW;
+
+	/* set desired mss and scale */
+	tcb->mss = tcpmtu(s->p, s->laddr, s->ipversion, &tcb->scale);
 }
 
 void
@@ -1204,6 +1285,7 @@ sndrst(Proto *tcp, uchar *source, uchar *dest, ushort length, Tcp *seg, uchar ve
 	seg->wnd = 0;
 	seg->urg = 0;
 	seg->mss = 0;
+	seg->ws = 0;
 	switch(version) {
 	case V4:
 		hbp = htontcp4(seg, nil, &ph4, nil);
@@ -1239,11 +1321,12 @@ tcphangup(Conv *s)
 	if(s->raddr != 0) {
 		seg.flags = RST | ACK;
 		seg.ack = tcb->rcv.nxt;
-		tcb->rcv.lastacked = tcb->rcv.nxt;
+		tcb->rcv.una = 0;
 		seg.seq = tcb->snd.ptr;
 		seg.wnd = 0;
 		seg.urg = 0;
 		seg.mss = 0;
+		seg.ws = 0;
 		switch(s->ipversion) {
 		case V4:
 			tcb->protohdr.tcp4hdr.vihl = IP_VER4;
@@ -1274,6 +1357,7 @@ sndsynack(Proto *tcp, Limbo *lp)
 	Tcp4hdr ph4;
 	Tcp6hdr ph6;
 	Tcp seg;
+	int scale;
 
 	/* make pseudo header */
 	switch(lp->version) {
@@ -1305,9 +1389,18 @@ sndsynack(Proto *tcp, Limbo *lp)
 	seg.ack = lp->irs+1;
 	seg.flags = SYN|ACK;
 	seg.urg = 0;
-	seg.mss = tcpmtu(tcp, lp->laddr, lp->version);
+	seg.mss = tcpmtu(tcp, lp->laddr, lp->version, &scale);
 	seg.wnd = QMAX;
 
+	/* if the other side set scale, we should too */
+	if(lp->rcvscale){
+		seg.ws = scale;
+		lp->sndscale = scale;
+	} else {
+		seg.ws = 0;
+		lp->sndscale = 0;
+	}
+
 	switch(lp->version) {
 	case V4:
 		hbp = htontcp4(&seg, nil, &ph4, nil);
@@ -1377,6 +1470,7 @@ limbo(Conv *s, uchar *source, uchar *dest, Tcp *seg, int version)
 		lp->lport = seg->dest;
 		lp->rport = seg->source;
 		lp->mss = seg->mss;
+		lp->rcvscale = seg->ws;
 		lp->irs = seg->seq;
 		lp->iss = (nrand(1<<16)<<16)|nrand(1<<16);
 	}
@@ -1474,6 +1568,7 @@ limborst(Conv *s, Tcp *segp, uchar *src, uchar *dst, uchar version)
 }
 
 /*
+ *  come here when we finally get an ACK to our SYN-ACK.
  *  lookup call in limbo.  if found, create a new conversation
  *
  *  called with proto locked
@@ -1558,6 +1653,9 @@ tcpincoming(Conv *s, Tcp *segp, uchar *src, uchar *dst, uchar version)
 	if(lp->mss != 0 && lp->mss < tcb->mss)
 		tcb->mss = lp->mss;
 
+	/* window scaling */
+	tcpsetscale(new, tcb, lp->rcvscale, lp->sndscale);
+
 	/* the congestion window always starts out as a single segment */
 	tcb->snd.wnd = segp->wnd;
 	tcb->cwind = tcb->mss;
@@ -1664,7 +1762,8 @@ update(Conv *s, Tcp *seg)
 {
 	int rtt, delta;
 	Tcpctl *tcb;
-	ushort acked, expand;
+	ulong acked;
+	ulong expand;
 	Tcppriv *tpriv;
 
 	tpriv = s->p->priv;
@@ -1752,7 +1851,7 @@ update(Conv *s, Tcp *seg)
 			expand = ((int)tcb->mss * tcb->mss) / tcb->cwind;
 
 		if(tcb->cwind + expand < tcb->cwind)
-			expand = 65535 - tcb->cwind;
+			expand = tcb->snd.wnd - tcb->cwind;
 		if(tcb->cwind + expand > tcb->snd.wnd)
 			expand = tcb->snd.wnd - tcb->cwind;
 		if(expand != 0)
@@ -1962,6 +2061,9 @@ reset:
 	qlock(s);
 	qunlock(tcp);
 
+	/* fix up window */
+	seg.wnd <<= tcb->rcv.scale;
+
 	if(tcb->kacounter > 0)
 		tcb->kacounter = MAXBACKMS / (tcb->katimer.start*MSPTICK);
 	if(tcb->kacounter < 3)
@@ -1991,10 +2093,11 @@ reset:
 				update(s, &seg);
 				tcpsynackrtt(s);
 				tcpsetstate(s, Established);
+				tcpsetscale(s, tcb, seg.ws, tcb->scale);
 			}
 			else {
 				tcb->time = NOW;
-				tcpsetstate(s, Syn_received);
+				tcpsetstate(s, Syn_received);	/* DLP - shouldn't this be a reset? */
 			}
 
 			if(length != 0 || (seg.flags & FIN))
@@ -2172,9 +2275,19 @@ reset:
 					qpassnolim(s->rq, bp);
 					bp = nil;
 
- 					/* force an ack every 2 data messages */
- 					if(++(tcb->rcv.una) >= 2)
- 						tcb->flags |= FORCE;
+					/* 
+					 *  Force an ack every 2 data messages.  This is
+					 *  a hack for rob to make his home system run
+					 *  faster.
+					 *
+					 *  this also keeps the standard TCP congestion
+					 *  control working since it needs an ack every
+					 *  2 max segs worth.  This is not quite that,
+					 *  but under a real stream is equivalent since
+					 *  every packet has a max seg in it.
+					 */
+					if(++(tcb->rcv.una) >= 2)
+						tcb->flags |= FORCE;
 				}
 				tcb->rcv.nxt += length;
 
@@ -2183,13 +2296,6 @@ reset:
 				 */
 				tcprcvwin(s);
 
-				/*
-				 *  force an ack if we've got 2 segs since we
-				 *  last acked.
-				 */
-				if(tcb->rcv.nxt - tcb->rcv.lastacked >= 2*tcb->mss)
-					tcb->flags |= FORCE;
-
 				/*
 				 *  turn on the acktimer if there's something
 				 *  to ack
@@ -2344,7 +2450,7 @@ tcpoutput(Conv *s)
 		}
 		ssize = sndcnt-sent;
 		if(ssize && usable < 2)
-			netlog(s->p->f, Logtcp, "throttled snd.wnd 0x%ux cwind 0x%ux\n",
+			netlog(s->p->f, Logtcp, "throttled snd.wnd %lud cwind %lud\n",
 				tcb->snd.wnd, tcb->cwind);
 		if(usable < ssize)
 			ssize = usable;
@@ -2357,25 +2463,25 @@ tcpoutput(Conv *s)
 		if((tcb->flags&FORCE) == 0)
 			break;
 
-		tcphalt(tpriv, &tcb->acktimer);
-
 		tcb->flags &= ~FORCE;
 		tcprcvwin(s);
 
 		/* By default we will generate an ack */
+		tcphalt(tpriv, &tcb->acktimer);
 		tcb->rcv.una = 0;
 		seg.source = s->lport;
 		seg.dest = s->rport;
 		seg.flags = ACK;
 		seg.mss = 0;
-
+		seg.ws = 0;
 		switch(tcb->state){
 		case Syn_sent:
 			seg.flags = 0;
 			if(tcb->snd.ptr == tcb->iss){
 				seg.flags |= SYN;
 				dsize--;
-				seg.mss = tcpmtu(s->p, s->laddr, s->ipversion);
+				seg.mss = tcb->mss;
+				seg.ws = tcb->scale;
 			}
 			break;
 		case Syn_received:
@@ -2388,13 +2494,13 @@ tcpoutput(Conv *s)
 				seg.flags |= SYN;
 				dsize = 0;
 				ssize = 1;
-				seg.mss = tcpmtu(s->p, s->laddr, s->ipversion);
+				seg.mss = tcb->mss;
+				seg.ws = tcb->scale;
 			}
 			break;
 		}
 		seg.seq = tcb->snd.ptr;
 		seg.ack = tcb->rcv.nxt;
-		tcb->rcv.lastacked = tcb->rcv.nxt;
 		seg.wnd = tcb->rcv.wnd;
 
 		/* Pull out data to send */
@@ -2510,12 +2616,13 @@ tcpsendka(Conv *s)
 	seg.dest = s->rport;
 	seg.flags = ACK|PSH;
 	seg.mss = 0;
+	seg.ws = 0;
 	if(tcpporthogdefense)
 		seg.seq = tcb->snd.una-(1<<30)-nrand(1<<20);
 	else
 		seg.seq = tcb->snd.una-1;
 	seg.ack = tcb->rcv.nxt;
-	tcb->rcv.lastacked = tcb->rcv.nxt;
+	tcb->rcv.una = 0;
 	seg.wnd = tcb->rcv.wnd;
 	if(tcb->state == Finwait2){
 		seg.flags |= FIN;
@@ -2906,6 +3013,18 @@ tcpadvise(Proto *tcp, Block *bp, char *msg)
 	freeblist(bp);
 }
 
+static char*
+tcpporthogdefensectl(char *val)
+{
+	if(strcmp(val, "on") == 0)
+		tcpporthogdefense = 1;
+	else if(strcmp(val, "off") == 0)
+		tcpporthogdefense = 0;
+	else
+		return "unknown value for tcpporthogdefense";
+	return nil;
+}
+
 /* called with c qlocked */
 char*
 tcpctl(Conv* c, char** f, int n)
@@ -2916,6 +3035,8 @@ tcpctl(Conv* c, char** f, int n)
 		return tcpstartka(c, f, n);
 	if(n >= 1 && strcmp(f[0], "checksum") == 0)
 		return tcpsetchecksum(c, f, n);
+	if(n >= 1 && strcmp(f[0], "tcpporthogdefense") == 0)
+		return tcpporthogdefensectl(f[1]);
 	return "unknown control request";
 }
 
@@ -3023,3 +3144,19 @@ tcpinit(Fs *fs)
 
 	Fsproto(fs, tcp);
 }
+
+void
+tcpsetscale(Conv *s, Tcpctl *tcb, ushort rcvscale, ushort sndscale)
+{
+	if(rcvscale){
+		tcb->rcv.scale = rcvscale & 0xff;
+		tcb->snd.scale = sndscale & 0xff;
+		tcb->window = QMAX<<tcb->snd.scale;
+		qsetlimit(s->rq, tcb->window);
+	} else {
+		tcb->rcv.scale = 0;
+		tcb->snd.scale = 0;
+		tcb->window = QMAX;
+		qsetlimit(s->rq, tcb->window);
+	}
+}

+ 5 - 5
sys/src/9/ip/tripmedium.c

@@ -21,8 +21,8 @@ static void	tripares(Fs*, int, uchar*, uchar*, int, int);
 Medium tripmedium =
 {
 .name=		"trip",
-.minmtu=	20,
-.maxmtu=	64*1024,
+.mintu=	20,
+.maxtu=	64*1024,
 .maclen=	LCIMACSIZE,
 .bind=		tripbind,
 .unbind=	tripunbind,
@@ -140,7 +140,7 @@ tripread(void *a)
 	er->readp = up;	/* hide identity under a rock for unbind */
 
 	for(;;) {
-		bp = devtab[er->mchan->type]->bread(er->mchan, ifc->maxmtu, 0);
+		bp = devtab[er->mchan->type]->bread(er->mchan, ifc->maxtu, 0);
 		ifc->in++;
 		ipiput4(er->fs, ifc, bp);
 	}
@@ -255,8 +255,8 @@ sendifcinfo(Ipifc *dest)
 			continue;
 
 		mtc.type = T_CTLIFADMIN;
-		mtc.maxtu = ifc->maxmtu;
-		mtc.mintu = ifc->minmtu;
+		mtc.maxtu = ifc->maxtu;
+		mtc.mintu = ifc->mintu;
 
 		mtc.port = 0;
 		if(ifc->m == &tripmedium) {

+ 0 - 1
sys/src/9/pc/etherif.h

@@ -9,7 +9,6 @@ struct Ether {
 
 	int	ctlrno;
 	int	tbdf;			/* type+busno+devno+funcno */
-	int	mbps;			/* Mbps */
 	int	minmtu;
 	int 	maxmtu;
 	uchar	ea[Eaddrlen];

+ 773 - 0
sys/src/9/pc/sd53c8xx.i

@@ -0,0 +1,773 @@
+unsigned long na_script[] = {
+			/*	extern	scsi_id_buf */
+			/*	extern	msg_out_buf */
+			/*	extern	cmd_buf */
+			/*	extern	data_buf */
+			/*	extern	status_buf */
+			/*	extern	msgin_buf */
+			/*	extern	dsa_0 */
+			/*	extern  dsa_1 */
+			/*	extern	dsa_head */
+			/*	extern	ssid_mask */
+			/*	SIR_MSG_IO_COMPLETE = 0 */
+			/*	error_not_cmd_complete = 1 */
+			/*	error_disconnected = 2 */
+			/*	error_reselected = 3 */
+			/*	error_unexpected_phase = 4 */
+			/*	error_weird_message = 5 */
+			/*	SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT = 6 */
+			/*	error_not_identify_after_reselect = 7 */
+			/*	error_too_much_data = 8 */
+			/*	error_too_little_data = 9 */
+			/*	SIR_MSG_REJECT = 10 */
+			/*	SIR_MSG_SDTR = 11 */
+			/*	SIR_EV_RESPONSE_OK = 12 */
+			/*	error_sigp_set = 13 */
+			/*	SIR_EV_PHASE_SWITCH_AFTER_ID = 14 */
+			/*	SIR_MSG_WDTR = 15 */
+			/*	SIR_MSG_IGNORE_WIDE_RESIDUE = 16 */
+			/*	SIR_NOTIFY_DISC = 100 */
+			/*	SIR_NOTIFY_RESELECT = 101 */
+			/*	SIR_NOTIFY_MSG_IN = 102 */
+			/*	SIR_NOTIFY_STATUS = 103 */
+			/*	SIR_NOTIFY_DUMP = 104 */
+			/*	SIR_NOTIFY_DUMP2 = 105 */
+			/*	SIR_NOTIFY_SIGP = 106 */
+			/*	SIR_NOTIFY_ISSUE = 107 */
+			/*	SIR_NOTIFY_WAIT_RESELECT = 108 */
+			/*	SIR_NOTIFY_ISSUE_CHECK = 109 */
+			/*	SIR_NOTIFY_DUMP_NEXT_CODE = 110 */
+			/*	SIR_NOTIFY_COMMAND = 111 */
+			/*	SIR_NOTIFY_DATA_IN = 112 */
+			/*	SIR_NOTIFY_DATA_OUT = 113 */
+			/*	SIR_NOTIFY_BLOCK_DATA_IN = 114 */
+			/*	SIR_NOTIFY_WSR = 115 */
+			/*	SIR_NOTIFY_LOAD_SYNC = 116 */
+			/*	SIR_NOTIFY_RESELECTED_ON_SELECT = 117 */
+			/*	STATE_FREE = 0 */
+			/*	STATE_ALLOCATED = 1 */
+			/*	STATE_ISSUE = 2 */
+			/*	STATE_DISCONNECTED = 3 */
+			/*	STATE_DONE = 4 */
+			/*	RESULT_OK = 0 */
+			/*	MSG_IDENTIFY = 0x80 */
+			/*	MSG_DISCONNECT = 0x04 */
+			/*	MSG_SAVE_DATA_POINTER = 0x02 */
+			/*	MSG_RESTORE_POINTERS = 0x03 */
+			/*	MSG_IGNORE_WIDE_RESIDUE = 0x23 */
+			/*	X_MSG = 0x01 */
+			/*	X_MSG_SDTR = 0x01 */
+			/*	X_MSG_WDTR = 0x03 */
+			/*	MSG_REJECT = 0x07 */
+			/*	BSIZE = 512 */
+/* 0000 */ 0x80880000L, /*		jump	wait_for_reselection */
+/* 0004 */ 0x00000514L,
+/* 0008 */ 0x88880000L, /*		call	load_sync */
+/* 000c */ 0x0000074cL,
+/* 0010 */ 0x60000200L, /*		clear	target */
+/* 0014 */ 0x00000000L,
+/* 0018 */ 0x47000000L, /*		select	atn from scsi_id_buf, reselected_on_select */
+/* 001c */ 0x000004ecL,
+/* 0020 */ 0x878b0000L, /*		jump	start1, when msg_in */
+/* 0024 */ 0x00000000L,
+/* 0028 */ 0x1e000000L, /*		move	from msg_out_buf, when msg_out */
+/* 002c */ 0x00000001L,
+/* 0030 */ 0x868b0000L, /*		jump	start1, when msg_out */
+/* 0034 */ 0x00fffff0L,
+/* 0038 */ 0x82830000L, /*		jump	to_decisions, when not cmd */
+/* 003c */ 0x000005f0L,
+/* 0040 */ 0x60000008L, /*		clear	atn */
+/* 0044 */ 0x00000000L,
+/* 0048 */ 0x1a000000L, /*		move	from cmd_buf, when cmd */
+/* 004c */ 0x00000002L,
+/* 0050 */ 0x81830000L, /*		jump	to_decisions, when not data_in */
+/* 0054 */ 0x000005d8L,
+/* 0058 */ 0xc0000004L, /*		move	memory 4, state, scratcha */
+/* 005c */ 0x00000678L,
+/* 0060 */ 0x00000034L,
+/* 0064 */ 0xc0000004L, /*		move	memory 4, dmaaddr, scratchb */
+/* 0068 */ 0x0000067cL,
+/* 006c */ 0x0000005cL,
+/* 0070 */ 0x72360000L, /*		move	scratcha2 to sfbr */
+/* 0074 */ 0x00000000L,
+/* 0078 */ 0x808c0000L, /*		jump	data_in_normal, if 0 */
+/* 007c */ 0x00000078L,
+/* 0080 */ 0x29000200L, /*		move	BSIZE, ptr dmaaddr, when data_in */
+/* 0084 */ 0x0000067cL,
+/* 0088 */ 0x7e5d0200L, /*		move	scratchb1 + BSIZE / 256 to scratchb1 */
+/* 008c */ 0x00000000L,
+/* 0090 */ 0x7f5e0000L, /*		move	scratchb2 + 0 to scratchb2 with carry */
+/* 0094 */ 0x00000000L,
+/* 0098 */ 0x7f5f0000L, /*		move	scratchb3 + 0 to scratchb3 with carry */
+/* 009c */ 0x00000000L,
+/* 00a0 */ 0x7e36ff00L, /*		move	scratcha2 + 255 to scratcha2 */
+/* 00a4 */ 0x00000000L,
+/* 00a8 */ 0xc0000004L, /*		move	memory 4, scratchb, dmaaddr */
+/* 00ac */ 0x0000005cL,
+/* 00b0 */ 0x0000067cL,
+/* 00b4 */ 0x818b0000L, /*		jump	data_in_block_loop, when data_in */
+/* 00b8 */ 0x00ffffb4L,
+/* 00bc */ 0xc0000004L, /*		move	memory 4, scratcha, state */
+/* 00c0 */ 0x00000034L,
+/* 00c4 */ 0x00000678L,
+/* 00c8 */ 0x88880000L, /*		call	save_state */
+/* 00cc */ 0x000005e0L,
+/* 00d0 */ 0x80880000L, /*		jump	to_decisions */
+/* 00d4 */ 0x00000558L,
+/* 00d8 */ 0xc0000004L, /*		move	memory 4, scratchb, dmaaddr */
+/* 00dc */ 0x0000005cL,
+/* 00e0 */ 0x0000067cL,
+/* 00e4 */ 0xc0000004L, /*		move	memory 4, scratcha, state */
+/* 00e8 */ 0x00000034L,
+/* 00ec */ 0x00000678L,
+/* 00f0 */ 0x80880000L, /*		jump	to_decisions */
+/* 00f4 */ 0x00000538L,
+/* 00f8 */ 0x72370000L, /*		move	scratcha3 to sfbr */
+/* 00fc */ 0x00000000L,
+/* 0100 */ 0x98040000L, /*		int	error_too_much_data, if not 0 */
+/* 0104 */ 0x00000008L,
+/* 0108 */ 0x19000000L, /*		move	from data_buf, when data_in */
+/* 010c */ 0x00000003L,
+/* 0110 */ 0x78370200L, /*		move	2 to scratcha3 */
+/* 0114 */ 0x00000000L,
+/* 0118 */ 0xc0000004L, /*		move	memory 4, scratcha, state */
+/* 011c */ 0x00000034L,
+/* 0120 */ 0x00000678L,
+/* 0124 */ 0x88880000L, /*		call	save_state */
+/* 0128 */ 0x00000584L,
+/* 012c */ 0x80880000L, /*		jump	post_data_to_decisions */
+/* 0130 */ 0x0000052cL,
+/* 0134 */ 0xc0000004L, /*		move	memory 4, state, scratcha */
+/* 0138 */ 0x00000678L,
+/* 013c */ 0x00000034L,
+/* 0140 */ 0xc0000004L, /*		move	memory 4, dmaaddr, scratchb */
+/* 0144 */ 0x0000067cL,
+/* 0148 */ 0x0000005cL,
+/* 014c */ 0x72360000L, /*		move	scratcha2 to sfbr */
+/* 0150 */ 0x00000000L,
+/* 0154 */ 0x808c0000L, /*		jump	data_out_normal, if 0 */
+/* 0158 */ 0x0000005cL,
+/* 015c */ 0xc0000004L, /*		move	memory 4, dmaaddr, scratchb */
+/* 0160 */ 0x0000067cL,
+/* 0164 */ 0x0000005cL,
+/* 0168 */ 0x28000200L, /*		move	BSIZE, ptr dmaaddr, when data_out */
+/* 016c */ 0x0000067cL,
+/* 0170 */ 0x7e5d0200L, /*		move	scratchb1 + BSIZE / 256 to scratchb1 */
+/* 0174 */ 0x00000000L,
+/* 0178 */ 0x7f5e0000L, /*		move	scratchb2 + 0 to scratchb2 with carry */
+/* 017c */ 0x00000000L,
+/* 0180 */ 0x7f5f0000L, /*		move	scratchb3 + 0 to scratchb3 with carry */
+/* 0184 */ 0x00000000L,
+/* 0188 */ 0x7e36ff00L, /*		move	scratcha2 + 255 to scratcha2 */
+/* 018c */ 0x00000000L,
+/* 0190 */ 0xc0000004L, /*		move	memory 4, scratchb, dmaaddr */
+/* 0194 */ 0x0000005cL,
+/* 0198 */ 0x0000067cL,
+/* 019c */ 0x808b0000L, /*		jump	data_out_block_loop, when data_out */
+/* 01a0 */ 0x00ffffa8L,
+/* 01a4 */ 0xc0000004L, /*		move	memory 4, scratcha, state */
+/* 01a8 */ 0x00000034L,
+/* 01ac */ 0x00000678L,
+/* 01b0 */ 0x80880000L, /*		jump	to_decisions */
+/* 01b4 */ 0x00000478L,
+/* 01b8 */ 0x72370000L, /*		move	scratcha3 to sfbr */
+/* 01bc */ 0x00000000L,
+/* 01c0 */ 0x98040000L, /*		int	error_too_little_data, if not 0 */
+/* 01c4 */ 0x00000009L,
+/* 01c8 */ 0x18000000L, /*		move	from data_buf, when data_out */
+/* 01cc */ 0x00000003L,
+/* 01d0 */ 0x78370200L, /*		move	2 to scratcha3 */
+/* 01d4 */ 0x00000000L,
+/* 01d8 */ 0xc0000004L, /*		move	memory 4, scratcha, state */
+/* 01dc */ 0x00000034L,
+/* 01e0 */ 0x00000678L,
+/* 01e4 */ 0x88880000L, /*		call	save_state */
+/* 01e8 */ 0x000004c4L,
+/* 01ec */ 0x80880000L, /*		jump	post_data_to_decisions */
+/* 01f0 */ 0x0000046cL,
+/* 01f4 */ 0x1b000000L, /*		move	from status_buf, when status */
+/* 01f8 */ 0x00000004L,
+/* 01fc */ 0x9f030000L, /*		int	error_unexpected_phase, when not msg_in */
+/* 0200 */ 0x00000004L,
+/* 0204 */ 0x0f000001L, /*		move	1, scratcha, when msg_in */
+/* 0208 */ 0x00000034L,
+/* 020c */ 0x808c0007L, /*		jump	rejected, if MSG_REJECT */
+/* 0210 */ 0x00000088L,
+/* 0214 */ 0x808c0004L, /*		jump	disconnected, if MSG_DISCONNECT */
+/* 0218 */ 0x00000298L,
+/* 021c */ 0x808c0002L, /*		jump	msg_in_skip, if MSG_SAVE_DATA_POINTER */
+/* 0220 */ 0x00000090L,
+/* 0224 */ 0x808c0003L, /*		jump	msg_in_skip, if MSG_RESTORE_POINTERS */
+/* 0228 */ 0x00000088L,
+/* 022c */ 0x808c0023L, /*		jump	ignore_wide, if MSG_IGNORE_WIDE_RESIDUE */
+/* 0230 */ 0x000001f0L,
+/* 0234 */ 0x808c0001L, /*		jump	extended, if X_MSG */
+/* 0238 */ 0x00000088L,
+/* 023c */ 0x98040000L, /*		int	error_not_cmd_complete, if not 0 */
+/* 0240 */ 0x00000001L,
+/* 0244 */ 0x7c027e00L, /*		move	scntl2&0x7e to scntl2 */
+/* 0248 */ 0x00000000L,
+/* 024c */ 0x60000040L, /*		clear	ack */
+/* 0250 */ 0x00000000L,
+/* 0254 */ 0x48000000L, /*		wait	disconnect */
+/* 0258 */ 0x00000000L,
+/* 025c */ 0xc0000004L, /*		move	memory 4, state, scratcha */
+/* 0260 */ 0x00000678L,
+/* 0264 */ 0x00000034L,
+/* 0268 */ 0x78340400L, /*		move	STATE_DONE to scratcha0 */
+/* 026c */ 0x00000000L,
+/* 0270 */ 0x78350000L, /*		move	RESULT_OK to scratcha1 */
+/* 0274 */ 0x00000000L,
+/* 0278 */ 0xc0000004L, /*		move	memory 4, scratcha, state */
+/* 027c */ 0x00000034L,
+/* 0280 */ 0x00000678L,
+/* 0284 */ 0x88880000L, /*		call	save_state */
+/* 0288 */ 0x00000424L,
+/* 028c */ 0x98180000L, /*		intfly	0 */
+/* 0290 */ 0x00000000L,
+/* 0294 */ 0x80880000L, /*		jump	issue_check */
+/* 0298 */ 0x0000043cL,
+/* 029c */ 0x98080000L, /*		int	SIR_MSG_REJECT */
+/* 02a0 */ 0x0000000aL,
+/* 02a4 */ 0x60000040L, /*		clear	ack */
+/* 02a8 */ 0x00000000L,
+/* 02ac */ 0x80880000L, /*		jump	to_decisions */
+/* 02b0 */ 0x0000037cL,
+/* 02b4 */ 0x60000040L, /*		clear	ack */
+/* 02b8 */ 0x00000000L,
+/* 02bc */ 0x80880000L, /*		jump	to_decisions */
+/* 02c0 */ 0x0000036cL,
+/* 02c4 */ 0x60000040L, /*		clear	ack */
+/* 02c8 */ 0x00000000L,
+/* 02cc */ 0x9f030000L, /*		int	error_unexpected_phase, when not msg_in */
+/* 02d0 */ 0x00000004L,
+/* 02d4 */ 0x0f000001L, /*		move	1, scratcha1, when msg_in */
+/* 02d8 */ 0x00000035L,
+/* 02dc */ 0x808c0003L, /*		jump	ext_3, if 3 */
+/* 02e0 */ 0x00000030L,
+/* 02e4 */ 0x808c0002L, /*		jump	ext_2, if 2 */
+/* 02e8 */ 0x00000098L,
+/* 02ec */ 0x98040001L, /*		int	error_weird_message, if not 1 */
+/* 02f0 */ 0x00000005L,
+/* 02f4 */ 0x60000040L, /*		clear	ack */
+/* 02f8 */ 0x00000000L,
+/* 02fc */ 0x9f030000L, /*		int	error_unexpected_phase, when not msg_in */
+/* 0300 */ 0x00000004L,
+/* 0304 */ 0x0f000001L, /*		move	1, scratcha1, when msg_in */
+/* 0308 */ 0x00000035L,
+/* 030c */ 0x80880000L, /*		jump	ext_done */
+/* 0310 */ 0x000000c8L,
+/* 0314 */ 0x60000040L, /*	ext_3:	clear	ack */
+/* 0318 */ 0x00000000L,
+/* 031c */ 0x9f030000L, /*		int	error_unexpected_phase, when not msg_in */
+/* 0320 */ 0x00000004L,
+/* 0324 */ 0x0f000001L, /*		move	1, scratcha1, when msg_in */
+/* 0328 */ 0x00000035L,
+/* 032c */ 0x60000040L, /*		clear	ack */
+/* 0330 */ 0x00000000L,
+/* 0334 */ 0x9f030000L, /*		int	error_unexpected_phase, when not msg_in */
+/* 0338 */ 0x00000004L,
+/* 033c */ 0x0f000001L, /*		move	1, scratcha2, when msg_in */
+/* 0340 */ 0x00000036L,
+/* 0344 */ 0x60000040L, /*		clear	ack */
+/* 0348 */ 0x00000000L,
+/* 034c */ 0x9f030000L, /*		int	error_unexpected_phase, when not msg_in */
+/* 0350 */ 0x00000004L,
+/* 0354 */ 0x0f000001L, /*		move	1, scratcha3, when msg_in */
+/* 0358 */ 0x00000037L,
+/* 035c */ 0x72350000L, /*		move	scratcha1 to sfbr */
+/* 0360 */ 0x00000000L,
+/* 0364 */ 0x80840001L, /*		jump	ext_done, if not X_MSG_SDTR */
+/* 0368 */ 0x00000070L,
+/* 036c */ 0x98080000L, /*	sdtr:	int	SIR_MSG_SDTR */
+/* 0370 */ 0x0000000bL,
+/* 0374 */ 0x60000040L, /*		clear	ack */
+/* 0378 */ 0x00000000L,
+/* 037c */ 0x80880000L, /*		jump	to_decisions */
+/* 0380 */ 0x000002acL,
+/* 0384 */ 0x60000040L, /*	ext_2:	clear	ack */
+/* 0388 */ 0x00000000L,
+/* 038c */ 0x9f030000L, /*		int	error_unexpected_phase, when not msg_in */
+/* 0390 */ 0x00000004L,
+/* 0394 */ 0x0f000001L, /*		move	1, scratcha1, when msg_in */
+/* 0398 */ 0x00000035L,
+/* 039c */ 0x60000040L, /*		clear	ack */
+/* 03a0 */ 0x00000000L,
+/* 03a4 */ 0x9f030000L, /*		int	error_unexpected_phase, when not msg_in */
+/* 03a8 */ 0x00000004L,
+/* 03ac */ 0x0f000001L, /*		move	1, scratcha2, when msg_in */
+/* 03b0 */ 0x00000036L,
+/* 03b4 */ 0x72350000L, /*		move	scratcha1 to sfbr */
+/* 03b8 */ 0x00000000L,
+/* 03bc */ 0x80840003L, /*		jump	ext_done, if not X_MSG_WDTR */
+/* 03c0 */ 0x00000018L,
+/* 03c4 */ 0x98080000L, /*	wdtr:	int	SIR_MSG_WDTR */
+/* 03c8 */ 0x0000000fL,
+/* 03cc */ 0x60000040L, /*		clear	ack */
+/* 03d0 */ 0x00000000L,
+/* 03d4 */ 0x80880000L, /*		jump	to_decisions */
+/* 03d8 */ 0x00000254L,
+/* 03dc */ 0x58000008L, /*		set	atn */
+/* 03e0 */ 0x00000000L,
+/* 03e4 */ 0x60000040L, /*		clear	ack */
+/* 03e8 */ 0x00000000L,
+/* 03ec */ 0x78340700L, /*		move	MSG_REJECT to scratcha */
+/* 03f0 */ 0x00000000L,
+/* 03f4 */ 0x9e030000L, /*		int	error_unexpected_phase, when not msg_out */
+/* 03f8 */ 0x00000004L,
+/* 03fc */ 0x60000008L, /*		clear	atn */
+/* 0400 */ 0x00000000L,
+/* 0404 */ 0x0e000001L, /*		move	1, scratcha, when msg_out */
+/* 0408 */ 0x00000034L,
+/* 040c */ 0x60000040L, /*		clear	ack */
+/* 0410 */ 0x00000000L,
+/* 0414 */ 0x868b0000L, /*		jump	reject, when msg_out */
+/* 0418 */ 0x00ffffc0L,
+/* 041c */ 0x80880000L, /*		jump	to_decisions */
+/* 0420 */ 0x0000020cL,
+/* 0424 */ 0x60000040L, /*		clear	ack */
+/* 0428 */ 0x00000000L,
+/* 042c */ 0x9f030000L, /*		int	error_unexpected_phase, when not msg_in */
+/* 0430 */ 0x00000004L,
+/* 0434 */ 0x0f000001L, /*		move	1, scratcha1, when msg_in */
+/* 0438 */ 0x00000035L,
+/* 043c */ 0x98080000L, /*		int	SIR_MSG_IGNORE_WIDE_RESIDUE */
+/* 0440 */ 0x00000010L,
+/* 0444 */ 0x60000040L, /*		clear	ack */
+/* 0448 */ 0x00000000L,
+/* 044c */ 0x80880000L, /*		jump	to_decisions */
+/* 0450 */ 0x000001dcL,
+/* 0454 */ 0x58000008L, /*		set	atn */
+/* 0458 */ 0x00000000L,
+/* 045c */ 0x60000040L, /*		clear	ack */
+/* 0460 */ 0x00000000L,
+/* 0464 */ 0x9e030000L, /*		int	error_unexpected_phase, when not msg_out */
+/* 0468 */ 0x00000004L,
+/* 046c */ 0x1e000000L, /*		move	from msg_out_buf, when msg_out */
+/* 0470 */ 0x00000001L,
+/* 0474 */ 0x868b0000L, /*		jump	response_repeat, when msg_out */
+/* 0478 */ 0x00fffff0L,
+/* 047c */ 0x878b0000L, /*		jump	response_msg_in, when msg_in */
+/* 0480 */ 0x00000010L,
+/* 0484 */ 0x98080000L, /*		int	SIR_EV_RESPONSE_OK */
+/* 0488 */ 0x0000000cL,
+/* 048c */ 0x80880000L, /*		jump	to_decisions */
+/* 0490 */ 0x0000019cL,
+/* 0494 */ 0x0f000001L, /*		move	1, scratcha, when msg_in */
+/* 0498 */ 0x00000034L,
+/* 049c */ 0x808c0007L, /*		jump	rejected, if MSG_REJECT */
+/* 04a0 */ 0x00fffdf8L,
+/* 04a4 */ 0x98080000L, /*		int	SIR_EV_RESPONSE_OK */
+/* 04a8 */ 0x0000000cL,
+/* 04ac */ 0x80880000L, /*		jump	msg_in_not_reject */
+/* 04b0 */ 0x00fffd60L,
+/* 04b4 */ 0x7c027e00L, /*		move	scntl2&0x7e to scntl2 */
+/* 04b8 */ 0x00000000L,
+/* 04bc */ 0x60000040L, /*		clear 	ack */
+/* 04c0 */ 0x00000000L,
+/* 04c4 */ 0x48000000L, /*		wait	disconnect */
+/* 04c8 */ 0x00000000L,
+/* 04cc */ 0xc0000004L, /*		move	memory 4, state, scratcha */
+/* 04d0 */ 0x00000678L,
+/* 04d4 */ 0x00000034L,
+/* 04d8 */ 0x78340300L, /*		move	STATE_DISCONNECTED to scratcha0 */
+/* 04dc */ 0x00000000L,
+/* 04e0 */ 0xc0000004L, /*		move	memory 4, scratcha, state */
+/* 04e4 */ 0x00000034L,
+/* 04e8 */ 0x00000678L,
+/* 04ec */ 0x88880000L, /*		call	save_state */
+/* 04f0 */ 0x000001bcL,
+/* 04f4 */ 0x74020100L, /*		move	scntl2&0x01 to sfbr */
+/* 04f8 */ 0x00000000L,
+/* 04fc */ 0x98040000L, /*		int	SIR_NOTIFY_WSR, if not 0 */
+/* 0500 */ 0x00000073L,
+/* 0504 */ 0x80880000L, /*		jump	issue_check */
+/* 0508 */ 0x000001ccL,
+/* 050c */ 0x98080000L, /*		int	SIR_NOTIFY_RESELECTED_ON_SELECT */
+/* 0510 */ 0x00000075L,
+/* 0514 */ 0x80880000L, /*		jump	reselected */
+/* 0518 */ 0x00000008L,
+/* 051c */ 0x54000000L, /*		wait reselect sigp_set */
+/* 0520 */ 0x000001acL,
+/* 0524 */ 0x60000200L, /*		clear	target */
+/* 0528 */ 0x00000000L,
+/* 052c */ 0x9f030000L, /*		int	SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT, when not msg_in */
+/* 0530 */ 0x00000006L,
+/* 0534 */ 0x0f000001L, /*		move	1, scratchb, when msg_in */
+/* 0538 */ 0x0000005cL,
+/* 053c */ 0x98041f80L, /*		int	error_not_identify_after_reselect, if not MSG_IDENTIFY and mask 0x1f */
+/* 0540 */ 0x00000007L,
+/* 0544 */ 0xc0000004L, /*	 	move	memory 4, dsa_head, dsa */
+/* 0548 */ 0x00000008L,
+/* 054c */ 0x00000010L,
+/* 0550 */ 0x72100000L, /*		move	dsa0 to sfbr */
+/* 0554 */ 0x00000000L,
+/* 0558 */ 0x80840000L, /*		jump	find_dsa_1, if not 0 */
+/* 055c */ 0x00000030L,
+/* 0560 */ 0x72110000L, /*		move	dsa1 to sfbr */
+/* 0564 */ 0x00000000L,
+/* 0568 */ 0x80840000L, /*		jump	find_dsa_1, if not 0 */
+/* 056c */ 0x00000020L,
+/* 0570 */ 0x72120000L, /*		move	dsa2 to sfbr */
+/* 0574 */ 0x00000000L,
+/* 0578 */ 0x80840000L, /*		jump	find_dsa_1, if not 0 */
+/* 057c */ 0x00000010L,
+/* 0580 */ 0x72130000L, /*		move	dsa3 to sfbr */
+/* 0584 */ 0x00000000L,
+/* 0588 */ 0x980c0000L, /*		int	error_reselected, if 0 */
+/* 058c */ 0x00000003L,
+/* 0590 */ 0x88880000L, /*		call	load_state */
+/* 0594 */ 0x000000f8L,
+/* 0598 */ 0xc0000004L, /*		move	memory 4, state, scratcha */
+/* 059c */ 0x00000678L,
+/* 05a0 */ 0x00000034L,
+/* 05a4 */ 0x72340000L, /*		move	scratcha0 to sfbr */
+/* 05a8 */ 0x00000000L,
+/* 05ac */ 0x80840003L, /*		jump	find_dsa_next, if not STATE_DISCONNECTED */
+/* 05b0 */ 0x00000038L,
+/* 05b4 */ 0x740a0900L, /*		move	ssid & ssid_mask to sfbr */
+/* 05b8 */ 0x00000000L,
+/* 05bc */ 0xc0000001L, /*		move	memory 1, targ, find_dsa_smc1 */
+/* 05c0 */ 0x00000680L,
+/* 05c4 */ 0x000005c8L,
+/* 05c8 */ 0x808400ffL, /*		jump	find_dsa_next, if not 255 */
+/* 05cc */ 0x0000001cL,
+/* 05d0 */ 0xc0000001L, /*		move	memory 1, lun, find_dsa_smc2 */
+/* 05d4 */ 0x00000684L,
+/* 05d8 */ 0x000005e4L,
+/* 05dc */ 0x725c0000L, /*		move	scratchb0 to sfbr */
+/* 05e0 */ 0x00000000L,
+/* 05e4 */ 0x808cf8ffL, /*		jump	reload_sync, if 255 and mask ~7 */
+/* 05e8 */ 0x00000034L,
+/* 05ec */ 0xc0000004L, /*		move	memory 4, next, dsa */
+/* 05f0 */ 0x0000068cL,
+/* 05f4 */ 0x00000010L,
+/* 05f8 */ 0x80880000L, /*		jump	find_dsa_loop */
+/* 05fc */ 0x00ffff50L,
+/* 0600 */ 0x60000008L, /*		clear	atn */
+/* 0604 */ 0x00000000L,
+/* 0608 */ 0x878b0000L, /*	        jump    msg_in_phase, when msg_in */
+/* 060c */ 0x00fffbf4L,
+/* 0610 */ 0x98080000L, /*	        int     SIR_MSG_REJECT */
+/* 0614 */ 0x0000000aL,
+/* 0618 */ 0x80880000L, /*	        jump    to_decisions */
+/* 061c */ 0x00000010L,
+/* 0620 */ 0x88880000L, /*		call	load_sync */
+/* 0624 */ 0x00000134L,
+/* 0628 */ 0x60000040L, /*		clear	ack */
+/* 062c */ 0x00000000L,
+/* 0630 */ 0x818b0000L, /*		jump	data_in_phase, when data_in */
+/* 0634 */ 0x00fffa20L,
+/* 0638 */ 0x828a0000L, /*		jump	cmd_phase, if cmd */
+/* 063c */ 0x00fffa00L,
+/* 0640 */ 0x808a0000L, /*		jump	data_out_phase, if data_out */
+/* 0644 */ 0x00fffaecL,
+/* 0648 */ 0x838a0000L, /*		jump	status_phase, if status */
+/* 064c */ 0x00fffba4L,
+/* 0650 */ 0x878a0000L, /*		jump	msg_in_phase, if msg_in */
+/* 0654 */ 0x00fffbacL,
+/* 0658 */ 0x98080000L, /*		int	error_unexpected_phase */
+/* 065c */ 0x00000004L,
+/* 0660 */ 0x838b0000L, /*		jump	status_phase, when status */
+/* 0664 */ 0x00fffb8cL,
+/* 0668 */ 0x878a0000L, /*		jump	msg_in_phase, if msg_in */
+/* 066c */ 0x00fffb94L,
+/* 0670 */ 0x98080000L, /*		int	error_unexpected_phase */
+/* 0674 */ 0x00000004L,
+/* 0678 */ 0x00000000L, /*	state:	defw	0 */
+/* 067c */ 0x00000000L, /*	dmaaddr: defw	0 */
+/* 0680 */ 0x00000000L, /*	targ:	defw	0 */
+/* 0684 */ 0x00000000L, /*	lun:	defw	0 */
+/* 0688 */ 0x00000000L, /*	sync:	defw	0 */
+/* 068c */ 0x00000000L, /*	next:	defw	0 */
+			/*	dsa_load_len = dsa_load_end - dsa_copy */
+			/*	dsa_save_len = dsa_save_end - dsa_copy */
+/* 0690 */ 0xc0000004L, /*		move	memory 4, dsa, load_state_smc0 + 4 */
+/* 0694 */ 0x00000010L,
+/* 0698 */ 0x000006a0L,
+/* 069c */ 0xc0000018L, /*		move	memory dsa_load_len, 0, dsa_copy */
+/* 06a0 */ 0x00000000L,
+/* 06a4 */ 0x00000678L,
+/* 06a8 */ 0x90080000L, /*		return */
+/* 06ac */ 0x00000000L,
+/* 06b0 */ 0xc0000004L, /*		move	memory 4, dsa, save_state_smc0 + 8 */
+/* 06b4 */ 0x00000010L,
+/* 06b8 */ 0x000006c4L,
+/* 06bc */ 0xc0000008L, /*		move	memory dsa_save_len, dsa_copy, 0 */
+/* 06c0 */ 0x00000678L,
+/* 06c4 */ 0x00000000L,
+/* 06c8 */ 0x90080000L, /*		return */
+/* 06cc */ 0x00000000L,
+/* 06d0 */ 0x721a0000L, /*		move	ctest2 to sfbr */
+/* 06d4 */ 0x00000000L,
+/* 06d8 */ 0xc0000004L, /*		move	memory 4, dsa_head, dsa */
+/* 06dc */ 0x00000008L,
+/* 06e0 */ 0x00000010L,
+/* 06e4 */ 0x72100000L, /*		move	dsa0 to sfbr */
+/* 06e8 */ 0x00000000L,
+/* 06ec */ 0x80840000L, /*		jump	issue_check_1, if not 0 */
+/* 06f0 */ 0x00000030L,
+/* 06f4 */ 0x72110000L, /*		move	dsa1 to sfbr */
+/* 06f8 */ 0x00000000L,
+/* 06fc */ 0x80840000L, /*		jump	issue_check_1, if not 0 */
+/* 0700 */ 0x00000020L,
+/* 0704 */ 0x72120000L, /*		move	dsa2 to sfbr */
+/* 0708 */ 0x00000000L,
+/* 070c */ 0x80840000L, /*		jump	issue_check_1, if not 0 */
+/* 0710 */ 0x00000010L,
+/* 0714 */ 0x72130000L, /*		move	dsa3 to sfbr */
+/* 0718 */ 0x00000000L,
+/* 071c */ 0x808c0000L, /*		jump	wait_for_reselection, if 0 */
+/* 0720 */ 0x00fffdf8L,
+/* 0724 */ 0x88880000L, /*	 	call	load_state */
+/* 0728 */ 0x00ffff64L,
+/* 072c */ 0xc0000004L, /*		move	memory 4, state, scratcha */
+/* 0730 */ 0x00000678L,
+/* 0734 */ 0x00000034L,
+/* 0738 */ 0x72340000L, /*		move	scratcha0 to sfbr */
+/* 073c */ 0x00000000L,
+/* 0740 */ 0x808c0002L, /*		jump	start, if STATE_ISSUE */
+/* 0744 */ 0x00fff8c0L,
+/* 0748 */ 0xc0000004L, /*		move	memory 4, next, dsa */
+/* 074c */ 0x0000068cL,
+/* 0750 */ 0x00000010L,
+/* 0754 */ 0x80880000L, /*		jump	issue_check_loop */
+/* 0758 */ 0x00ffff88L,
+/* 075c */ 0xc0000004L, /*		move	memory 4, sync, scratcha */
+/* 0760 */ 0x00000688L,
+/* 0764 */ 0x00000034L,
+/* 0768 */ 0x72340000L, /*		move	scratcha0 to sfbr */
+/* 076c */ 0x00000000L,
+/* 0770 */ 0x6a030000L, /*		move	sfbr to scntl3 */
+/* 0774 */ 0x00000000L,
+/* 0778 */ 0x72350000L, /*		move	scratcha1 to sfbr */
+/* 077c */ 0x00000000L,
+/* 0780 */ 0x6a050000L, /*		move	sfbr to sxfer */
+/* 0784 */ 0x00000000L,
+/* 0788 */ 0x90080000L, /*		return */
+/* 078c */ 0x00000000L,
+};
+
+#define NA_SCRIPT_SIZE 484
+
+struct na_patch na_patches[] = {
+	{ 0x0006, 5 }, /* 00000018 */
+	{ 0x000b, 4 }, /* 0000002c */
+	{ 0x0013, 4 }, /* 0000004c */
+	{ 0x0017, 1 }, /* 0000005c */
+	{ 0x0018, 2 }, /* 00000060 */
+	{ 0x001a, 1 }, /* 00000068 */
+	{ 0x001b, 2 }, /* 0000006c */
+	{ 0x0021, 1 }, /* 00000084 */
+	{ 0x002b, 2 }, /* 000000ac */
+	{ 0x002c, 1 }, /* 000000b0 */
+	{ 0x0030, 2 }, /* 000000c0 */
+	{ 0x0031, 1 }, /* 000000c4 */
+	{ 0x0037, 2 }, /* 000000dc */
+	{ 0x0038, 1 }, /* 000000e0 */
+	{ 0x003a, 2 }, /* 000000e8 */
+	{ 0x003b, 1 }, /* 000000ec */
+	{ 0x0043, 4 }, /* 0000010c */
+	{ 0x0047, 2 }, /* 0000011c */
+	{ 0x0048, 1 }, /* 00000120 */
+	{ 0x004e, 1 }, /* 00000138 */
+	{ 0x004f, 2 }, /* 0000013c */
+	{ 0x0051, 1 }, /* 00000144 */
+	{ 0x0052, 2 }, /* 00000148 */
+	{ 0x0058, 1 }, /* 00000160 */
+	{ 0x0059, 2 }, /* 00000164 */
+	{ 0x005b, 1 }, /* 0000016c */
+	{ 0x0065, 2 }, /* 00000194 */
+	{ 0x0066, 1 }, /* 00000198 */
+	{ 0x006a, 2 }, /* 000001a8 */
+	{ 0x006b, 1 }, /* 000001ac */
+	{ 0x0073, 4 }, /* 000001cc */
+	{ 0x0077, 2 }, /* 000001dc */
+	{ 0x0078, 1 }, /* 000001e0 */
+	{ 0x007e, 4 }, /* 000001f8 */
+	{ 0x0082, 2 }, /* 00000208 */
+	{ 0x0098, 1 }, /* 00000260 */
+	{ 0x0099, 2 }, /* 00000264 */
+	{ 0x009f, 2 }, /* 0000027c */
+	{ 0x00a0, 1 }, /* 00000280 */
+	{ 0x00b6, 2 }, /* 000002d8 */
+	{ 0x00c2, 2 }, /* 00000308 */
+	{ 0x00ca, 2 }, /* 00000328 */
+	{ 0x00d0, 2 }, /* 00000340 */
+	{ 0x00d6, 2 }, /* 00000358 */
+	{ 0x00e6, 2 }, /* 00000398 */
+	{ 0x00ec, 2 }, /* 000003b0 */
+	{ 0x0102, 2 }, /* 00000408 */
+	{ 0x010e, 2 }, /* 00000438 */
+	{ 0x011c, 4 }, /* 00000470 */
+	{ 0x0126, 2 }, /* 00000498 */
+	{ 0x0134, 1 }, /* 000004d0 */
+	{ 0x0135, 2 }, /* 000004d4 */
+	{ 0x0139, 2 }, /* 000004e4 */
+	{ 0x013a, 1 }, /* 000004e8 */
+	{ 0x014e, 2 }, /* 00000538 */
+	{ 0x0152, 4 }, /* 00000548 */
+	{ 0x0153, 2 }, /* 0000054c */
+	{ 0x0167, 1 }, /* 0000059c */
+	{ 0x0168, 2 }, /* 000005a0 */
+	{ 0x016d, 3 }, /* 000005b4 */
+	{ 0x0170, 1 }, /* 000005c0 */
+	{ 0x0171, 1 }, /* 000005c4 */
+	{ 0x0175, 1 }, /* 000005d4 */
+	{ 0x0176, 1 }, /* 000005d8 */
+	{ 0x017c, 1 }, /* 000005f0 */
+	{ 0x017d, 2 }, /* 000005f4 */
+	{ 0x01a5, 2 }, /* 00000694 */
+	{ 0x01a6, 1 }, /* 00000698 */
+	{ 0x01a9, 1 }, /* 000006a4 */
+	{ 0x01ad, 2 }, /* 000006b4 */
+	{ 0x01ae, 1 }, /* 000006b8 */
+	{ 0x01b0, 1 }, /* 000006c0 */
+	{ 0x01b7, 4 }, /* 000006dc */
+	{ 0x01b8, 2 }, /* 000006e0 */
+	{ 0x01cc, 1 }, /* 00000730 */
+	{ 0x01cd, 2 }, /* 00000734 */
+	{ 0x01d3, 1 }, /* 0000074c */
+	{ 0x01d4, 2 }, /* 00000750 */
+	{ 0x01d8, 1 }, /* 00000760 */
+	{ 0x01d9, 2 }, /* 00000764 */
+};
+#define NA_PATCHES 80
+
+enum na_external {
+	X_scsi_id_buf,
+	X_msg_out_buf,
+	X_cmd_buf,
+	X_data_buf,
+	X_status_buf,
+	X_msgin_buf,
+	X_dsa_0,
+	X_dsa_1,
+	X_dsa_head,
+	X_ssid_mask,
+};
+
+enum {
+	E_issue_check_next = 1864,
+	E_issue_check_1 = 1828,
+	E_issue_check_loop = 1764,
+	E_save_state_smc0 = 1724,
+	E_load_state_smc0 = 1692,
+	E_dsa_load_end = 1680,
+	E_sync = 1672,
+	E_dsa_save_end = 1664,
+	E_dsa_copy = 1656,
+	E_id_out_mismatch_recover = 1536,
+	E_next = 1676,
+	E_reload_sync = 1568,
+	E_find_dsa_smc2 = 1508,
+	E_lun = 1668,
+	E_find_dsa_smc1 = 1480,
+	E_targ = 1664,
+	E_find_dsa_next = 1516,
+	E_load_state = 1680,
+	E_find_dsa_1 = 1424,
+	E_find_dsa_loop = 1360,
+	E_find_dsa = 1348,
+	E_sigp_set = 1744,
+	E_reselected = 1316,
+	E_wsr_check = 1268,
+	E_response_msg_in = 1172,
+	E_response_repeat = 1132,
+	E_response = 1108,
+	E_reject = 988,
+	E_wdtr = 964,
+	E_sdtr = 876,
+	E_ext_done = 988,
+	E_ext_1 = 756,
+	E_ext_2 = 900,
+	E_ext_3 = 788,
+	E_issue_check = 1752,
+	E_extended = 708,
+	E_ignore_wide = 1060,
+	E_msg_in_skip = 692,
+	E_disconnected = 1204,
+	E_msg_in_not_reject = 532,
+	E_rejected = 668,
+	E_msg_in_phase = 516,
+	E_status_phase = 500,
+	E_data_out_mismatch = 464,
+	E_data_out_block_mismatch = 368,
+	E_data_out_normal = 440,
+	E_data_out_block_loop = 332,
+	E_data_out_phase = 308,
+	E_post_data_to_decisions = 1632,
+	E_data_in_mismatch = 272,
+	E_data_mismatch_recover = 228,
+	E_data_block_mismatch_recover = 216,
+	E_save_state = 1712,
+	E_data_in_block_mismatch = 136,
+	E_data_in_normal = 248,
+	E_data_in_block_loop = 112,
+	E_dmaaddr = 1660,
+	E_state = 1656,
+	E_data_in_phase = 88,
+	E_cmd_out_mismatch = 80,
+	E_cmd_phase = 64,
+	E_to_decisions = 1584,
+	E_id_out_mismatch = 48,
+	E_start1 = 40,
+	E_reselected_on_select = 1292,
+	E_load_sync = 1884,
+	E_start = 8,
+	E_wait_for_reselection = 1308,
+	E_idle = 0,
+};
+#define A_dsa_save_len 8
+#define A_dsa_load_len 24
+#define A_BSIZE 512
+#define A_MSG_REJECT 7
+#define A_X_MSG_WDTR 3
+#define A_X_MSG_SDTR 1
+#define A_X_MSG 1
+#define A_MSG_IGNORE_WIDE_RESIDUE 35
+#define A_MSG_RESTORE_POINTERS 3
+#define A_MSG_SAVE_DATA_POINTER 2
+#define A_MSG_DISCONNECT 4
+#define A_MSG_IDENTIFY 128
+#define A_RESULT_OK 0
+#define A_STATE_DONE 4
+#define A_STATE_DISCONNECTED 3
+#define A_STATE_ISSUE 2
+#define A_STATE_ALLOCATED 1
+#define A_STATE_FREE 0
+#define A_SIR_NOTIFY_RESELECTED_ON_SELECT 117
+#define A_SIR_NOTIFY_LOAD_SYNC 116
+#define A_SIR_NOTIFY_WSR 115
+#define A_SIR_NOTIFY_BLOCK_DATA_IN 114
+#define A_SIR_NOTIFY_DATA_OUT 113
+#define A_SIR_NOTIFY_DATA_IN 112
+#define A_SIR_NOTIFY_COMMAND 111
+#define A_SIR_NOTIFY_DUMP_NEXT_CODE 110
+#define A_SIR_NOTIFY_ISSUE_CHECK 109
+#define A_SIR_NOTIFY_WAIT_RESELECT 108
+#define A_SIR_NOTIFY_ISSUE 107
+#define A_SIR_NOTIFY_SIGP 106
+#define A_SIR_NOTIFY_DUMP2 105
+#define A_SIR_NOTIFY_DUMP 104
+#define A_SIR_NOTIFY_STATUS 103
+#define A_SIR_NOTIFY_MSG_IN 102
+#define A_SIR_NOTIFY_RESELECT 101
+#define A_SIR_NOTIFY_DISC 100
+#define A_SIR_MSG_IGNORE_WIDE_RESIDUE 16
+#define A_SIR_MSG_WDTR 15
+#define A_SIR_EV_PHASE_SWITCH_AFTER_ID 14
+#define A_error_sigp_set 13
+#define A_SIR_EV_RESPONSE_OK 12
+#define A_SIR_MSG_SDTR 11
+#define A_SIR_MSG_REJECT 10
+#define A_error_too_little_data 9
+#define A_error_too_much_data 8
+#define A_error_not_identify_after_reselect 7
+#define A_SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT 6
+#define A_error_weird_message 5
+#define A_error_unexpected_phase 4
+#define A_error_reselected 3
+#define A_error_disconnected 2
+#define A_error_not_cmd_complete 1
+#define A_SIR_MSG_IO_COMPLETE 0

+ 0 - 14
sys/src/9/port/devssl.c

@@ -591,19 +591,6 @@ sslbread(Chan *c, long n, ulong)
 		}
 		ensure(s, &s->unprocessed, toconsume+len);
 
-		/*
-		 * Now we have a full SSL packet in the unprocessed list.
-		 * Start processing.  We can't get Eintr's here.
-		 * The only cause for errors from here until the end of the
-		 * loop is allocation failures in the block manipulation.
-		 * We'll worry about that when we come across it.
-		 */
-
-		if(waserror()){
-			print("devssl: unhandled allocation failure\n");
-			nexterror();
-		}
-
 		/* skip header */
 		consume(&s->unprocessed, consumed, toconsume);
 
@@ -653,7 +640,6 @@ sslbread(Chan *c, long n, ulong)
 		s->in.mid++;
 		qunlock(&s->in.ctlq);
 		poperror();
-		poperror();
 	}
 
 	/* return at most what was asked for */

+ 1 - 0
sys/src/9/port/netif.c

@@ -212,6 +212,7 @@ netifread(Netif *nif, Chan *c, void *a, long n, ulong offset)
 		j += snprint(p+j, READSTR-j, "buffer errs: %d\n", nif->buffs);
 		j += snprint(p+j, READSTR-j, "output errs: %d\n", nif->oerrs);
 		j += snprint(p+j, READSTR-j, "prom: %d\n", nif->prom);
+		j += snprint(p+j, READSTR-j, "mbps: %d\n", nif->mbps);
 		j += snprint(p+j, READSTR-j, "addr: ");
 		for(i = 0; i < nif->alen; i++)
 			j += snprint(p+j, READSTR-j, "%2.2ux", nif->addr[i]);

+ 1 - 0
sys/src/9/port/netif.h

@@ -74,6 +74,7 @@ struct Netif
 	/* about net */
 	int	limit;			/* flow control */
 	int	alen;			/* address length */
+	int	mbps;			/* megabits per sec */
 	uchar	addr[Nmaxaddr];
 	uchar	bcast[Nmaxaddr];
 	Netaddr	*maddr;			/* known multicast addresses */

+ 10 - 1
sys/src/cmd/stats.c

@@ -1177,6 +1177,7 @@ main(int argc, char *argv[])
 	char *s;
 	long v, vmax, nargs;
 	char args[100];
+	int sleeptime = 1000;
 
 	nmach = 1;
 	mysysname = getenv("sysname");
@@ -1188,6 +1189,14 @@ main(int argc, char *argv[])
 
 	nargs = 0;
 	ARGBEGIN{
+	case 'T':
+		s = ARGF();
+		if(s == nil)
+			usage();
+		i = atoi(s);
+		if(i > 0)
+			sleeptime = 1000*i;
+		break;
 	case 'S':
 		s = ARGF();
 		if(s == nil)
@@ -1307,6 +1316,6 @@ main(int argc, char *argv[])
 		}
 		flushimage(display, 1);
 		unlockdisplay(display);
-		sleep(1000);
+		sleep(sleeptime);
 	}
 }