Browse Source

Plan 9 from Bell Labs 2010-01-21

David du Colombier 14 years ago
parent
commit
48baaac4d4

+ 22 - 6
rc/bin/9fs

@@ -1,4 +1,7 @@
 #!/bin/rc
+# 9fs filesystem [mountpoint] - srv & mount filesystem, usually from plan 9
+
+rfork e
 switch($1){
 case ''
 	echo usage: 9fs service '[mountpoint]' >[1=2]
@@ -7,18 +10,16 @@ case kfs
 	if(! test -f /srv/kfs)
 		disk/kfs
 	mount -c /srv/kfs /n/kfs
-case netlib
-	9fs netlib2 && bind /n/netlib2/netlib /netlib
 case dump
 	mount /srv/boot /n/dump dump >[2]/dev/null ||
-	mount /srv/boot /n/dump main/archive ||
-	mount /srv/boot /n/dump dump	# again to print error
+		mount /srv/boot /n/dump main/archive ||
+		mount /srv/boot /n/dump dump	# again to print error
 case snap
 	mount /srv/boot /n/snap main/snapshot
 case other
 	mount -C /srv/boot /n/other other
-case juke
-	srv -q il!jukefs && mount /srv/il!jukefs /n/njuke && bind -c /n/njuke/juke /n/juke
+case juke					# ye olde file server
+	srv -q il!jukefs && mount /srv/il!jukefs /n/juke
 case sources
 	srv -nq tcp!sources.cs.bell-labs.com sources /n/sources
 case sourcesdump
@@ -27,6 +28,21 @@ case sourcesdump
 case sourcessnap
 	9fs sources
 	mount -n /srv/sources /n/sourcessnap main/snapshot
+# arbitrary venti archives
+case vac:*
+	vacfs <{echo $1}
+case *.vac
+	if (test -e $1)
+		score=$1
+	if not if (! ~ $1 /* && test -e $home/lib/vac/$1)
+		score=$home/lib/vac/$1
+	if not if (! ~ $1 /* && test -e /lib/vac/$1)
+		score=/lib/vac/$1
+	if not {
+		echo $0: $1: no such score file >[1=2]
+		exit 'no score file'
+	}
+	vacfs -m /n/`{basename $1 .vac} `{cat $score}
 case wiki
 	srv -m 'net!plan9.bell-labs.com!wiki' wiki /mnt/wiki
 case *

+ 13 - 14
rc/bin/patch/move

@@ -1,29 +1,28 @@
 #!/bin/rc
-
+# patch/move target patch-tree... - move patch tree(s) to target dir
 rfork e
+pats=/n/sources/patch
 if(~ $#* 0 1){
 	echo 'usage: patch/move dst patch-name...' >[1=2]
 	exit usage
 }
 
-if(! test -d /n/sources/patch){
+if(! test -d $pats){
 	rfork n
 	9fs sources
 }
+cd $pats
 
 dst=$1
 shift
-for(i){
-	j=`{basename $i}
-	if(! test -d /n/sources/patch/$i)
-		echo 'no such patch' /n/sources/patch/$i >[1=2]
-	if not if(test -d /n/sources/patch/$dst/$j)
-		echo 'already have' /n/sources/patch/$dst/$j >[1=2]
+for(src){
+	patdest=$dst/^`{basename $src}
+	if(! test -d $src)
+		echo 'no such patch' $pats/$src >[1=2]
+	if not if(test -d $patdest)
+		echo 'already have' $pats/$patdest >[1=2]
 	if not
-		ls -ldp /n/sources/patch/$i >/n/sources/patch/$i/origls &&
-		mkdir /n/sources/patch/$dst/$j && 
-		dircp /n/sources/patch/$i /n/sources/patch/$dst/$j &&
-		rm -rf /n/sources/patch/$i &&
-		test -s /n/sources/patch/$dst/$j/email &&
-		patch/notify $dst/$j
+		ls -ldp $src >$src/origls &&
+			mkdir $patdest && dircp $src $patdest && rm -rf $src &&
+			test -s $patdest/email && patch/notify $patdest
 }

+ 3 - 3
sys/include/ape/sys/time.h

@@ -1,8 +1,5 @@
 #ifndef __SYSTIME_H
 #define __SYSTIME_H
-#ifndef _BSD_EXTENSION
-    This header file is an extension to ANSI/POSIX
-#endif
 #pragma lib "/$M/lib/ape/libap.a"
 
 #ifndef __TIMEVAL__
@@ -11,10 +8,13 @@ struct timeval {
 	long	tv_sec;
 	long	tv_usec;
 };
+
+#ifdef _BSD_EXTENSION
 struct timezone {
 	int	tz_minuteswest;
 	int	tz_dsttime;
 };
+#endif
 #endif /* __TIMEVAL__ */
 
 extern int gettimeofday(struct timeval *, struct timezone *);

+ 1 - 6
sys/man/2/getfcr

@@ -112,12 +112,7 @@ internal registers are 80 bits long):
 .EX
 .IP
 .ft L
-ulong fcr;
-fcr = getfcr();
-fcr |= FPOVFL;
-fcr &= ~FPPMASK;
-fcr |= FPPDBL;
-setfcr(fcr);
+setfcr((getfcr() & ~FPPMASK) | FPPDBL | FPOVFL);
 .ft
 .EE
 .SH SOURCE

+ 8 - 0
sys/man/2/nan

@@ -26,6 +26,12 @@ and division by zero.
 Also, the library functions sometimes return them when
 the arguments are not in the domain, or the result is
 out of range.
+By default, manipulating these values may cause a floating point exception
+on some processors but
+.I setfcr
+(see
+.IR getfcr (2))
+can change that behavior.
 .PP
 .I NaN
 returns a double that is not-a-number.
@@ -42,3 +48,5 @@ returns true if its first argument is infinity
 with the same sign as the second argument.
 .SH SOURCE
 .B /sys/src/libc/port/nan.c
+.SH "SEE ALSO"
+.IR getfcr (2)

+ 4 - 3
sys/man/3/audio

@@ -1,6 +1,6 @@
 .TH AUDIO 3 
 .SH NAME
-audio \- SoundBlaster audio controller
+audio \- SoundBlaster or ESS1688 audio controller
 .SH SYNOPSIS
 .nf
 .B bind -a #A /dev
@@ -47,8 +47,7 @@ was reached.  Using
 and
 .IR o ,
 it is possible to calculate at what time a byte with a different offset will
-be recorded or played back.  See also
-.IR usb (4).
+be recorded or played back.
 .PP
 .B Volume
 is the control file associated with the audio port.
@@ -126,3 +125,5 @@ expressed in Hz.
 Defaults to 44100.
 .SH SOURCE
 .B /sys/src/9/port/devaudio.c
+.SH SEE ALSO
+.IR usb (4)

+ 16 - 8
sys/man/8/prep

@@ -1,6 +1,6 @@
 .TH PREP 8
 .SH NAME
-prep, fdisk, format, mbr \- prepare hard and floppy diskettes, flashes
+prep, fdisk, format, mbr \- prepare disks, floppies and flashes
 .SH SYNOPSIS
 .B disk/prep
 [
@@ -364,21 +364,29 @@ is set to the maximum value that
 .I end
 can take on without running off the disk
 or into another partition.
+Numeric constants followed by
+.LR k ,
+.LR m ,
+.LR g ,
+or
+.LR t
+(or upper-case equivalents)
+are scaled to the respective size in kilo-, mega-, giga-, or tera-bytes.
 Finally, the expression
 .IB n %
 evaluates to
 .RI ( n × disksize )/100.
-As an example,
-.B a
-.B .
-.B .+20%
+As examples,
+.L "a . .+20%"
 creates a new partition starting at
 .B .
 that takes up a fifth of the disk,
+.L "a . .+21G"
+creates a new partition starting at
+.B .
+that takes up 21 gigabytes (21×2\u\s-130\s0\d bytes),
 and
-.B a
-.B 1000
-.B $
+.L "a 1000 $"
 creates a new partition starting at
 sector 1000 and
 extending as far as possible.

+ 11 - 14
sys/src/9/pc/ether82563.c

@@ -4,8 +4,8 @@
  *	82575eb
  * Pretty basic, does not use many of the chip smarts.
  * The interrupt mitigation tuning for each chip variant
- * is probably different. The reset/initialisation
- * sequence needs straightened out. Doubt the PHY code
+ * is probably different.  The reset/initialisation
+ * sequence needs straightening out.  Doubt the PHY code
  * for the 82575eb is right.
  */
 #include "u.h"
@@ -793,6 +793,7 @@ static void
 i82563rbfree(Block* b)
 {
 	b->rp = b->wp = (uchar*)PGROUND((uintptr)b->base);
+ 	b->flag &= ~(Bipck | Budpck | Btcpck | Bpktck);
 	ilock(&i82563rblock);
 	b->next = i82563rbpool;
 	i82563rbpool = b;
@@ -995,9 +996,9 @@ i82563rxinit(Ctlr* ctlr)
 	ctlr->rdt = 0;
 	csr32w(ctlr, Rdt, 0);
 	/* to hell with interrupt moderation, we've got fast cpus */
+	ctlr->radv = ctlr->rdtr = 0;
 //	ctlr->rdtr = 25;		/* µs units? */
 //	ctlr->radv = 500;		/* µs units? */
-	ctlr->radv = ctlr->rdtr = 0;
 	csr32w(ctlr, Rdtr, ctlr->rdtr);
 	csr32w(ctlr, Radv, ctlr->radv);
 
@@ -1244,31 +1245,27 @@ i82563attach(Ether* edev)
 	ctlr->ntd = Ntd;
 
 	if(waserror()){
-		while(ctlr->nrb > 0){
+		for(; ctlr->nrb > 0; ctlr->nrb--){
 			bp = i82563rballoc();
 			bp->free = nil;
 			freeb(bp);
-			ctlr->nrb--;
 		}
 		free(ctlr->tb);
-		ctlr->tb = nil;
 		free(ctlr->rb);
+		ctlr->tb = nil;
 		ctlr->rb = nil;
 		free(ctlr->tdba);
-		ctlr->tdba = nil;
 		free(ctlr->rdba);
+		ctlr->tdba = nil;
 		ctlr->rdba = nil;
 		qunlock(&ctlr->alock);
 		nexterror();
 	}
 
-	if((ctlr->rdba = mallocalign(ctlr->nrd*sizeof(Rd), 128, 0, 0)) == nil)
-		error(Enomem);
-	if((ctlr->tdba = mallocalign(ctlr->ntd*sizeof(Td), 128, 0, 0)) == nil)
-		error(Enomem);
-	if((ctlr->rb = malloc(ctlr->nrd*sizeof(Block*))) == nil)
-		error(Enomem);
-	if((ctlr->tb = malloc(ctlr->ntd*sizeof(Block*))) == nil)
+	if((ctlr->rdba = mallocalign(ctlr->nrd*sizeof(Rd), 128, 0, 0)) == nil ||
+	   (ctlr->tdba = mallocalign(ctlr->ntd*sizeof(Td), 128, 0, 0)) == nil ||
+	   (ctlr->rb = malloc(ctlr->nrd*sizeof(Block*))) == nil ||
+	   (ctlr->tb = malloc(ctlr->ntd*sizeof(Block*))) == nil)
 		error(Enomem);
 
 	for(ctlr->nrb = 0; ctlr->nrb < Nrb; ctlr->nrb++){

+ 1 - 0
sys/src/9/pc/ether82598.c

@@ -419,6 +419,7 @@ void
 rbfree(Block *b)
 {
 	b->rp = b->wp = (uchar*)PGROUND((uintptr)b->base);
+ 	b->flag &= ~(Bipck | Budpck | Btcpck | Bpktck);
 	ilock(&rblock);
 	b->next = rbpool;
 	rbpool = b;

+ 1 - 0
sys/src/9/pc/etherigbe.c

@@ -780,6 +780,7 @@ igberbfree(Block* bp)
 {
 	bp->rp = bp->lim - Rbsz;
 	bp->wp = bp->rp;
+ 	bp->flag &= ~(Bipck | Budpck | Btcpck | Bpktck);
 
 	ilock(&igberblock);
 	bp->next = igberbpool;

+ 10 - 14
sys/src/9/pc/etherm10g.c

@@ -875,12 +875,11 @@ balloc(Rx* rx)
 }
 
 static void
-smbfree(Block *b)
+rbfree(Block *b, Bpool *p)
 {
-	Bpool *p;
-
 	b->rp = b->wp = (uchar*)PGROUND((uintptr)b->base);
-	p = &smpool;
+ 	b->flag &= ~(Bipck | Budpck | Btcpck | Bpktck);
+
 	ilock(p);
 	b->next = p->head;
 	p->head = b;
@@ -890,18 +889,15 @@ smbfree(Block *b)
 }
 
 static void
-bgbfree(Block *b)
+smbfree(Block *b)
 {
-	Bpool *p;
+	rbfree(b, &smpool);
+}
 
-	b->rp = b->wp = (uchar*)PGROUND((uintptr)b->base);
-	p = &bgpool;
-	ilock(p);
-	b->next = p->head;
-	p->head = b;
-	p->n++;
-	p->cnt++;
-	iunlock(p);
+static void
+bgbfree(Block *b)
+{
+	rbfree(b, &bgpool);
 }
 
 static void

+ 1 - 0
sys/src/9/pc/ethervt6105m.c

@@ -579,6 +579,7 @@ vt6105Mrbfree(Block* bp)
 {
 	bp->rp = bp->lim - (Rdbsz+3);
 	bp->wp = bp->rp;
+ 	bp->flag &= ~(Bipck | Budpck | Btcpck | Bpktck);
 
 	ilock(&vt6105Mrblock);
 	bp->next = vt6105Mrbpool;

+ 21 - 7
sys/src/cmd/aux/acidleak.c

@@ -56,11 +56,13 @@ struct Data {
 };
 
 Block *block;
-int nblock;
+uint nblock;
+uint ablock;
 
 Data *data;
 Data *edata;
-int ndata;
+uint ndata;
+uint adata;
 
 int
 addrcmp(void *va, void *vb)
@@ -200,17 +202,28 @@ main(int argc, char **argv)
 		p[Blinelen(&bio)-1] = '\0';
 		nf = tokenize(p, f, nelem(f));
 		if(nf >= 4 && strcmp(f[0], "data") == 0) {
-			if(ndata%64==0)
-				data = erealloc(data, (ndata+64)*sizeof(Data));
+			if(ndata >= adata){
+				if(adata == 0)
+					adata = 4096;
+				else
+					adata += adata / 4;  /* increase 25% */
+				data = erealloc(data, adata * sizeof(Data));
+			}
 			data[ndata].addr = strtoul(f[1], nil, 0);
 			data[ndata].val = strtoul(f[2], nil, 0);
 			data[ndata].type = f[3][0];
 			data[ndata].b = 0;
 			ndata++;
 		}
-		if(nf >= 5 && (strcmp(f[0], "block") == 0 || strcmp(f[0], "free") == 0)) {
-			if(nblock%64 == 0)
-				block = erealloc(block, (nblock+64)*sizeof(Block));
+		if(nf >= 5 &&
+		    (strcmp(f[0], "block") == 0 || strcmp(f[0], "free") == 0)) {
+			if(nblock >= ablock){
+				if(ablock == 0)
+					ablock = 4096;
+				else
+					ablock += ablock / 4; /* increase 25% */
+				block = erealloc(block, ablock * sizeof(Block));
+			}
 			block[nblock].addr = strtoul(f[1], nil, 0);
 			block[nblock].size = strtoul(f[2], nil, 0);
 			block[nblock].w0 = strtoul(f[3], nil, 0);
@@ -319,4 +332,5 @@ main(int argc, char **argv)
 				Bprint(&bio, "block 0x%.8lux 0x%.8lux 0x%.8lux 0x%.8lux %s %s\n", b->addr, b->size, b->w0, b->w1, b->s0, b->s1);
 	}
 	Bterm(&bio);
+	exits(nil);
 }

+ 25 - 2
sys/src/cmd/disk/prep/calc.y

@@ -85,6 +85,9 @@ static char** errp;
 static int
 yylex(void)
 {
+	int c;
+	uvlong n;
+
 	while(isspace(*inp))
 		inp++;
 
@@ -92,10 +95,30 @@ yylex(void)
 		return 0;
 
 	if(isdigit(*inp)) {
-		yylval = mkNUM(strtoll(inp, &inp, 0));
+		n = strtoull(inp, &inp, 0);	/* default unit is sectors */
+		c = *inp++;
+		if(isascii(c) && isupper(c))
+			c = tolower(c);
+		switch(c) {
+		case 't':
+			n *= 1024;
+			/* fall through */
+		case 'g':
+			n *= 1024;
+			/* fall through */
+		case 'm':
+			n *= 1024;
+			/* fall through */
+		case 'k':
+			n *= 2;
+			break;
+		default:
+			--inp;
+			break;
+		}
+		yylval = mkNUM(n);
 		return NUMBER;
 	}
-
 	return *inp++;
 }
 

+ 4 - 7
sys/src/cmd/usb/lib/dev.c

@@ -420,9 +420,7 @@ cmdrep(Dev *d, void *buf, int nb)
 int
 usbcmd(Dev *d, int type, int req, int value, int index, uchar *data, int count)
 {
-	int r;
-	int i;
-	int nerr;
+	int i, r, nerr;
 	char err[64];
 
 	/*
@@ -432,12 +430,12 @@ usbcmd(Dev *d, int type, int req, int value, int index, uchar *data, int count)
 	r = -1;
 	*err = 0;
 	for(i = nerr = 0; i < Uctries; i++){
-		if(type&Rd2h)
+		if(type & Rd2h)
 			r = cmdreq(d, type, req, value, index, nil, count);
 		else
 			r = cmdreq(d, type, req, value, index, data, count);
 		if(r > 0){
-			if((type&Rd2h) == 0)
+			if((type & Rd2h) == 0)
 				break;
 			r = cmdrep(d, data, count);
 			if(r > 0)
@@ -450,11 +448,10 @@ usbcmd(Dev *d, int type, int req, int value, int index, uchar *data, int count)
 			rerrstr(err, sizeof(err));
 		sleep(Ucdelay);
 	}
-	if(r > 0 && i >= 2){
+	if(r > 0 && i >= 2)
 		/* let the user know the device is not in good shape */
 		fprint(2, "%s: usbcmd: %s: required %d attempts (%s)\n",
 			argv0, d->dir, i, err);
-	}
 	return r;
 }
 

+ 5 - 7
sys/src/cmd/usb/lib/dump.c

@@ -31,27 +31,25 @@ classname(int c)
 	}
 }
 
-char*
+char *
 hexstr(void *a, int n)
 {
 	int i;
+	char *dbuff, *s, *e;
 	uchar *b;
-	char *dbuff;
-	char *s;
-	char *e;
 
 	b = a;
 	dbuff = s = emallocz(1024, 0);
 	*s = 0;
-	e = s+1024;
-	for(i=0; i < n; i++)
+	e = s + 1024;
+	for(i = 0; i < n; i++)
 		s = seprint(s, e, " %.2ux", b[i]);
 	if(s == e)
 		fprint(2, "%s: usb/lib: hexdump: bug: small buffer\n", argv0);
 	return dbuff;
 }
 
-static char*
+static char *
 seprintiface(char *s, char *e, Iface *i)
 {
 	int	j;

+ 11 - 8
sys/src/cmd/usb/serial/ftdi.c

@@ -631,9 +631,11 @@ epreader(void *u)
 	dfd = ser->epin->dfd;
 	qunlock(ser);
 
+	p = nil;
 	do {
-		p = emallocz(sizeof(Packser), 1);
-		rcount = read(dfd, p->b, Packsz);
+		if (p == nil)
+			p = emallocz(sizeof(Packser), 1);
+		rcount = read(dfd, p->b, sizeof p->b);
 		if(serialdebug > 5)
 			dsprint(2, "%d %#ux%#ux ", rcount, ser->data[0],
 				ser->data[1]);
@@ -642,16 +644,18 @@ epreader(void *u)
 		if(rcount >= ser->inhdrsz){
 			ftuseinhdr(ser, p->b);
 			rcount -= ser->inhdrsz;
-			memmove(p->b, p->b+ser->inhdrsz, rcount);
+			memmove(p->b, p->b + ser->inhdrsz, rcount);
 			if(rcount != 0){
 				p->nb = rcount;
 				sendp(c, p);
+				p = nil;
 			}
 		}
 	} while(rcount >= 0 || (rcount < 0 && strstr(err, "timed out") != nil));
 
 	if(rcount < 0)
 		fprint(2, "error reading: %r\n");
+	free(p);
 	sendp(c, nil);
 	closedev(ser->dev);
 }
@@ -677,15 +681,15 @@ statusreader(void *u)
 	while((p = recvp(c)) != nil){
 		memmove(ser->data, p->b, p->nb);
 		ser->ndata = p->nb;
-		dsprint(2, "serial: status reader %d \n", p->nb);
+		free(p);
+		dsprint(2, "serial: status reader %d \n", ser->ndata);
 		/* consume it all */
 		while(ser->ndata != 0){
 			dsprint(2, "serial: status reader to consume: %d\n",
-				p->nb);
+				ser->ndata);
 			sendul(ser->w4data, 1);
 			recvul(ser->gotdata);
 		}
-		free(p);
 	}
 	free(a);
 	free(c);
@@ -785,9 +789,8 @@ ftseteps(Serial *ser)
 
 	s = smprint("maxpkt %d", Packsz);
 	devctl(ser->epin, s);
-	ser->maxread = Packsz;
 	devctl(ser->epout, s);
-	ser->maxwrite = Packsz;
+	ser->maxread = ser->maxwrite = Packsz;
 	free(s);
 	return 0;
 }

+ 14 - 7
sys/src/cmd/usb/serial/serial.c

@@ -87,7 +87,7 @@ serialreset(Serial *ser)
 	return 0;
 }
 
-/*call this if something goes wrong */
+/* call this if something goes wrong */
 int
 serialrecover(Serial *ser, char *err)
 {
@@ -400,6 +400,10 @@ dirgen(Usbfs *fs, Qid, int i, Dir *d, void *)
 	return 0;
 }
 
+enum {
+	Serbufsize	= 255,
+};
+
 static long
 dread(Usbfs *fs, Fid *fid, void *data, long count, vlong offset)
 {
@@ -414,8 +418,8 @@ dread(Usbfs *fs, Fid *fid, void *data, long count, vlong offset)
 	path = fid->qid.path & ~fs->qid;
 	ser = fs->aux;
 
-	buf = emallocz(255, 1);
-	err = emallocz(255, 1);
+	buf = emallocz(Serbufsize, 1);
+	err = emallocz(Serbufsize, 1);
 	qlock(ser);
 	switch(path){
 	case Qroot:
@@ -439,7 +443,7 @@ dread(Usbfs *fs, Fid *fid, void *data, long count, vlong offset)
 				qlock(ser);
 			}
 			if(rcount < 0)
-				snprint(err, 255, "%r");
+				snprint(err, Serbufsize, "%r");
 			if(usbdebug >= 3)
 				dsprint(2, "serial: read: %s %ld\n", err, rcount);
 		} while(rcount < 0 && strstr(err, "timed out") != nil);
@@ -457,7 +461,7 @@ dread(Usbfs *fs, Fid *fid, void *data, long count, vlong offset)
 		if(offset != 0)
 			count = 0;
 		else {
-			e = serdumpst(ser, buf, 255);
+			e = serdumpst(ser, buf, Serbufsize);
 			count = usbreadbuf(data, count, 0, buf, e - buf);
 		}
 		break;
@@ -682,11 +686,11 @@ serialmain(Dev *dev, int argc, char* argv[])
 		return usage();
 
 	ser = dev->aux = emallocz(sizeof(Serial), 1);
-	/* BUG could this go wrong?,channel leaks? */
+	/* BUG: could this go wrong? channel leaks? */
 	ser->w4data  = chancreate(sizeof(ulong), 0);
 	ser->gotdata = chancreate(sizeof(ulong), 0);
 	ser->w4empty = chancreate(sizeof(ulong), 0);
-	ser->maxread = ser->maxwrite = 8*1024;
+	ser->maxread = ser->maxwrite = sizeof ser->data;
 	ser->dev = dev;
 	dev->free = serdevfree;
 
@@ -702,15 +706,18 @@ serialmain(Dev *dev, int argc, char* argv[])
 		ser->Serialops = ftops;
 	else {
 		werrstr("serial: no serial devices found");
+		closedev(dev);
 		return -1;
 	}
 
 	if(findendpoints(ser) < 0){
 		werrstr("serial: no endpoints found");
+		closedev(dev);
 		return -1;
 	}
 	if(serinit(ser) < 0){
 		dprint(2, "serial: serinit: %r\n");
+		closedev(dev);
 		return -1;
 	}
 

+ 84 - 34
sys/src/cmd/vl/asm.c

@@ -45,6 +45,34 @@ long	BADOFFSET	=	-1;
 			cflush();\
 	}
 
+#define HPUT(h) { \
+		if (little) { \
+			HLEPUT(h); \
+		} else { \
+			HBEPUT(h); \
+		} \
+	}
+
+#define	HLEPUT(c)\
+	{\
+		cbp[0] = (c);\
+		cbp[1] = (c)>>8;\
+		cbp += 2;\
+		cbc -= 2;\
+		if(cbc <= 0)\
+			cflush();\
+	}
+
+#define	HBEPUT(c)\
+	{\
+		cbp[0] = (c)>>8;\
+		cbp[1] = (c);\
+		cbp += 2;\
+		cbc -= 2;\
+		if(cbc <= 0)\
+			cflush();\
+	}
+
 
 #define	CPUT(c)\
 	{\
@@ -61,6 +89,12 @@ objput(long l)	/* emit long in byte order appropriate to object machine */
 	LPUT(l);
 }
 
+void
+objhput(short s)
+{
+	HPUT(s);
+}
+
 void
 lput(long l)		/* emit long in big-endian byte order */
 {
@@ -357,48 +391,64 @@ asmb(void)
 		lput(0x80L);			/* flags */
 		break;
 	case 5:
+		/* strings are order-independent */
 		strnput("\177ELF", 4);		/* e_ident */
 		CPUT(1);			/* class = 32 bit */
-		CPUT(2);			/* data = MSB */
-		CPUT(1);			/* version = CURRENT */
-		strnput("", 9);
-		lput((2L<<16)|8L);		/* type = EXEC; machine = MIPS */
-		lput(1L);			/* version = CURRENT */
-		lput(entryvalue());		/* entry vaddr */
-		lput(52L);			/* offset to first phdr */
-		lput(0L);			/* offset to first shdr */
-		lput(0L);			/* flags = MIPS */
-		lput((52L<<16)|32L);		/* Ehdr & Phdr sizes*/
-		lput((3L<<16)|0L);		/* # Phdrs & Shdr size */
-		lput((0L<<16)|0L);		/* # Shdrs & shdr string size */
-
-		/* TODO: only these few words are in native byte order? */
-		objput(1L);			/* text - type = PT_LOAD */
+		CPUT(little? 1: 2);		/* data: 1 = LSB, 2 = MSB */
+		CPUT(1);			/* version = 1 */
+		strnput("", 9);			/* reserved for expansion */
+		/* entire remainder of ELF file is in target byte order */
+
+		/* file header part of ELF header */
+		objhput(2);			/* type = EXEC */
+		objhput(8);			/* machine = MIPS */
+		objput(1L);			/* version = CURRENT */
+		objput(entryvalue());		/* entry vaddr */
+		objput(52L);			/* offset to first phdr */
+		objput(0L);			/* offset to first shdr */
+		objput(0L);			/* flags (no MIPS flags defined) */
+		objhput(52);			/* Ehdr size */
+		objhput(32);			/* Phdr size */
+		objhput(3);			/* # of Phdrs */
+		objhput(0);			/* Shdr size */
+		objhput(0);			/* # of Shdrs */
+		objhput(0);			/* Shdr string size */
+
+		/* "Program headers" - one per chunk of file to load */
+
+		/*
+		 * include ELF headers in text -- 8l doesn't,
+		 * but in theory it aids demand loading.
+		 */
+		objput(1L);			/* text: type = PT_LOAD */
 		objput(0L);			/* file offset */
 		objput(INITTEXT-HEADR);		/* vaddr */
 		objput(INITTEXT-HEADR);		/* paddr */
 		objput(HEADR+textsize);		/* file size */
 		objput(HEADR+textsize);		/* memory size */
 		objput(0x05L);			/* protections = RX */
-		objput(0x10000L);		/* alignment code?? */
-
-		lput(1L);			/* data - type = PT_LOAD */
-		lput(HEADR+textsize);		/* file offset */
-		lput(INITDAT);			/* vaddr */
-		lput(INITDAT);			/* paddr */
-		lput(datsize);			/* file size */
-		lput(datsize+bsssize);		/* memory size */
-		lput(0x06L);			/* protections = RW */
-		lput(0x10000L);			/* alignment code?? */
-
-		lput(0L);			/* data - type = PT_NULL */
-		lput(HEADR+textsize+datsize);	/* file offset */
-		lput(0L);
-		lput(0L);
-		lput(symsize);			/* symbol table size */
-		lput(lcsize);			/* line number size */
-		lput(0x04L);			/* protections = R */
-		lput(0x04L);			/* alignment code?? */
+		objput(0x1000L);		/* page-align text off's & vaddrs */
+
+		objput(1L);			/* data: type = PT_LOAD */
+		objput(HEADR+textsize);		/* file offset */
+		objput(INITDAT);		/* vaddr */
+		objput(INITDAT);		/* paddr */
+		objput(datsize);		/* file size */
+		objput(datsize+bsssize);	/* memory size */
+		objput(0x06L);			/* protections = RW */
+		if(INITDAT % 4096 == 0 && (HEADR + textsize) % 4096 == 0)
+			objput(0x1000L);	/* page-align data off's & vaddrs */
+		else
+			objput(0L);		/* do not claim alignment */
+
+		objput(0L);			/* P9 symbols: type = PT_NULL */
+		objput(HEADR+textsize+datsize);	/* file offset */
+		objput(0L);
+		objput(0L);
+		objput(symsize);		/* symbol table size */
+		objput(lcsize);			/* line number size */
+		objput(0x04L);			/* protections = R */
+		objput(0L);			/* do not claim alignment */
 		break;
 	case 6:
 		break;